Condividi tramite


Completamento dei membri di IntelliSense (managed package Framework)

Il completamento dei membri di IntelliSense è una descrizione comandi che visualizza un elenco di possibili membri di un determinato ambito ad esempio una classe, una struttura, l'enumerazione, o spazio dei nomi. In c, ad esempio, se l'utente digita “this this„ è seguito da un punto, un elenco di tutti i membri di classe o struttura l'ambito corrente viene visualizzato in un elenco da cui l'utente può selezionare.

Il framework gestito del pacchetto (MPF) fornisce il supporto per la descrizione comandi e gestire l'elenco nella descrizione comandi; l'unica operazione necessaria è la cooperazione dal parser per fornire i dati visualizzati nell'elenco.

Funzionamento

Di seguito sono indicate due modalità in cui un elenco dei membri viene illustrato l'utilizzo di classi di MPF:

  • Posizionando il cursore su un identificatore o dopo un carattere e selezionare di completamento del membro Elenca membri dal menu di IntelliSense .

  • Lo scanner di IScanner rileva un carattere di terminazione del membro e imposta un trigger token di MemberSelect per tale carattere.

Un carattere di terminazione del membro indica che un membro di una classe, struttura, o di un'enumerazione deve seguire. Ad esempio, in c# o in Visual Basic il carattere di terminazione del membro è ., mentre in C++ il carattere è . o ->. Il valore del trigger viene impostato quando il carattere selezionato del membro viene analizzato.

Il comando dell'elenco dei membri di IntelliSense

Il comando di SHOWMEMBERLIST avviare una chiamata al metodo di Completion sulla classe di Source e il metodo di Completion , a sua volta, chiamare il parser del metodo di ParseSource con il motivo di analisi di DisplayMemberList.

Il parser determina il contesto della posizione corrente nonché il token in o immediatamente prima della posizione corrente. In base a questo token, un elenco delle dichiarazioni è verificato. In c, ad esempio, se si posiziona il cursore sul membro di classe e su Elenca membriselezionato, si ottiene un elenco di tutti i membri della classe. Se si posiziona il cursore dopo un periodo che segue una variabile oggetto, si ottiene un elenco di tutti i membri della classe che l'oggetto rappresenta. Si noti che se il cursore viene posizionato su un membro quando l'elenco dei membri viene visualizzato, selezionare un membro da l sostituisce il membro a cui si trova il cursore con quello nell'elenco.

Il trigger di token

Il trigger di MemberSelect avviare una chiamata al metodo di Completion sulla classe di Source e il metodo di Completion , a sua volta, chiamare il parser con il motivo di analisi di MemberSelect (se il trigger token anche abbia importato il flag di MatchBraces , il motivo di analisi viene MemberSelectAndHighlightBraces che combina la selezione dei membri e l'evidenziazione di parentesi graffe).

Il parser determina il contesto della posizione corrente nonché ciò che è stato inserito prima del carattere selezionato del membro. Da queste informazioni, il parser crea un elenco di tutti i membri dell'ambito richiesto. Questo elenco delle dichiarazioni è archiviato nell'oggetto di AuthoringScope restituito dal metodo di ParseSource . Se le dichiarazioni vengono restituite, la descrizione comandi di completamento del membro in. La descrizione comandi viene gestita da un'istanza della classe di CompletionSet .

Abilitare supporto al completamento del membro

È necessario che la voce del Registro di sistema di CodeSense impostata su 1 per supportare qualsiasi operazione di IntelliSense. Questa voce del Registro di sistema può essere impostata con un parametro denominato passato all'attributo dell'utente di ProvideLanguageServiceAttribute associato al pacchetto di linguaggio. Le classi del servizio di linguaggio leggere il valore di questa chiave del Registro di sistema dalla proprietà di EnableCodeSense sulla classe di LanguagePreferences .

Se lo scanner restituisce il trigger token di MemberSelecte il parser restituisce un elenco delle dichiarazioni, l'elenco di completamento del membro in.

Completamento dell'elemento portante lo scanner

Lo scanner deve essere in grado di rilevare un carattere di terminazione del membro e impostare il trigger token di MemberSelect quando tale carattere viene analizzato.

Esempio

Di seguito è riportato un esempio semplice di individuare il carattere di terminazione del membro e impostare il flag appropriato di TokenTriggers . Questo esempio è solo a titolo esemplificativo. Si presuppone che lo scanner contenga un metodo GetNextToken che identifica e restituisce i token da una riga di testo. Il codice di esempio riportato di seguito viene semplicemente il trigger ogni volta che rileva il corretto tipo di carattere.

using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;

namespace TestLanguagePackage
{
    public class TestScanner : IScanner
    {
        private Lexer lex;
        private const char memberSelectChar = '.';

        public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo,
                                                   ref int state)
        {
            bool foundToken = false
            string token = lex.GetNextToken();
            if (token != null)
            {
                foundToken = true;
                char c = token[0];
                if (c == memberSelectChar)
                {
                        tokenInfo.Trigger |= TokenTriggers.MemberSelect;
                }
            }
            return foundToken;
        }
    }
}

Completamento dell'elemento portante nel parser

Per il completamento del membro, la classe di Source chiama il metodo di GetDeclarations . È necessario distribuire l'elenco nella classe derivata dalla classe di Declarations . Vedere la classe di Declarations per informazioni dettagliate sui metodi che devono essere implementati.

Il parser viene chiamato con MemberSelect o MemberSelectAndHighlightBraces quando un carattere selezionato del membro viene digitato. La posizione arresa l'oggetto di ParseRequest è subito dopo che il carattere selezionato del membro. Il parser necessario raccogliere i nomi di tutti i membri che possono essere visualizzate in un elenco di membri a quel determinato punto del codice sorgente. Quindi il parser necessario analizzare la riga corrente per determinare l'ambito che l'utente desidera associato al carattere selezionato del membro.

Questo ambito è basato sul tipo dell'identificatore prima che il carattere selezionato del membro. Ad esempio, in c#, data la variabile membro languageService con un tipo di LanguageService, viene spostato in languageService. elabora un elenco di tutti i membri della classe di LanguageService . Inoltre in c#, viene spostato in questo. elabora un elenco di tutti i membri della classe nell'ambito corrente.

Esempio

Nell'esempio seguente viene illustrato un modo per popolare un elenco di Declarations . In questo codice si presuppone che il parser costruisca una dichiarazione e la venga aggiunto alla chiamata di un metodo di AddDeclaration sulla classe di TestAuthoringScope .

using System.Collections;
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;

namespace TestLanguagePackage
{
    internal class TestDeclaration
    {
        public string Name;            // Name of declaration
        public int     TypeImageIndex; // Glyph index
        public string Description;     // Description of declaration

        public TestDeclaration(string name, int typeImageIndex, string description)
        {
            this.Name = name;
            this.TypeImageIndex = typeImageIndex;
            this.Description = description;
        }
    }


    //===================================================
    internal class TestDeclarations : Declarations
    {
        private ArrayList declarations;

        public TestDeclarations()
            : base()
        {
            declarations = new ArrayList();
        }

        public void AddDeclaration(TestDeclaration declaration)
        {
            declarations.Add(declaration);
        }

        //////////////////////////////////////////////////////////////////////
        // Declarations of class methods that must be implemented.
        public override int GetCount()
        {
            // Return the number of declarations to show.
            return declarations.Count;
        }

        public override string GetDescription(int index)
        {
            // Return the description of the specified item.
            string description = "";
            if (index >= 0 && index < declarations.Count)
            {
                description = ((TestDeclaration)declarations[index]).Description;
            }
            return description;
        }

        public override string GetDisplayText(int index)
        {
            // Determine what is displayed in the tool tip list.
            string text = null;
            if (index >= 0 && index < declarations.Count)
            {
                text = ((TestDeclaration)declarations[index]).Name;
            }
            return text;
        }

        public override int GetGlyph(int index)
        {
            // Return index of image to display next to the display text.
            int imageIndex = -1;
            if (index >= 0 && index < declarations.Count)
            {
                imageIndex = ((TestDeclaration)declarations[index]).TypeImageIndex;
            }
            return imageIndex;
        }

        public override string GetName(int index)
        {
            string name = null;
            if (index >= 0 && index < declarations.Count)
            {
                name = ((TestDeclaration)declarations[index]).Name;
            }
            return name;
        }
    }


    //===================================================
    public class TestAuthoringScope : AuthoringScope
    {
        private TestDeclarations declarationsList;

        public void AddDeclaration(TestDeclaration declaration)
        {
            if (declaration != null)
            {
                if (declarationsList == null)
                {
                    declarationsList = new TestDeclarations();
                }
                declarationsList.AddDeclaration(declaration);
            }
        }

        public override Declarations GetDeclarations(IVsTextView view,
                                                     int line,
                                                     int col,
                                                     TokenInfo info,
                                                     ParseReason reason)
        {
            return declarationsList;
        }

        /////////////////////////////////////////////////
        // Remainder of AuthoringScope methods not shown.
        /////////////////////////////////////////////////
    }


    //===================================================
    class TestLanguageService : LanguageService
    {
        public override AuthoringScope ParseSource(ParseRequest req)
        {
            TestAuthoringScope scope = new TestAuthoringScope();
            if (req.Reason == ParseReason.MemberSelect ||
                req.Reason == ParseReason.MemberSelectAndHighlightBraces)
            {
                // Gather list of declarations based on what the user
                // has typed so far. In this example, this list is an array of
                // MemberDeclaration objects (a helper class you might implement
                // to hold member declarations).
                // How this list is gathered is dependent on the parser
                // and is not shown here.
                MemberDeclarations memberDeclarations;
                memberDeclarations = GetDeclarationsForScope();

                // Now populate the Declarations list in the authoring scope.
                // GetImageIndexBasedOnType() is a helper method you
                // might implement to convert a member type to an index into
                // the image list returned from the language service.
                foreach (MemberDeclaration dec in memberDeclarations)
                {
                    scope.AddDeclaration(new TestDeclaration(
                                             dec.Name,
                                             GetImageIndexBasedOnType(dec.Type),
                                             dec.Description));
                }
            }
            return scope;
        }
    }
}