Delen via


Overzicht: Suggesties voor gloeilampen weergeven

Gloeilampen zijn pictogrammen in de Visual Studio-editor die worden uitgebreid om een reeks acties weer te geven, bijvoorbeeld oplossingen voor problemen die zijn geïdentificeerd door de ingebouwde codeanalyses of codeherstructurering.

In de Visual C# en Visual Basic-editors kunt u ook het .NET Compiler Platform ('Roslyn') gebruiken om uw eigen codeanalyses te schrijven en te verpakken met acties die automatisch gloeilampen weergeven. Zie voor meer informatie:

  • Instructies: een C#-diagnose en codeoplossing schrijven

  • nl-NL: Instructies: een Visual Basic-diagnostiek en codecorrectie maken

    Andere talen zoals C++ bieden ook gloeilampen voor enkele snelle acties, zoals een suggestie voor het maken van een stub-implementatie van die functie.

    Hier ziet een gloeilamp eruit. In een Visual Basic- of Visual C#-project wordt een rode kronkel weergegeven onder een variabelenaam wanneer deze ongeldig is. Als u met de muis over de ongeldige identificator beweegt, verschijnt er een lampje bij de cursor.

    gloeilamp

    Als u op de pijl-omlaag van de gloeilamp klikt, wordt er een reeks voorgestelde acties weergegeven, samen met een voorbeeld van de geselecteerde actie. In dit geval worden de wijzigingen weergegeven die in uw code worden aangebracht als u de actie uitvoert.

    gloeilampvoorbeeld

    U kunt gloeilampen gebruiken om uw eigen voorgestelde acties te leveren. U kunt bijvoorbeeld acties opgeven om openende accolades naar een nieuwe regel te verplaatsen of ze aan het einde van de voorgaande regel te plaatsen. In de volgende procedure wordt getoond hoe u een gloeilamp kunt maken die bij het huidige woord verschijnt en twee voorgestelde acties heeft: Converteren naar hoofdletters en Converteren naar kleine letters.

Een MEF-project (Managed Extensibility Framework) maken

  1. Maak een C# VSIX-project. (Selecteer in het dialoogvenster Nieuw projectVisual C# / Uitbreidbaarheiden VSIX Project.) Noem de oplossing LightBulbTest.

  2. Voeg een Editor Classificatie item sjabloon toe aan het project. Zie Een extensie maken met een sjabloon voor editoritemsvoor meer informatie.

  3. Verwijder de bestaande klassebestanden.

  4. Voeg de volgende verwijzing toe aan het project en stel Kopieer lokaal in op False.

    Microsoft.VisualStudio.Language.Intellisense

  5. Voeg een nieuw klassebestand toe en geef het LightBulbTest.

  6. Voeg het volgende toe met behulp van instructies:

    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;
    
    

De bronprovider van de gloeilamp implementeren

  1. Verwijder in het LightBulbTest.cs klassebestand de klasse LightBulbTest. Voeg een klasse toe met de naam TestSuggestedActionsSourceProvider die ISuggestedActionsSourceProviderimplementeert. Exporteer het met de naam Test van Voorgestelde Acties en een ContentTypeAttribute van "tekst".

    [Export(typeof(ISuggestedActionsSourceProvider))]
    [Name("Test Suggested Actions")]
    [ContentType("text")]
    internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
    
  2. Importeer de ITextStructureNavigatorSelectorService in de bronproviderklasse en voeg deze toe als een eigenschap.

    [Import(typeof(ITextStructureNavigatorSelectorService))]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implementeer de methode CreateSuggestedActionsSource om een ISuggestedActionsSource-object te retourneren. De bron wordt in de volgende sectie besproken.

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

De ISuggestedActionSource implementeren

De voorgestelde actiebron is verantwoordelijk voor het verzamelen van de set voorgestelde acties en het toevoegen ervan in de juiste context. In dit geval is de context het huidige woord en de voorgestelde acties worden UpperCaseSuggestedAction en LowerCaseSuggestedAction, die in de volgende sectie worden besproken.

  1. Voeg een klasse TestSuggestedActionsSource- toe waarmee ISuggestedActionsSourcewordt geïmplementeerd.

    internal class TestSuggestedActionsSource : ISuggestedActionsSource
    
  2. Voeg privévelden toe voor de voorgestelde actiebronprovider, de tekstbuffer en de tekstweergave.

    private readonly TestSuggestedActionsSourceProvider m_factory;
    private readonly ITextBuffer m_textBuffer;
    private readonly ITextView m_textView;
    
  3. Voeg een constructor toe waarmee de persoonlijke velden worden ingesteld.

    public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer)
    {
        m_factory = testSuggestedActionsSourceProvider;
        m_textBuffer = textBuffer;
        m_textView = textView;
    }
    
  4. Voeg een privémethode toe die het woord retourneert dat zich momenteel onder de cursor bevindt. Met de volgende methode wordt de huidige locatie van de cursor bekeken en wordt de tekststructuurnavigator gevraagd voor de omvang van het woord. Als de cursor op een woord staat, wordt de TextExtent geretourneerd in de outparameter; anders wordt de parameter outnull en retourneert de methode 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. Implementeer de methode HasSuggestedActionsAsync. De editor roept deze methode aan om erachter te komen of de gloeilamp moet worden weergegeven. Deze aanroep wordt vaak gedaan, bijvoorbeeld wanneer de cursor van de ene regel naar de andere wordt verplaatst of wanneer de muisaanwijzer boven een foutmarkering beweegt. Het is asynchroon om toe te staan dat andere UI-bewerkingen worden uitgevoerd terwijl deze methode werkt. In de meeste gevallen moet deze methode enige parsering en analyse van de huidige regel uitvoeren, zodat de verwerking enige tijd kan duren.

    In deze implementatie wordt de TextExtent asynchroon opgehaald en wordt bepaald of de inhoud significant is, dat wil zeggen, of er tekst aanwezig is anders dan alleen witruimte.

    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. Implementeer de GetSuggestedActions methode, die een matrix retourneert van SuggestedActionSet objecten die de verschillende ISuggestedAction-objecten bevatten. Deze methode wordt aangeroepen wanneer de gloeilamp wordt uitgevouwen.

    Waarschuwing

    Zorg ervoor dat de implementaties van HasSuggestedActionsAsync() en GetSuggestedActions() consistent zijn; Als HasSuggestedActionsAsync()trueretourneert, moet GetSuggestedActions() dus enkele acties hebben om weer te geven. In veel gevallen wordt HasSuggestedActionsAsync() net voor GetSuggestedActions()aangeroepen, maar dit is niet altijd het geval. Als de gebruiker bijvoorbeeld de gloeilampacties aanroept door op (Ctrl+ .) te drukken, wordt alleen GetSuggestedActions() aangeroepen.

    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. Definieer een SuggestedActionsChanged gebeurtenis.

    public event EventHandler<EventArgs> SuggestedActionsChanged;
    
  8. Als u de implementatie wilt voltooien, voegt u implementaties toe voor de Dispose() en TryGetTelemetryId() methoden. U wilt geen telemetrie uitvoeren, dus retourneer false en stel de GUID in op 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;
    }
    

Acties voor gloeilampen implementeren

  1. Voeg in het project een verwijzing toe naar Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll en stel Lokaal kopiëren in op False.

  2. Maak twee klassen, de eerste benoemde UpperCaseSuggestedAction en de tweede met de naam LowerCaseSuggestedAction. Beide klassen implementeren ISuggestedAction.

    internal class UpperCaseSuggestedAction : ISuggestedAction
    internal class LowerCaseSuggestedAction : ISuggestedAction
    

    Beide klassen zijn hetzelfde, behalve dat de ene ToUpper aanroept en de andere ToLoweraanroept. De volgende stappen hebben alleen betrekking op de hoofdletters-actieklasse, maar u moet beide klassen implementeren. Gebruik de stappen voor het implementeren van de hoofdletteractie als patroon voor het implementeren van de kleineletteractie.

  3. Voeg de volgende gebruiksrichtlijnen toe voor deze klassen:

    using Microsoft.VisualStudio.Imaging.Interop;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Media;
    
    
  4. Een set privévelden declareren.

    private ITrackingSpan m_span;
    private string m_upper;
    private string m_display;
    private ITextSnapshot m_snapshot;
    
  5. Voeg een constructor toe waarmee de velden worden ingesteld.

    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. Implementeer de methode GetPreviewAsync zodat het voorbeeld van de actie wordt weergegeven.

    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. Implementeer de methode GetActionSetsAsync zodat deze een lege opsomming SuggestedActionSet retourneert.

    public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult<IEnumerable<SuggestedActionSet>>(null);
    }
    
  8. Implementeer de eigenschappen als volgt.

    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. Implementeer de methode Invoke door de tekst in de spanne te vervangen door het equivalent in hoofdletters.

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

    Waarschuwing

    De actie gloeilamp De methode Aanroepen wordt niet verwacht om de gebruikersinterface weer te geven. Als uw actie nieuwe gebruikersinterface weergeeft (bijvoorbeeld een voorbeeld- of selectiedialoogvenster), geeft u de gebruikersinterface niet rechtstreeks weer vanuit de methode Aanroepen, maar plant u in plaats daarvan om uw gebruikersinterface weer te geven nadat deze is geretourneerd vanuit Aanroepen.

  10. Voeg de Dispose()- en TryGetTelemetryId()-methoden toe om de implementatie te voltooien.

    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. Vergeet niet hetzelfde te doen voor LowerCaseSuggestedAction de weergavetekst te wijzigen in 'Converteren '{0}' in kleine letters' en het aanroepen van ToUpper naar ToLower.

De code bouwen en testen

Als u deze code wilt testen, bouwt u de LightBulbTest-oplossing en voert u deze uit in het experimentele exemplaar.

  1. Bouw de oplossing.

  2. Wanneer u dit project uitvoert in het foutopsporingsprogramma, wordt een tweede exemplaar van Visual Studio gestart.

  3. Maak een tekstbestand en typ tekst. U ziet een gloeilamp links van de tekst.

    de gloeilamp testen

  4. Wijs de gloeilamp aan. U ziet een pijltje omlaag.

  5. Wanneer u op de gloeilamp klikt, worden er twee voorgestelde acties weergegeven, samen met het voorbeeld van de geselecteerde actie.

    testlamp, uitgevouwen

  6. Als u op de eerste actie klikt, moet alle tekst in het huidige woord worden geconverteerd naar hoofdletters. Als u op de tweede actie klikt, moet alle tekst worden geconverteerd naar kleine letters.