如何使我的代码诊断语法节点操作对关闭的文件起作用?


73

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

有很多选择,但是我很难让其中任何一个都能一致地工作。我设法实现了基本的语法节点操作,即已向

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中”处理?这可能只是Roslyn集成的一部分,还没有完成?

(如果有用的话,我可以包括该类的完整代码-在这种情况下,我怀疑它比信号要多的噪音。)


1
根据我在一次演讲中RegisterCompilationEndAction所了解的,确实是您所需要的,并且不一致触发的事实是一个错误。我会给发言人发电子邮件并询问。
Benjamin Gruenbaum 2014年

Answers:


46

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

对于的第二个问题RegisterCompilationEndedAnalyzer,在VS 2015 Preview中无法在Visual Studio内部可靠地调用它。这是因为我们进行了一些优化,以避免重新分析所有方法体内的“局部”更改。出于同样的原因,我们目前没有报告所报道的地点错误方法体。我们最近进行了更改,以便在较长的延迟后VS将启动全面的重新分析,因此RegisterCompilationEndedAnalyzer在以后的版本中应可靠地调用它,并且无论位置在哪里,我们都会报告错误。

但是,对于您而言,正确的做法是保留SyntaxNodeAnalyzer,切换VS选项以在关闭的文件中启用诊断,然后将诊断附加到项目编译选项。

希望这可以帮助!


2
啊哈-位置部分肯定可以解释我所看到的奇怪之处。我的“只是检查一下我能使它正常工作”诊断程序没有位置,因此这些位置出现了……并且关闭文件中的诊断程序运行得很好。谢谢!回到现在让诊断程序本身做正确的事情:)
Jon Skeet 2014年

您是否看到有关使用项目附带的诊断程序也将其纳入命令行构建的说明?
凯文·皮尔奇

是的 只要我在正确的位置上稍后再做,我现在就可以开始做它:)
Jon Skeet 2014年

1
@KevinPilch对于VS2017.4,它似乎仍然默认为关闭,这让我感到非常惊讶。关于这是否会改变有任何说法吗?
JamesFaix
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.