在C#编辑器窗口中查找当前位置的项目类型

时间:2012-07-03 09:29:44

标签: c# visual-studio vs-extensibility roslyn

我正在编写Visual Studio intellisense的扩展,并希望在C#编辑器中获取光标之前的项目类型。

我目前有一个ITextBuffer可以用来获取当前的源文件。

我也可以在编辑器中获取当前位置,如下所示:

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

但是我不太清楚如何在编辑器中检测当前光标后面的项目类型。我尝试过使用Roslyn,但看起来这应该是一个比这更简单的事情。 Roslyn是最好的工具(通过编译文档并导航到文档中的正确位置),还是有更好的方法。

以下是我尝试使用Roslyn查找项目的类型:

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

1 个答案:

答案 0 :(得分:3)

编译器API是非常慎重的,需要您提出正确的问题(没有模糊逻辑。)只需在光标位置找到事物的类型需要一些上下文,并且最初可能看起来很明显的答案可能是不是其他用途的正确答案。

对于一般表达式,你可以这样做:(注意它不是很健壮)

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

更全面的解决方案将检查令牌的父节点并从那里开始:

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

...

有很多有趣的案例,您想要显示的内容与源文件中任何特定标识符或标记相对应的类型可能会因您尝试完成的内容而异。