Tutorial: Mostrar la Ayuda de firmaWalkthrough: Display Signature Help

Ayuda para la firma (también conocido como información de parámetros) muestra la firma de un método en una información sobre herramientas cuando un usuario escribe el carácter de inicio de lista de parámetros (normalmente un paréntesis de apertura).Signature Help (also known as Parameter Info) displays the signature of a method in a tooltip when a user types the parameter list start character (typically an opening parenthesis). Como se ha escrito un parámetro y el separador de parámetro (normalmente una coma), la información sobre herramientas se actualiza para mostrar el siguiente parámetro en negrita.As a parameter and parameter separator (typically a comma) are typed, the tooltip is updated to show the next parameter in bold. Puede definir la Ayuda de signatura de las siguientes maneras: en el contexto de un servicio de lenguaje, definir su propia extensión de nombre de archivo y el tipo de contenido y mostrar la Ayuda de firma para solo ese tipo o mostrar la Ayuda de firma para un tipo de contenido existente (por ejemplo, "text").You can define Signature Help in the following ways: in the context of a language service, define your own file name extension and content type and display Signature Help for just that type, or display Signature Help for an existing content type (for example, "text"). En este tutorial se muestra cómo mostrar la Ayuda de signatura para el tipo de contenido "text".This walkthrough shows how to display Signature Help for the "text" content type.

Normalmente se activa la Ayuda de signatura escribiendo un carácter específico, por ejemplo, "(" (paréntesis de apertura) y se descartan escribiendo otro carácter, por ejemplo, ")" (paréntesis de cierre).Signature Help is typically triggered by typing a specific character, for example, "(" (opening parenthesis), and dismissed by typing another character, for example, ")" (closing parenthesis). Las características de IntelliSense que se desencadenan escribiendo un carácter pueden implementarse mediante el uso de un controlador de comandos para las pulsaciones de teclas (el IOleCommandTarget interfaz) y un proveedor del controlador que implementa el IVsTextViewCreationListener interfaz.IntelliSense features that are triggered by typing a character can be implemented by using a command handler for the keystrokes (the IOleCommandTarget interface) and a handler provider that implements the IVsTextViewCreationListener interface. Para crear el origen de Ayuda de signatura, que es la lista de firmas que participan en la Ayuda de signatura, implemente el ISignatureHelpSource interfaz y un proveedor de código fuente que se ejecuta el ISignatureHelpSourceProvider interfaz.To create the Signature Help source, which is the list of signatures that participate in Signature Help, implement the ISignatureHelpSource interface and a source provider that runs the ISignatureHelpSourceProvider interface. Los proveedores son partes de componentes de Managed Extensibility Framework (MEF) y son responsables de las clases de origen y el controlador de exportación e importación de los servicios y los agentes, por ejemplo, el ITextStructureNavigatorSelectorService, que permite navegar en el búfer de texto y el ISignatureHelpBroker, lo que desencadena la sesión de Ayuda de signatura.The providers are Managed Extensibility Framework (MEF) component parts, and are responsible for exporting the source and controller classes and importing services and brokers, for example, the ITextStructureNavigatorSelectorService, which lets you navigate in the text buffer, and the ISignatureHelpBroker, which triggers the Signature Help session.

Este tutorial muestra cómo configurar la Ayuda de firma para un conjunto codificado de forma rígida de identificadores.This walkthrough shows how to set up Signature Help for a hard-coded set of identifiers. En implementaciones completas, el lenguaje es responsable de proporcionar ese contenido.In full implementations, the language is responsible for providing that content.

Requisitos previosPrerequisites

A partir de Visual Studio 2015, no instale el SDK de Visual Studio desde el centro de descarga.Starting in Visual Studio 2015, you don't install the Visual Studio SDK from the download center. Ha incluido como una característica opcional en el programa de instalación de Visual Studio.It's included as an optional feature in Visual Studio setup. También puede instalar el SDK de VS más adelante.You can also install the VS SDK later on. Para obtener más información, consulte instalar el SDK de Visual Studio.For more information, see Install the Visual Studio SDK.

Creación de un proyecto MEFCreating a MEF project

Para crear un nuevo proyecto de MEFTo create a MEF project

  1. Cree un proyecto de VSIX de C#.Create a C# VSIX project. (En el nuevo proyecto cuadro de diálogo, seleccione Visual C# / extensibilidad, a continuación, proyecto VSIX.) Nombre de la solución SignatureHelpTest.(In the New Project dialog, select Visual C# / Extensibility, then VSIX Project.) Name the solution SignatureHelpTest.

  2. Agregar una plantilla de elemento de clasificador de Editor para el proyecto.Add an Editor Classifier item template to the project. Para obtener más información, consulte crear una extensión con una plantilla de elementos de editor.For more information, see Create an extension with an editor item template.

  3. Elimine los archivos de clase existentes.Delete the existing class files.

  4. Agregue las siguientes referencias al proyecto y asegúrese de que CopyLocal está establecido en false:Add the following references to the project, and make sure CopyLocal is set to false:

    Microsoft.VisualStudio.EditorMicrosoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.IntellisenseMicrosoft.VisualStudio.Language.Intellisense

    Microsoft.VisualStudio.OLE.InteropMicrosoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.InteropMicrosoft.VisualStudio.TextManager.Interop

Implementar firmas de Ayuda de signatura y parámetrosImplement Signature Help signatures and parameters

El origen de la Ayuda de signatura se basa en las firmas que implementan ISignature, cada uno de los cuales contiene los parámetros que implementan IParameter.The Signature Help source is based on signatures that implement ISignature, each of which contains parameters that implement IParameter. En una implementación completa, esta información se obtiene con la documentación del lenguaje, pero en este ejemplo, las firmas están codificados de forma rígida.In a full implementation, this information would be obtained from the language documentation, but in this example, the signatures are hard-coded.

Para implementar la Ayuda de signatura firmas y los parámetrosTo implement the Signature Help signatures and parameters

  1. Agregue un archivo de clase y asígnele el nombre SignatureHelpSource.Add a class file and name it SignatureHelpSource.

  2. Agregue las siguientes importaciones.Add the following imports.

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Collections.ObjectModel
    Imports System.ComponentModel.Composition
    Imports System.Runtime.InteropServices
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Utilities
    Imports Microsoft.VisualStudio.Editor
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio
    Imports Microsoft.VisualStudio.TextManager.Interop
    Imports Microsoft.VisualStudio.OLE.Interop
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Utilities;
    using Microsoft.VisualStudio.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.TextManager.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    
  3. Agregue una clase denominada TestParameter que implementa IParameter.Add a class named TestParameter that implements IParameter.

    Friend Class TestParameter
        Implements IParameter
    
    internal class TestParameter : IParameter
    
  4. Agregue un constructor que establece todas las propiedades.Add a constructor that sets all the properties.

    Public Sub New(ByVal documentation As String, ByVal locus As Span, ByVal name As String, ByVal signature As ISignature)
        Me.privateDocumentation = documentation
        Me.privateLocus = locus
        Me.privateName = name
        Me.privateSignature = signature
    End Sub
    
    public TestParameter(string documentation, Span locus, string name, ISignature signature)
    {
        Documentation = documentation;
        Locus = locus;
        Name = name;
        Signature = signature;
    }
    
  5. Agregue las propiedades de IParameter.Add the properties of IParameter.

    Private privateDocumentation As String
    ReadOnly Property Documentation() As String Implements IParameter.Documentation
        Get
            Return privateDocumentation
        End Get
    
    End Property
    Private privateLocus As Span
    ReadOnly Property Locus() As Span Implements IParameter.Locus
        Get
            Return privateLocus
        End Get
    End Property
    Private privateName As String
    ReadOnly Property Name() As String Implements IParameter.Name
        Get
            Return privateName
        End Get
    End Property
    Private privateSignature As ISignature
    ReadOnly Property Signature() As ISignature Implements IParameter.Signature
        Get
            Return privateSignature
        End Get
    End Property
    Private privatePrettyPrintedLocus As Span
    ReadOnly Property PrettyPrintedLocus() As Span Implements IParameter.PrettyPrintedLocus
        Get
            Return privatePrettyPrintedLocus
        End Get
    End Property
    
    public string Documentation { get; private set; }
    public Span Locus { get; private set; }
    public string Name { get; private set; }
    public ISignature Signature { get; private set; }
    public Span PrettyPrintedLocus { get; private set; }
    
  6. Agregue una clase denominada TestSignature que implementa ISignature.Add a class named TestSignature that implements ISignature.

    Friend Class TestSignature
        Implements ISignature
    
    internal class TestSignature : ISignature
    
  7. Agregue algunos campos privados.Add some private fields.

    Private m_subjectBuffer As ITextBuffer
    Private m_currentParameter As IParameter
    Private m_content As String
    Private m_documentation As String
    Friend m_applicableToSpan As ITrackingSpan
    Friend m_parameters As ReadOnlyCollection(Of IParameter)
    Private m_printContent As String
    
    private ITextBuffer m_subjectBuffer;
    private IParameter m_currentParameter;
    private string m_content;
    private string m_documentation;
    private ITrackingSpan m_applicableToSpan;
    private ReadOnlyCollection<IParameter> m_parameters;
    private string m_printContent;
    
  8. Agregue un constructor que establece los campos y se suscribe a la Changed eventos.Add a constructor that sets the fields and subscribes to the Changed event.

    Friend Sub New(ByVal subjectBuffer As ITextBuffer, ByVal content As String, ByVal doc As String, ByVal parameters As ReadOnlyCollection(Of IParameter))
        m_subjectBuffer = subjectBuffer
        m_content = content
        m_documentation = doc
        m_parameters = parameters
        AddHandler m_subjectBuffer.Changed, AddressOf OnSubjectBufferChanged
    End Sub
    
    internal TestSignature(ITextBuffer subjectBuffer, string content, string doc, ReadOnlyCollection<IParameter> parameters)
    {
        m_subjectBuffer = subjectBuffer;
        m_content = content;
        m_documentation = doc;
        m_parameters = parameters;
        m_subjectBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(OnSubjectBufferChanged);
    }
    
  9. Declarar un CurrentParameterChanged eventos.Declare a CurrentParameterChanged event. Este evento se desencadena cuando el usuario se rellene en uno de los parámetros de la firma.This event is raised when the user fills in one of the parameters in the signature.

    Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
    
    public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
    
  10. Implemente el CurrentParameter propiedad, por lo que TI provoca la CurrentParameterChanged eventos cuando se cambia el valor de propiedad.Implement the CurrentParameter property so that it raises the CurrentParameterChanged event when the property value is changed.

    ReadOnly Property CurrentParameter() As IParameter Implements ISignature.CurrentParameter
        Get
            Return m_currentParameter
        End Get
    End Property
    
    public IParameter CurrentParameter
    {
        get { return m_currentParameter; }
        internal set
        {
            if (m_currentParameter != value)
            {
                IParameter prevCurrentParameter = m_currentParameter;
                m_currentParameter = value;
                this.RaiseCurrentParameterChanged(prevCurrentParameter, m_currentParameter);
            }
        }
    }
    
  11. Agregue un método que genera el CurrentParameterChanged eventos.Add a method that raises the CurrentParameterChanged event.

    Private Sub RaiseCurrentParameterChanged(ByVal prevCurrentParameter As IParameter, ByVal newCurrentParameter As IParameter)
        Dim tempHandler As EventHandler(Of CurrentParameterChangedEventArgs) = Me.CurrentParameterChangedEvent
        If tempHandler IsNot Nothing Then
            tempHandler(Me, New CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter))
        End If
    End Sub
    
    private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
    {
        EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
        if (tempHandler != null)
        {
            tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
        }
    }
    
  12. Agregue un método que calcula el parámetro actual comparando el número de comas en el ApplicableToSpan al número de comas en la firma.Add a method that computes the current parameter by comparing the number of commas in the ApplicableToSpan to the number of commas in the signature.

    Friend Sub ComputeCurrentParameter()
        If Parameters.Count = 0 Then
            Me.m_currentParameter = Nothing
            Return
        End If
    
        'the number of commas in the string is the index of the current parameter
        Dim sigText As String = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot)
    
        Dim currentIndex As Integer = 0
        Dim commaCount As Integer = 0
        Do While currentIndex < sigText.Length
            Dim commaIndex As Integer = sigText.IndexOf(","c, currentIndex)
            If commaIndex = -1 Then
                Exit Do
            End If
            commaCount += 1
            currentIndex = commaIndex + 1
        Loop
    
        If commaCount < Parameters.Count Then
            Me.m_currentParameter = Parameters(commaCount)
        Else
            'too many commas, so use the last parameter as the current one.
            Me.m_currentParameter = Parameters(Parameters.Count - 1)
        End If
    End Sub
    
    internal void ComputeCurrentParameter()
    {
        if (Parameters.Count == 0)
        {
            this.CurrentParameter = null;
            return;
        }
    
        //the number of commas in the string is the index of the current parameter
        string sigText = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot);
    
        int currentIndex = 0;
        int commaCount = 0;
        while (currentIndex < sigText.Length)
        {
            int commaIndex = sigText.IndexOf(',', currentIndex);
            if (commaIndex == -1)
            {
                break;
            }
            commaCount++;
            currentIndex = commaIndex + 1;
        }
    
        if (commaCount < Parameters.Count)
        {
            this.CurrentParameter = Parameters[commaCount];
        }
        else
        {
            //too many commas, so use the last parameter as the current one.
            this.CurrentParameter = Parameters[Parameters.Count - 1];
        }
    }
    
  13. Agregar un controlador de eventos para el Changed evento que llama el ComputeCurrentParameter() método.Add an event handler for the Changed event that calls the ComputeCurrentParameter() method.

    Friend Sub OnSubjectBufferChanged(ByVal sender As Object, ByVal e As TextContentChangedEventArgs)
        Me.ComputeCurrentParameter()
    End Sub
    
    internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
    {
        this.ComputeCurrentParameter();
    }
    
  14. Implemente la propiedad ApplicableToSpan.Implement the ApplicableToSpan property. Esta propiedad contiene un ITrackingSpan que corresponde al intervalo de texto en el búfer al que se aplica la firma.This property holds an ITrackingSpan that corresponds to the span of text in the buffer to which the signature applies.

    ReadOnly Property ApplicableToSpan() As ITrackingSpan Implements ISignature.ApplicableToSpan
        Get
            Return (m_applicableToSpan)
        End Get
    End Property
    
    public ITrackingSpan ApplicableToSpan
    {
        get { return (m_applicableToSpan); }
        internal set { m_applicableToSpan = value; }
    }
    
  15. Implementar los demás parámetros.Implement the other parameters.

    ReadOnly Property Content() As String Implements ISignature.Content
        Get
            Return (m_content)
        End Get
    End Property
    
    ReadOnly Property Documentation() As String Implements ISignature.Documentation
        Get
            Return (m_documentation)
        End Get
    End Property
    
    ReadOnly Property Parameters() As ReadOnlyCollection(Of IParameter) Implements ISignature.Parameters
        Get
            Return (m_parameters)
        End Get
    End Property
    
    ReadOnly Property PrettyPrintedContent() As String Implements ISignature.PrettyPrintedContent
        Get
            Return (m_printContent)
        End Get
    End Property
    
    public string Content
    {
        get { return (m_content); }
        internal set { m_content = value; }
    }
    
    public string Documentation
    {
        get { return (m_documentation); }
        internal set { m_documentation = value; }
    }
    
    public ReadOnlyCollection<IParameter> Parameters
    {
        get { return (m_parameters); }
        internal set { m_parameters = value; }
    }
    
    public string PrettyPrintedContent
    {
        get { return (m_printContent); }
        internal set { m_printContent = value; }
    }
    

Implementar el origen de la Ayuda de signaturaImplement the Signature Help source

El origen de la Ayuda de signatura es el conjunto de firmas para el que proporcionar información.The Signature Help source is the set of signatures for which you provide information.

Para implementar el origen de la Ayuda de signaturaTo implement the Signature Help source

  1. Agregue una clase denominada TestSignatureHelpSource que implementa ISignatureHelpSource.Add a class named TestSignatureHelpSource that implements ISignatureHelpSource.

    Friend Class TestSignatureHelpSource
        Implements ISignatureHelpSource
    
    internal class TestSignatureHelpSource : ISignatureHelpSource
    
  2. Agregue una referencia al búfer de texto.Add a reference to the text buffer.

    Private m_textBuffer As ITextBuffer
    
    private ITextBuffer m_textBuffer;
    
  3. Agregue un constructor que establece el búfer de texto y el proveedor de código fuente de Ayuda de signatura.Add a constructor that sets the text buffer and the Signature Help source provider.

    Public Sub New(ByVal textBuffer As ITextBuffer)
        m_textBuffer = textBuffer
    End Sub
    
    public TestSignatureHelpSource(ITextBuffer textBuffer)
    {
        m_textBuffer = textBuffer;
    }
    
  4. Implemente el método AugmentSignatureHelpSession.Implement the AugmentSignatureHelpSession method. En este ejemplo, las firmas están codificados, pero en una implementación completa podría obtener esta información de la documentación del lenguaje.In this example, the signatures are hard-coded, but in a full implementation you would get this information from the language documentation.

    Public Sub AugmentSignatureHelpSession(ByVal session As ISignatureHelpSession, ByVal signatures As IList(Of ISignature)) Implements ISignatureHelpSource.AugmentSignatureHelpSession
        Dim snapshot As ITextSnapshot = m_textBuffer.CurrentSnapshot
        Dim position As Integer = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot)
    
        Dim applicableToSpan As ITrackingSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(New Span(position, 0), SpanTrackingMode.EdgeInclusive, 0)
    
        signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan))
        signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan))
    End Sub
    
    public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList<ISignature> signatures)
    {
        ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot;
        int position = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot);
    
        ITrackingSpan applicableToSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(
         new Span(position, 0), SpanTrackingMode.EdgeInclusive, 0);
    
        signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan));
        signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan));
    
    }
    
  5. El método auxiliar CreateSignature() viene meramente ilustrativos.The helper method CreateSignature() is provided just for illustration.

    Private Function CreateSignature(ByVal textBuffer As ITextBuffer, ByVal methodSig As String, ByVal methodDoc As String, ByVal span As ITrackingSpan) As TestSignature
        Dim sig As New TestSignature(textBuffer, methodSig, methodDoc, Nothing)
        AddHandler textBuffer.Changed, AddressOf sig.OnSubjectBufferChanged
    
        'find the parameters in the method signature (expect methodname(one, two)
        Dim pars() As String = methodSig.Split(New Char() {"("c, ","c, ")"c})
        Dim paramList As New List(Of IParameter)()
    
        Dim locusSearchStart As Integer = 0
        For i As Integer = 1 To pars.Length - 1
            Dim param As String = pars(i).Trim()
    
            If String.IsNullOrEmpty(param) Then
                Continue For
            End If
    
            'find where this parameter is located in the method signature
            Dim locusStart As Integer = methodSig.IndexOf(param, locusSearchStart)
            If locusStart >= 0 Then
                Dim locus As New Span(locusStart, param.Length)
                locusSearchStart = locusStart + param.Length
                paramList.Add(New TestParameter("Documentation for the parameter.", locus, param, sig))
            End If
        Next i
    
        sig.m_Parameters = New ReadOnlyCollection(Of IParameter)(paramList)
        sig.m_ApplicableToSpan = span
        sig.ComputeCurrentParameter()
        Return sig
    End Function
    
    private TestSignature CreateSignature(ITextBuffer textBuffer, string methodSig, string methodDoc, ITrackingSpan span)
    {
        TestSignature sig = new TestSignature(textBuffer, methodSig, methodDoc, null);
        textBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(sig.OnSubjectBufferChanged);
    
        //find the parameters in the method signature (expect methodname(one, two)
        string[] pars = methodSig.Split(new char[] { '(', ',', ')' });
        List<IParameter> paramList = new List<IParameter>();
    
        int locusSearchStart = 0;
        for (int i = 1; i < pars.Length; i++)
        {
            string param = pars[i].Trim();
    
            if (string.IsNullOrEmpty(param))
                continue;
    
            //find where this parameter is located in the method signature
            int locusStart = methodSig.IndexOf(param, locusSearchStart);
            if (locusStart >= 0)
            {
                Span locus = new Span(locusStart, param.Length);
                locusSearchStart = locusStart + param.Length;
                paramList.Add(new TestParameter("Documentation for the parameter.", locus, param, sig));
            }
        }
    
        sig.Parameters = new ReadOnlyCollection<IParameter>(paramList);
        sig.ApplicableToSpan = span;
        sig.ComputeCurrentParameter();
        return sig;
    }
    
  6. Implemente el método GetBestMatch.Implement the GetBestMatch method. En este ejemplo, hay solo dos firmas, cada uno de los cuales tiene dos parámetros.In this example, there are just two signatures, each of which has two parameters. Por lo tanto, este método no es necesario.Therefore, this method is not required. En una implementación más completa, en el que más de un origen de Ayuda de signatura está disponible, este método se utiliza para decidir si el origen de Ayuda de signatura de prioridad más alta puede proporcionar una signatura coincidente.In a fuller implementation, in which more than one Signature Help source is available, this method is used to decide whether the highest-priority Signature Help source can supply a matching signature. Si no es posible, el método devuelve null y el origen de la siguiente prioridad más alta se le pide que proporcione a una coincidencia.If it can't, the method returns null and the next-highest-priority source is asked to supply a match.

    Public Function GetBestMatch(ByVal session As ISignatureHelpSession) As ISignature Implements ISignatureHelpSource.GetBestMatch
        If session.Signatures.Count > 0 Then
            Dim applicableToSpan As ITrackingSpan = session.Signatures(0).ApplicableToSpan
            Dim text As String = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot)
    
            If text.Trim().Equals("add") Then 'get only "add"
                Return session.Signatures(0)
            End If
        End If
        Return Nothing
    End Function
    
    public ISignature GetBestMatch(ISignatureHelpSession session)
    {
        if (session.Signatures.Count > 0)
        {
            ITrackingSpan applicableToSpan = session.Signatures[0].ApplicableToSpan;
            string text = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot);
    
            if (text.Trim().Equals("add"))  //get only "add" 
                return session.Signatures[0];
        }
        return null;
    }
    
  7. Implemente el Dispose() método:Implement the Dispose() method:

    Private m_isDisposed As Boolean
    
    Public Sub Dispose() Implements IDisposable.Dispose
        If Not m_isDisposed Then
            GC.SuppressFinalize(Me)
            m_isDisposed = True
        End If
    End Sub
    
    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

Implementar el proveedor de código fuente de Ayuda de signaturaImplement the Signature Help source provider

El proveedor de código fuente de Ayuda de signatura es responsable para exportar la parte del componente de Managed Extensibility Framework (MEF) y para crear una instancia del origen de la Ayuda de signatura.The Signature Help source provider is responsible for exporting the Managed Extensibility Framework (MEF) component part and for instantiating the Signature Help source.

Para implementar el proveedor de código fuente de Ayuda de signaturaTo implement the Signature Help source provider

  1. Agregue una clase denominada TestSignatureHelpSourceProvider que implementa ISignatureHelpSourceProvidery se exporta con un NameAttribute, un ContentTypeAttribute de "text" y un OrderAttribute de Before = "default".Add a class named TestSignatureHelpSourceProvider that implements ISignatureHelpSourceProvider, and export it with a NameAttribute, a ContentTypeAttribute of "text", and an OrderAttribute of Before="default".

    <Export(GetType(ISignatureHelpSourceProvider)), Name("Signature Help source"), Order(Before:="default"), ContentType("text")>
    Friend Class TestSignatureHelpSourceProvider
        Implements ISignatureHelpSourceProvider
    
    [Export(typeof(ISignatureHelpSourceProvider))]
    [Name("Signature Help source")]
    [Order(Before = "default")]
    [ContentType("text")]
    internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
    
  2. Implemente TryCreateSignatureHelpSource creando el TestSignatureHelpSource.Implement TryCreateSignatureHelpSource by instantiating the TestSignatureHelpSource.

    Public Function TryCreateSignatureHelpSource(ByVal textBuffer As ITextBuffer) As ISignatureHelpSource Implements ISignatureHelpSourceProvider.TryCreateSignatureHelpSource
        Return New TestSignatureHelpSource(textBuffer)
    End Function
    
    public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer)
    {
        return new TestSignatureHelpSource(textBuffer);
    }
    

Implementar el controlador de comandosImplement the command handler

Ayuda para las firmas normalmente se desencadena por un paréntesis de apertura "(" carácter y descartadas por un paréntesis de cierre")" caracteres.Signature Help is typically triggered by an opening parenthesis "(" character and dismissed by a closing parenthesis ")" character. Puede controlar estas pulsaciones de teclas mediante la ejecución de un IOleCommandTarget para que se desencadene una sesión de Ayuda de signatura cuando recibe una apertura paréntesis precedido por un nombre de método conocidos y descarta la sesión cuando recibe un cierre de paréntesis.You can handle these keystrokes by running a IOleCommandTarget so that it triggers a Signature Help session when it receives an opening parenthesis character preceded by a known method name, and dismisses the session when it receives a closing parenthesis character.

Para implementar el controlador de comandosTo implement the command handler

  1. Agregue una clase denominada TestSignatureHelpCommand que implementa IOleCommandTarget.Add a class named TestSignatureHelpCommand that implements IOleCommandTarget.

    Friend NotInheritable Class TestSignatureHelpCommandHandler
        Implements IOleCommandTarget
    
    internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
    
  2. Agregar campos privados para el IVsTextView adaptador (que le permite agregar el controlador de comandos a los controladores de cadena de comandos), la vista de texto, el agente de Ayuda de signatura y sesión, un ITextStructureNavigatory la siguiente IOleCommandTarget.Add private fields for the IVsTextView adapter (which lets you add the command handler to the chain of command handlers), the text view, the Signature Help broker and session, a ITextStructureNavigator, and the next IOleCommandTarget.

    Private m_nextCommandHandler As IOleCommandTarget
    Private m_textView As ITextView
    Private m_broker As ISignatureHelpBroker
    Private m_session As ISignatureHelpSession
    Private m_navigator As ITextStructureNavigator
    
    IOleCommandTarget m_nextCommandHandler;
    ITextView m_textView;
    ISignatureHelpBroker m_broker;
    ISignatureHelpSession m_session;
    ITextStructureNavigator m_navigator;
    
  3. Agregue un constructor para inicializar estos campos y agregar el filtro de comandos a la cadena de filtros de comandos.Add a constructor to initialize these fields and to add the command filter to the chain of command filters.

    Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal nav As ITextStructureNavigator, ByVal broker As ISignatureHelpBroker)
        Me.m_textView = textView
        Me.m_broker = broker
        Me.m_navigator = nav
    
        'add this to the filter chain
        textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
    End Sub
    
    internal TestSignatureHelpCommandHandler(IVsTextView textViewAdapter, ITextView textView, ITextStructureNavigator nav, ISignatureHelpBroker broker)
    {
        this.m_textView = textView;
        this.m_broker = broker;
        this.m_navigator = nav;
    
        //add this to the filter chain
        textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
    }
    
  4. Implemente el Exec método para desencadenar la sesión de Ayuda de signatura cuando el filtro de comandos recibe un paréntesis de apertura carácter "(" carácter después de que uno de los nombres de método conocidos y para cerrar la sesión cuando recibe un paréntesis de cierre")" mientras la sesión está activa.Implement the Exec method to trigger the Signature Help session when the command filter receives an opening parenthesis "(" character after one of the known method names, and to dismiss the session when it receives a closing parenthesis ")" character while the session is still active. En todos los casos, se reenvía el comando.In every case, the command is forwarded.

    Public Function Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdID As UInteger, ByVal nCmdexecopt As UInteger, ByVal pvaIn As IntPtr, ByVal pvaOut As IntPtr) As Integer Implements IOleCommandTarget.Exec
        Dim typedChar As Char = Char.MinValue
    
        If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
            typedChar = CChar(ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn))))
            If typedChar.Equals("("c) Then
                'move the point back so it's in the preceding word
                Dim point As SnapshotPoint = m_textView.Caret.Position.BufferPosition - 1
                Dim extent As TextExtent = m_navigator.GetExtentOfWord(point)
                Dim word As String = extent.Span.GetText()
                If word.Equals("add") Then
                    m_session = m_broker.TriggerSignatureHelp(m_textView)
                End If
    
            ElseIf typedChar.Equals(")"c) AndAlso m_session IsNot Nothing Then
                m_session.Dismiss()
                m_session = Nothing
            End If
        End If
        Return m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
    End Function
    
    public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        char typedChar = char.MinValue;
    
        if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
        {
            typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            if (typedChar.Equals('('))
            {
                //move the point back so it's in the preceding word
                SnapshotPoint point = m_textView.Caret.Position.BufferPosition - 1;
                TextExtent extent = m_navigator.GetExtentOfWord(point);
                string word = extent.Span.GetText();
                if (word.Equals("add"))
                    m_session = m_broker.TriggerSignatureHelp(m_textView);
    
            }
            else if (typedChar.Equals(')') && m_session != null)
            {
                m_session.Dismiss();
                m_session = null;
            }
        }
        return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
    }
    
  5. Implemente el QueryStatus método por lo que TI siempre reenvía el comando.Implement the QueryStatus method so that it always forwards the command.

    Public Function QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As UInteger, ByVal prgCmds() As OLECMD, ByVal pCmdText As IntPtr) As Integer Implements IOleCommandTarget.QueryStatus
        Return m_nextCommandHandler.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText)
    End Function
    
    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    

Implementar el proveedor de comandos de Ayuda de signaturaImplement the Signature Help command provider

Puede proporcionar el comando de Ayuda de signatura implementando el IVsTextViewCreationListener para crear el controlador de comandos cuando se crea la vista de texto.You can provide the Signature Help command by implementing the IVsTextViewCreationListener to instantiate the command handler when the text view is created.

Para implementar el proveedor de comandos de Ayuda de signaturaTo implement the Signature Help command provider

  1. Agregue una clase denominada TestSignatureHelpController que implementa IVsTextViewCreationListener y exportarlo con la NameAttribute, ContentTypeAttribute, y TextViewRoleAttribute.Add a class named TestSignatureHelpController that implements IVsTextViewCreationListener and export it with the NameAttribute, ContentTypeAttribute, and TextViewRoleAttribute.

    <Export(GetType(IVsTextViewCreationListener)), Name("Signature Help controller"), TextViewRole(PredefinedTextViewRoles.Editable), ContentType("text")>
    Friend Class TestSignatureHelpCommandProvider
        Implements IVsTextViewCreationListener
    
    [Export(typeof(IVsTextViewCreationListener))]
    [Name("Signature Help controller")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    [ContentType("text")]
    internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
    
  2. Importar el IVsEditorAdaptersFactoryService (utilizado para obtener el ITextView, dado el IVsTextView objeto), el ITextStructureNavigatorSelectorService (que se utiliza para buscar la palabra actual) y el ISignatureHelpBroker (para desencadenar la sesión de Ayuda de signatura).Import the IVsEditorAdaptersFactoryService (used to get the ITextView, given the IVsTextView object), the ITextStructureNavigatorSelectorService (used to find the current word), and the ISignatureHelpBroker (to trigger the Signature Help session).

    <Import()>
    Friend AdapterService As IVsEditorAdaptersFactoryService
    
    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    <Import()>
    Friend SignatureHelpBroker As ISignatureHelpBroker
    
    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService;
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ISignatureHelpBroker SignatureHelpBroker;
    
  3. Implemente el VsTextViewCreated método creando el TestSignatureCommandHandler.Implement the VsTextViewCreated method by instantiating the TestSignatureCommandHandler.

    Public Sub VsTextViewCreated(ByVal textViewAdapter As IVsTextView) Implements IVsTextViewCreationListener.VsTextViewCreated
        Dim textView As ITextView = AdapterService.GetWpfTextView(textViewAdapter)
        If textView Is Nothing Then
            Return
        End If
    
        textView.Properties.GetOrCreateSingletonProperty(Function() New TestSignatureHelpCommandHandler(textViewAdapter, textView, NavigatorService.GetTextStructureNavigator(textView.TextBuffer), SignatureHelpBroker))
    End Sub
    
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
        if (textView == null)
            return;
    
        textView.Properties.GetOrCreateSingletonProperty(
             () => new TestSignatureHelpCommandHandler(textViewAdapter,
                textView,
                NavigatorService.GetTextStructureNavigator(textView.TextBuffer),
                SignatureHelpBroker));
    }
    

Compilar y probar el códigoBuild and Test the Code

Para probar este código, compile la solución SignatureHelpTest y ejecútelo en la instancia experimental.To test this code, build the SignatureHelpTest solution and run it in the experimental instance.

Para compilar y probar la solución SignatureHelpTestTo build and test the SignatureHelpTest solution

  1. Compile la solución.Build the solution.

  2. Al ejecutar este proyecto en el depurador, se inicia una segunda instancia de Visual Studio.When you run this project in the debugger, a second instance of Visual Studio is started.

  3. Cree un archivo de texto y escriba algún texto que incluye la palabra "Agregar" Además de un paréntesis de apertura.Create a text file and type some text that includes the word "add" plus an opening parenthesis.

  4. Después de escribir el paréntesis de apertura, debería ver una información sobre herramientas que muestra una lista de las dos firmas para el add() método.After you type the opening parenthesis, you should see a tooltip that displays a list of the two signatures for the add() method.

Vea tambiénSee also

Tutorial: Vincular un tipo de contenido a una extensión de nombre de archivoWalkthrough: Link a content type to a file name extension