如何使我的代码诊断语法节点操作在关闭的文件上工作?

我正在使用 Roslyn (在 VS2015预览版中)构建一组代码诊断。理想情况下,我希望它们产生的任何错误都能作为持久性错误,就像我违反了正常的语言规则一样。

有很多选择,但我很难让它们中的任何一个始终如一地发挥作用。我已经设法实现了一个基本的语法节点操作,即一个注册了

context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);

在我的诊断类的 Initialize方法中。你瞧,当我打开一个违反此诊断的文件(在运行 VSIX 项目时)时,VS2015显示了一个错误:

  • 在右边的代码下面用红色的波浪线
  • 红色块在边缘
  • 错误列表中的错误

但是,当我关闭文件时,错误消失了。

我也试过使用 context.RegisterCompilationEndAction,但有两个问题:

  • 它似乎不稳定地开火。当我打开解决方案时,它会触发 通常是这样,但并不总是如此。它不会在清理/重建的时候发射,这看起来很奇怪。
  • 虽然诊断程序在分析方法中创建了 直接,但是为了实现诊断程序,我使用了一个访问程序,就像下面这样——这可能是不合适的:

    private static void AnalyzeEndCompilation(CompilationEndAnalysisContext context)
    {
    foreach (var tree in context.Compilation.SyntaxTrees)
    {
    var visitor = new ReportingVisitor(context.Compilation.GetSemanticModel(tree));
    visitor.Visit(tree.GetRoot());
    foreach (var diagnostic in visitor.Diagnostics)
    {
    context.ReportDiagnostic(diagnostic);
    }
    }
    }
    

    我知道正在创建诊断程序-ReportDiagnostic行上的断点被多次命中-但是我在错误列表中没有看到任何东西。(在方法的开始部分有一个类似的 ReportDiagnostic调用,或者每个语法树有一个文件路径,这时会显示 是的。)

我做错了什么?如果可行的话,第一种方法(一个语法节点操作)将是理想的——它给我提供了我所需要的上下文。在项目属性中是否有一些设置,我需要让编译器使用它来进行“完整的项目”编译,以及交互式的“在 IDE 中”处理?这或许只是罗斯林一体化的一小部分,而且还没有完全结束?

(如果这个类有用的话,我可以包含它的完整代码——在这种情况下,我怀疑它的噪音比信号更大。)

4148 次浏览

对于关闭的文件问题,我们的意图是,所有的诊断将报告,无论是打开或关闭的文件。在工具选项文本编辑器 C # 高级预览中有一个用户选项,您可以切换该选项以在关闭的文件中包含诊断信息。我们希望在 VS2015发布之前将其作为默认设置。然而,请注意,该选项仅适用于 VS 中的分析。如果您的分析器被传递给编译器(通过在解决方案资源管理器中添加分析器,或者通过分析器添加对包的 NuGet 包引用,而不是将 VSIX 安装到 Visual Studio 中) ,那么编译器将在用户构建时报告 所有诊断,无论文件是否打开。

对于 RegisterCompilationEndedAnalyzer的第二个问题,在 VS2015预览版中 VisualStudio 中并不可靠地调用它。这是因为我们进行了一些优化,以避免重新分析方法主体内“本地”更改的所有内容。出于类似的原因,我们目前不报告与位置 进去方法体一起报告的错误。我们最近做了一些改动,这样 VS 会在较长的延迟之后开始一个全面的重新分析,所以在未来的构建中应该可靠地调用 RegisterCompilationEndedAnalyzer,并且我们将报告错误,而不管位置如何。

但是,对于您的情况,正确的做法是使用 SyntaxNodeAnalyzer,切换 VS 选项以在关闭的文件中启用诊断,并将诊断附加到项目编译选项。

希望这个能帮上忙!