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