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

Posted

技术标签:

【中文标题】如何使我的代码诊断语法节点操作对关闭的文件起作用?【英文标题】:How can I make my code diagnostic syntax node action work on closed files? 【发布时间】:2014-12-08 19:58:17 【问题描述】:

我正在使用 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 中”处理?这可能只是 Roslyn 的一点整合,还没有完全完成吗?

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

【问题讨论】:

根据我在一次谈话中的理解RegisterCompilationEndAction 确实是您所需要的,而且它触发不一致的事实是一个错误。我会通过电子邮件向演讲者发送电子邮件并询问。 【参考方案1】:

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

对于 RegisterCompilationEndedAnalyzer 的第二个问题,在 VS 2015 预览版的 Visual Studio 中不能可靠地调用它。这是因为我们做了一些优化以避免重新分析方法体内部的“局部”变化。出于类似的原因,我们目前不报告使用位置 in 方法体报告的错误。我们最近刚刚更改了这一点,以便 VS 将在更长的延迟后启动完整的重新分析,因此在未来的构建中应该可靠地调用 RegisterCompilationEndedAnalyzer,并且无论位置如何,我们都会报告错误。

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

希望这会有所帮助!

【讨论】:

啊哈 - 位置部分肯定会解释我所看到的奇怪之处。我的“只是检查我可以得到一些工作”的诊断没有位置,所以那些出现了......并且关闭文件中的诊断选项非常有效。谢谢!现在回到让诊断本身做正确的事情:) 你有没有看到关于使用项目附加诊断来让它们也进入命令行构建的注释? 是的。只要我以后走在正确的轨道上,我现在就可以踢它:) @KevinPilch 这似乎仍然默认为 VS2017.4 关闭,这让我感到非常惊讶。关于这是否会改变的任何消息?

以上是关于如何使我的代码诊断语法节点操作对关闭的文件起作用?的主要内容,如果未能解决你的问题,请参考以下文章

快速排序模板不起作用,并使我的程序无响应

为啥我的扩展语法在节点 v7.0.0 中不起作用?

java 流操作对文件的分割和合并的实例详解_java - JAVA

MATLAB 部署:如何使我的 .exe 文件可以被其他计算机使用?

如何使用 CAShapeLayer 使我的 UIBezierPath 动画?

如何使用 thunk 操作对 mapDispatchToProps 进行单元测试