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:
- Red squiggle under the right bit of code
- Red block in the margin
- Error in the error list
However, the error goes away when I close the file.
I've tried using context.RegisterCompilationEndAction
as well, but this has two problems:
- It seems to fire inconsistently. Usually when I open the solution it fires, but not always. It doesn't fire on a clean/rebuild, which seems odd.
Although diagnostics created directly 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 similarReportDiagnostic
call at the start of the method, or one per syntax tree with the file path, does 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.)
RegisterCompilationEndAction
is indeed what you need and the fact it fires inconsistently is a bug. I'll email the speaker and ask. – Touchstone