Procédure pas à pas : Afficher l’aide sur la signature
L’aide sur la signature (également appelée Informations sur les paramètres) affiche la signature d’une méthode dans une info-bulle lorsqu’un utilisateur tape le caractère de début de la liste de paramètres (généralement une parenthèse ouvrante). En tant que paramètre et séparateur de paramètres (généralement une virgule) sont tapés, l’info-bulle est mise à jour pour afficher le paramètre suivant en gras. Vous pouvez définir l’aide de signature de la manière suivante : dans le contexte d’un service de langage, définissez votre propre extension de nom de fichier et votre propre type de contenu et affichez l’aide de signature pour ce type, ou affichez l’aide de signature pour un type de contenu existant (par exemple, « text »). Cette procédure pas à pas montre comment afficher l’aide de signature pour le type de contenu « text ».
L’aide de signature est généralement déclenchée en tapant un caractère spécifique, par exemple « (« (« (parenthèse ouvrante) et ignorée en tapant un autre caractère, par exemple , ») (parenthèse fermante). Les fonctionnalités IntelliSense déclenchées en tapant un caractère peuvent être implémentées à l’aide d’un gestionnaire de commandes pour les séquences de touches (l’interface IOleCommandTarget ) et d’un fournisseur de gestionnaires qui implémente l’interface IVsTextViewCreationListener . Pour créer la source d’aide de signature, qui est la liste des signatures qui participent à l’aide de signature, implémentez l’interface ISignatureHelpSource et un fournisseur source qui exécute l’interface ISignatureHelpSourceProvider . Les fournisseurs sont des composants MEF (Managed Extensibility Framework) et sont responsables de l’exportation des classes source et du contrôleur et de l’importation de services et de répartiteurs, par exemple, le ITextStructureNavigatorSelectorService, qui vous permet de naviguer dans la mémoire tampon de texte et le ISignatureHelpBroker, qui déclenche la session d’aide de signature.
Cette procédure pas à pas montre comment configurer l’aide de signature pour un ensemble codé en dur d’identificateurs. Dans les implémentations complètes, la langue est chargée de fournir ce contenu.
Création d’un projet MEF
Pour créer un projet MEF
Créez un projet VSIX C#. (Dans le Boîte de dialogue Nouveau projet , sélectionnez Visual C# / Extensibilité, puis VSIX Project.) Nommez la solution
SignatureHelpTest
.Ajoutez un modèle d’élément Classifieur d’éditeur au projet. Pour plus d’informations, consultez Créer une extension avec un modèle d’élément d’éditeur.
Supprimez les fichiers de classe existants.
Ajoutez les références suivantes au projet et vérifiez que CopyLocal est défini sur
false
:Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell.14.0
Microsoft.VisualStudio.TextManager.Interop
Implémenter des signatures et des paramètres d’aide sur la signature
La source d’aide de signature est basée sur les signatures qui implémentent ISignaturechacune des paramètres qui implémentent IParameter. Dans une implémentation complète, ces informations sont obtenues à partir de la documentation linguistique, mais dans cet exemple, les signatures sont codées en dur.
Pour implémenter les signatures et paramètres d’aide de signature
Ajoutez un fichier de classe et nommez-le
SignatureHelpSource
.Ajoutez les importations suivantes.
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;
Ajoutez une classe nommée
TestParameter
qui implémente IParameter.Ajoutez un constructeur qui définit toutes les propriétés.
Ajoutez les propriétés de IParameter.
Ajoutez une classe nommée
TestSignature
qui implémente ISignature.Ajoutez des champs privés.
Ajoutez un constructeur qui définit les champs et s’abonne à l’événement Changed .
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); }
Déclarez un
CurrentParameterChanged
événement. Cet événement est déclenché lorsque l’utilisateur remplit l’un des paramètres de la signature.Implémentez la CurrentParameter propriété afin qu’elle déclenche l’événement
CurrentParameterChanged
lorsque la valeur de la propriété est modifiée.Ajoutez une méthode qui déclenche l’événement
CurrentParameterChanged
.private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter) { EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged; if (tempHandler != null) { tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter)); } }
Ajoutez une méthode qui calcule le paramètre actuel en comparant le nombre de virgules dans la ApplicableToSpan signature au nombre de virgules dans la signature.
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]; } }
Ajoutez un gestionnaire d’événements pour l’événement Changed qui appelle la
ComputeCurrentParameter()
méthode.Implémentez la propriété ApplicableToSpan. Cette propriété contient une ITrackingSpan valeur qui correspond à l’étendue du texte dans la mémoire tampon à laquelle la signature s’applique.
Implémentez les autres paramètres.
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; } }
Implémenter la source d’aide sur la signature
La source d’aide sur la signature est l’ensemble de signatures pour lesquelles vous fournissez des informations.
Pour implémenter la source d’aide sur la signature
Ajoutez une classe nommée
TestSignatureHelpSource
qui implémente ISignatureHelpSource.Ajoutez une référence à la mémoire tampon de texte.
Ajoutez un constructeur qui définit la mémoire tampon de texte et le fournisseur source d’aide de signature.
Implémentez la méthode AugmentSignatureHelpSession. Dans cet exemple, les signatures sont codées en dur, mais dans une implémentation complète, vous obtenez ces informations à partir de la documentation linguistique.
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)); }
La méthode
CreateSignature()
d’assistance est fournie uniquement pour l’illustration.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; }
Implémentez la méthode GetBestMatch. Dans cet exemple, il n’existe que deux signatures, chacune ayant deux paramètres. Par conséquent, cette méthode n’est pas requise. Dans une implémentation plus complète, dans laquelle plusieurs sources d’aide sur la signature sont disponibles, cette méthode est utilisée pour déterminer si la source d’aide de signature la plus prioritaire peut fournir une signature correspondante. Si ce n’est pas le cas, la méthode retourne null et la source de priorité la plus élevée suivante est demandée pour fournir une correspondance.
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; }
Implémentez la
Dispose()
méthode :
Implémenter le fournisseur de source d’aide sur la signature
Le fournisseur de source d’aide à la signature est responsable de l’exportation du composant MEF (Managed Extensibility Framework) et de l’instanciation de la source d’aide de signature.
Pour implémenter le fournisseur source d’aide sur la signature
Ajoutez une classe nommée
TestSignatureHelpSourceProvider
qui implémente ISignatureHelpSourceProvider, puis exportez-la avec un NameAttribute, un ContentTypeAttribute texte et un OrderAttribute before="default ».Implémentez en TryCreateSignatureHelpSource instanciant le
TestSignatureHelpSource
.
Implémenter le gestionnaire de commandes
L’aide de signature est généralement déclenchée par une parenthèse ouvrante « (« caractère » et ignorée par un caractère fermant ) ». Vous pouvez gérer ces séquences de touches en exécutant une IOleCommandTarget session d’aide de signature pour qu’elle déclenche une session d’aide de signature lorsqu’elle reçoit un caractère de parenthèse ouvrant précédée d’un nom de méthode connu et ignore la session lorsqu’elle reçoit un caractère de parenthèse fermante.
Pour implémenter le gestionnaire de commandes
Ajoutez une classe nommée
TestSignatureHelpCommand
qui implémente IOleCommandTarget.Ajoutez des champs privés pour l’adaptateur IVsTextView (ce qui vous permet d’ajouter le gestionnaire de commandes à la chaîne de gestionnaires de commandes), l’affichage texte, le répartiteur d’aide de signature et la session, a ITextStructureNavigator, et le suivant IOleCommandTarget.
Ajoutez un constructeur pour initialiser ces champs et ajouter le filtre de commandes à la chaîne de filtres de commandes.
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); }
Implémentez la Exec méthode pour déclencher la session d’aide de signature lorsque le filtre de commande reçoit un caractère « (« » après l’un des noms de méthode connus, et pour ignorer la session lorsqu’elle reçoit un caractère de parenthèse fermante « ) pendant que la session est toujours active. Dans tous les cas, la commande est transférée.
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); }
Implémentez la QueryStatus méthode afin qu’elle transfère toujours la commande.
Implémenter le fournisseur de commandes d’aide sur la signature
Vous pouvez fournir la commande d’aide de signature en implémentant le IVsTextViewCreationListener gestionnaire de commandes lors de la création de la vue de texte.
Pour implémenter le fournisseur de commandes d’aide sur la signature
Ajoutez une classe nommée
TestSignatureHelpController
qui implémente et l’exporte IVsTextViewCreationListener avec le NameAttribute, ContentTypeAttributeet TextViewRoleAttribute.Importez le IVsEditorAdaptersFactoryService (utilisé pour obtenir l’objet ITextView, donné l’objet IVsTextView ), le ITextStructureNavigatorSelectorService (utilisé pour rechercher le mot actuel) et le ISignatureHelpBroker (pour déclencher la session d’aide de signature).
Implémentez la VsTextViewCreated méthode en instanciant le
TestSignatureCommandHandler
.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)); }
Générer et tester le code
Pour tester ce code, générez la solution SignatureHelpTest et exécutez-la dans l’instance expérimentale.
Pour générer et tester la solution SignatureHelpTest
Générez la solution.
Lorsque vous exécutez ce projet dans le débogueur, une deuxième instance de Visual Studio est démarrée.
Créez un fichier texte et tapez du texte incluant le mot « ajouter » ainsi qu’une parenthèse ouvrante.
Une fois que vous avez tapé la parenthèse ouvrante, vous devez voir une info-bulle qui affiche une liste des deux signatures de la
add()
méthode.