Návod: Zobrazení návrhů žárovky

Žárovky jsou ikony v editoru sady Visual Studio, které rozbalují zobrazení sady akcí, například opravy problémů identifikovaných integrovanými analyzátory kódu nebo refaktoringem kódu.

V editorech Visual C# a Visual Basic můžete také pomocí platformy .NET Compiler Platform (Roslyn) napsat a zabalit vlastní analyzátory kódu s akcemi, které zobrazují žárovky automaticky. Další informace naleznete v tématu:

  • Postupy: Zápis diagnostiky a opravy kódu jazyka C#

  • Postupy: Zápis diagnostiky a opravy kódu jazyka Visual Basic

    Další jazyky, jako je C++, také poskytují žárovky pro některé rychlé akce, například návrh na vytvoření implementace této funkce zástupných procedur.

    Takto vypadá žárovka. V projektu Jazyka Visual Basic nebo Visual C# se pod názvem proměnné zobrazí červená vlnovka, pokud je neplatná. Pokud najedete myší na neplatný identifikátor, zobrazí se u kurzoru žárovka.

    light bulb

    Pokud kliknete na šipku dolů u žárovky, zobrazí se sada navrhovaných akcí spolu s náhledem vybrané akce. V tomto případě se zobrazí změny provedené v kódu, pokud akci provedete.

    light bulb preview

    Žárovky můžete použít k poskytnutí vlastních navrhovaných akcí. Můžete například zadat akce pro přesunutí levých složených závorek na nový řádek nebo jejich přesunutí na konec předchozího řádku. Následující návod ukazuje, jak vytvořit žárovku, která se zobrazí na aktuálním slově a má dvě navrhované akce: Převést na velká a malá písmena.

Vytvoření projektu MEF (Managed Extensibility Framework)

  1. Vytvořte projekt VSIX jazyka C#. (V Dialogové okno Nový projekt , vyberte Visual C# / Rozšiřitelnost a pak projekt VSIX.) Pojmenujte řešení LightBulbTest.

  2. Přidejte do projektu šablonu položky klasifikátoru editoru. Další informace najdete v tématu Vytvoření rozšíření pomocí šablony položky editoru.

  3. Odstraňte existující soubory třídy.

  4. Přidejte do projektu následující odkaz a nastavte kopírovat místní na False:

    Microsoft.VisualStudio.Language.Intellisense

  5. Přidejte nový soubor třídy a pojmenujte ho LightBulbTest.

  6. Přidejte následující direktivy using:

    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;
    
    

Implementace poskytovatele zdroje žárovky

  1. V souboru třídy LightBulbTest.cs odstraňte třídu LightBulbTest. Přidejte třídu s názvem TestSuggestedActionsSourceProvider , která implementuje ISuggestedActionsSourceProvider. Exportujte ho s názvem navrhovaných akcí testu a textem ContentTypeAttribute .

    [Export(typeof(ISuggestedActionsSourceProvider))]
    [Name("Test Suggested Actions")]
    [ContentType("text")]
    internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
    
  2. Uvnitř třídy zdrojového poskytovatele naimportujte ITextStructureNavigatorSelectorService a přidejte ji jako vlastnost.

    [Import(typeof(ITextStructureNavigatorSelectorService))]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implementujte metodu CreateSuggestedActionsSource pro vrácení objektu ISuggestedActionsSource . Zdroj je popsán v další části.

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

Implementace ISuggestedActionSource

Navrhovaný zdroj akcí zodpovídá za shromažďování sady navrhovaných akcí a jejich přidání do správného kontextu. V tomto případě je kontext aktuálním slovem a navrhované akce jsou UpperCaseSuggestedAction a LowerCaseSuggestedAction, které jsou popsány v následující části.

  1. Přidejte třídu TestSuggestedActionsSource , která implementuje ISuggestedActionsSource.

    internal class TestSuggestedActionsSource : ISuggestedActionsSource
    
  2. Přidejte soukromá pole určená jen pro čtení pro navrhovaného zprostředkovatele zdroje akcí, vyrovnávací paměť textu a textové zobrazení.

    private readonly TestSuggestedActionsSourceProvider m_factory;
    private readonly ITextBuffer m_textBuffer;
    private readonly ITextView m_textView;
    
  3. Přidejte konstruktor, který nastaví soukromá pole.

    public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer)
    {
        m_factory = testSuggestedActionsSourceProvider;
        m_textBuffer = textBuffer;
        m_textView = textView;
    }
    
  4. Přidejte soukromou metodu, která vrací slovo, které je právě pod kurzorem. Následující metoda se podívá na aktuální umístění kurzoru a požádá navigátor struktury textu o rozsah slova. Pokud je kurzor na slově, TextExtent vrátí se v out parametru; v opačném případě out je null parametr a metoda vrátí 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. Implementujte metodu HasSuggestedActionsAsync . Editor volá tuto metodu, aby zjistil, zda se má žárovka zobrazit. Toto volání se často provádí například pokaždé, když se kurzor přesune z jednoho řádku na jiný nebo když najede myší na vlnovku chyby. Je asynchronní, aby ostatní operace uživatelského rozhraní mohly pokračovat v době, kdy tato metoda funguje. Ve většině případů tato metoda potřebuje provést analýzu a analýzu aktuálního řádku, takže zpracování může nějakou dobu trvat.

    V této implementaci asynchronně získá TextExtent a určuje, zda je rozsah významný, stejně jako v, zda má jiný text než prázdné znaky.

    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. Implementujte metodu GetSuggestedActions , která vrací pole SuggestedActionSet objektů, které obsahují různé ISuggestedAction objekty. Tato metoda se volá při rozbalení žárovky.

    Upozorňující

    Měli byste se ujistit, že implementace HasSuggestedActionsAsync() a GetSuggestedActions() jsou konzistentní; to znamená, že pokud HasSuggestedActionsAsync() se vrátí true, pak GetSuggestedActions() by měly mít některé akce k zobrazení. V mnoha případech, HasSuggestedActionsAsync() je volána těsně před GetSuggestedActions(), ale to není vždy případ. Pokud například uživatel vyvolá akce žárovky stisknutím klávesy (CTRL+.) je volána.GetSuggestedActions()

    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. Definujte SuggestedActionsChanged událost.

    public event EventHandler<EventArgs> SuggestedActionsChanged;
    
  8. K dokončení implementace přidejte implementace pro metody Dispose() a TryGetTelemetryId() metody. Nechcete provádět telemetrii, takže stačí vrátit false a nastavit identifikátor GUID na Emptyhodnotu .

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

Implementace akcí žárovky

  1. V projektu přidejte odkaz na Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll a nastavte Kopírovat místní na False.

  2. Vytvořte dvě třídy, první název UpperCaseSuggestedAction a druhý pojmenovaný LowerCaseSuggestedAction. Obě třídy implementují ISuggestedAction.

    internal class UpperCaseSuggestedAction : ISuggestedAction
    internal class LowerCaseSuggestedAction : ISuggestedAction
    

    Obě třídy jsou stejné s tím rozdílem, že jedno volání ToUpper a druhé volání ToLower. Následující kroky pokrývají pouze třídu akcí velkými písmeny, ale musíte implementovat obě třídy. Kroky pro implementaci akce velkými písmeny použijte jako vzor pro implementaci akce malými písmeny.

  3. Přidejte následující direktivy using pro tyto třídy:

    using Microsoft.VisualStudio.Imaging.Interop;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Media;
    
    
  4. Deklarujte sadu privátních polí.

    private ITrackingSpan m_span;
    private string m_upper;
    private string m_display;
    private ITextSnapshot m_snapshot;
    
  5. Přidejte konstruktor, který nastaví pole.

    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. Implementujte metodu GetPreviewAsync tak, aby zobrazila náhled akce.

    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. Implementujte metodu GetActionSetsAsync tak, aby vrátila prázdný SuggestedActionSet výčet.

    public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult<IEnumerable<SuggestedActionSet>>(null);
    }
    
  8. Implementujte vlastnosti následujícím způsobem.

    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. Implementujte metodu Invoke nahrazením textu v rozsahu jeho velkými písmeny ekvivalentem.

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

    Upozorňující

    Metoda Vyvolání akce žárovky se neočekává, že se zobrazí uživatelské rozhraní. Pokud vaše akce vyvolá nové uživatelské rozhraní (například dialogové okno náhledu nebo výběru), nezobrazí uživatelské rozhraní přímo z metody Invoke , ale místo toho naplánujte zobrazení uživatelského rozhraní po návratu z Invoke.

  10. K dokončení implementace přidejte metody Dispose() a TryGetTelemetryId() metody.

    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. Nezapomeňte udělat totéž, LowerCaseSuggestedAction když změníte zobrazovaný text na "Převést{0} '' na malá písmena" a volání ToUpper na ToLower.

Sestavení a otestování kódu

Tento kód otestujete tak, že sestavíte řešení LightBulbTest a spustíte ho v experimentální instanci.

  1. Sestavte řešení.

  2. Když tento projekt spustíte v ladicím programu, spustí se druhá instance sady Visual Studio.

  3. Vytvořte textový soubor a zadejte nějaký text. Nalevo od textu by se měla zobrazit žárovka.

    test the light bulb

  4. Nasměrujte na žárovku. Měla by se zobrazit šipka dolů.

  5. Když kliknete na žárovku, měly by se zobrazit dvě navrhované akce spolu s náhledem vybrané akce.

    test light bulb, expanded

  6. Pokud kliknete na první akci, měl by být veškerý text v aktuálním slově převeden na velká písmena. Pokud kliknete na druhou akci, měl by být veškerý text převeden na malá písmena.