İzlenecek yol: İmza Yardımını Görüntüleme

İmza Yardımı (Parametre Bilgisi olarak da bilinir), kullanıcı parametre listesi başlangıç karakterini (genellikle açma parantezi) yazdığınızda araç ipucunda bir yöntemin imzasını görüntüler. Parametre ve parametre ayırıcısı (genellikle virgül) yazıldığında, araç ipucu sonraki parametreyi kalın olarak gösterecek şekilde güncelleştirilir. İmza Yardımı'nı aşağıdaki yollarla tanımlayabilirsiniz: dil hizmeti bağlamında, kendi dosya adı uzantınızı ve içerik türünüzü tanımlayın ve yalnızca bu tür için İmza Yardımı'nı görüntüleyin veya var olan bir içerik türü için İmza Yardımı'nı (örneğin, "metin") görüntüleyin. Bu kılavuz, "metin" içerik türü için İmza Yardımı'nın nasıl görüntüleneceğini gösterir.

İmza Yardımı genellikle "(" (parantez açma) gibi belirli bir karakter yazılarak tetiklenerek tetikler ve başka bir karakter( örneğin, ")" (parantez kapatılarak) kapatılır. Karakter yazarak tetiklenen IntelliSense özellikleri, tuş vuruşları ( IOleCommandTarget arabirim) için bir komut işleyicisi ve arabirimi uygulayan IVsTextViewCreationListener bir işleyici sağlayıcısı kullanılarak uygulanabilir. İmza Yardımı'na katılan imzaların listesi olan İmza Yardımı kaynağını oluşturmak için arabirimi ve arabirimi çalıştıran bir kaynak sağlayıcısı uygulayın ISignatureHelpSource ISignatureHelpSourceProvider . Sağlayıcılar Yönetilen Genişletilebilirlik Çerçevesi (MEF) bileşen parçalarıdır ve kaynak ve denetleyici sınıflarını dışarı aktarmak ve hizmet ve aracıları içeri aktarmakla sorumludur; örneğin, ITextStructureNavigatorSelectorServicemetin arabelleğinde gezinmenizi sağlayan ve İmza Yardımı oturumunu ISignatureHelpBrokertetikleyen .

Bu kılavuzda, sabit kodlanmış bir tanımlayıcı kümesi için İmza Yardımı'nın nasıl ayarlanacağı gösterilmektedir. Tam uygulamalarda, bu içeriğin sağlanmasından dil sorumludur.

MEF projesi oluşturma

MEF projesi oluşturmak için

  1. C# VSIX projesi oluşturun. (Yeni Proje iletişim kutusu, Visual C# / Genişletilebilirlik'i ve ardından VSIX Projesi'ni seçin.) Çözümü SignatureHelpTestolarak adlandırın.

  2. Projeye bir Düzenleyici Sınıflandırıcısı öğesi şablonu ekleyin. Daha fazla bilgi için bkz . Düzenleyici öğesi şablonuyla uzantı oluşturma.

  3. Varolan sınıf dosyalarını silin.

  4. Projeye aşağıdaki başvuruları ekleyin ve CopyLocal öğesinin olarak falseayarlandığından emin olun:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.Intellisense

    Microsoft.visualstudio.ole

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

İmza Yardımı imzalarını ve parametrelerini uygulama

İmza Yardımı kaynağı, uygulamasını uygulayan ISignatureimzaları temel alır ve bunların her biri uygulayan IParameterparametreleri içerir. Tam bir uygulamada, bu bilgiler dil belgelerinden alınabilir, ancak bu örnekte imzalar sabit kodlanmıştır.

İmza Yardımı imzalarını ve parametrelerini uygulamak için

  1. Bir sınıf dosyası ekleyin ve adını verin SignatureHelpSource.

  2. Aşağıdaki içeri aktarmaları ekleyin.

    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. uygulayan IParameteradlı TestParameter bir sınıf ekleyin.

    internal class TestParameter : IParameter
    
  4. Tüm özellikleri ayarlayan bir oluşturucu ekleyin.

    public TestParameter(string documentation, Span locus, string name, ISignature signature)
    {
        Documentation = documentation;
        Locus = locus;
        Name = name;
        Signature = signature;
    }
    
  5. özelliklerini IParameterekleyin.

    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. uygulayan ISignatureadlı TestSignature bir sınıf ekleyin.

    internal class TestSignature : ISignature
    
  7. Bazı özel alanlar ekleyin.

    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. Alanları ayarlayan ve olaya abone Changed olan bir oluşturucu ekleyin.

    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. Bir CurrentParameterChanged olay bildirin. Bu olay, kullanıcı imzadaki parametrelerden birini doldurduğunda oluşturulur.

    public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
    
  10. CurrentParameter özellik değeri değiştirildiğinde olayı tetiklemesi CurrentParameterChanged için özelliğini uygulayın.

    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. Olayı tetikleyen CurrentParameterChanged bir yöntem ekleyin.

    private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
    {
        EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
        if (tempHandler != null)
        {
            tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
        }
    }
    
  12. içindeki virgül ApplicableToSpan sayısını imzadaki virgül sayısıyla karşılaştırarak geçerli parametreyi hesaplayan bir yöntem ekleyin.

    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. yöntemini çağıran olay için Changed bir olay işleyicisi ComputeCurrentParameter() ekleyin.

    internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
    {
        this.ComputeCurrentParameter();
    }
    
  14. ApplicableToSpan özelliğini uygulayın. Bu özellik, imzanın uygulandığı arabellekteki metnin yayılmasına karşılık gelen bir ITrackingSpan değeri tutar.

    public ITrackingSpan ApplicableToSpan
    {
        get { return (m_applicableToSpan); }
        internal set { m_applicableToSpan = value; }
    }
    
  15. Diğer parametreleri uygulayın.

    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; }
    }
    

İmza Yardımı kaynağını uygulama

İmza Yardımı kaynağı, bilgi sağladığınız imza kümesidir.

İmza Yardımı kaynağını uygulamak için

  1. uygulayan ISignatureHelpSourceadlı TestSignatureHelpSource bir sınıf ekleyin.

    internal class TestSignatureHelpSource : ISignatureHelpSource
    
  2. Metin arabelleğine bir başvuru ekleyin.

    private ITextBuffer m_textBuffer;
    
  3. Metin arabelleği ve İmza Yardımı kaynak sağlayıcısını ayarlayan bir oluşturucu ekleyin.

    public TestSignatureHelpSource(ITextBuffer textBuffer)
    {
        m_textBuffer = textBuffer;
    }
    
  4. AugmentSignatureHelpSession yöntemini uygulayın. Bu örnekte imzalar sabit kodlanmıştır, ancak tam bir uygulamada bu bilgileri dil belgelerinden alabilirsiniz.

    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. Yardımcı yöntemi CreateSignature() yalnızca çizim için sağlanır.

    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. GetBestMatch yöntemini uygulayın. Bu örnekte, her biri iki parametreye sahip olan yalnızca iki imza vardır. Bu nedenle, bu yöntem gerekli değildir. Birden fazla İmza Yardımı kaynağının kullanılabildiği daha kapsamlı bir uygulamada, en yüksek öncelikli İmza Yardımı kaynağının eşleşen bir imza sağlayıp sağlayamayacağına karar vermek için bu yöntem kullanılır. Bunu yapamazsa, yöntemi null döndürür ve sonraki en yüksek öncelikli kaynağın bir eşleşme sağlaması istenir.

    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. Dispose() Yöntemini uygulayın:

    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

İmza Yardımı kaynak sağlayıcısını uygulama

İmza Yardımı kaynak sağlayıcısı, Yönetilen Genişletilebilirlik Çerçevesi (MEF) bileşeni bölümünü dışarı aktarmak ve İmza Yardımı kaynağının örneğini başlatmakla sorumludur.

İmza Yardımı kaynak sağlayıcısını uygulamak için

  1. uygulayan ISignatureHelpSourceProvideradlı TestSignatureHelpSourceProvider bir sınıf ekleyin ve bunu bir NameAttribute, ContentTypeAttribute bir "metin" ve BeforeOrderAttribute="default" ile dışarı aktarın.

    [Export(typeof(ISignatureHelpSourceProvider))]
    [Name("Signature Help source")]
    [Order(Before = "default")]
    [ContentType("text")]
    internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
    
  2. örneğini ekleyerek TestSignatureHelpSourceuygulayınTryCreateSignatureHelpSource.

    public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer)
    {
        return new TestSignatureHelpSource(textBuffer);
    }
    

Komut işleyicisini uygulama

İmza Yardımı genellikle bir açma parantezi "(" karakteriyle tetiklenerek ve kapatma parantezi ")" karakteriyle kapatılır. Bu tuş vuruşlarını, bilinen bir yöntem adından önce bir açma parantezi karakteri aldığında bir İmza Yardımı oturumunu tetikleyecek şekilde çalıştırarak IOleCommandTarget ve kapatma parantezi karakteri aldığında oturumu kapatarak işleyebilirsiniz.

Komut işleyicisini uygulamak için

  1. uygulayan IOleCommandTargetadlı TestSignatureHelpCommand bir sınıf ekleyin.

    internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
    
  2. Bağdaştırıcı için IVsTextView özel alanlar ekleyin (komut işleyicisini komut işleyicileri zincirine eklemenize olanak tanır), metin görünümü, İmza Yardımı aracısı ve oturumu, bir ITextStructureNavigatorve sonraki IOleCommandTarget.

    IOleCommandTarget m_nextCommandHandler;
    ITextView m_textView;
    ISignatureHelpBroker m_broker;
    ISignatureHelpSession m_session;
    ITextStructureNavigator m_navigator;
    
  3. Bu alanları başlatmak ve komut filtresini komut filtreleri zincirine eklemek için bir oluşturucu ekleyin.

    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. Exec Komut filtresi bilinen yöntem adlarından birinin sonunda bir açma parantezi "(" karakter) aldığında İmza Yardımı oturumunu tetikleme yöntemini uygulayın ve oturum hala etkin durumdayken kapatma parantezi "" karakterini aldığında oturumu kapatın. Her durumda, komut iletilir.

    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. QueryStatus komutunu her zaman iletebilmesi için yöntemini uygulayın.

    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    

İmza Yardımı komut sağlayıcısını uygulama

Metin görünümü oluşturulduğunda komut işleyicisinin örneğini oluşturmak için komutunu uygulayarak IVsTextViewCreationListener İmza Yardımı komutunu sağlayabilirsiniz.

İmza Yardımı komut sağlayıcısını uygulamak için

  1. , ve TextViewRoleAttributeile NameAttributeContentTypeAttributeuygulayan IVsTextViewCreationListener ve dışarı aktaran adlı TestSignatureHelpController bir sınıf ekleyin.

    [Export(typeof(IVsTextViewCreationListener))]
    [Name("Signature Help controller")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    [ContentType("text")]
    internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
    
  2. IVsEditorAdaptersFactoryService öğesini (nesnesine göre IVsTextView değerini almak ITextViewiçin kullanılır), ITextStructureNavigatorSelectorService (geçerli sözcüğü bulmak için kullanılır) ve ISignatureHelpBroker (İmza Yardımı oturumunu tetikleme amacıyla) içeri aktarın.

    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService;
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ISignatureHelpBroker SignatureHelpBroker;
    
  3. örneğini VsTextViewCreated ekleyerek TestSignatureCommandHandleryöntemini uygulayın.

    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));
    }
    

Kodu Derleme ve Test Etme

Bu kodu test etmek için SignatureHelpTest çözümünü derleyin ve deneysel örnekte çalıştırın.

SignatureHelpTest çözümünü derlemek ve test etmek için

  1. Çözümü oluşturun.

  2. Bu projeyi hata ayıklayıcıda çalıştırdığınızda, Visual Studio'nun ikinci bir örneği başlatılır.

  3. Bir metin dosyası oluşturun ve "ekle" sözcüğünün yanı sıra bir açılış ayracı içeren bir metin yazın.

  4. Açma parantezini yazdıktan sonra, yöntem için add() iki imzanın listesini görüntüleyen bir araç ipucu görmeniz gerekir.