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

Not*_*ple 9 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;
Run Code Online (Sandbox Code Playgroud)

但是我不太确定如何在编辑器中检测当前光标后面的项目类型.我尝试过使用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);
Run Code Online (Sandbox Code Playgroud)

Mat*_*ren 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;
Run Code Online (Sandbox Code Playgroud)

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

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);   
}
Run Code Online (Sandbox Code Playgroud)

...

有很多有趣的情况,您想要显示为与源文件中任何特定标识符或标记相对应的类型的内容可能会有所不同,具体取决于您想要完成的任务。