서명 도움말(매개 변수 정보라고도 함)은 사용자가 매개 변수 목록 시작 문자(일반적으로 여는 괄호)를 입력할 때 도구 설명에 메서드의 서명을 표시합니다. 매개 변수와 매개 변수 구분 기호(일반적으로 쉼표)를 입력하면 도구 설명이 업데이트되어 다음 매개 변수를 굵게 표시합니다. 언어 서비스의 컨텍스트에서 사용자 고유의 파일 이름 확장명 및 콘텐츠 형식을 정의하고 해당 형식에 대해서만 서명 도움말을 표시하거나, 기존 콘텐츠 형식(예: "텍스트")에 대한 서명 도움말을 표시하는 식으로 서명 도움말을 정의할 수 있습니다. 이 연습에서는 "텍스트" 콘텐츠 형식에 대해 서명 도움말을 표시하는 방법을 보여 줍니다.
서명 도움말은 일반적으로 "("(여는 괄호)와 같은 특정 문자를 입력하여 트리거되고 ")"(닫는 괄호) 같은 다른 문자를 입력하여 해제됩니다. 문자 입력으로 트리거되는 IntelliSense 기능은 키 입력에 대한 명령 처리기(IOleCommandTarget 인터페이스) 및 IVsTextViewCreationListener 인터페이스를 구현하는 처리기 공급자를 사용하여 구현할 수 있습니다. 서명 도움말에 참여하는 서명 목록인 서명 도움말 원본을 만들려면 ISignatureHelpSource 인터페이스와, ISignatureHelpSourceProvider 인터페이스를 실행하는 원본 공급자를 구현합니다. 공급자는 MEF(Managed Extensibility Framework) 구성 요소 파트이며 원본 및 컨트롤러 클래스 내보내기와 서비스 및 브로커 가져오기를 담당합니다. 예를 들어 ITextStructureNavigatorSelectorService를 통해 텍스트 버퍼에서 탐색할 수 있고 ISignatureHelpBroker는 서명 도움말 세션을 트리거합니다.
이 연습에서는 하드 코딩된 식별자 집합에 대한 서명 도움말을 설정하는 방법을 보여 줍니다. 전체 구현에서 언어는 해당 콘텐츠를 제공해야 합니다.
MEF 프로젝트 만들기
MEF 프로젝트를 만들려면
C# VSIX 프로젝트를 만듭니다. (새 프로젝트 대화 상자에서 Visual C#/확장성, VSIX 프로젝트를 차례로 선택합니다.) 솔루션 이름을 SignatureHelpTest
로 지정합니다.
프로젝트에 편집기 분류자 항목 템플릿을 추가합니다. 자세한 내용은 편집기 항목 템플릿을 사용하여 확장 만들기를 참조하세요.
기존 클래스 파일을 삭제합니다.
프로젝트에 다음 참조를 추가하고 CopyLocal이 false
로 설정되었는지 확인합니다.
Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell.14.0
Microsoft.VisualStudio.TextManager.Interop
서명 도움말 서명 및 매개 변수 구현
서명 도움말 원본은 각각 IParameter를 구현하는 매개 변수를 포함하는 ISignature 구현 서명을 기반으로 합니다. 전체 구현에서 이 정보는 언어 설명서에서 가져오지만 이 예제에서는 서명이 하드 코딩됩니다.
서명 도움말 서명 및 매개 변수를 구현하려면
클래스 파일을 추가하고 이름을 SignatureHelpSource
로 지정합니다.
다음 가져오기를 추가합니다.
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;
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
IParameter를 구현하는 TestParameter
라는 클래스를 추가합니다.
internal class TestParameter : IParameter
Friend Class TestParameter
Implements IParameter
모든 속성을 설정하는 생성자를 추가합니다.
public TestParameter(string documentation, Span locus, string name, ISignature signature)
{
Documentation = documentation;
Locus = locus;
Name = name;
Signature = signature;
}
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
IParameter 속성을 추가합니다.
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; }
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
ISignature를 구현하는 TestSignature
라는 클래스를 추가합니다.
internal class TestSignature : ISignature
Friend Class TestSignature
Implements ISignature
일부 프라이빗 필드를 추가합니다.
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;
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
필드를 설정하고 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);
}
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
CurrentParameterChanged
이벤트를 선언합니다. 이 이벤트는 사용자가 서명의 매개 변수 중 하나를 채울 때 발생합니다.
public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
CurrentParameter 속성 값이 변경될 때 CurrentParameterChanged
이벤트를 발생시키는 속성을 구현합니다.
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);
}
}
}
ReadOnly Property CurrentParameter() As IParameter Implements ISignature.CurrentParameter
Get
Return m_currentParameter
End Get
End Property
CurrentParameterChanged
이벤트를 발생시키는 메서드를 추가합니다.
private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
{
EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
if (tempHandler != null)
{
tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
}
}
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
ApplicableToSpan의 쉼표 수를 서명의 쉼표 수와 비교하여 현재 매개 변수를 계산하는 메서드를 추가합니다.
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];
}
}
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
ComputeCurrentParameter()
메서드를 호출하는 Changed 이벤트에 대한 이벤트 처리기를 추가합니다.
internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
{
this.ComputeCurrentParameter();
}
Friend Sub OnSubjectBufferChanged(ByVal sender As Object, ByVal e As TextContentChangedEventArgs)
Me.ComputeCurrentParameter()
End Sub
ApplicableToSpan 속성을 구현합니다. 이 속성은 서명이 적용되는 버퍼의 텍스트 범위에 해당하는 ITrackingSpan을 보유합니다.
public ITrackingSpan ApplicableToSpan
{
get { return (m_applicableToSpan); }
internal set { m_applicableToSpan = value; }
}
ReadOnly Property ApplicableToSpan() As ITrackingSpan Implements ISignature.ApplicableToSpan
Get
Return (m_applicableToSpan)
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; }
}
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
서명 도움말 원본 구현
서명 도움말 원본은 정보를 제공하는 서명 집합입니다.
서명 도움말 원본을 구현하려면
ISignatureHelpSource를 구현하는 TestSignatureHelpSource
라는 클래스를 추가합니다.
internal class TestSignatureHelpSource : ISignatureHelpSource
Friend Class TestSignatureHelpSource
Implements ISignatureHelpSource
텍스트 버퍼에 참조를 추가합니다.
private ITextBuffer m_textBuffer;
Private m_textBuffer As ITextBuffer
텍스트 버퍼 및 서명 도움말 원본 공급자를 설정하는 생성자를 추가합니다.
public TestSignatureHelpSource(ITextBuffer textBuffer)
{
m_textBuffer = textBuffer;
}
Public Sub New(ByVal textBuffer As ITextBuffer)
m_textBuffer = textBuffer
End Sub
AugmentSignatureHelpSession 메서드를 구현합니다. 이 예제에서는 서명이 하드 코딩되지만 전체 구현에서 이 정보는 언어 설명서에서 가져옵니다.
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));
}
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
도우미 메서드 CreateSignature()
는 그림에만 있습니다.
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;
}
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
GetBestMatch 메서드를 구현합니다. 이 예제에는 각각 두 개의 매개 변수가 있는 두 개의 서명만 있습니다. 따라서 이 메서드는 필요하지 않습니다. 둘 이상의 서명 도움말 원본을 사용할 수 있는 전체 구현에서 이 메서드는 우선 순위가 가장 높은 서명 도움말 원본이 일치하는 서명을 제공할 수 있는지 여부를 결정하는 데 사용됩니다. 이렇게 할 수 없는 경우 메서드는 null을 반환하고 다음으로 우선 순위가 가장 높은 원본에 일치 항목을 제공하라는 메시지가 표시됩니다.
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;
}
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
Dispose()
메서드를 구현합니다.
private bool m_isDisposed;
public void Dispose()
{
if (!m_isDisposed)
{
GC.SuppressFinalize(this);
m_isDisposed = true;
}
}
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
서명 도움말 원본 공급자 구현
서명 도움말 원본 공급자는 MEF(Managed Extensibility Framework) 구성 요소 부분을 내보내고 서명 도움말 원본을 인스턴스화하는 역할을 담당합니다.
서명 도움말 원본 공급자를 구현하려면
ISignatureHelpSourceProvider를 구현하는 이름이 TestSignatureHelpSourceProvider
인 클래스를 추가하고 NameAttribute, “text” 특성의 ContentTypeAttribute, Before="default"의 OrderAttribute로 내보냅니다.
[Export(typeof(ISignatureHelpSourceProvider))]
[Name("Signature Help source")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
<Export(GetType(ISignatureHelpSourceProvider)), Name("Signature Help source"), Order(Before:="default"), ContentType("text")>
Friend Class TestSignatureHelpSourceProvider
Implements ISignatureHelpSourceProvider
TestSignatureHelpSource
를 인스턴스화하여 TryCreateSignatureHelpSource를 구현합니다.
public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer)
{
return new TestSignatureHelpSource(textBuffer);
}
Public Function TryCreateSignatureHelpSource(ByVal textBuffer As ITextBuffer) As ISignatureHelpSource Implements ISignatureHelpSourceProvider.TryCreateSignatureHelpSource
Return New TestSignatureHelpSource(textBuffer)
End Function
명령 처리기 구현
서명 도움말은 일반적으로 여는 괄호 "(" 문자에 의해 트리거되고 닫는 괄호 ")" 문자에 의해 해제됩니다. 알려진 메서드 이름 앞에 오는 여는 괄호 문자를 받을 때 서명 도움말 세션을 트리거하고 닫는 괄호 문자를 받으면 세션을 해제할 수 있도록 IOleCommandTarget을 실행하여 이러한 키 입력을 처리할 수 있습니다.
명령 처리기를 구현하려면
IOleCommandTarget를 구현하는 TestSignatureHelpCommand
라는 클래스를 추가합니다.
internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
Friend NotInheritable Class TestSignatureHelpCommandHandler
Implements IOleCommandTarget
IVsTextView 어댑터에 대한 프라이빗 필드(명령 처리기 체인에 명령 처리기를 추가할 수 있음), 텍스트 보기, 서명 도움말 브로커 및 세션, ITextStructureNavigator 및 다음 IOleCommandTarget을 추가합니다.
IOleCommandTarget m_nextCommandHandler;
ITextView m_textView;
ISignatureHelpBroker m_broker;
ISignatureHelpSession m_session;
ITextStructureNavigator m_navigator;
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
생성자를 추가하여 이러한 필드를 초기화하고 명령 필터 체인에 명령 필터를 추가합니다.
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);
}
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
명령 필터가 알려진 메서드 이름 중 하나에서 여는 괄호 "(" 문자를 받을 때 서명 도움말 세션을 트리거하고 세션이 활성 상태인 동안 닫는 괄호 ")" 문자를 받으면 세션을 해제하는 Exec 메서드를 구현합니다. 모든 경우에 명령이 전달됩니다.
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);
}
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
QueryStatus 메서드를 구현하여 항상 명령을 전달합니다.
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
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
서명 도움말 명령 공급자 구현
텍스트 뷰를 만들 때 명령 처리기를 인스턴스화하도록 IVsTextViewCreationListener를 구현하여 서명 도움말 명령을 제공할 수 있습니다.
서명 도움말 명령 공급자를 구현하려면
IVsTextViewCreationListener를 구현하는 클래스 TestSignatureHelpController
를 추가하고 NameAttribute, ContentTypeAttribute 및 TextViewRoleAttribute로 내보냅니다.
[Export(typeof(IVsTextViewCreationListener))]
[Name("Signature Help controller")]
[TextViewRole(PredefinedTextViewRoles.Editable)]
[ContentType("text")]
internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
<Export(GetType(IVsTextViewCreationListener)), Name("Signature Help controller"), TextViewRole(PredefinedTextViewRoles.Editable), ContentType("text")>
Friend Class TestSignatureHelpCommandProvider
Implements IVsTextViewCreationListener
IVsEditorAdaptersFactoryService(ITextView 가져오기에 사용, IVsTextView 개체의 경우), ITextStructureNavigatorSelectorService(현재 단어 찾기에 사용) 및 ISignatureHelpBroker(서명 도움말 세션 트리거)를 가져옵니다.
[Import]
internal IVsEditorAdaptersFactoryService AdapterService;
[Import]
internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
[Import]
internal ISignatureHelpBroker SignatureHelpBroker;
<Import()>
Friend AdapterService As IVsEditorAdaptersFactoryService
<Import()>
Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
<Import()>
Friend SignatureHelpBroker As ISignatureHelpBroker
TestSignatureCommandHandler
를 인스턴스화하여 VsTextViewCreated 메서드를 구현합니다.
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));
}
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
코드 빌드 및 테스트
이 코드를 테스트하려면 SignatureHelpTest 솔루션을 빌드하고 실험적 인스턴스에서 실행합니다.
SignatureHelpTest 솔루션을 빌드하고 테스트하려면
솔루션을 빌드합니다.
디버거에서 이 프로젝트를 실행하면 Visual Studio의 두 번째 인스턴스가 시작됩니다.
텍스트 파일을 만들고 단어 "add"와 여는 괄호를 포함하는 일부 텍스트를 입력합니다.
여는 괄호를 입력한 후 add()
메서드에 대한 두 서명 목록을 표시하는 도구 설명이 표시됩니다.
관련 콘텐츠