Bagikan melalui


Panduan: Bantuan Tampilkan Tanda Tangan

Bantuan Tanda Tangan (juga dikenal sebagai Info Parameter) menampilkan tanda tangan metode dalam tipsalat saat pengguna mengetik karakter mulai daftar parameter (biasanya tanda kurung buka). Sebagai pemisah parameter dan parameter (biasanya koma) di ketik, tipsalat diperbarui untuk menampilkan parameter berikutnya dalam huruf tebal. Anda dapat menentukan Bantuan Tanda Tangan dengan cara berikut: dalam konteks layanan bahasa, tentukan ekstensi nama file dan tipe konten Anda sendiri dan tampilkan Bantuan Tanda Tangan hanya untuk jenis tersebut, atau tampilkan Bantuan Tanda Tangan untuk tipe konten yang ada (misalnya, "teks"). Panduan ini memperlihatkan cara menampilkan Bantuan Tanda Tangan untuk tipe isi "teks".

Bantuan Tanda Tangan biasanya dipicu dengan mengetik karakter tertentu, misalnya, "(" (kurung buka), dan ditutup dengan mengetik karakter lain, misalnya, ")" (menutup tanda kurung). Fitur IntelliSense yang dipicu dengan mengetik karakter dapat diimplementasikan dengan menggunakan handler perintah untuk penekanan tombol ( IOleCommandTarget antarmuka) dan penyedia handler yang mengimplementasikan IVsTextViewCreationListener antarmuka. Untuk membuat sumber Bantuan Tanda Tangan, yang merupakan daftar tanda tangan yang berpartisipasi dalam Bantuan Tanda Tangan, terapkan ISignatureHelpSource antarmuka dan penyedia sumber yang menjalankan ISignatureHelpSourceProvider antarmuka. Penyedia adalah bagian komponen Managed Extensibility Framework (MEF), dan bertanggung jawab untuk mengekspor kelas sumber dan pengontrol dan mengimpor layanan dan broker, misalnya, ITextStructureNavigatorSelectorService, yang memungkinkan Anda menavigasi dalam buffer teks, dan ISignatureHelpBroker, yang memicu sesi Bantuan Tanda Tangan.

Panduan ini menunjukkan cara menyiapkan Bantuan Tanda Tangan untuk sekumpulan pengidentifikasi yang dikodekan secara permanen. Dalam implementasi penuh, bahasa bertanggung jawab untuk menyediakan konten tersebut.

Membuat proyek MEF

Untuk membuat proyek MEF

  1. Buat proyek C# VSIX. (Dalam Dialog Proyek Baru, pilih Visual C# / Ekstensibilitas, lalu Proyek VSIX.) Beri nama solusi SignatureHelpTest.

  2. Tambahkan templat item Pengklasifikasi Editor ke proyek. Untuk informasi selengkapnya, lihat Membuat ekstensi dengan templat item editor.

  3. Hapus file kelas yang ada.

  4. Tambahkan referensi berikut ke proyek, dan pastikan CopyLocal diatur ke false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.Intellisense

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

Menerapkan tanda tangan dan parameter Bantuan Tanda Tangan

Sumber Bantuan Tanda Tangan didasarkan pada tanda tangan yang mengimplementasikan ISignature, yang masing-masing berisi parameter yang mengimplementasikan IParameter. Dalam implementasi lengkap, informasi ini akan diperoleh dari dokumentasi bahasa, tetapi dalam contoh ini, tanda tangan dikodekan secara permanen.

Untuk mengimplementasikan tanda tangan dan parameter Bantuan Tanda Tangan

  1. Tambahkan file kelas dan beri nama SignatureHelpSource.

  2. Tambahkan impor berikut.

    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. Tambahkan kelas bernama TestParameter yang mengimplementasikan IParameter.

    internal class TestParameter : IParameter
    
  4. Tambahkan konstruktor yang mengatur semua properti.

    public TestParameter(string documentation, Span locus, string name, ISignature signature)
    {
        Documentation = documentation;
        Locus = locus;
        Name = name;
        Signature = signature;
    }
    
  5. Tambahkan properti .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; }
    
  6. Tambahkan kelas bernama TestSignature yang mengimplementasikan ISignature.

    internal class TestSignature : ISignature
    
  7. Tambahkan beberapa bidang privat.

    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. Tambahkan konstruktor yang mengatur bidang dan berlangganan acara 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);
    }
    
  9. Mendeklarasikan CurrentParameterChanged peristiwa. Kejadian ini dimunculkan ketika pengguna mengisi salah satu parameter dalam tanda tangan.

    public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
    
  10. Terapkan CurrentParameter properti sehingga meningkatkan CurrentParameterChanged peristiwa saat nilai properti diubah.

    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. Tambahkan metode yang meningkatkan CurrentParameterChanged peristiwa.

    private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
    {
        EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
        if (tempHandler != null)
        {
            tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
        }
    }
    
  12. Tambahkan metode yang menghitung parameter saat ini dengan membandingkan jumlah koma dalam ApplicableToSpan jumlah koma dalam tanda tangan.

    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. Tambahkan penanganan aktivitas untuk Changed peristiwa yang memanggil ComputeCurrentParameter() metode .

    internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
    {
        this.ComputeCurrentParameter();
    }
    
  14. Implementasikan properti ApplicableToSpan. Properti ini menyimpan ITrackingSpan yang sesuai dengan rentang teks dalam buffer tempat tanda tangan diterapkan.

    public ITrackingSpan ApplicableToSpan
    {
        get { return (m_applicableToSpan); }
        internal set { m_applicableToSpan = value; }
    }
    
  15. Terapkan parameter lainnya.

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

Menerapkan sumber Bantuan Tanda Tangan

Sumber Bantuan Tanda Tangan adalah kumpulan tanda tangan yang Anda berikan informasinya.

Untuk mengimplementasikan sumber Bantuan Tanda Tangan

  1. Tambahkan kelas bernama TestSignatureHelpSource yang mengimplementasikan ISignatureHelpSource.

    internal class TestSignatureHelpSource : ISignatureHelpSource
    
  2. Tambahkan referensi ke buffer teks.

    private ITextBuffer m_textBuffer;
    
  3. Tambahkan konstruktor yang mengatur buffer teks dan penyedia sumber Bantuan Tanda Tangan.

    public TestSignatureHelpSource(ITextBuffer textBuffer)
    {
        m_textBuffer = textBuffer;
    }
    
  4. Mengimplementasikan metode AugmentSignatureHelpSession. Dalam contoh ini, tanda tangan dikodekan secara permanen, tetapi dalam implementasi lengkap Anda akan mendapatkan informasi ini dari dokumentasi bahasa.

    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. Metode pembantu CreateSignature() disediakan hanya untuk ilustrasi.

    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. Mengimplementasikan metode GetBestMatch. Dalam contoh ini, hanya ada dua tanda tangan, yang masing-masing memiliki dua parameter. Oleh karena itu, metode ini tidak diperlukan. Dalam implementasi yang lebih lengkap, di mana lebih dari satu sumber Bantuan Tanda Tangan tersedia, metode ini digunakan untuk memutuskan apakah sumber Bantuan Tanda Tangan prioritas tertinggi dapat memberikan tanda tangan yang cocok. Jika tidak bisa, metode mengembalikan null dan sumber prioritas tertinggi berikutnya diminta untuk menyediakan kecocokan.

    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. Terapkan Dispose() metode :

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

Menerapkan penyedia sumber Bantuan Tanda Tangan

Penyedia sumber Bantuan Tanda Tangan bertanggung jawab untuk mengekspor bagian komponen Managed Extensibility Framework (MEF) dan untuk membuat instans sumber Bantuan Tanda Tangan.

Untuk mengimplementasikan penyedia sumber Bantuan Tanda Tangan

  1. Tambahkan kelas bernama TestSignatureHelpSourceProvider yang mengimplementasikan ISignatureHelpSourceProvider, dan ekspor dengan NameAttribute, ContentTypeAttribute dari "teks", dan OrderAttribute default Before=".

    [Export(typeof(ISignatureHelpSourceProvider))]
    [Name("Signature Help source")]
    [Order(Before = "default")]
    [ContentType("text")]
    internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
    
  2. Terapkan TryCreateSignatureHelpSource dengan membuat instans TestSignatureHelpSource.

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

Menerapkan handler perintah

Bantuan Tanda Tangan biasanya dipicu oleh karakter tanda kurung pembuka "(" dan diberhentikan oleh karakter kurung tutup ")". Anda dapat menangani penekanan tombol ini dengan menjalankan IOleCommandTarget sehingga memicu sesi Bantuan Tanda Tangan saat menerima karakter tanda kurung pembuka yang didahului oleh nama metode yang diketahui, dan menutup sesi saat menerima karakter tanda kurung penutup.

Untuk mengimplementasikan handler perintah

  1. Tambahkan kelas bernama TestSignatureHelpCommand yang mengimplementasikan IOleCommandTarget.

    internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
    
  2. Tambahkan bidang privat untuk IVsTextView adaptor (yang memungkinkan Anda menambahkan handler perintah ke rantai penangan perintah), tampilan teks, broker dan sesi Bantuan Tanda Tangan, ITextStructureNavigator, dan berikutnya IOleCommandTarget.

    IOleCommandTarget m_nextCommandHandler;
    ITextView m_textView;
    ISignatureHelpBroker m_broker;
    ISignatureHelpSession m_session;
    ITextStructureNavigator m_navigator;
    
  3. Tambahkan konstruktor untuk menginisialisasi bidang ini dan untuk menambahkan filter perintah ke rantai filter perintah.

    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 Terapkan metode untuk memicu sesi Bantuan Tanda Tangan ketika filter perintah menerima karakter tanda kurung pembuka "(" setelah salah satu nama metode yang diketahui, dan untuk menutup sesi ketika menerima karakter tanda kurung penutup ")" saat sesi masih aktif. Dalam setiap kasus, perintah diteruskan.

    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. Terapkan QueryStatus metode sehingga selalu meneruskan perintah.

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

Menerapkan penyedia perintah Bantuan Tanda Tangan

Anda dapat memberikan perintah Bantuan Tanda Tangan dengan mengimplementasikan IVsTextViewCreationListener untuk membuat instans handler perintah saat tampilan teks dibuat.

Untuk mengimplementasikan penyedia perintah Bantuan Tanda Tangan

  1. Tambahkan kelas bernama TestSignatureHelpController yang mengimplementasikan IVsTextViewCreationListener dan mengekspornya dengan NameAttribute, ContentTypeAttribute, dan TextViewRoleAttribute.

    [Export(typeof(IVsTextViewCreationListener))]
    [Name("Signature Help controller")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    [ContentType("text")]
    internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
    
  2. IVsEditorAdaptersFactoryService Impor (digunakan untuk mendapatkan ITextView, diberikan IVsTextView objek), ITextStructureNavigatorSelectorService (digunakan untuk menemukan kata saat ini), dan ISignatureHelpBroker (untuk memicu sesi Bantuan Tanda Tangan).

    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService;
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ISignatureHelpBroker SignatureHelpBroker;
    
  3. Terapkan VsTextViewCreated metode dengan membuat instans 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));
    }
    

Membangun dan Menguji Kode

Untuk menguji kode ini, buat solusi SignatureHelpTest dan jalankan dalam instans eksperimental.

Untuk membangun dan menguji solusi SignatureHelpTest

  1. Bangun solusinya.

  2. Saat Anda menjalankan proyek ini di debugger, instans kedua Visual Studio dimulai.

  3. Buat file teks dan ketik beberapa teks yang menyertakan kata "tambahkan" ditambah tanda kurung pembuka.

  4. Setelah Anda mengetik tanda kurung pembuka, Anda akan melihat tipsalat yang menampilkan daftar dua tanda tangan untuk metode tersebut add() .