Procedura dettagliata: Visualizzare le descrizioni comando QuickInfo

QuickInfo è una funzionalità di IntelliSense che visualizza le firme e le descrizioni dei metodi quando un utente sposta il puntatore su un nome di metodo. È possibile implementare funzionalità basate sul linguaggio, ad esempio QuickInfo, definendo gli identificatori per i quali si desidera fornire descrizioni di Informazioni rapide e quindi creando una descrizione comando in cui visualizzare il contenuto. È possibile definire QuickInfo nel contesto di un servizio linguistico oppure definire l'estensione del nome file e il tipo di contenuto e visualizzare quickInfo solo per quel tipo oppure è possibile visualizzare QuickInfo per un tipo di contenuto esistente, ad esempio "text". Questa procedura dettagliata illustra come visualizzare QuickInfo per il tipo di contenuto "text".

Nell'esempio QuickInfo di questa procedura dettagliata vengono visualizzate le descrizioni comando quando un utente sposta il puntatore su un nome di metodo. Questa progettazione richiede l'implementazione di queste quattro interfacce:

  • interfaccia di origine

  • interfaccia del provider di origine

  • interfaccia controller

  • interfaccia del provider controller

    I provider di origine e controller sono parti del componente MEF (Managed Extensibility Framework) e sono responsabili dell'esportazione delle classi di origine e controller e dell'importazione di servizi e broker, ad esempio ITextBufferFactoryService, che crea il buffer di testo della descrizione comando e , IQuickInfoBrokerche attiva la sessione QuickInfo.

    In questo esempio, l'origine QuickInfo usa un elenco hardcoded di nomi e descrizioni dei metodi, ma nelle implementazioni complete, il servizio di linguaggio e la documentazione del linguaggio sono responsabili della fornitura di tale contenuto.

Creare un progetto MEF

Per creare un progetto MEF

  1. Creare un progetto VSIX C#. (In Finestra di dialogo Nuovo progetto , selezionare Visual C# / Estendibilità e quindi progetto VSIX. Assegnare alla soluzione QuickInfoTestil nome .

  2. Aggiungere un modello di elemento classificatore dell'editor al progetto. Per altre informazioni, vedere Creare un'estensione con un modello di elemento dell'editor.

  3. Eliminare i file di classe esistenti.

Implementare l'origine QuickInfo

L'origine QuickInfo è responsabile della raccolta del set di identificatori e delle relative descrizioni e dell'aggiunta del contenuto al buffer di testo della descrizione comando quando viene rilevato uno degli identificatori. In questo esempio, gli identificatori e le relative descrizioni vengono aggiunti nel costruttore di origine.

Per implementare l'origine QuickInfo

  1. Aggiungere un file di classe e assegnargli il nome TestQuickInfoSource.

  2. Aggiungere un riferimento a Microsoft.VisualStudio.Language.IntelliSense.

  3. Aggiungere le importazioni seguenti.

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  4. Dichiarare una classe che implementa IQuickInfoSourcee denominarla TestQuickInfoSource.

    internal class TestQuickInfoSource : IQuickInfoSource
    
  5. Aggiungere campi per il provider di origine QuickInfo, il buffer di testo e un set di nomi di metodo e firme del metodo. In questo esempio i nomi dei metodi e le firme vengono inizializzati nel TestQuickInfoSource costruttore.

    private TestQuickInfoSourceProvider m_provider;
    private ITextBuffer m_subjectBuffer;
    private Dictionary<string, string> m_dictionary;
    
  6. Aggiungere un costruttore che imposta il provider di origine QuickInfo e il buffer di testo e popola il set di nomi di metodo e le firme e le descrizioni dei metodi.

    public TestQuickInfoSource(TestQuickInfoSourceProvider provider, ITextBuffer subjectBuffer)
    {
        m_provider = provider;
        m_subjectBuffer = subjectBuffer;
    
        //these are the method names and their descriptions
        m_dictionary = new Dictionary<string, string>();
        m_dictionary.Add("add", "int add(int firstInt, int secondInt)\nAdds one integer to another.");
        m_dictionary.Add("subtract", "int subtract(int firstInt, int secondInt)\nSubtracts one integer from another.");
        m_dictionary.Add("multiply", "int multiply(int firstInt, int secondInt)\nMultiplies one integer by another.");
        m_dictionary.Add("divide", "int divide(int firstInt, int secondInt)\nDivides one integer by another.");
    }
    
  7. Implementa il metodo AugmentQuickInfoSession. In questo esempio, il metodo trova la parola corrente o la parola precedente se il cursore si trova alla fine di una riga o di un buffer di testo. Se la parola è uno dei nomi di metodo, la descrizione del nome del metodo viene aggiunta al contenuto QuickInfo.

    public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> qiContent, out ITrackingSpan applicableToSpan)
    {
        // Map the trigger point down to our buffer.
        SnapshotPoint? subjectTriggerPoint = session.GetTriggerPoint(m_subjectBuffer.CurrentSnapshot);
        if (!subjectTriggerPoint.HasValue)
        {
            applicableToSpan = null;
            return;
        }
    
        ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot;
        SnapshotSpan querySpan = new SnapshotSpan(subjectTriggerPoint.Value, 0);
    
        //look for occurrences of our QuickInfo words in the span
        ITextStructureNavigator navigator = m_provider.NavigatorService.GetTextStructureNavigator(m_subjectBuffer);
        TextExtent extent = navigator.GetExtentOfWord(subjectTriggerPoint.Value);
        string searchText = extent.Span.GetText();
    
        foreach (string key in m_dictionary.Keys)
        {
            int foundIndex = searchText.IndexOf(key, StringComparison.CurrentCultureIgnoreCase);
            if (foundIndex > -1)
            {
                applicableToSpan = currentSnapshot.CreateTrackingSpan
                    (
                    //querySpan.Start.Add(foundIndex).Position, 9, SpanTrackingMode.EdgeInclusive
                                            extent.Span.Start + foundIndex, key.Length, SpanTrackingMode.EdgeInclusive
                    );
    
                string value;
                m_dictionary.TryGetValue(key, out value);
                if (value != null)
                    qiContent.Add(value);
                else
                    qiContent.Add("");
    
                return;
            }
        }
    
        applicableToSpan = null;
    }
    
  8. È anche necessario implementare un metodo Dispose(), poiché IQuickInfoSource implementa IDisposable:

    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

Implementare un provider di origine QuickInfo

Il provider dell'origine QuickInfo serve principalmente per esportare se stesso come parte del componente MEF e creare un'istanza dell'origine QuickInfo. Poiché si tratta di una parte del componente MEF, può importare altre parti del componente MEF.

Per implementare un provider di origine QuickInfo

  1. Dichiarare un provider di origine QuickInfo denominato TestQuickInfoSourceProvider che implementa IQuickInfoSourceProvidered esportarlo con " NameAttribute ToolTip QuickInfo Source", un OrderAttribute oggetto Before="default" e " ContentTypeAttribute text".

    [Export(typeof(IQuickInfoSourceProvider))]
    [Name("ToolTip QuickInfo Source")]
    [Order(Before = "Default Quick Info Presenter")]
    [ContentType("text")]
    internal class TestQuickInfoSourceProvider : IQuickInfoSourceProvider
    
  2. Importare due servizi ITextStructureNavigatorSelectorService dell'editor e ITextBufferFactoryService, come proprietà di TestQuickInfoSourceProvider.

    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ITextBufferFactoryService TextBufferFactoryService { get; set; }
    
  3. Implementare TryCreateQuickInfoSource per restituire un nuovo TestQuickInfoSourceoggetto .

    public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer)
    {
        return new TestQuickInfoSource(this, textBuffer);
    }
    

Implementare un controller QuickInfo

I controller QuickInfo determinano quando viene visualizzato QuickInfo. In questo esempio QuickInfo viene visualizzato quando il puntatore si trova su una parola che corrisponde a uno dei nomi di metodo. Il controller QuickInfo implementa un gestore eventi al passaggio del mouse che attiva una sessione QuickInfo.

Per implementare un controller QuickInfo

  1. Dichiarare una classe che implementa IIntellisenseControllere denominarla TestQuickInfoController.

    internal class TestQuickInfoController : IIntellisenseController
    
  2. Aggiungere campi privati per la visualizzazione testo, i buffer di testo rappresentati nella visualizzazione testo, la sessione QuickInfo e il provider di controller QuickInfo.

    private ITextView m_textView;
    private IList<ITextBuffer> m_subjectBuffers;
    private TestQuickInfoControllerProvider m_provider;
    private IQuickInfoSession m_session;
    
  3. Aggiungere un costruttore che imposta i campi e aggiunge il gestore eventi del passaggio del mouse.

    internal TestQuickInfoController(ITextView textView, IList<ITextBuffer> subjectBuffers, TestQuickInfoControllerProvider provider)
    {
        m_textView = textView;
        m_subjectBuffers = subjectBuffers;
        m_provider = provider;
    
        m_textView.MouseHover += this.OnTextViewMouseHover;
    }
    
  4. Aggiungere il gestore eventi al passaggio del mouse che attiva la sessione QuickInfo.

    private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e)
    {
        //find the mouse position by mapping down to the subject buffer
        SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch
             (new SnapshotPoint(m_textView.TextSnapshot, e.Position),
            PointTrackingMode.Positive,
            snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer),
            PositionAffinity.Predecessor);
    
        if (point != null)
        {
            ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position,
            PointTrackingMode.Positive);
    
            if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView))
            {
                m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true);
            }
        }
    }
    
  5. Implementare il Detach metodo in modo da rimuovere il gestore eventi al passaggio del mouse quando il controller viene scollegato dalla visualizzazione testo.

    public void Detach(ITextView textView)
    {
        if (m_textView == textView)
        {
            m_textView.MouseHover -= this.OnTextViewMouseHover;
            m_textView = null;
        }
    }
    
  6. Implementare il ConnectSubjectBuffer metodo e il DisconnectSubjectBuffer metodo come metodi vuoti per questo esempio.

    public void ConnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    
    public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    

Implementazione del provider di controller QuickInfo

Il provider del controller QuickInfo serve principalmente per esportare se stesso come parte del componente MEF e creare un'istanza del controller QuickInfo. Poiché si tratta di una parte del componente MEF, può importare altre parti del componente MEF.

Per implementare il provider di controller QuickInfo

  1. Dichiarare una classe denominata TestQuickInfoControllerProvider che implementa IIntellisenseControllerProvidered esportarla con " NameAttribute ToolTip QuickInfo Controller" e una ContentTypeAttribute di "text":

    [Export(typeof(IIntellisenseControllerProvider))]
    [Name("ToolTip QuickInfo Controller")]
    [ContentType("text")]
    internal class TestQuickInfoControllerProvider : IIntellisenseControllerProvider
    
  2. Importare IQuickInfoBroker come proprietà.

    [Import]
    internal IQuickInfoBroker QuickInfoBroker { get; set; }
    
  3. Implementare il TryCreateIntellisenseController metodo creando un'istanza del controller QuickInfo.

    public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList<ITextBuffer> subjectBuffers)
    {
        return new TestQuickInfoController(textView, subjectBuffers, this);
    }
    

Compilare e testare il codice

Per testare questo codice, compilare la soluzione QuickInfoTest ed eseguirla nell'istanza sperimentale.

Per compilare e testare la soluzione QuickInfoTest

  1. Compilare la soluzione.

  2. Quando si esegue questo progetto nel debugger, viene avviata una seconda istanza di Visual Studio.

  3. Creare un file di testo e digitare un testo che includa le parole "add" e "sottrazione".

  4. Spostare il puntatore su una delle occorrenze di "add". La firma e la descrizione del add metodo devono essere visualizzate.