Przewodnik: wyświetlanie pomocy dotyczącej podpisu
Pomoc podpisu (nazywana również informacjami o parametrach) wyświetla podpis metody w etykietce narzędzia, gdy użytkownik wpisze znak początkowy listy parametrów (zazwyczaj nawias otwierający). Jako separator parametru i parametru (zazwyczaj przecinek) są wpisywane, etykietka narzędzia jest aktualizowana w celu wyświetlenia następnego parametru pogrubionego. Pomoc podpisu można zdefiniować na następujące sposoby: w kontekście usługi językowej zdefiniuj rozszerzenie nazwy pliku i typ zawartości oraz wyświetlić Pomoc podpisu dla tylko tego typu lub wyświetlić Pomoc podpisu dla istniejącego typu zawartości (na przykład "tekst"). W tym przewodniku pokazano, jak wyświetlić pomoc dotyczącą podpisu dla typu zawartości "tekst".
Pomoc podpisu jest zwykle wyzwalana przez wpisanie określonego znaku, na przykład "(" (nawias otwierający) i odrzucone przez wpisanie innego znaku, na przykład ")" (nawias zamykający). Funkcje intelliSense wyzwalane przez wpisanie znaku można zaimplementować za pomocą procedury obsługi poleceń dla naciśnięć klawiszy ( IOleCommandTarget interfejsu) i dostawcy obsługi implementujących IVsTextViewCreationListener interfejs. Aby utworzyć źródło pomocy sygnatury, czyli listę podpisów, które uczestniczą w Pomocy podpisu, zaimplementuj ISignatureHelpSource interfejs i dostawcę źródłowego, który uruchamia ISignatureHelpSourceProvider interfejs. Dostawcy są częściami składników Managed Extensibility Framework (MEF) i są odpowiedzialni za eksportowanie klas źródłowych i kontrolerów oraz importowanie usług i brokerów, na przykład ITextStructureNavigatorSelectorService, który umożliwia nawigowanie w buforze tekstowym i ISignatureHelpBroker, który wyzwala sesję Pomocy sygnatury.
W tym przewodniku pokazano, jak skonfigurować pomoc sygnatury dla ustalonego zestawu identyfikatorów. W pełnych implementacjach język jest odpowiedzialny za dostarczanie tej zawartości.
Tworzenie projektu MEF
Aby utworzyć projekt MEF
Utwórz projekt VSIX w języku C#. (W Okno dialogowe Nowy projekt , wybierz pozycję Visual C# / Rozszerzalność, a następnie projekt VSIX. Nadaj rozwiązaniu
SignatureHelpTest
nazwę .Dodaj szablon elementu Klasyfikator edytora do projektu. Aby uzyskać więcej informacji, zobacz Tworzenie rozszerzenia za pomocą szablonu elementu edytora.
Usuń istniejące pliki klas.
Dodaj następujące odwołania do projektu i upewnij się, że właściwość CopyLocal jest ustawiona na
false
:Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell.14.0
Microsoft.VisualStudio.TextManager.Interop
Implementowanie podpisów i parametrów pomocy dotyczącej podpisu
Źródło pomocy sygnatury jest oparte na podpisach, które implementują ISignatureelement , z których każdy zawiera parametry implementujące IParameterelement . W pełnej implementacji te informacje będą uzyskiwane z dokumentacji języka, ale w tym przykładzie podpisy są zakodowane w kodzie.
Aby zaimplementować podpisy i parametry pomocy podpisów podpisów
Dodaj plik klasy i nadaj mu
SignatureHelpSource
nazwę .Dodaj następujące 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;
Dodaj klasę o nazwie
TestParameter
, która implementuje IParameterelement .Dodaj konstruktor, który ustawia wszystkie właściwości.
Dodaj właściwości elementu IParameter.
Dodaj klasę o nazwie
TestSignature
, która implementuje ISignatureelement .Dodaj niektóre pola prywatne.
Dodaj konstruktor, który ustawia pola i subskrybuje Changed zdarzenie.
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); }
Zadeklaruj
CurrentParameterChanged
zdarzenie. To zdarzenie jest zgłaszane, gdy użytkownik wypełni jeden z parametrów w podpisie.Zaimplementuj CurrentParameter właściwość tak, aby zgłaszała
CurrentParameterChanged
zdarzenie po zmianie wartości właściwości.Dodaj metodę, która zgłasza
CurrentParameterChanged
zdarzenie.private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter) { EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged; if (tempHandler != null) { tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter)); } }
Dodaj metodę, która oblicza bieżący parametr, porównując liczbę przecinków z ApplicableToSpan liczbą przecinków w podpisie.
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]; } }
Dodaj procedurę obsługi zdarzeń dla Changed zdarzenia, które wywołuje metodę
ComputeCurrentParameter()
.Zaimplementuj ApplicableToSpan właściwość . Ta właściwość zawiera właściwość odpowiadającą ITrackingSpan zakresowi tekstu w buforze, do którego ma zastosowanie podpis.
Zaimplementuj inne 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; } }
Implementowanie źródła pomocy dotyczącej podpisu
Źródło Pomocy podpisu to zestaw podpisów, dla których podajesz informacje.
Aby zaimplementować źródło pomocy sygnatury
Dodaj klasę o nazwie
TestSignatureHelpSource
, która implementuje ISignatureHelpSourceelement .Dodaj odwołanie do buforu tekstowego.
Dodaj konstruktor, który ustawia bufor tekstowy i dostawcę źródła Pomocy sygnatury.
Zaimplementuj metodę AugmentSignatureHelpSession . W tym przykładzie podpisy są zakodowane na twardo, ale w pełnej implementacji uzyskasz te informacje z dokumentacji językowej.
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)); }
Metoda
CreateSignature()
pomocnika jest udostępniana tylko na potrzeby ilustracji.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; }
Zaimplementuj metodę GetBestMatch . W tym przykładzie istnieją tylko dwa podpisy, z których każdy ma dwa parametry. W związku z tym ta metoda nie jest wymagana. W pełnijszej implementacji, w której jest dostępne więcej niż jedno źródło pomocy sygnatury, ta metoda służy do decydowania, czy źródło pomocy sygnatury o najwyższym priorycie może dostarczyć pasujący podpis. Jeśli nie, metoda zwraca wartość null, a źródło o następnym najwyższym priorytetzie zostanie poproszone o podanie dopasowania.
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; }
Zaimplementuj metodę
Dispose()
:
Implementowanie dostawcy źródła pomocy sygnatury
Dostawca źródła pomocy sygnatury jest odpowiedzialny za eksportowanie części składnika Managed Extensibility Framework (MEF) i tworzenia wystąpienia źródła pomocy sygnatury.
Aby zaimplementować dostawcę źródła pomocy sygnatury
Dodaj klasę o nazwie
TestSignatureHelpSourceProvider
, która implementuje ISignatureHelpSourceProviderelement , i eksportuj go za pomocą NameAttributeelementu , z wartością ContentTypeAttribute "text" i wartością OrderAttribute Before="default".Zaimplementuj TryCreateSignatureHelpSource , tworząc wystąpienie obiektu
TestSignatureHelpSource
.
Implementowanie programu obsługi poleceń
Pomoc podpisu jest zwykle wyzwalana przez nawias otwierający "(" znak i odrzucany przez nawias zamykający ")". Możesz obsłużyć te naciśnięcia klawiszy, uruchamiając IOleCommandTarget element , aby wyzwolić sesję Pomocy sygnatury, gdy otrzymuje znak nawiasu otwierającego poprzedzony znaną nazwą metody, i odrzuca sesję po otrzymaniu znaku nawiasu zamykającego.
Aby zaimplementować procedurę obsługi poleceń
Dodaj klasę o nazwie
TestSignatureHelpCommand
, która implementuje IOleCommandTargetelement .Dodaj pola prywatne dla IVsTextView karty (która umożliwia dodanie programu obsługi poleceń do łańcucha procedur obsługi poleceń), widoku tekstowego, brokera i sesji Pomocy sygnatury, a ITextStructureNavigatori następnego IOleCommandTarget.
Dodaj konstruktor, aby zainicjować te pola i dodać filtr poleceń do łańcucha filtrów poleceń.
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); }
Zaimplementuj metodę Exec , aby wyzwolić sesję Pomocy sygnatury, gdy filtr polecenia odbiera nawias otwierający "(" znak po jednej ze znanych nazw metod, i odrzucić sesję, gdy otrzymuje nawias zamykający ")" znak, podczas gdy sesja jest nadal aktywna. W każdym przypadku polecenie jest przekazywane.
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); }
Zaimplementuj metodę QueryStatus , aby zawsze przekazywać dalej polecenie.
Implementowanie dostawcy poleceń Pomocy sygnatury
Możesz podać polecenie Pomoc podpisu, implementując polecenie IVsTextViewCreationListener , aby utworzyć wystąpienie programu obsługi poleceń po utworzeniu widoku tekstowego.
Aby zaimplementować dostawcę poleceń Pomocy sygnatury
Dodaj klasę o nazwie
TestSignatureHelpController
, która implementuje i eksportuje IVsTextViewCreationListener ją za NameAttributepomocą elementów , ContentTypeAttributei TextViewRoleAttribute.Zaimportuj IVsEditorAdaptersFactoryService element (używany do pobrania ITextViewobiektu ), IVsTextView ( ITextStructureNavigatorSelectorService używany do znalezienia bieżącego wyrazu) i ISignatureHelpBroker (w celu wyzwolenia sesji Pomocy podpisu).
Zaimplementuj metodę VsTextViewCreated , tworząc
TestSignatureCommandHandler
wystąpienie klasy .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)); }
Kompilowanie i testowanie kodu
Aby przetestować ten kod, skompiluj rozwiązanie SignatureHelpTest i uruchom je w wystąpieniu eksperymentalnym.
Aby skompilować i przetestować rozwiązanie SignatureHelpTest
Stwórz rozwiązanie.
Po uruchomieniu tego projektu w debugerze zostanie uruchomione drugie wystąpienie programu Visual Studio.
Utwórz plik tekstowy i wpisz tekst zawierający wyraz "add" oraz nawias otwierający.
Po wpisaniu nawiasu otwierającego powinna zostać wyświetlona etykietka narzędzia zawierająca listę dwóch podpisów dla
add()
metody .