How can I make my code diagnostic syntax node action work on closed files?

asked11 years ago
last updated6 years ago
viewed4.2k times
Up Vote74Down Vote

I'm building a set of code diagnostics using Roslyn (in VS2015 Preview). Ideally, I'd like any errors they produce to act as persistent errors, just as if I were violating a normal language rule.

There are a bunch of options, but I'm having a hard time getting any of them to work consistently. I've managed to implement a rudimentary syntax node action, i.e. one registered with

context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);

in the Initialize method of my diagnostic class. Lo and behold, when I open up a file which violates this diagnostic (while running the VSIX project), VS2015 shows an error:


However, the error goes away when I close the file.

I've tried using context.RegisterCompilationEndAction as well, but this has two problems:

    • Although diagnostics created in the analysis method fire, in order to implement the diagnostics I'm using a visitor, like this - which may be inept:``` 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); } } }
I know that the diagnostics are being created - a breakpoint on the `ReportDiagnostic` line is hit several times - but I'm not seeing anything in the error list. (Whereas a similar `ReportDiagnostic` call at the start of the method, or one per syntax tree with the file path,  get shown.)

What am I doing wrong here? The first approach (a syntax node action) would be ideal if feasible - it gives me exactly the context I need. Is there some setting in the project properties that I need to make the compiler use that for "full project" compilation as well as just interactive "in the IDE" handling? Is this perhaps just a bit of Roslyn integration which isn't quite finished yet?

(I can include the full code for the class if it would be useful - in this case I suspect it would be more noise than signal though.)