Exemplarische Vorgehensweise: Vorschläge zur Anzeige von Glühbirne

Glühbirnen sind Symbole im Visual Studio-Editor, die erweitert werden, um eine Reihe von Aktionen anzuzeigen, z. B. Korrekturen für Probleme, die von den integrierten Codeanalysatoren oder der Codeumgestaltung identifiziert werden.

In den Editoren für Visual C# und Visual Basic können Sie auch die .NET-Compilerplattform ("Roslyn") verwenden, um Eigene Codeanalysatoren mit Aktionen zu schreiben und zu verpacken, die Glühbirnen automatisch anzeigen. Weitere Informationen finden Sie unter:

  • How To: Write a C# diagnostic and code fix

  • Gewusst wie: Schreiben einer Visual Basic-Diagnose- und Codekorrektur

    Andere Sprachen wie C++ bieten auch Glühbirnen für einige schnelle Aktionen, z. B. einen Vorschlag zum Erstellen einer Stubimplementierung dieser Funktion.

    So sieht eine Glühbirne aus. In einem Visual Basic- oder Visual C#-Projekt wird unter einem Variablennamen ein roter Wellenschalter angezeigt, wenn er ungültig ist. Wenn Sie mit dem Mauszeiger auf den ungültigen Bezeichner zeigen, wird in der Nähe des Cursors eine Glühbirne angezeigt.

    light bulb

    Wenn Sie auf den Abwärtspfeil durch die Glühbirne klicken, wird eine Reihe von vorgeschlagenen Aktionen zusammen mit einer Vorschau der ausgewählten Aktion angezeigt. In diesem Fall werden die Änderungen angezeigt, die an Ihrem Code vorgenommen werden, wenn Sie die Aktion ausführen.

    light bulb preview

    Sie können Glühbirnen verwenden, um Ihre eigenen vorgeschlagenen Aktionen bereitzustellen. Sie können z. B. Aktionen bereitstellen, um geschweifte geschweifte Klammern in eine neue Zeile zu verschieben oder sie an das Ende der vorherigen Zeile zu verschieben. Die folgende exemplarische Vorgehensweise zeigt, wie Sie eine Glühbirne erstellen, die auf dem aktuellen Wort angezeigt wird und zwei vorgeschlagene Aktionen enthält: In Großbuchstaben konvertieren und in Kleinbuchstaben konvertieren.

Erstellen eines Projekts für verwaltetes Erweiterbarkeitsframework (MEF)

  1. Erstellen Sie ein C#VSIX-Projekt. (Im Dialogfeld "Neues Projekt ", wählen Sie Visual C# / Erweiterbarkeit und dann VSIX-Projekt aus.) Benennen Sie die Lösung LightBulbTest.

  2. Fügen Sie dem Projekt eine Elementvorlage für Editorklassifizierer hinzu. Weitere Informationen finden Sie unter Erstellen einer Erweiterung mit einer Editorelementvorlage.

  3. Löschen Sie die vorhandenen Klassendateien.

  4. Fügen Sie den folgenden Verweis auf das Projekt hinzu, und legen Sie "Lokal kopieren" auf folgendes fest False:

    Microsoft.VisualStudio.Language.IntelliSense

  5. Fügen Sie eine neue Klassendatei hinzu, und nennen Sie sie LightBulbTest.

  6. Fügen Sie die folgenden using-Direktiven hinzu:

    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;
    
    

Implementieren des Anbieters der Glühbirne

  1. Löschen Sie in der Klassendatei LightBulbTest.cs die LightBulbTest-Klasse. Fügen Sie eine Klasse namens TestSuggestedActionsSourceProvider hinzu, die implementiert ISuggestedActionsSourceProviderwird. Exportieren Sie ihn mit dem Namen " Vorgeschlagene Testaktionen " und einem ContentTypeAttribute "Text".

    [Export(typeof(ISuggestedActionsSourceProvider))]
    [Name("Test Suggested Actions")]
    [ContentType("text")]
    internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
    
  2. Importieren Sie die ITextStructureNavigatorSelectorService Klasse innerhalb der Quellanbieterklasse, und fügen Sie sie als Eigenschaft hinzu.

    [Import(typeof(ITextStructureNavigatorSelectorService))]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implementieren Sie die CreateSuggestedActionsSource Methode, um ein ISuggestedActionsSource Objekt zurückzugeben. Die Quelle wird im nächsten Abschnitt erläutert.

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

Implementieren der ISuggestedActionSource

Die vorgeschlagene Aktionsquelle ist für das Sammeln der vorgeschlagenen Aktionen und das Hinzufügen im richtigen Kontext verantwortlich. In diesem Fall ist der Kontext das aktuelle Wort, und die vorgeschlagenen Aktionen sind "UpperCaseSuggestedAction " und "LowerCaseSuggestedAction", die im folgenden Abschnitt erläutert wird.

  1. Fügen Sie eine Klasse TestSuggestedActionsSource hinzu, die implementiert ISuggestedActionsSourcewird.

    internal class TestSuggestedActionsSource : ISuggestedActionsSource
    
  2. Fügen Sie private, schreibgeschützte Felder für den vorgeschlagenen Aktionsquellenanbieter, den Textpuffer und die Textansicht hinzu.

    private readonly TestSuggestedActionsSourceProvider m_factory;
    private readonly ITextBuffer m_textBuffer;
    private readonly ITextView m_textView;
    
  3. Fügen Sie einen Konstruktor hinzu, der die privaten Felder festlegt.

    public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer)
    {
        m_factory = testSuggestedActionsSourceProvider;
        m_textBuffer = textBuffer;
        m_textView = textView;
    }
    
  4. Fügen Sie eine private Methode hinzu, die das Wort zurückgibt, das sich derzeit unter dem Cursor befindet. Die folgende Methode untersucht die aktuelle Position des Cursors und fragt den Textstrukturnavigator nach dem Umfang des Worts. Wenn sich der Cursor auf einem Wort befindet, wird der TextExtent Wert im Ausgabeparameter zurückgegeben. Andernfalls wird null der out Parameter und die Methode zurückgegebenfalse.

    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. Implementieren Sie die HasSuggestedActionsAsync-Methode. Der Editor ruft diese Methode auf, um herauszufinden, ob die Glühbirne angezeigt werden soll. Dieser Aufruf wird häufig ausgeführt, wenn der Cursor von einer Zeile zu einer anderen wechselt, oder wenn die Maus über eine Fehler-Wellenlinie bewegt wird. Es ist asynchron, um anderen UI-Vorgängen zu ermöglichen, während diese Methode funktioniert. In den meisten Fällen muss diese Methode einige Analyse und Analyse der aktuellen Zeile durchführen, sodass die Verarbeitung einige Zeit in Anspruch nehmen kann.

    In dieser Implementierung ruft sie asynchron ab TextExtent und bestimmt, ob der Umfang erheblich ist, wie in, ob er einen anderen Text als Leerzeichen hat.

    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. Implementieren Sie die GetSuggestedActions Methode, die ein Array von SuggestedActionSet Objekten zurückgibt, die die verschiedenen ISuggestedAction Objekte enthalten. Diese Methode wird aufgerufen, wenn die Glühbirne erweitert wird.

    Warnung

    Sie sollten sicherstellen, dass die Implementierungen von HasSuggestedActionsAsync() und GetSuggestedActions() konsistent sind, d. h., wenn HasSuggestedActionsAsync() sie zurückgegeben truewerden, einige GetSuggestedActions() Aktionen anzeigen sollen. In vielen Fällen HasSuggestedActionsAsync() wird kurz davor GetSuggestedActions()aufgerufen, aber dies ist nicht immer der Fall. Wenn der Benutzer z. B. die Glühbirnenaktionen aufruft, wird nur GetSuggestedActions() strg+.) aufgerufen.

    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. Definieren sie ein SuggestedActionsChanged Ereignis.

    public event EventHandler<EventArgs> SuggestedActionsChanged;
    
  8. Um die Implementierung abzuschließen, fügen Sie Implementierungen für die Dispose() und TryGetTelemetryId() Methoden hinzu. Sie möchten keine Telemetrie ausführen. Geben Sie also einfach die GUID zurück false und legen Sie sie auf Emptyfest.

    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;
    }
    

Implementieren von Glühbirnenaktionen

  1. Fügen Sie im Projekt einen Verweis auf Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll hinzu, und legen Sie "Lokal kopieren" auf False" fest.

  2. Erstellen Sie zwei Klassen, die erste mit dem Namen UpperCaseSuggestedAction und die zweite mit dem Namen LowerCaseSuggestedAction. Beide Klassen implementieren ISuggestedAction.

    internal class UpperCaseSuggestedAction : ISuggestedAction
    internal class LowerCaseSuggestedAction : ISuggestedAction
    

    Beide Klassen sind bis auf eine Ausnahme identisch: Die eine ruft ToUpper und die andere ToLower auf. In den folgenden Schritten wird nur die Klasse für die Umwandlung in Großbuchstaben behandelt; Sie müssen aber beide Klassen implementieren. Verwenden Sie diese Schritte als Muster für die Implementierung der Aktion zur Umwandlung in Kleinbuchstaben.

  3. Fügen Sie die folgenden Using-Direktiven für diese Klassen hinzu:

    using Microsoft.VisualStudio.Imaging.Interop;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Media;
    
    
  4. Deklarieren Sie einen Satz privater Felder.

    private ITrackingSpan m_span;
    private string m_upper;
    private string m_display;
    private ITextSnapshot m_snapshot;
    
  5. Fügen Sie einen Konstruktor hinzu, der die Felder festlegt.

    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. Implementieren Sie die GetPreviewAsync Methode so, dass sie die Aktionsvorschau anzeigt.

    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. Implementieren Sie die GetActionSetsAsync Methode so, dass sie eine leere SuggestedActionSet Aufzählung zurückgibt.

    public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult<IEnumerable<SuggestedActionSet>>(null);
    }
    
  8. Implementieren Sie die Eigenschaften wie folgt:

    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. Implementieren Sie die Invoke-Methode, indem Sie den Text im Bereich durch entsprechende Großbuchstaben ersetzen.

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

    Warnung

    Die Glühbirnenaktion Invoke-Methode wird nicht erwartet, dass die Benutzeroberfläche angezeigt wird. Wenn ihre Aktion neue UI (z. B. ein Vorschau- oder Auswahldialogfeld) anzeigt, zeigen Sie die Benutzeroberfläche nicht direkt in der Invoke-Methode an, sondern planen Sie stattdessen, die Benutzeroberfläche nach der Rückgabe von Invoke anzuzeigen.

  10. Um die Implementierung abzuschließen, fügen Sie die Dispose() Und TryGetTelemetryId() Methoden hinzu.

    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. Vergessen Sie nicht, dasselbe zu tun, um LowerCaseSuggestedAction den Anzeigetext in "Konvertieren "{0} in Kleinbuchstabe" und den Aufruf ToUpper zu ToLowerändern.

Erstellen und Testen des Codes

Um diesen Code zu testen, erstellen Sie die LightBulbTest-Lösung, und führen Sie sie in der Experimental-Instanz aus.

  1. Erstellen Sie die Projektmappe.

  2. Wenn Sie dieses Projekt im Debugger ausführen, wird eine zweite Instanz von Visual Studio gestartet.

  3. Erstellen Sie eine Textdatei, und geben Sie Text ein. Sie sollten links neben dem Text eine Glühbirne sehen.

    test the light bulb

  4. Zeigen Sie auf die Glühbirne. Es sollte ein Pfeil nach unten angezeigt werden.

  5. Wenn Sie auf die Glühbirne klicken, sollten zwei vorgeschlagene Aktionen zusammen mit der Vorschau der ausgewählten Aktion angezeigt werden.

    test light bulb, expanded

  6. Wenn Sie auf die erste Aktion klicken, sollte der gesamte Text im aktuellen Wort in Großbuchstaben konvertiert werden. Wenn Sie auf die zweite Aktion klicken, sollte der gesamte Text in Kleinbuchstaben konvertiert werden.