-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Roslyn Analyzer not clearing last diagnostic #53192
Comments
This issue is likely related to the use of no-location diagnostics. Updating the result to report the diagnostic within the context of a specific additional file should allow the diagnostic to be cleared when that file is closed. |
To update I have found a workaround using code generators (expand below for example) ⚠ Note from @sharwell: Don't do this unless you want the IDE to be very slow with no workaround [Generator]
public class SchemaTestAnalyzer : ISourceGenerator
{
public const string DiagnosticId = "TestCompilationAnalyzer";
private static readonly LocalizableString Title = "TestAnalyzer";
private static readonly LocalizableString MessageFormat = "This message should always appear {0}";
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, "Test", DiagnosticSeverity.Warning, isEnabledByDefault: true);
public void Execute(GeneratorExecutionContext context)
{
var additionalFile = context.AdditionalFiles.FirstOrDefault();
if (additionalFile != null)
{
var text = File.ReadAllText(additionalFile.Path);
if (text.Contains("help"))
{
context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, "help"));
}
if (text.Contains("test"))
{
context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, "test"));
}
}
}
public void Initialize(GeneratorInitializationContext context) { }
} These clear as expected when the last issue is addressed |
@joncoello That approach comes with a non-trivial performance penalty. Is there a reason why the reported diagnostics cannot be updated to set the location within the additional file? |
@joncoello The sample is very interesting, but due to the magnitude of the performance impact incurred I've added a warning to it so users don't think this is something worth trying. It will have really, really bad impacts. |
@mavasani I think the solution here is to internally associate no-location diagnostics in live analysis with the source getting analyzed at the time the diagnostic was reported, so if that source is analyzed again later it knows to clear the diagnostic. |
@sharwell fair enough - I'd be happy to go back to using CompilationAction but the last issue I clear doesn't go and Locations don't work in non-code files |
Locations should work fine in non-code files. Public API analyzer reports diagnostics in additional files. |
I have updated my original example with a location but the diagnostics are now not appearing [DiagnosticAnalyzer(LanguageNames.CSharp)]
public class Analyzer1Analyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "TestCompilationAnalyzer";
private static readonly LocalizableString Title = "TestAnalyzer";
private static readonly LocalizableString MessageFormat = "This message should always appear {0}";
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, "Test", DiagnosticSeverity.Warning, isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterAdditionalFileAction(AdditionalFileAction);
}
private void AdditionalFileAction(AdditionalFileAnalysisContext cxt)
{
var fileText = cxt.AdditionalFile.GetText();
foreach (var line in fileText.Lines)
{
var linePositionSpan = fileText.Lines.GetLinePositionSpan(line.Span);
var location = Location.Create(cxt.AdditionalFile.Path, line.Span, linePositionSpan);
if (line.Text.ToString().Contains("help"))
{
cxt.ReportDiagnostic(Diagnostic.Create(Rule, location, $"help"));
}
if (line.Text.ToString().Contains("test"))
{
cxt.ReportDiagnostic(Diagnostic.Create(Rule, location, $"test"));
}
}
}
} Passing in Location.None makes them appear again but back to the original problem of the last diagnostic not disappearing |
Investigated a bit more and identified that AdditionalFileActions are not being consistently invoked in the IDE during intellisense builds. These actions are consistently invoked during explicit builds and the diagnostics show up fine. I'll continue investigating the IDE issue. |
Fixes dotnet#53192 Currently, work coordinator only enqueues source document IDs for project analysis work items. This means we don't analyze the additional documents, which can now report standalone diagnostics through RegisterAdditionalFileAction. This PR fixes this by enqueuing project's additional document IDs and analyzer config document IDs.
I have created a Roslyn Analyzer that validates text files against a set of rules and have noticed that when I fix the last issue that diagnostic does not disappear. I have created a simple example to replicate the problem below.
if I add the words help and test to my additional file both diagnostics appear but if I remove both whatever was showing last won't disappear.
The text was updated successfully, but these errors were encountered: