我正在使用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集成的一点还没有完成呢?
(如果它有用的话,我可以包括该类的完整代码 - 在这种情况下,我怀疑它会比信号更多的噪音。)
答案 0 :(得分:43)
对于已关闭的文件问题,我们的意图是从打开或关闭的文件中报告所有诊断。在Tools \ Options \ Text Editor \ C#\ Advanced的预览中有一个用户选项,您可以切换到包含已关闭文件中的诊断。我们希望在VS 2015发布之前将其设为默认值。但请注意,该选项仅适用于VS内的分析。如果您的分析器传递给编译器(通过在解决方案资源管理器中添加分析器,或者将NuGet包引用添加到带有分析器的包,而不是将VSIX安装到Visual Studio中),则编译器将报告 all 用户构建时的诊断,无论文件是否打开。
对于RegisterCompilationEndedAnalyzer
的第二个问题,在VS 2015预览版中,在Visual Studio中无法可靠地调用它。这是因为我们做了一些优化,以避免重新分析" local"方法体内的变化。出于类似原因,我们目前不报告使用方法正文中的位置报告的错误。我们最近刚改变了这一点,以便VS在更长的延迟后启动完整的重新分析,因此在将来的版本中应该可靠地调用RegisterCompilationEndedAnalyzer
,我们将报告错误,无论位置如何。
但是,对于您的情况,正确的做法是使用SyntaxNodeAnalyzer,切换VS选项以在已关闭的文件中启用诊断,并将诊断附加到项目编译选项。
希望这有帮助!