9

我正在编写 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);
4

1 回答 1

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

...

有很多有趣的案例,您希望显示为与源文件中任何特定标识符或令牌对应的类型可能会因您要完成的工作而异。

于 2012-07-03T18:54:52.917 回答