Návod: Nápověda k zobrazení podpisu
Nápověda k podpisu (označovaná také jako Informace o parametrech) zobrazuje podpis metody v popisu, když uživatel zadá počáteční znak seznamu parametrů (obvykle levou závorku). Jako typ parametru a oddělovače parametrů (obvykle čárka) se popis aktualizuje tak, aby zobrazoval další parametr tučně. Nápovědu k podpisu můžete definovat následujícími způsoby: v kontextu služby jazyka, definujte vlastní příponu názvu souboru a typ obsahu a zobrazte nápovědu k podpisu pro tento typ nebo zobrazte nápovědu k podpisu pro existující typ obsahu (například "text"). Tento názorný postup ukazuje, jak zobrazit nápovědu k podpisu pro typ obsahu "text".
Nápovědu k podpisu obvykle aktivujete zadáním konkrétního znaku, například "(" (levá závorka) a zavřete zadáním jiného znaku, například ")" (pravá závorka). Funkce IntelliSense aktivované zadáním znaku lze implementovat pomocí obslužné rutiny příkazu pro stisknutí kláves ( IOleCommandTarget rozhraní) a zprostředkovatele obslužné rutiny, který implementuje IVsTextViewCreationListener rozhraní. Chcete-li vytvořit zdroj nápovědy podpisu, což je seznam podpisů, které se účastní nápovědy k podpisu, implementujte ISignatureHelpSource rozhraní a zdrojového zprostředkovatele, který spouští ISignatureHelpSourceProvider rozhraní. Zprostředkovatelé jsou součásti meF (Managed Extensibility Framework) a jsou zodpovědní za export tříd zdrojového a kontroleru a import služeb a zprostředkovatelů, ITextStructureNavigatorSelectorServicenapříklad , který umožňuje navigaci v textové vyrovnávací paměti a ISignatureHelpBroker, který aktivuje relaci Nápovědy podpisu.
Tento návod ukazuje, jak nastavit nápovědu k podpisu pro pevně zakódovanou sadu identifikátorů. V úplných implementacích je jazyk zodpovědný za poskytování daného obsahu.
Vytvoření projektu MEF
Vytvoření projektu MEF
Vytvořte projekt VSIX jazyka C#. (V Dialogové okno Nový projekt , vyberte Visual C# / Rozšiřitelnost a pak projekt VSIX.) Pojmenujte řešení
SignatureHelpTest
.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.
Odstraňte existující soubory třídy.
Přidejte do projektu následující odkazy a ujistěte se, že je vlastnost CopyLocal nastavená na
false
:Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell.14.0
Microsoft.VisualStudio.TextManager.Interop
Implementace podpisových podpisů a parametrů nápovědy
Zdroj nápovědy podpisu je založen na podpisech, které implementují ISignature, každý z nich obsahuje parametry, které implementují IParameter. V úplné implementaci by se tyto informace získaly z dokumentace jazyka, ale v tomto příkladu jsou podpisy pevně zakódované.
Implementace podpisových podpisů a parametrů nápovědy
Přidejte soubor třídy a pojmenujte ho
SignatureHelpSource
.Přidejte následující importy.
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;
Přidejte třídu s názvem
TestParameter
, která implementuje IParameter.Přidejte konstruktor, který nastaví všechny vlastnosti.
Přidejte vlastnosti .IParameter
Přidejte třídu s názvem
TestSignature
, která implementuje ISignature.Přidejte některá soukromá pole.
Přidejte konstruktor, který nastaví pole a přihlásí se k odběru Changed události.
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); }
Deklarujte
CurrentParameterChanged
událost. Tato událost se vyvolá, když uživatel vyplní jeden z parametrů v podpisu.CurrentParameter Implementujte vlastnost tak, aby vyvolala
CurrentParameterChanged
událost při změně hodnoty vlastnosti.Přidejte metodu, která vyvolá
CurrentParameterChanged
událost.private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter) { EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged; if (tempHandler != null) { tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter)); } }
Přidejte metodu, která vypočítá aktuální parametr porovnáním počtu čárek v ApplicableToSpan podpisu s počtem čárek v podpisu.
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]; } }
Přidejte obslužnou rutinu Changed události pro událost, která volá metodu
ComputeCurrentParameter()
.Implementujte ApplicableToSpan vlastnost. Tato vlastnost obsahuje ITrackingSpan rozsah textu ve vyrovnávací paměti, na který se podpis vztahuje.
Implementujte další parametry.
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; } }
Implementace zdroje nápovědy podpisu
Zdroj nápovědy k podpisu je sada podpisů, pro které zadáte informace.
Implementace zdroje nápovědy podpisu
Přidejte třídu s názvem
TestSignatureHelpSource
, která implementuje ISignatureHelpSource.Přidejte odkaz na textovou vyrovnávací paměť.
Přidejte konstruktor, který nastaví vyrovnávací paměť textu a zprostředkovatele zdroje nápovědy podpisu.
Implementujte metodu AugmentSignatureHelpSession . V tomto příkladu jsou podpisy pevně zakódované, ale v úplné implementaci získáte tyto informace z dokumentace jazyka.
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)); }
Pomocná metoda
CreateSignature()
je k dispozici pouze pro ilustraci.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; }
Implementujte metodu GetBestMatch . V tomto příkladu jsou jenom dva podpisy, z nichž každý má dva parametry. Proto tato metoda není nutná. V plnohodnotné implementaci, ve které je k dispozici více než jeden zdroj nápovědy podpisu, se tato metoda používá k rozhodnutí, zda zdroj nápovědy podpisu s nejvyšší prioritou může poskytnout odpovídající podpis. Pokud to nejde, metoda vrátí hodnotu null a zdroj další nejvyšší priority se zobrazí výzva k zadání shody.
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; }
Implementujte metodu
Dispose()
:
Implementace zprostředkovatele zdroje nápovědy podpisu
Poskytovatel zdroje nápovědy podpisu zodpovídá za export součásti MEF (Managed Extensibility Framework) a vytvoření instance zdroje nápovědy podpisu.
Implementace zprostředkovatele zdroje nápovědy podpisu
Přidejte třídu s názvem
TestSignatureHelpSourceProvider
, která implementuje ISignatureHelpSourceProvider, a exportujte ji s textem NameAttributeContentTypeAttribute "text" a hodnotou OrderAttribute Before="default".Implementujte TryCreateSignatureHelpSource vytvořením instance objektu
TestSignatureHelpSource
.
Implementace obslužné rutiny příkazu
Nápovědu k podpisu obvykle aktivuje levá závorka (znak () a zavřený pravou závorkou )." znak. Tyto stisknutí kláves můžete zpracovat tak, že spustí IOleCommandTarget relaci nápovědy podpisu, když obdrží počáteční znak závorky před známým názvem metody a zavře relaci, když obdrží pravou závorku.
Implementace obslužné rutiny příkazu
Přidejte třídu s názvem
TestSignatureHelpCommand
, která implementuje IOleCommandTarget.Přidejte soukromá pole pro IVsTextView adaptér (která umožňuje přidat obslužnou rutinu příkazu do řetězu obslužných rutin příkazů), textové zobrazení, zprostředkovatele nápovědy podpisu a relaci, ITextStructureNavigatora a další IOleCommandTarget.
Přidejte konstruktor pro inicializaci těchto polí a přidejte filtr příkazů do řetězu filtrů příkazů.
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); }
Implementujte metodu Exec , která aktivuje relaci nápovědy podpisu, když filtr příkazu obdrží levou závorku "(" znak za jedním ze známých názvů metod a zavře relaci, když obdrží pravou závorku ")" znak, zatímco relace je stále aktivní. V každém případě se příkaz předá.
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); }
Implementujte metodu QueryStatus tak, aby vždy předal příkaz.
Implementace zprostředkovatele příkazů nápovědy podpisu
Příkaz Nápovědy k podpisu můžete zadat implementací IVsTextViewCreationListener instance obslužné rutiny příkazu při vytvoření textového zobrazení.
Implementace zprostředkovatele příkazů Nápovědy podpisu
Přidejte třídu s názvem
TestSignatureHelpController
, která implementuje IVsTextViewCreationListener a exportuje ji pomocí NameAttributetřídy , ContentTypeAttributea TextViewRoleAttribute.Naimportujte IVsEditorAdaptersFactoryService (používá se k získání objektu IVsTextViewITextView), ITextStructureNavigatorSelectorService objektu (použitému k vyhledání aktuálního slova) a ISignatureHelpBroker (k aktivaci relace nápovědy podpisu).
Implementujte metodu VsTextViewCreated vytvořením instance
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)); }
Sestavení a otestování kódu
Tento kód otestujete tak, že sestavíte řešení SignatureHelpTest a spustíte ho v experimentální instanci.
Sestavení a testování řešení SignatureHelpTest
Sestavte řešení.
Když tento projekt spustíte v ladicím programu, spustí se druhá instance sady Visual Studio.
Vytvořte textový soubor a zadejte nějaký text, který obsahuje slovo "přidat" a levou závorku.
Po zadání levých závorek by se měl zobrazit popis, který zobrazí seznam dvou podpisů metody
add()
.