Bagikan melalui


Panduan: Menampilkan saran bola lampu

Bola lampu adalah ikon di editor Visual Studio yang diperluas untuk menampilkan serangkaian tindakan, misalnya, perbaikan untuk masalah yang diidentifikasi oleh penganalisis kode bawaan atau pemfaktoran ulang kode.

Di editor Visual C# dan Visual Basic, Anda juga dapat menggunakan .NET Compiler Platform ("Roslyn") untuk menulis dan mengemas penganalisis kode Anda sendiri dengan tindakan yang menampilkan bola lampu secara otomatis. Untuk informasi selengkapnya, lihat:

  • Cara: Menulis diagnostik C# dan perbaikan kode

  • Cara: Menulis diagnostik Visual Basic dan perbaikan kode

    Bahasa lain seperti C++ juga menyediakan bola lampu untuk beberapa tindakan cepat, seperti, saran untuk membuat implementasi stub dari fungsi tersebut.

    Seperti inilah bola lampu terlihat. Dalam proyek Visual Basic atau Visual C#, squiggle merah muncul di bawah nama variabel saat tidak valid. Jika Anda mengarahkan mouse ke pengidentifikasi yang tidak valid, bola lampu muncul di dekat kursor.

    light bulb

    Jika Anda mengklik panah bawah oleh bola lampu, sekumpulan tindakan yang disarankan muncul, bersama dengan pratinjau tindakan yang dipilih. Dalam hal ini, ini menunjukkan perubahan yang dibuat pada kode Anda jika Anda menjalankan tindakan.

    light bulb preview

    Anda dapat menggunakan bola lampu untuk memberikan tindakan yang anda sarankan sendiri. Misalnya, Anda dapat memberikan tindakan untuk memindahkan kurung kurawal pembuka ke baris baru atau memindahkannya ke akhir baris sebelumnya. Panduan berikut menunjukkan cara membuat bola lampu yang muncul pada kata saat ini dan memiliki dua tindakan yang disarankan: Konversi ke huruf besar dan Konversi ke huruf kecil.

Membuat proyek Managed Extensibility Framework (MEF)

  1. Buat proyek C# VSIX. (Dalam Dialog Proyek Baru, pilih Visual C# / Ekstensibilitas, lalu Proyek VSIX.) Beri nama solusi LightBulbTest.

  2. Tambahkan templat item Pengklasifikasi Editor ke proyek. Untuk informasi selengkapnya, lihat Membuat ekstensi dengan templat item editor.

  3. Hapus file kelas yang ada.

  4. Tambahkan referensi berikut ke proyek, dan atur Salin Lokal ke False:

    Microsoft.VisualStudio.Language.Intellisense

  5. Tambahkan file kelas baru dan beri nama LightBulbTest.

  6. Tambahkan hal berikut menggunakan instruksi:

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Utilities;
    using System.ComponentModel.Composition;
    using System.Threading;
    
    

Menerapkan penyedia sumber bola lampu

  1. Dalam file kelas LightBulbTest.cs, hapus kelas LightBulbTest. Tambahkan kelas bernama TestSuggestedActionsSourceProvider yang mengimplementasikan ISuggestedActionsSourceProvider. Ekspor dengan Nama Tindakan yang Disarankan Pengujian dan ContentTypeAttribute "teks".

    [Export(typeof(ISuggestedActionsSourceProvider))]
    [Name("Test Suggested Actions")]
    [ContentType("text")]
    internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
    
  2. Di dalam kelas penyedia sumber, impor ITextStructureNavigatorSelectorService dan tambahkan sebagai properti.

    [Import(typeof(ITextStructureNavigatorSelectorService))]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Terapkan CreateSuggestedActionsSource metode untuk mengembalikan ISuggestedActionsSource objek. Sumber dibahas di bagian berikutnya.

    public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView, ITextBuffer textBuffer)
    {
        if (textBuffer == null || textView == null)
        {
            return null;
        }
        return new TestSuggestedActionsSource(this, textView, textBuffer);
    }
    

Menerapkan ISuggestedActionSource

Sumber tindakan yang disarankan bertanggung jawab untuk mengumpulkan serangkaian tindakan yang disarankan dan menambahkannya dalam konteks yang tepat. Dalam hal ini, konteksnya adalah kata saat ini dan tindakan yang disarankan adalah UpperCaseSuggestedAction dan LowerCaseSuggestedAction, yang dibahas di bagian berikut.

  1. Tambahkan kelas TestSuggestedActionsSource yang mengimplementasikan ISuggestedActionsSource.

    internal class TestSuggestedActionsSource : ISuggestedActionsSource
    
  2. Tambahkan bidang privat baca-saja untuk penyedia sumber tindakan yang disarankan, buffer teks, dan tampilan teks.

    private readonly TestSuggestedActionsSourceProvider m_factory;
    private readonly ITextBuffer m_textBuffer;
    private readonly ITextView m_textView;
    
  3. Tambahkan konstruktor yang mengatur bidang privat.

    public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer)
    {
        m_factory = testSuggestedActionsSourceProvider;
        m_textBuffer = textBuffer;
        m_textView = textView;
    }
    
  4. Tambahkan metode privat yang mengembalikan kata yang saat ini berada di bawah kursor. Metode berikut melihat lokasi kursor saat ini dan meminta navigator struktur teks sejauh mana kata tersebut. Jika kursor ada pada kata, TextExtent dikembalikan dalam parameter keluar; jika tidak, out parameter adalah null dan metode mengembalikan false.

    private bool TryGetWordUnderCaret(out TextExtent wordExtent)
    {
        ITextCaret caret = m_textView.Caret;
        SnapshotPoint point;
    
        if (caret.Position.BufferPosition > 0)
        {
            point = caret.Position.BufferPosition - 1;
        }
        else
        {
            wordExtent = default(TextExtent);
            return false;
        }
    
        ITextStructureNavigator navigator = m_factory.NavigatorService.GetTextStructureNavigator(m_textBuffer);
    
        wordExtent = navigator.GetExtentOfWord(point);
        return true;
    }
    
  5. Mengimplementasikan metode HasSuggestedActionsAsync. Editor memanggil metode ini untuk mengetahui apakah akan menampilkan bola lampu. Panggilan ini sering dilakukan, misalnya, setiap kali kursor bergerak dari satu baris ke baris lain, atau ketika mouse mengarahkan kursor ke kesalahan berlekuk. Ini asinkron untuk memungkinkan operasi UI lain untuk dilaksanakan saat metode ini berfungsi. Dalam kebanyakan kasus, metode ini perlu melakukan beberapa penguraian dan analisis baris saat ini, sehingga pemrosesan mungkin memakan waktu.

    Dalam implementasi ini, secara asinkron mendapatkan TextExtent dan menentukan apakah tingkatnya signifikan, seperti dalam, apakah ia memiliki beberapa teks selain spasi putih.

    public Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
    {
        return Task.Factory.StartNew(() =>
        {
            TextExtent extent;
            if (TryGetWordUnderCaret(out extent))
            {
                // don't display the action if the extent has whitespace
                return extent.IsSignificant;
              }
            return false;
        });
    }
    
  6. Terapkan GetSuggestedActions metode , yang mengembalikan array SuggestedActionSet objek yang berisi objek yang berbeda ISuggestedAction . Metode ini dipanggil ketika bola lampu diperluas.

    Peringatan

    Anda harus memastikan bahwa implementasi HasSuggestedActionsAsync() dan GetSuggestedActions() konsisten; yaitu, jika HasSuggestedActionsAsync() mengembalikan true, maka GetSuggestedActions() harus memiliki beberapa tindakan untuk ditampilkan. Dalam banyak kasus, HasSuggestedActionsAsync() dipanggil tepat sebelum GetSuggestedActions(), tetapi ini tidak selalu terjadi. Misalnya, jika pengguna memanggil tindakan bola lampu dengan menekan (CTRL+ .) hanya GetSuggestedActions() dipanggil.

    public IEnumerable<SuggestedActionSet> GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
    {
        TextExtent extent;
        if (TryGetWordUnderCaret(out extent) && extent.IsSignificant)
        {
            ITrackingSpan trackingSpan = range.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
            var upperAction = new UpperCaseSuggestedAction(trackingSpan);
            var lowerAction = new LowerCaseSuggestedAction(trackingSpan);
            return new SuggestedActionSet[] { new SuggestedActionSet(new ISuggestedAction[] { upperAction, lowerAction }) };
        }
        return Enumerable.Empty<SuggestedActionSet>();
    }
    
  7. SuggestedActionsChanged Tentukan peristiwa.

    public event EventHandler<EventArgs> SuggestedActionsChanged;
    
  8. Untuk menyelesaikan implementasi, tambahkan implementasi untuk Dispose() metode dan TryGetTelemetryId() . Anda tidak ingin melakukan telemetri, jadi kembalikan false saja dan atur GUID ke Empty.

    public void Dispose()
    {
    }
    
    public bool TryGetTelemetryId(out Guid telemetryId)
    {
        // This is a sample provider and doesn't participate in LightBulb telemetry
        telemetryId = Guid.Empty;
        return false;
    }
    

Menerapkan tindakan bola lampu

  1. Dalam proyek, tambahkan referensi ke Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll dan atur Salin Lokal ke False.

  2. Buat dua kelas, yang pertama bernama UpperCaseSuggestedAction dan yang kedua bernama LowerCaseSuggestedAction. Kedua kelas mengimplementasikan ISuggestedAction.

    internal class UpperCaseSuggestedAction : ISuggestedAction
    internal class LowerCaseSuggestedAction : ISuggestedAction
    

    Kedua kelas sama kecuali satu panggilan ToUpper dan panggilan ToLowerlainnya . Langkah-langkah berikut hanya mencakup kelas tindakan huruf besar, tetapi Anda harus mengimplementasikan kedua kelas. Gunakan langkah-langkah untuk menerapkan tindakan huruf besar sebagai pola untuk menerapkan tindakan huruf kecil.

  3. Tambahkan hal berikut menggunakan direktif untuk kelas-kelas ini:

    using Microsoft.VisualStudio.Imaging.Interop;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Media;
    
    
  4. Mendeklarasikan sekumpulan bidang privat.

    private ITrackingSpan m_span;
    private string m_upper;
    private string m_display;
    private ITextSnapshot m_snapshot;
    
  5. Tambahkan konstruktor yang mengatur bidang.

    public UpperCaseSuggestedAction(ITrackingSpan span)
    {
        m_span = span;
        m_snapshot = span.TextBuffer.CurrentSnapshot;
        m_upper = span.GetText(m_snapshot).ToUpper();
        m_display = string.Format("Convert '{0}' to upper case", span.GetText(m_snapshot));
    }
    
  6. Terapkan GetPreviewAsync metode sehingga menampilkan pratinjau tindakan.

    public Task<object> GetPreviewAsync(CancellationToken cancellationToken)
    {
        var textBlock = new TextBlock();
        textBlock.Padding = new Thickness(5);
        textBlock.Inlines.Add(new Run() { Text = m_upper });
        return Task.FromResult<object>(textBlock);
    }
    
  7. Terapkan GetActionSetsAsync metode sehingga mengembalikan enumerasi kosong SuggestedActionSet .

    public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult<IEnumerable<SuggestedActionSet>>(null);
    }
    
  8. Terapkan properti sebagai berikut.

    public bool HasActionSets
    {
        get { return false; }
    }
    public string DisplayText
    {
        get { return m_display; }
    }
    public ImageMoniker IconMoniker
    {
       get { return default(ImageMoniker); }
    }
    public string IconAutomationText
    {
        get
        {
            return null;
        }
    }
    public string InputGestureText
    {
        get
        {
            return null;
        }
    }
    public bool HasPreview
    {
        get { return true; }
    }
    
  9. Terapkan Invoke metode dengan mengganti teks dalam rentang dengan huruf besar yang setara.

    public void Invoke(CancellationToken cancellationToken)
    {
        m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper);
    }
    

    Peringatan

    Metode Pemanggilan tindakan bola lampu tidak diharapkan untuk menunjukkan UI. Jika tindakan Anda memunculkan UI baru (misalnya dialog pratinjau atau pilihan), jangan tampilkan UI langsung dari dalam metode Panggil tetapi sebaliknya jadwalkan untuk menampilkan UI Anda setelah kembali dari Panggil.

  10. Untuk menyelesaikan implementasi, tambahkan Dispose() metode dan TryGetTelemetryId() .

    public void Dispose()
    {
    }
    
    public bool TryGetTelemetryId(out Guid telemetryId)
    {
        // This is a sample action and doesn't participate in LightBulb telemetry
        telemetryId = Guid.Empty;
        return false;
    }
    
  11. Jangan lupa untuk melakukan hal yang sama untuk LowerCaseSuggestedAction mengubah teks tampilan menjadi "Konversi '{0}' ke huruf kecil" dan panggilan ToUpper ke ToLower.

Membangun dan menguji kode

Untuk menguji kode ini, buat solusi LightBulbTest dan jalankan dalam instans Eksperimental.

  1. Bangun solusinya.

  2. Saat Anda menjalankan proyek ini di debugger, instans kedua Visual Studio dimulai.

  3. Buat file teks dan ketik beberapa teks. Anda akan melihat bola lampu di sebelah kiri teks.

    test the light bulb

  4. Arahkan ke bola lampu. Anda akan melihat panah bawah.

  5. Saat Anda mengklik bola lampu, dua tindakan yang disarankan harus ditampilkan, bersama dengan pratinjau tindakan yang dipilih.

    test light bulb, expanded

  6. Jika Anda mengklik tindakan pertama, semua teks dalam kata saat ini harus dikonversi ke huruf besar. Jika Anda mengklik tindakan kedua, semua teks harus dikonversi ke huruf kecil.