2012-07-03 8 views
9

Escribo una extensión de Visual Studio intellisense y me gustaría obtener el tipo de elemento justo antes del cursor en un editor de C#.Encuentra el tipo de artículo en la posición actual en una ventana del editor de C#

Actualmente tengo un ITextBuffer que puedo usar para obtener el archivo fuente actual.

también puedo obtener la posición actual en el editor de la siguiente manera:

var dte = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE._DTE)) as EnvDTE.DTE;    
TextSelection sel = (TextSelection)dte.ActiveDocument.Selection; 

Sin embargo, no estoy muy seguro de cómo detectar el tipo del elemento actualmente detrás del cursor en el editor. Intenté usar Roslyn pero parece que esto debería ser mucho más simple que esto. ¿Es Roslyn la mejor herramienta para hacerlo (compilando el documento y navegando hasta la posición correcta en el documento) o existe una mejor manera?

A continuación es mi intento de encontrar el tipo del elemento utilizando Roslyn: (n. ° lógica difusa)

ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot; 
SnapshotPoint? triggerPoint = session.GetTriggerPoint(snapshot); 

var tree = SyntaxTree.ParseCompilationUnit(m_textBuffer.CurrentSnapshot.GetText()); 

var nodes = tree.GetRoot().DescendantNodes(); 

var element = nodes.Where(n => n.Span.End <= triggerPoint.Value.Position).Last(); 

var comp = Compilation.Create("test", syntaxTrees: new[] { tree }); 
var semModel = comp.GetSemanticModel(tree); 

//I cant work out what to do here to get the type as the element doesnt seem to be of the required type 
var s = semModel.GetTypeInfo((AttributeSyntax)element); 
+0

+1 Será interesante escuchar lo que Eric tiene que decir al respecto. – MoonKnight

+2

¿Por qué no estás usando 'ITextView.Caret.Position'? – leppie

+0

@leppie soy bastante nuevo en el sdk VS pero parece una forma mucho más fácil de obtener el cursor actual pos, lo cambiaré –

Respuesta

3

El compilador de API son muy deliberada y requieren que la pregunta correcta Simplemente encontrar el tipo de lo que está en la posición del cursor requiere algo de contexto, y la respuesta que puede parecerle obvia al principio puede no ser la respuesta correcta para otros usos.

Para expresiones generales que puede hacer algo como esto: (Nota No es muy robusta)

var root = tree.GetRoot(); 
var token = root.FindToken(pos); 
var nearestExpr = token.Parent.AncestorsAndSelf().OfType<ExpressionSyntax>().First(); 
var type = semModel.GetTypeInfo(nearestExpr).Type; 

una solución más completa sería comprobar el nodo padre del testigo e ir de allí:

var node = token.Parent; 
if (node is ExpressionSyntax) 
{ 
    type = semModel.GetTypeInfo((ExpressionSyntax)node).Type; 
} 
else if (node is VariableDeclaratorSyntax && ((VariableDeclaratorSyntax)node).Identifier == token) 
{ 
    type = (TypeSymbol)semModel.GetDeclaredSymbol((VariableDeclaratorSyntax)node); 
} 

...

Hay una gran cantidad de casos interesantes, y lo que se quiere mostrar como el tipo correspondiente a cualquier identificador particular, o ficha en el origen de f Puede variar dependiendo de lo que intenta lograr.

+0

Impresionante que se parece a lo que estoy buscando, lo intentaré esta noche. –

+0

Lo probé pero estoy teniendo problemas con la llamada a GetTypeInfo (IdentifierNameSyntax), cuando la ejecuto obtengo un ExtendedErrorTypeSymbol, ¿alguna idea de cómo evitar esto? –

Cuestiones relacionadas