提交 b2f29f7a 编写于 作者: H Heejae Chang

Merge pull request #2597 from heejaechang/supression

share GetEffectiveSeverity between AnalyzerNode and service
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Microsoft.CodeAnalysis.ErrorReporting;
......@@ -102,5 +103,105 @@ private static VersionStamp GetAnalyzerVersion(string path)
return VersionStamp.Create(File.GetLastWriteTimeUtc(path));
}
public static ReportDiagnostic GetEffectiveSeverity(
this Compilation compilation,
string ruleId,
DiagnosticSeverity defaultSeverity,
bool enabledByDefault)
{
return GetEffectiveSeverity(
compilation.Options,
ruleId,
defaultSeverity,
enabledByDefault);
}
public static ReportDiagnostic GetEffectiveSeverity(
this CompilationOptions options,
string ruleId,
DiagnosticSeverity defaultSeverity,
bool enabledByDefault)
{
return GetEffectiveSeverity(
options.GeneralDiagnosticOption,
options.SpecificDiagnosticOptions,
ruleId,
defaultSeverity,
enabledByDefault);
}
public static ReportDiagnostic GetEffectiveSeverity(
this DiagnosticDescriptor descriptor,
CompilationOptions options)
{
return GetEffectiveSeverity(
options,
descriptor.Id,
descriptor.DefaultSeverity,
descriptor.IsEnabledByDefault);
}
public static ReportDiagnostic GetEffectiveSeverity(
ReportDiagnostic generalOption,
IDictionary<string, ReportDiagnostic> specificOptions,
string ruleId,
DiagnosticSeverity defaultSeverity,
bool enabledByDefault)
{
ReportDiagnostic report = ReportDiagnostic.Default;
var isSpecified = specificOptions.TryGetValue(ruleId, out report);
if (!isSpecified)
{
report = enabledByDefault ? ReportDiagnostic.Default : ReportDiagnostic.Suppress;
}
if (report == ReportDiagnostic.Default)
{
switch (generalOption)
{
case ReportDiagnostic.Error:
if (defaultSeverity == DiagnosticSeverity.Warning)
{
if (!isSpecified)
{
return ReportDiagnostic.Error;
}
}
break;
case ReportDiagnostic.Suppress:
if (defaultSeverity == DiagnosticSeverity.Warning || defaultSeverity == DiagnosticSeverity.Info)
{
return ReportDiagnostic.Suppress;
}
break;
default:
break;
}
return MapSeverityToReport(defaultSeverity);
}
return report;
}
private static ReportDiagnostic MapSeverityToReport(DiagnosticSeverity defaultSeverity)
{
switch (defaultSeverity)
{
case DiagnosticSeverity.Hidden:
return ReportDiagnostic.Hidden;
case DiagnosticSeverity.Info:
return ReportDiagnostic.Info;
case DiagnosticSeverity.Warning:
return ReportDiagnostic.Warn;
case DiagnosticSeverity.Error:
return ReportDiagnostic.Error;
default:
throw new ArgumentException("Unhandled DiagnosticSeverity: " + defaultSeverity, "defaultSeverity");
}
}
}
}
\ No newline at end of file
......@@ -142,12 +142,13 @@ private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet<string
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
{
if (userDiagnosticDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
if (SkipRunningAnalyzer(document.Project.CompilationOptions, userDiagnosticDriver, openedDocument, skipClosedFileChecks, stateSet))
{
await HandleSuppressedAnalyzerAsync(document, stateSet, StateType.Syntax, cancellationToken).ConfigureAwait(false);
await ClearExistingDiagnostics(document, stateSet, StateType.Syntax, cancellationToken).ConfigureAwait(false);
continue;
}
else if (await ShouldRunAnalyzerForStateTypeAsync(userDiagnosticDriver, stateSet.Analyzer, StateType.Syntax, diagnosticIds).ConfigureAwait(false) &&
(skipClosedFileChecks || ShouldRunAnalyzerForClosedFile(openedDocument, stateSet.Analyzer)))
if (await ShouldRunAnalyzerForStateTypeAsync(userDiagnosticDriver, stateSet.Analyzer, StateType.Syntax, diagnosticIds).ConfigureAwait(false))
{
var data = await _executor.GetSyntaxAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);
if (data.FromCache)
......@@ -220,9 +221,11 @@ private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member
{
if (spanBasedDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
{
await HandleSuppressedAnalyzerAsync(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
continue;
}
else if (await ShouldRunAnalyzerForStateTypeAsync(spanBasedDriver, stateSet.Analyzer, StateType.Document).ConfigureAwait(false))
if (await ShouldRunAnalyzerForStateTypeAsync(spanBasedDriver, stateSet.Analyzer, StateType.Document).ConfigureAwait(false))
{
var supportsSemanticInSpan = await stateSet.Analyzer.SupportsSpanBasedSemanticDiagnosticAnalysisAsync(spanBasedDriver).ConfigureAwait(false);
var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;
......@@ -264,12 +267,13 @@ private async Task AnalyzeDocumentAsync(Document document, VersionArgument versi
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
{
if (userDiagnosticDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
if (SkipRunningAnalyzer(document.Project.CompilationOptions, userDiagnosticDriver, openedDocument, skipClosedFileChecks, stateSet))
{
await HandleSuppressedAnalyzerAsync(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
continue;
}
else if (await ShouldRunAnalyzerForStateTypeAsync(userDiagnosticDriver, stateSet.Analyzer, StateType.Document, diagnosticIds).ConfigureAwait(false) &&
(skipClosedFileChecks || ShouldRunAnalyzerForClosedFile(openedDocument, stateSet.Analyzer)))
if (await ShouldRunAnalyzerForStateTypeAsync(userDiagnosticDriver, stateSet.Analyzer, StateType.Document, diagnosticIds).ConfigureAwait(false))
{
var data = await _executor.GetDocumentAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);
if (data.FromCache)
......@@ -318,12 +322,13 @@ private async Task AnalyzeProjectAsync(Project project, CancellationToken cancel
var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(project))
{
if (analyzerDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
if (SkipRunningAnalyzer(project.CompilationOptions, analyzerDriver, openedDocument: false, skipClosedFileChecks: false, stateSet: stateSet))
{
await HandleSuppressedAnalyzerAsync(project, stateSet, cancellationToken).ConfigureAwait(false);
await ClearExistingDiagnostics(project, stateSet, cancellationToken).ConfigureAwait(false);
continue;
}
else if (await ShouldRunAnalyzerForStateTypeAsync(analyzerDriver, stateSet.Analyzer, StateType.Project, diagnosticIds: null).ConfigureAwait(false) &&
(ShouldRunAnalyzerForClosedFile(openedDocument: false, analyzer: stateSet.Analyzer)))
if (await ShouldRunAnalyzerForStateTypeAsync(analyzerDriver, stateSet.Analyzer, StateType.Project, diagnosticIds: null).ConfigureAwait(false))
{
var data = await _executor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions).ConfigureAwait(false);
if (data.FromCache)
......@@ -345,6 +350,31 @@ private async Task AnalyzeProjectAsync(Project project, CancellationToken cancel
}
}
private bool SkipRunningAnalyzer(
CompilationOptions compilationOptions,
DiagnosticAnalyzerDriver userDiagnosticDriver,
bool openedDocument,
bool skipClosedFileChecks,
StateSet stateSet)
{
if (userDiagnosticDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
{
return true;
}
if (skipClosedFileChecks)
{
return false;
}
if (ShouldRunAnalyzerForClosedFile(compilationOptions, openedDocument, stateSet.Analyzer))
{
return false;
}
return true;
}
private static async Task PersistProjectData(Project project, DiagnosticState state, AnalysisData data)
{
// TODO: Cancellation is not allowed here to prevent data inconsistency. But there is still a possibility of data inconsistency due to
......@@ -439,7 +469,7 @@ public override async Task<IEnumerable<DiagnosticData>> GetDiagnosticsForSpanAsy
return getter.Diagnostics;
}
private bool ShouldRunAnalyzerForClosedFile(bool openedDocument, DiagnosticAnalyzer analyzer)
private bool ShouldRunAnalyzerForClosedFile(CompilationOptions options, bool openedDocument, DiagnosticAnalyzer analyzer)
{
// we have opened document, doesnt matter
if (openedDocument)
......@@ -447,7 +477,7 @@ private bool ShouldRunAnalyzerForClosedFile(bool openedDocument, DiagnosticAnaly
return true;
}
return Owner.GetDiagnosticDescriptors(analyzer).Any(d => d.DefaultSeverity != DiagnosticSeverity.Hidden);
return Owner.GetDiagnosticDescriptors(analyzer).Any(d => d.GetEffectiveSeverity(options) != ReportDiagnostic.Hidden);
}
private async Task<bool> ShouldRunAnalyzerForStateTypeAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet<string> diagnosticIds)
......@@ -889,7 +919,7 @@ private void ClearProjectState(Project project, StateSet stateSet)
RaiseDiagnosticsUpdated(StateType.Project, project.Id, stateSet, solutionArgs, ImmutableArray<DiagnosticData>.Empty);
}
private async Task HandleSuppressedAnalyzerAsync(Document document, StateSet stateSet, StateType type, CancellationToken cancellationToken)
private async Task ClearExistingDiagnostics(Document document, StateSet stateSet, StateType type, CancellationToken cancellationToken)
{
var state = stateSet.GetState(type);
var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);
......@@ -899,7 +929,7 @@ private async Task HandleSuppressedAnalyzerAsync(Document document, StateSet sta
}
}
private async Task HandleSuppressedAnalyzerAsync(Project project, StateSet stateSet, CancellationToken cancellationToken)
private async Task ClearExistingDiagnostics(Project project, StateSet stateSet, CancellationToken cancellationToken)
{
var state = stateSet.GetState(StateType.Project);
var existingData = await state.TryGetExistingDataAsync(project, cancellationToken).ConfigureAwait(false);
......
......@@ -143,59 +143,7 @@ private void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs
// VisualBasicDiagnosticFilter.GetDiagnosticReport.
internal static ReportDiagnostic GetEffectiveSeverity(string ruleId, IDictionary<string, ReportDiagnostic> specificOptions, ReportDiagnostic generalOption, DiagnosticSeverity defaultSeverity, bool enabledByDefault)
{
ReportDiagnostic report = ReportDiagnostic.Default;
var isSpecified = specificOptions.TryGetValue(ruleId, out report);
if (!isSpecified)
{
report = enabledByDefault ? ReportDiagnostic.Default : ReportDiagnostic.Suppress;
}
if (report == ReportDiagnostic.Default)
{
switch (generalOption)
{
case ReportDiagnostic.Error:
if (defaultSeverity == DiagnosticSeverity.Warning)
{
if (!isSpecified)
{
return ReportDiagnostic.Error;
}
}
break;
case ReportDiagnostic.Suppress:
if (defaultSeverity == DiagnosticSeverity.Warning || defaultSeverity == DiagnosticSeverity.Info)
{
return ReportDiagnostic.Suppress;
}
break;
default:
break;
}
return MapSeverityToReport(defaultSeverity);
}
return report;
}
private static ReportDiagnostic MapSeverityToReport(DiagnosticSeverity defaultSeverity)
{
switch (defaultSeverity)
{
case DiagnosticSeverity.Hidden:
return ReportDiagnostic.Hidden;
case DiagnosticSeverity.Info:
return ReportDiagnostic.Info;
case DiagnosticSeverity.Warning:
return ReportDiagnostic.Warn;
case DiagnosticSeverity.Error:
return ReportDiagnostic.Error;
default:
throw new ArgumentException("Unhandled DiagnosticSeverity: " + defaultSeverity, "defaultSeverity");
}
return AnalyzerHelper.GetEffectiveSeverity(generalOption, specificOptions, ruleId, defaultSeverity, enabledByDefault);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册