Partilhar via


Conclusão do membro IntelliSense (estrutura de pacote gerenciado)

A conclusão do membro IntelliSense é uma dica de ferramenta que exibe uma lista dos possíveis participantes de um escopo específico como, por exemplo, uma classe, estrutura, enumeração ou namespace. Por exemplo, em C#, se o usuário digitar "Este" seguido por um período, uma lista de todos os membros da classe ou estrutura no escopo atual é apresentada em uma lista na qual o usuário pode selecionar.

A estrutura de pacote gerenciado (MPF) oferece suporte para a dica de ferramenta e o gerenciamento da lista na dica de ferramenta; tudo o que é necessário é cooperação do analisador para fornecer os dados que aparece na lista.

Como ele funciona

Estas são as duas maneiras em que uma lista de membros é mostrada, usando as classes do MPF:

  • Posicionando o cursor em um identificador ou após um caractere de conclusão do membro e selecionando Membros da lista partir do IntelliSense menu.

  • O IScanner scanner detecta um caractere de conclusão do membro e define um disparador de token de MemberSelect desse caractere.

Um caractere de conclusão do membro indica que um membro de uma classe, estrutura ou enumeração a seguir. Por exemplo, em C# ou Visual Basic o caractere de conclusão do membro é um ., enquanto em C++ o caractere é um . ou um ->. O valor de disparador é definido quando o caractere de seleção de membro é verificado.

O comando da lista de membros de IntelliSense

O SHOWMEMBERLIST comando inicia uma chamada para o Completion método na Source classe e o Completion método, por sua vez, chama o ParseSource analisador de método com o motivo de análise de DisplayMemberList.

O analisador determina o contexto da posição atual, bem como o token em ou imediatamente antes da posição atual. Com base nesse token, é apresentada uma lista de declarações. Por exemplo, em C#, se você posicionar o cursor em um membro da classe e selecione Membros da lista de, você obtém uma lista de todos os membros da classe. Se você posicionar o cursor após um período que segue uma variável de objeto, você obtém uma lista de todos os membros da classe que o objeto representa. Observe que se o cursor é posicionado em um membro quando a lista de membros é mostrada, selecionando um membro da lista substitui o membro que o cursor estiver em um na lista.

O disparador de Token

O MemberSelect disparador inicia uma chamada para o Completion método na Source classe e o Completion método, por sua vez, chama o analisador com o motivo de análise de MemberSelect (se o disparador token incluído também o MatchBraces sinalizador, o motivo de análise é MemberSelectAndHighlightBraces que combina a seleção de membro e realce a chave).

O analisador determina o contexto do atual posicionar, bem como o que foi digitado antes que o membro seleciona o caractere. Essas informações, o analisador cria uma lista de todos os membros do escopo solicitado. Esta lista de declarações é armazenada na AuthoringScope o objeto que é retornado a ParseSource método. Se todas as declarações são retornadas, a dica de ferramenta de conclusão do membro é exibida. A dica de ferramenta é gerenciada por uma instância da CompletionSet classe.

Ativando o suporte para a conclusão do membro

Você deve ter o CodeSense entrada do registro é definido como 1 para suportar qualquer operação de IntelliSense. Essa entrada do Registro pode ser definida com um parâmetro nomeado passado para o ProvideLanguageServiceAttribute atributo associado com o pacote de idioma do usuário. As classes de serviço de linguagem ler o valor desta entrada do registro a partir do EnableCodeSense propriedade no LanguagePreferences classe.

Se o seu scanner retorna o disparador de token de MemberSelect, o parser retorna uma lista de declarações e a lista de conclusão do membro é exibida.

Com suporte para a conclusão do membro no Scanner

O mecanismo de varredura deve ser capaz de detectar um caractere de conclusão do membro e defina o disparador de token de MemberSelect quando esse caractere é analisado.

Exemplo

Aqui está um exemplo simplificado de detectar o caractere de conclusão do membro e definindo o apropriado TokenTriggers sinalizador. Este exemplo é apenas para fins ilustrativos. Ele assume que o scanner contém um método GetNextToken que identifica e retorna tokens a partir de uma linha de texto. O exemplo de código simplesmente define o disparador sempre que ele vê o tipo certo de caractere.

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

Com suporte para a conclusão do membro no analisador

Para a conclusão do membro, o Source chamadas de classes de GetDeclarations método. Você deve implementar a lista em uma classe que é derivada de Declarations classe. Consulte o Declarations classe para obter detalhes sobre os métodos que você deve implementar.

O analisador é chamado com MemberSelect ou MemberSelectAndHighlightBraces quando um caractere de seleção de membro é digitado. Localização fornecida ParseRequest objeto é imediatamente após o membro seleciona o caractere. O analisador deve coletar os nomes de todos os membros que podem aparecer em uma lista de membros naquele ponto específico no código fonte. Em seguida, o analisador deve analisar a linha atual para determinar o escopo em que o usuário deseja associado com o caractere de seleção de membro.

Este escopo baseia-se no tipo do identificador antes que o membro seleciona o caractere. Por exemplo, em C#, dada a variável de membro languageService que tem o tipo de LanguageService, digitando languageService. produz uma lista de todos os membros da LanguageService classe. Também em C#, digitando isso. produz uma lista de todos os membros da classe no escopo atual.

Exemplo

O exemplo a seguir mostra uma maneira para preencher um Declarations lista. Esse código pressupõe que o analisador constrói uma declaração e o adiciona à lista, chamando um AddDeclaration método sobre o TestAuthoringScope classe.

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