提交 148402bf 编写于 作者: M Manish Vasani

Address some more review feedback

上级 80f7a3a2
......@@ -23,9 +23,9 @@ protected override TestWorkspace CreateWorkspaceFromFile(string initialMarkup, T
protected override ParseOptions GetScriptOptions() => Options.Script;
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CSharpUseObjectInitializerDiagnosticAnalyzer(), new ConfigureSeverityLevelCodeFixProvider());
}
......
......@@ -43,9 +43,9 @@ protected override TestWorkspace CreateWorkspaceFromFile(string initialMarkup, T
protected override ParseOptions GetScriptOptions() => Options.Script;
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CustomDiagnosticAnalyzer(), new ConfigureSeverityLevelCodeFixProvider());
}
......
......@@ -53,9 +53,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
public class CSharpDiagnosticWithLocationRemoveSuppressionTests : CSharpRemoveSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -944,9 +944,9 @@ class Class2
public class CSharpDiagnosticWithoutLocationRemoveSuppressionTests : CSharpRemoveSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(reportDiagnosticsWithoutLocation: true), new CSharpSuppressionCodeFixProvider());
}
......
......@@ -19,9 +19,9 @@ public class CSharpSuppressionAllCodeTests : AbstractSuppressionAllCodeTests
protected override TestWorkspace CreateWorkspaceFromFile(string definition, ParseOptions parseOptions)
=> TestWorkspace.CreateCSharp(definition, (CSharpParseOptions)parseOptions);
internal override Tuple<Analyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<Analyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<Analyzer, ISuppressionOrConfigurationFixProvider>(new Analyzer(), new CSharpSuppressionCodeFixProvider());
return new Tuple<Analyzer, IConfigurationFixProvider>(new Analyzer(), new CSharpSuppressionCodeFixProvider());
}
[WorkItem(956453, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/956453")]
......
......@@ -23,9 +23,9 @@ public abstract class CSharpFixMultipleSuppressionTests : CSharpSuppressionTests
{
protected override int CodeActionIndex => 0;
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......
......@@ -46,9 +46,9 @@ protected sealed override int CodeActionIndex
public class CompilerDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return Tuple.Create<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
return Tuple.Create<DiagnosticAnalyzer, IConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
......@@ -199,7 +199,7 @@ void Method()
var diagnosticService = new TestDiagnosticAnalyzerService(LanguageNames.CSharp, new CSharpCompilerDiagnosticAnalyzer());
var incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace);
var suppressionProvider = CreateDiagnosticProviderAndFixer(workspace).Item2;
var suppressionProviderFactory = new Lazy<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>(() => suppressionProvider,
var suppressionProviderFactory = new Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>(() => suppressionProvider,
new CodeChangeProviderMetadata("SuppressionProvider", languages: new[] { LanguageNames.CSharp }));
var fixService = new CodeFixService(
workspace.ExportProvider.GetExportedValue<IThreadingContext>(),
......@@ -211,7 +211,7 @@ void Method()
var diagnostics = await diagnosticService.GetDiagnosticsForSpanAsync(document, span);
Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());
var allFixes = (await fixService.GetFixesAsync(document, span, includeSuppressionAndConfigurationFixes: true, cancellationToken: CancellationToken.None))
var allFixes = (await fixService.GetFixesAsync(document, span, includeConfigurationFixes: true, cancellationToken: CancellationToken.None))
.SelectMany(fixCollection => fixCollection.Fixes);
var cs0219Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");
......@@ -422,9 +422,9 @@ class C2 {{ }} /// <summary><see cref=""abc""/></summary>
public class UserHiddenDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CSharpSimplifyTypeNamesDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -473,9 +473,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -535,9 +535,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -600,9 +600,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -652,9 +652,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -690,9 +690,9 @@ protected sealed override int CodeActionIndex
public class CompilerDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return Tuple.Create<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
return Tuple.Create<DiagnosticAnalyzer, IConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
......@@ -713,9 +713,9 @@ void Method()
public class UserHiddenDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
{
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CSharpSimplifyTypeNamesDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -800,9 +800,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -1595,9 +1595,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......@@ -1874,9 +1874,9 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
}
internal override Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider>(
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
}
......
......@@ -478,7 +478,7 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
}
private static bool IsTopLevelSuppressionAction(CodeAction action)
=> action is AbstractTopLevelConfigurationOrSuppressionCodeAction;
=> action is AbstractConfigurationActionWithNestedActions;
private void AddCodeActions(
Workspace workspace, IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
......@@ -619,6 +619,8 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
codeAction: new SolutionChangeAction(EditorFeaturesWpfResources.Configure_or_Suppress_issues, createChangedSolution: _ => null),
nestedActionSets: suppressionSets.ToImmutable());
// Combine the spans and the category of each of the nested suggested actions
// to get the span and category for the new top level suggested action.
var (span, category) = CombineSpansAndCategory(suppressionSets);
var wrappingSet = new SuggestedActionSet(
category,
......@@ -631,6 +633,48 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
suppressionSets.Free();
return sets;
// Local functions
static (Span? span, string category) CombineSpansAndCategory(IEnumerable<SuggestedActionSet> sets)
{
// We are combining the spans and categories of the given set of suggested action sets
// to generate a result span containing the spans of individual suggested action sets and
// a result category which is the maximum severity category amongst the set
int minStart = -1;
int maxEnd = -1;
string category = PredefinedSuggestedActionCategoryNames.CodeFix;
foreach (var set in sets)
{
if (set.ApplicableToSpan.HasValue)
{
var currentStart = set.ApplicableToSpan.Value.Start;
var currentEnd = set.ApplicableToSpan.Value.End;
if (minStart == -1 || currentStart < minStart)
{
minStart = currentStart;
}
if (maxEnd == -1 || currentEnd > maxEnd)
{
maxEnd = currentEnd;
}
}
Debug.Assert(set.CategoryName == PredefinedSuggestedActionCategoryNames.CodeFix ||
set.CategoryName == PredefinedSuggestedActionCategoryNames.ErrorFix);
// If this set contains an error fix, then change the result category to ErrorFix
if (set.CategoryName == PredefinedSuggestedActionCategoryNames.ErrorFix)
{
category = PredefinedSuggestedActionCategoryNames.ErrorFix;
}
}
var combinedSpan = minStart >= 0 ? new Span(minStart, maxEnd) : (Span?)null;
return (combinedSpan, category);
}
}
private static void AddSuggestedActionsSet(
......@@ -649,42 +693,6 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
}
}
private static (Span? span, string category) CombineSpansAndCategory(IEnumerable<SuggestedActionSet> sets)
{
int minStart = -1;
int maxEnd = -1;
string category = PredefinedSuggestedActionCategoryNames.CodeFix;
foreach (var set in sets)
{
if (set.ApplicableToSpan.HasValue)
{
var currentStart = set.ApplicableToSpan.Value.Start;
var currentEnd = set.ApplicableToSpan.Value.End;
if (minStart == -1 || currentStart < minStart)
{
minStart = currentStart;
}
if (maxEnd == -1 || currentEnd > maxEnd)
{
maxEnd = currentEnd;
}
}
Debug.Assert(set.CategoryName == PredefinedSuggestedActionCategoryNames.CodeFix ||
set.CategoryName == PredefinedSuggestedActionCategoryNames.ErrorFix);
if (set.CategoryName == PredefinedSuggestedActionCategoryNames.ErrorFix)
{
category = PredefinedSuggestedActionCategoryNames.ErrorFix;
}
}
var combinedSpan = minStart >= 0 ? new Span(minStart, maxEnd) : (Span?)null;
return (combinedSpan, category);
}
private static string GetFixCategory(DiagnosticSeverity severity)
{
switch (severity)
......
......@@ -43,7 +43,7 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
private readonly ConditionalWeakTable<AnalyzerReference, ProjectCodeFixProvider> _analyzerReferenceToFixersMap;
private readonly ConditionalWeakTable<AnalyzerReference, ProjectCodeFixProvider>.CreateValueCallback _createProjectCodeFixProvider;
private readonly ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<ISuppressionOrConfigurationFixProvider>>> _suppressionOrConfigurationProvidersMap;
private readonly ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<IConfigurationFixProvider>>> _configurationProvidersMap;
private readonly IEnumerable<Lazy<IErrorLoggerService>> _errorLoggers;
private ImmutableDictionary<object, FixAllProviderInfo> _fixAllProviderMap;
......@@ -54,16 +54,16 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
IDiagnosticAnalyzerService service,
[ImportMany]IEnumerable<Lazy<IErrorLoggerService>> loggers,
[ImportMany]IEnumerable<Lazy<CodeFixProvider, CodeChangeProviderMetadata>> fixers,
[ImportMany]IEnumerable<Lazy<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>> suppressionOrConfigurationProviders)
[ImportMany]IEnumerable<Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>> configurationProviders)
: base(threadingContext, assertIsForeground: false)
{
_errorLoggers = loggers;
_diagnosticService = service;
var fixersPerLanguageMap = fixers.ToPerLanguageMapWithMultipleLanguages();
var suppressionOrConfigurationProvidersPerLanguageMap = suppressionOrConfigurationProviders.ToPerLanguageMapWithMultipleLanguages();
var configurationProvidersPerLanguageMap = configurationProviders.ToPerLanguageMapWithMultipleLanguages();
_workspaceFixersMap = GetFixerPerLanguageMap(fixersPerLanguageMap, null);
_suppressionOrConfigurationProvidersMap = GetsuppressionOrConfigurationProvidersPerLanguageMap(suppressionOrConfigurationProvidersPerLanguageMap);
_configurationProvidersMap = GetConfigurationProvidersPerLanguageMap(configurationProvidersPerLanguageMap);
// REVIEW: currently, fixer's priority is statically defined by the fixer itself. might considering making it more dynamic or configurable.
_fixerPriorityMap = GetFixerPriorityPerLanguageMap(fixersPerLanguageMap);
......@@ -142,7 +142,7 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
return null;
}
public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document document, TextSpan range, bool includeSuppressionAndConfigurationFixes, CancellationToken cancellationToken)
public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document document, TextSpan range, bool includeConfigurationFixes, CancellationToken cancellationToken)
{
// REVIEW: this is the first and simplest design. basically, when ctrl+. is pressed, it asks diagnostic service to give back
// current diagnostics for the given span, and it will use that to get fixes. internally diagnostic service will either return cached information
......@@ -151,7 +151,7 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
// this design's weakness is that each side don't have enough information to narrow down works to do. it will most likely always do more works than needed.
// sometimes way more than it is needed. (compilation)
Dictionary<TextSpan, List<DiagnosticData>> aggregatedDiagnostics = null;
foreach (var diagnostic in await _diagnosticService.GetDiagnosticsForSpanAsync(document, range, diagnosticIdOpt: null, includeSuppressionAndConfigurationFixes, cancellationToken).ConfigureAwait(false))
foreach (var diagnostic in await _diagnosticService.GetDiagnosticsForSpanAsync(document, range, diagnosticIdOpt: null, includeConfigurationFixes, cancellationToken).ConfigureAwait(false))
{
if (diagnostic.IsSuppressed)
{
......@@ -202,11 +202,11 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
}
// TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
if (document.Project.Solution.Workspace.Kind != WorkspaceKind.Interactive && includeSuppressionAndConfigurationFixes)
if (document.Project.Solution.Workspace.Kind != WorkspaceKind.Interactive && includeConfigurationFixes)
{
foreach (var spanAndDiagnostic in aggregatedDiagnostics)
{
await AppendSuppressionsAndConfigurationsAsync(
await AppendConfigurationsAsync(
document, spanAndDiagnostic.Key, spanAndDiagnostic.Value,
result, cancellationToken).ConfigureAwait(false);
}
......@@ -303,7 +303,7 @@ public async Task<Document> ApplyCodeFixesForSpecificDiagnosticIdAsync(Document
{
cancellationToken.ThrowIfCancellationRequested();
await AppendFixesOrSuppressionsAsync(
await AppendFixesOrConfigurationsAsync(
document, span, diagnostics, fixAllForInSpan, result, fixer,
hasFix: d => this.GetFixableDiagnosticIds(fixer, extensionManager).Contains(d.Id),
getFixes: dxs =>
......@@ -349,18 +349,18 @@ public async Task<Document> ApplyCodeFixesForSpecificDiagnosticIdAsync(Document
return fixes.ToImmutableAndFree();
}
private async Task AppendSuppressionsAndConfigurationsAsync(
private async Task AppendConfigurationsAsync(
Document document, TextSpan span, IEnumerable<DiagnosticData> diagnostics,
ArrayBuilder<CodeFixCollection> result, CancellationToken cancellationToken)
{
if (!_suppressionOrConfigurationProvidersMap.TryGetValue(document.Project.Language, out var lazySuppressionOrConfigurationProviders) || lazySuppressionOrConfigurationProviders.Value == null)
if (!_configurationProvidersMap.TryGetValue(document.Project.Language, out var lazyConfigurationProviders) || lazyConfigurationProviders.Value == null)
{
return;
}
foreach (var provider in lazySuppressionOrConfigurationProviders.Value)
foreach (var provider in lazyConfigurationProviders.Value)
{
await AppendFixesOrSuppressionsAsync(
await AppendFixesOrConfigurationsAsync(
document, span, diagnostics, fixAllForInSpan: false, result, provider,
hasFix: d => provider.IsFixableDiagnostic(d),
getFixes: dxs => provider.GetFixesAsync(
......@@ -369,7 +369,7 @@ public async Task<Document> ApplyCodeFixesForSpecificDiagnosticIdAsync(Document
}
}
private async Task AppendFixesOrSuppressionsAsync<TCodeFixProvider>(
private async Task AppendFixesOrConfigurationsAsync<TCodeFixProvider>(
Document document,
TextSpan span,
IEnumerable<DiagnosticData> diagnosticsWithSameSpan,
......@@ -407,7 +407,7 @@ await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
var supportedScopes = ImmutableArray<FixAllScope>.Empty;
if (fixAllProviderInfo != null)
{
var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionOrConfigurationFixProvider)fixer, diagnostics.Select(d => d.Id));
var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((IConfigurationFixProvider)fixer, diagnostics.Select(d => d.Id));
var diagnosticIds = diagnostics.Where(fixAllProviderInfo.CanBeFixed)
.Select(d => d.Id)
......@@ -438,14 +438,14 @@ await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
/// <summary> Looks explicitly for an <see cref="AbstractSuppressionCodeFixProvider"/>.</summary>
public CodeFixProvider GetSuppressionFixer(string language, IEnumerable<string> diagnosticIds)
{
if (!_suppressionOrConfigurationProvidersMap.TryGetValue(language, out var lazySuppressionOrConfigurationProviders) ||
lazySuppressionOrConfigurationProviders.Value.IsDefault)
if (!_configurationProvidersMap.TryGetValue(language, out var lazyConfigurationProviders) ||
lazyConfigurationProviders.Value.IsDefault)
{
return null;
}
// Explicitly looks for an AbstractSuppressionCodeFixProvider
var fixer = lazySuppressionOrConfigurationProviders.Value.OfType<AbstractSuppressionCodeFixProvider>().FirstOrDefault();
var fixer = lazyConfigurationProviders.Value.OfType<AbstractSuppressionCodeFixProvider>().FirstOrDefault();
if (fixer == null)
{
return null;
......@@ -496,11 +496,11 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
hasAnySharedFixer = workspaceFixers.Any();
}
var hasSuppressionOrConfigurationFixer =
_suppressionOrConfigurationProvidersMap.TryGetValue(document.Project.Language, out var lazySuppressionOrConfigurationProviders) &&
!lazySuppressionOrConfigurationProviders.Value.IsDefaultOrEmpty;
var hasConfigurationFixer =
_configurationProvidersMap.TryGetValue(document.Project.Language, out var lazyConfigurationProviders) &&
!lazyConfigurationProviders.Value.IsDefaultOrEmpty;
if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasSuppressionOrConfigurationFixer)
if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasConfigurationFixer)
{
return false;
}
......@@ -518,11 +518,11 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
var dx = await diagnostic.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false);
if (hasSuppressionOrConfigurationFixer)
if (hasConfigurationFixer)
{
foreach (var lazySuppressionOrConfigurationProvider in lazySuppressionOrConfigurationProviders.Value)
foreach (var lazyConfigurationProvider in lazyConfigurationProviders.Value)
{
if (lazySuppressionOrConfigurationProvider.IsFixableDiagnostic(dx))
if (lazyConfigurationProvider.IsFixableDiagnostic(dx))
{
return true;
}
......@@ -669,23 +669,28 @@ private static ImmutableArray<string> GetAndTestFixableDiagnosticIds(CodeFixProv
return fixerMap;
}
private static ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<ISuppressionOrConfigurationFixProvider>>> GetsuppressionOrConfigurationProvidersPerLanguageMap(
Dictionary<LanguageKind, List<Lazy<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>>> suppressionOrConfigurationProvidersPerLanguage)
private static ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<IConfigurationFixProvider>>> GetConfigurationProvidersPerLanguageMap(
Dictionary<LanguageKind, List<Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>>> configurationProvidersPerLanguage)
{
var suppressionOrConfigurationFixerMap = ImmutableDictionary.Create<LanguageKind, Lazy<ImmutableArray<ISuppressionOrConfigurationFixProvider>>>();
foreach (var languageKindAndFixers in suppressionOrConfigurationProvidersPerLanguage)
var configurationFixerMap = ImmutableDictionary.Create<LanguageKind, Lazy<ImmutableArray<IConfigurationFixProvider>>>();
foreach (var languageKindAndFixers in configurationProvidersPerLanguage)
{
var builder = ArrayBuilder<ISuppressionOrConfigurationFixProvider>.GetInstance();
foreach (var languageKindAndFixersValue in languageKindAndFixers.Value)
var lazyConfigurationFixers = new Lazy<ImmutableArray<IConfigurationFixProvider>>(() => GetConfigurationFixProviders(languageKindAndFixers.Value));
configurationFixerMap = configurationFixerMap.Add(languageKindAndFixers.Key, lazyConfigurationFixers);
}
return configurationFixerMap;
static ImmutableArray<IConfigurationFixProvider> GetConfigurationFixProviders(List<Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>> languageKindAndFixers)
{
var builder = ArrayBuilder<IConfigurationFixProvider>.GetInstance();
foreach (var languageKindAndFixersValue in languageKindAndFixers)
{
builder.Add(languageKindAndFixersValue.Value);
}
var lazySuppressionOrConfigurationFixers = new Lazy<ImmutableArray<ISuppressionOrConfigurationFixProvider>>(() => builder.ToImmutableAndFree());
suppressionOrConfigurationFixerMap = suppressionOrConfigurationFixerMap.Add(languageKindAndFixers.Key, lazySuppressionOrConfigurationFixers);
return builder.ToImmutableAndFree();
}
return suppressionOrConfigurationFixerMap;
}
private static ImmutableDictionary<LanguageKind, Lazy<ImmutableDictionary<CodeFixProvider, int>>> GetFixerPriorityPerLanguageMap(
......
......@@ -39,7 +39,7 @@ public async Task TestGetFirstDiagnosticWithFixAsync()
var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => workspace.Services.GetService<IErrorLoggerService>()));
var fixService = new CodeFixService(
workspace.ExportProvider.GetExportedValue<IThreadingContext>(),
diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>>());
diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>>());
var incrementalAnalyzer = (IIncrementalAnalyzerProvider)diagnosticService;
......@@ -100,7 +100,7 @@ private async Task GetDefaultFixesAsync(CodeFixProvider codefix)
using (var workspace = tuple.Item1)
{
GetDocumentAndExtensionManager(tuple.Item2, workspace, out var document, out var extensionManager);
var fixes = await tuple.Item3.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionAndConfigurationFixes: true, cancellationToken: CancellationToken.None);
var fixes = await tuple.Item3.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: true, cancellationToken: CancellationToken.None);
Assert.True(((TestErrorLogger)tuple.Item4).Messages.Count == 1);
Assert.True(((TestErrorLogger)tuple.Item4).Messages.TryGetValue(codefix.GetType().Name, out var message));
}
......@@ -117,7 +117,7 @@ private async Task GetAddedFixesAsync(CodeFixProvider codefix)
var reference = new MockAnalyzerReference(codefix);
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
document = project.Documents.Single();
var fixes = await tuple.Item3.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionAndConfigurationFixes: true, cancellationToken: CancellationToken.None);
var fixes = await tuple.Item3.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: true, cancellationToken: CancellationToken.None);
Assert.True(extensionManager.IsDisabled(codefix));
Assert.False(extensionManager.IsIgnored(codefix));
......@@ -149,7 +149,7 @@ private async Task GetFirstDiagnosticWithFixAsync(CodeFixProvider codefix)
var errorLogger = logger.First().Value;
var fixService = new CodeFixService(
workspace.ExportProvider.GetExportedValue<IThreadingContext>(),
diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>>());
diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>>());
return Tuple.Create(workspace, diagnosticService, fixService, errorLogger);
}
......
......@@ -54,7 +54,7 @@ public void TestNoCyclesInSuppressionProviders()
// This test will fail if a cycle is detected in the ordering of our suppression fix providers.
// If this test fails, you can break the cycle by inspecting and fixing up the contents of
// any [ExtensionOrder()] attributes present on our suppression fix providers.
var providers = ExportProvider.GetExports<ISuppressionOrConfigurationFixProvider, CodeChangeProviderMetadata>();
var providers = ExportProvider.GetExports<IConfigurationFixProvider, CodeChangeProviderMetadata>();
var providersPerLanguage = providers.ToPerLanguageMapWithMultipleLanguages();
var csharpProviders = providersPerLanguage[LanguageNames.CSharp];
......
......@@ -51,7 +51,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
{New Lazy(Of CodeFixProvider, Mef.CodeChangeProviderMetadata)(
Function() workspaceCodeFixProvider,
New Mef.CodeChangeProviderMetadata(New Dictionary(Of String, Object)() From {{"Name", "C#"}, {"Languages", {LanguageNames.CSharp}}}))},
SpecializedCollections.EmptyEnumerable(Of Lazy(Of ISuppressionOrConfigurationFixProvider, Mef.CodeChangeProviderMetadata)))
SpecializedCollections.EmptyEnumerable(Of Lazy(Of IConfigurationFixProvider, Mef.CodeChangeProviderMetadata)))
' Verify available diagnostics
Dim document = project.Documents.Single()
......@@ -63,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
' Verify available codefix with a global fixer
Dim fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
includeSuppressionAndConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
' Verify available codefix with a global fixer + a project fixer
......@@ -76,7 +76,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
includeSuppressionAndConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(1, fixes.Count())
' Remove a project analyzer
......@@ -84,7 +84,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
includeSuppressionAndConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
End Using
End Function
......@@ -115,7 +115,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
{New Lazy(Of CodeFixProvider, Mef.CodeChangeProviderMetadata)(
Function() workspaceCodeFixProvider,
New Mef.CodeChangeProviderMetadata(New Dictionary(Of String, Object)() From {{"Name", "C#"}, {"Languages", {LanguageNames.CSharp}}}))},
SpecializedCollections.EmptyEnumerable(Of Lazy(Of ISuppressionOrConfigurationFixProvider, Mef.CodeChangeProviderMetadata)))
SpecializedCollections.EmptyEnumerable(Of Lazy(Of IConfigurationFixProvider, Mef.CodeChangeProviderMetadata)))
' Verify available diagnostics
Dim document = project.Documents.Single()
......@@ -127,7 +127,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
' Verify no codefix with a global fixer
Dim fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
includeSuppressionAndConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
' Verify no codefix with a global fixer + a project fixer
......@@ -140,7 +140,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
includeSuppressionAndConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
End Using
End Function
......
......@@ -523,7 +523,7 @@ private static async Task VerifyAgainstWorkspaceDefinitionAsync(string expectedT
return;
// Local functions.
void VerifyExpectedDocumentText(string expected, string actual)
static void VerifyExpectedDocumentText(string expected, string actual)
{
if (expected == "")
{
......
......@@ -23,7 +23,7 @@ public abstract class AbstractSuppressionAllCodeTests : IEqualityComparer<Diagno
{
protected abstract TestWorkspace CreateWorkspaceFromFile(string definition, ParseOptions parseOptions);
internal abstract Tuple<Analyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace);
internal abstract Tuple<Analyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace);
protected Task TestPragmaAsync(string code, ParseOptions options, Func<string, bool> verifier)
{
......
......@@ -27,11 +27,11 @@ protected Task TestAsync(string initial, string expected)
return TestAsync(initial, expected, parseOptions: null, index: CodeActionIndex);
}
internal abstract Tuple<DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace);
internal abstract Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace);
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
{
return actions.SelectMany(a => a is AbstractTopLevelConfigurationOrSuppressionCodeAction
return actions.SelectMany(a => a is AbstractConfigurationActionWithNestedActions
? a.NestedCodeActions
: ImmutableArray.Create(a)).ToImmutableArray();
}
......
......@@ -26,8 +26,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Suppre
Return TestOptions.Script
End Function
Friend Overrides Function CreateDiagnosticProviderAndFixer(ByVal workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New VisualBasicUseObjectInitializerDiagnosticAnalyzer(), New ConfigureSeverityLevelCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(ByVal workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New VisualBasicUseObjectInitializerDiagnosticAnalyzer(), New ConfigureSeverityLevelCodeFixProvider())
End Function
Public Class NoneConfigurationTests
......
......@@ -49,8 +49,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Suppre
Return TestOptions.Script
End Function
Friend Overrides Function CreateDiagnosticProviderAndFixer(ByVal workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New CustomDiagnosticAnalyzer(), New ConfigureSeverityLevelCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(ByVal workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New CustomDiagnosticAnalyzer(), New ConfigureSeverityLevelCodeFixProvider())
End Function
Public Class NoneConfigurationTests
......
......@@ -15,8 +15,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Suppre
Return TestWorkspace.CreateVisualBasic(definition, DirectCast(parseOptions, VisualBasicParseOptions))
End Function
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of Analyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of Analyzer, ISuppressionOrConfigurationFixProvider)(New Analyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of Analyzer, IConfigurationFixProvider)
Return New Tuple(Of Analyzer, IConfigurationFixProvider)(New Analyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......
......@@ -48,8 +48,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Suppre
Public Class CompilerDiagnosticSuppressionTests
Inherits VisualBasicPragmaWarningDisableSuppressionTests
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(Nothing, New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, IConfigurationFixProvider)(Nothing, New VisualBasicSuppressionCodeFixProvider())
End Function
<WorkItem(730770, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/730770")>
......@@ -595,8 +595,8 @@ Class C3 : End Class"
Public Class UserHiddenDiagnosticSuppressionTests
Inherits VisualBasicPragmaWarningDisableSuppressionTests
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New VisualBasicSimplifyTypeNamesDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New VisualBasicSimplifyTypeNamesDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......@@ -638,8 +638,8 @@ End Class]]>
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
......@@ -712,8 +712,8 @@ End Class]]>
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<WorkItem(730770, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/730770")>
......@@ -756,8 +756,8 @@ End Class]]>
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<WorkItem(730770, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/730770")>
......@@ -820,8 +820,8 @@ End Class]]>
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......@@ -875,8 +875,8 @@ End Class]]>
Public Class CompilerDiagnosticSuppressionTests
Inherits VisualBasicGlobalSuppressMessageSuppressionTests
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(Nothing, New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, IConfigurationFixProvider)(Nothing, New VisualBasicSuppressionCodeFixProvider())
End Function
......@@ -897,8 +897,8 @@ End Class]]>
Public Class UserHiddenDiagnosticSuppressionTests
Inherits VisualBasicGlobalSuppressMessageSuppressionTests
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New VisualBasicSimplifyTypeNamesDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New VisualBasicSimplifyTypeNamesDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......@@ -967,8 +967,8 @@ End Class]]>
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......@@ -1625,8 +1625,8 @@ End Class
End Sub
End Class
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, ISuppressionOrConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, IConfigurationFixProvider)(New UserDiagnosticAnalyzer(), New VisualBasicSuppressionCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
......
......@@ -15,7 +15,7 @@
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.Suppression
{
[ExportSuppressionFixProvider(PredefinedCodeFixProviderNames.Suppression, LanguageNames.CSharp), Shared]
[ExportConfigurationFixProvider(PredefinedCodeFixProviderNames.Suppression, LanguageNames.CSharp), Shared]
internal class CSharpSuppressionCodeFixProvider : AbstractSuppressionCodeFixProvider
{
[ImportingConstructor]
......
......@@ -5,9 +5,14 @@
namespace Microsoft.CodeAnalysis.CodeFixes
{
internal abstract class AbstractTopLevelConfigurationOrSuppressionCodeAction : CodeAction.CodeActionWithNestedActions
/// <summary>
/// Represents a configuration code action with nested actions registered by individual <see cref="IConfigurationFixProvider"/>s.
/// Note that the code fix/light bulb engine groups all such <see cref="AbstractConfigurationActionWithNestedActions"/> from different providers
/// into another top level suggested action to avoid light bulb clutter. This topmost suggested action is *not* represented by this code action.
/// </summary>
internal abstract class AbstractConfigurationActionWithNestedActions : CodeAction.CodeActionWithNestedActions
{
protected AbstractTopLevelConfigurationOrSuppressionCodeAction(ImmutableArray<CodeAction> nestedActions, string title)
protected AbstractConfigurationActionWithNestedActions(ImmutableArray<CodeAction> nestedActions, string title)
: base(title, nestedActions, isInlinable: false)
{
}
......
......@@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.CodeFixes
{
/// <summary>
/// Represents a collection of <see cref="CodeFix"/>es supplied by a given fix provider
/// (such as <see cref="CodeFixProvider"/> or <see cref="ISuppressionOrConfigurationFixProvider"/>).
/// (such as <see cref="CodeFixProvider"/> or <see cref="IConfigurationFixProvider"/>).
/// </summary>
internal class CodeFixCollection
{
......
......@@ -14,7 +14,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Configuration
{
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : IConfigurationFixProvider
{
private sealed partial class ConfigurationUpdater
{
......@@ -57,14 +57,14 @@ private sealed partial class ConfigurationUpdater
/// so that the severity of the given <paramref name="diagnostic"/> is configured to be the given
/// <paramref name="severity"/>.
/// </summary>
public static async Task<Solution> ConfigureEditorConfig(
public static Task<Solution> ConfigureEditorConfig(
string severity,
Diagnostic diagnostic,
Project project,
CancellationToken cancellationToken)
{
var updater = new ConfigurationUpdater(severity, diagnostic, project, cancellationToken);
return await updater.Configure().ConfigureAwait(false);
return updater.Configure();
}
private async Task<Solution> Configure()
......@@ -72,40 +72,30 @@ private async Task<Solution> Configure()
var solution = _project.Solution;
// Find existing .editorconfig or generate a new one if none exists.
var editorConfigDocument = FindOrGenerateEditorConfig(ref solution);
var editorConfigDocument = FindOrGenerateEditorConfig(solution);
if (editorConfigDocument == null)
{
return solution;
}
var result = await editorConfigDocument.GetTextAsync(_cancellationToken).ConfigureAwait(false);
var headers = new Dictionary<string, TextLine>();
solution = editorConfigDocument.Project.Solution;
// For option based code style diagnostic, try to find the .editorconfig key-value pair for the
// option setting.
var (optionNameOpt, optionValueOpt) = FindEditorConfigOptionKeyValueForRule();
// Check if an entry to configure the rule severity already exists in the .editorconfig file.
// If it does, we update the existing entry with the new severity.
var configureExistingRuleText = CheckIfRuleExistsAndReplaceInFile(optionNameOpt, result, headers);
if (configureExistingRuleText != null)
{
return solution.WithAnalyzerConfigDocumentText(editorConfigDocument.Id, configureExistingRuleText);
}
var headers = new Dictionary<string, TextLine>();
var originalText = await editorConfigDocument.GetTextAsync(_cancellationToken).ConfigureAwait(false);
// We did not find any existing entry in the in the .editorconfig file to configure rule severity.
// So we add a new configuration entry to the .editorconfig file.
var addMissingRuleText = AddMissingRule(optionNameOpt, optionValueOpt, result, headers);
if (addMissingRuleText != null)
{
return solution.WithAnalyzerConfigDocumentText(editorConfigDocument.Id, addMissingRuleText);
}
// Compute the updated text for analyzer config document.
var newText = GetNewAnalyzerConfigDocumentText(originalText, headers, optionNameOpt, optionValueOpt);
// Bail out and return the old solution for error cases.
return solution;
return newText != null
? solution.WithAnalyzerConfigDocumentText(editorConfigDocument.Id, newText)
: solution;
}
private AnalyzerConfigDocument FindOrGenerateEditorConfig(ref Solution solution)
private AnalyzerConfigDocument FindOrGenerateEditorConfig(Solution solution)
{
if (_project.AnalyzerConfigDocuments.Any())
{
......@@ -149,8 +139,8 @@ private AnalyzerConfigDocument FindOrGenerateEditorConfig(ref Solution solution)
var newEditorConfigPath = PathUtilities.CombineAbsoluteAndRelativePaths(projectFilePath, ".editorconfig");
var id = DocumentId.CreateNewId(_project.Id);
var documentInfo = DocumentInfo.Create(id, ".editorconfig", filePath: newEditorConfigPath);
solution = solution.AddAnalyzerConfigDocuments(ImmutableArray.Create(documentInfo));
return solution.GetProject(_project.Id).GetAnalyzerConfigDocument(id);
var newSolution = solution.AddAnalyzerConfigDocuments(ImmutableArray.Create(documentInfo));
return newSolution.GetProject(_project.Id).GetAnalyzerConfigDocument(id);
}
private (string optionName, string optionValue) FindEditorConfigOptionKeyValueForRule()
......@@ -183,6 +173,25 @@ private AnalyzerConfigDocument FindOrGenerateEditorConfig(ref Solution solution)
return (null, null);
}
private SourceText GetNewAnalyzerConfigDocumentText(
SourceText originalText,
Dictionary<string, TextLine> headers,
string optionNameOpt,
string optionValueOpt)
{
// Check if an entry to configure the rule severity already exists in the .editorconfig file.
// If it does, we update the existing entry with the new severity.
var configureExistingRuleText = CheckIfRuleExistsAndReplaceInFile(optionNameOpt, originalText, headers);
if (configureExistingRuleText != null)
{
return configureExistingRuleText;
}
// We did not find any existing entry in the in the .editorconfig file to configure rule severity.
// So we add a new configuration entry to the .editorconfig file.
return AddMissingRule(optionNameOpt, optionValueOpt, originalText, headers);
}
private SourceText CheckIfRuleExistsAndReplaceInFile(
string nameOpt,
SourceText result,
......
......@@ -5,9 +5,9 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Configuration
{
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : IConfigurationFixProvider
{
private sealed class TopLevelConfigureSeverityCodeAction : AbstractTopLevelConfigurationOrSuppressionCodeAction
private sealed class TopLevelConfigureSeverityCodeAction : AbstractConfigurationActionWithNestedActions
{
public TopLevelConfigureSeverityCodeAction(Diagnostic diagnostic, ImmutableArray<CodeAction> nestedActions)
: base(nestedActions, string.Format(FeaturesResources.Configure_0_severity, diagnostic.Id))
......
......@@ -9,15 +9,24 @@
using Microsoft.CodeAnalysis.CodeFixes.Suppression;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.CodeActions.CodeAction;
namespace Microsoft.CodeAnalysis.CodeFixes.Configuration
{
[ExportSuppressionFixProvider(PredefinedCodeFixProviderNames.ConfigureSeverity, LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
[ExportConfigurationFixProvider(PredefinedCodeFixProviderNames.ConfigureSeverity, LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
[ExtensionOrder(Before = PredefinedCodeFixProviderNames.Suppression)]
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : IConfigurationFixProvider
{
private static readonly ImmutableArray<(string name, string value)> s_editorConfigSeverityStrings =
ImmutableArray.Create(
(nameof(EditorConfigSeverityStrings.None), EditorConfigSeverityStrings.None),
(nameof(EditorConfigSeverityStrings.Silent), EditorConfigSeverityStrings.Silent),
(nameof(EditorConfigSeverityStrings.Suggestion), EditorConfigSeverityStrings.Suggestion),
(nameof(EditorConfigSeverityStrings.Warning), EditorConfigSeverityStrings.Warning),
(nameof(EditorConfigSeverityStrings.Error), EditorConfigSeverityStrings.Error));
// We only offer fix for configurable diagnostics.
// Also skip suppressed diagnostics defensively, though the code fix engine should ideally never call us for suppressed diagnostics.
public bool IsFixableDiagnostic(Diagnostic diagnostic)
=> !diagnostic.IsSuppressed && !SuppressionHelpers.IsNotConfigurableDiagnostic(diagnostic);
......@@ -32,38 +41,20 @@ public Task<ImmutableArray<CodeFix>> GetFixesAsync(Project project, IEnumerable<
private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
var result = ArrayBuilder<CodeFix>.GetInstance();
foreach (var diagnostic in diagnostics)
{
nestedActions.Add(
new SolutionChangeAction(
"None",
solution => ConfigurationUpdater.ConfigureEditorConfig(EditorConfigSeverityStrings.None, diagnostic, project, cancellationToken)));
nestedActions.Add(
new SolutionChangeAction(
"Silent",
solution => ConfigurationUpdater.ConfigureEditorConfig(EditorConfigSeverityStrings.Silent, diagnostic, project, cancellationToken)));
nestedActions.Add(
new SolutionChangeAction(
"Suggestion",
solution => ConfigurationUpdater.ConfigureEditorConfig(EditorConfigSeverityStrings.Suggestion, diagnostic, project, cancellationToken)));
nestedActions.Add(
new SolutionChangeAction(
"Warning",
solution => ConfigurationUpdater.ConfigureEditorConfig(EditorConfigSeverityStrings.Warning, diagnostic, project, cancellationToken)));
nestedActions.Add(
new SolutionChangeAction(
"Error",
solution => ConfigurationUpdater.ConfigureEditorConfig(EditorConfigSeverityStrings.Error, diagnostic, project, cancellationToken)));
var codeAction = new TopLevelConfigureSeverityCodeAction(diagnostic, nestedActions.ToImmutable());
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
foreach (var (name, value) in s_editorConfigSeverityStrings)
{
nestedActions.Add(
new SolutionChangeAction(name, solution => ConfigurationUpdater.ConfigureEditorConfig(value, diagnostic, project, cancellationToken)));
}
var codeAction = new TopLevelConfigureSeverityCodeAction(diagnostic, nestedActions.ToImmutableAndFree());
result.Add(new CodeFix(project, codeAction, diagnostic));
nestedActions.Clear();
}
nestedActions.Free();
return result.ToImmutableAndFree();
}
}
......
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal abstract class AbstractGlobalSuppressMessageCodeAction : AbstractSuppressionCodeAction
{
......
......@@ -6,7 +6,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
private class SuppressionFixAllProvider : FixAllProvider
{
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal sealed class GlobalSuppressMessageCodeAction : AbstractGlobalSuppressMessageCodeAction
{
......
......@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal sealed class GlobalSuppressMessageFixAllCodeAction : AbstractGlobalSuppressMessageCodeAction
{
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal sealed class LocalSuppressMessageCodeAction : AbstractSuppressionCodeAction
{
......
......@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
/// <summary>
/// Batch fixer for pragma suppress code action.
......
......@@ -6,7 +6,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal sealed class PragmaWarningCodeAction : AbstractSuppressionCodeAction, IPragmaBasedCodeAction
{
......
......@@ -13,7 +13,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal abstract partial class RemoveSuppressionCodeAction
{
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
/// <summary>
/// Base type for remove suppression code actions.
......
......@@ -6,7 +6,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal abstract partial class RemoveSuppressionCodeAction
{
......
......@@ -11,7 +11,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
internal abstract partial class RemoveSuppressionCodeAction
{
......
......@@ -15,7 +15,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal abstract partial class AbstractSuppressionCodeFixProvider : ISuppressionOrConfigurationFixProvider
internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurationFixProvider
{
public const string SuppressMessageAttributeName = "System.Diagnostics.CodeAnalysis.SuppressMessage";
private const string s_globalSuppressionsFileName = "GlobalSuppressions";
......
......@@ -3,17 +3,17 @@
using System;
using System.Composition;
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
namespace Microsoft.CodeAnalysis.CodeFixes
{
/// <summary>
/// Use this attribute to declare a <see cref="ISuppressionOrConfigurationFixProvider"/> implementation so that it can be discovered by the host.
/// Use this attribute to declare a <see cref="IConfigurationFixProvider"/> implementation so that it can be discovered by the host.
/// </summary>
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
internal class ExportSuppressionFixProviderAttribute : ExportAttribute
internal class ExportConfigurationFixProviderAttribute : ExportAttribute
{
/// <summary>
/// The name of the <see cref="ISuppressionOrConfigurationFixProvider"/>.
/// The name of the <see cref="IConfigurationFixProvider"/>.
/// </summary>
public string Name { get; }
......@@ -22,10 +22,10 @@ internal class ExportSuppressionFixProviderAttribute : ExportAttribute
/// </summary>
public string[] Languages { get; }
public ExportSuppressionFixProviderAttribute(
public ExportConfigurationFixProviderAttribute(
string name,
params string[] languages)
: base(typeof(ISuppressionOrConfigurationFixProvider))
: base(typeof(IConfigurationFixProvider))
{
if (languages == null)
{
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
{
internal sealed class TopLevelSuppressionCodeAction : AbstractTopLevelConfigurationOrSuppressionCodeAction
internal sealed class TopLevelSuppressionCodeAction : AbstractConfigurationActionWithNestedActions
{
public TopLevelSuppressionCodeAction(Diagnostic diagnostic, ImmutableArray<NestedSuppressionCodeAction> nestedActions)
: base(ImmutableArray<CodeAction>.CastUp(nestedActions), string.Format(FeaturesResources.Suppress_0, diagnostic.Id))
......
......@@ -10,32 +10,32 @@ namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
internal sealed class WrapperCodeFixProvider : CodeFixProvider
{
private readonly ImmutableArray<string> _originalDiagnosticIds;
private readonly ISuppressionOrConfigurationFixProvider _suppressionOrConfigurationFixProvider;
private readonly IConfigurationFixProvider _suppressionFixProvider;
public WrapperCodeFixProvider(ISuppressionOrConfigurationFixProvider suppressionFixProvider, IEnumerable<string> diagnosticIds)
public WrapperCodeFixProvider(IConfigurationFixProvider suppressionFixProvider, IEnumerable<string> diagnosticIds)
{
_suppressionOrConfigurationFixProvider = suppressionFixProvider;
_suppressionFixProvider = suppressionFixProvider;
_originalDiagnosticIds = diagnosticIds.Distinct().ToImmutableArray();
}
public ISuppressionOrConfigurationFixProvider SuppressionFixProvider => _suppressionOrConfigurationFixProvider;
public IConfigurationFixProvider SuppressionFixProvider => _suppressionFixProvider;
public override ImmutableArray<string> FixableDiagnosticIds => _originalDiagnosticIds;
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostics = context.Diagnostics.Where(_suppressionOrConfigurationFixProvider.IsFixableDiagnostic);
var diagnostics = context.Diagnostics.Where(_suppressionFixProvider.IsFixableDiagnostic);
var documentDiagnostics = diagnostics.Where(d => d.Location.IsInSource).ToImmutableArray();
if (!documentDiagnostics.IsEmpty)
{
var suppressionFixes = await _suppressionOrConfigurationFixProvider.GetFixesAsync(context.Document, context.Span, documentDiagnostics, context.CancellationToken).ConfigureAwait(false);
var suppressionFixes = await _suppressionFixProvider.GetFixesAsync(context.Document, context.Span, documentDiagnostics, context.CancellationToken).ConfigureAwait(false);
RegisterSuppressionFixes(context, suppressionFixes);
}
var projectDiagnostics = diagnostics.Where(d => !d.Location.IsInSource).ToImmutableArray();
if (!projectDiagnostics.IsEmpty)
{
var suppressionFixes = await _suppressionOrConfigurationFixProvider.GetFixesAsync(context.Project, projectDiagnostics, context.CancellationToken).ConfigureAwait(false);
var suppressionFixes = await _suppressionFixProvider.GetFixesAsync(context.Project, projectDiagnostics, context.CancellationToken).ConfigureAwait(false);
RegisterSuppressionFixes(context, suppressionFixes);
}
}
......@@ -53,7 +53,7 @@ private static void RegisterSuppressionFixes(CodeFixContext context, ImmutableAr
public override FixAllProvider GetFixAllProvider()
{
return _suppressionOrConfigurationFixProvider.GetFixAllProvider();
return _suppressionFixProvider.GetFixAllProvider();
}
}
}
......@@ -31,7 +31,10 @@ public static void AddOptionMapping(string diagnosticId, IOption option, string
? s_diagnosticIdToLanguageSpecificOptionsMap.GetOrAdd(languageOpt, _ => new ConcurrentDictionary<string, IOption>())
: s_diagnosticIdToOptionMap;
// Verify that the option is either being added for the first time, or the existing option is already the same.
// Latter can happen in tests as we re-instantiate the analyzer for every test, which attempts to add the mapping every time.
Debug.Assert(!map.TryGetValue(diagnosticId, out var existingOption) || option == existingOption);
map.TryAdd(diagnosticId, option);
}
}
......
......@@ -10,7 +10,7 @@ Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.Suppression
<ExportSuppressionFixProvider(PredefinedCodeFixProviderNames.Suppression, LanguageNames.VisualBasic), [Shared]>
<ExportConfigurationFixProvider(PredefinedCodeFixProviderNames.Suppression, LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicSuppressionCodeFixProvider
Inherits AbstractSuppressionCodeFixProvider
......
......@@ -33,7 +33,7 @@ public static FixAllProviderInfo Create(object provider)
return CreateWithCodeFixer(codeFixProvider);
}
return CreateWithSuppressionFixer((ISuppressionOrConfigurationFixProvider)provider);
return CreateWithSuppressionFixer((IConfigurationFixProvider)provider);
}
/// <summary>
......@@ -65,7 +65,7 @@ private static FixAllProviderInfo CreateWithCodeFixer(CodeFixProvider provider)
/// <summary>
/// Gets an optional <see cref="FixAllProviderInfo"/> for the given suppression fix provider.
/// </summary>
private static FixAllProviderInfo CreateWithSuppressionFixer(ISuppressionOrConfigurationFixProvider provider)
private static FixAllProviderInfo CreateWithSuppressionFixer(IConfigurationFixProvider provider)
{
var fixAllProvider = provider.GetFixAllProvider();
if (fixAllProvider == null)
......@@ -109,7 +109,7 @@ private class SuppressionFixerFixAllProviderInfo : FixAllProviderInfo
public SuppressionFixerFixAllProviderInfo(
FixAllProvider fixAllProvider,
ISuppressionOrConfigurationFixProvider suppressionFixer,
IConfigurationFixProvider suppressionFixer,
ImmutableArray<FixAllScope> supportedScopes)
: base(fixAllProvider, supportedScopes)
{
......
......@@ -9,7 +9,10 @@
namespace Microsoft.CodeAnalysis.CodeFixes
{
internal interface ISuppressionOrConfigurationFixProvider
/// <summary>
/// Provides suppression or configuration code fixes.
/// </summary>
internal interface IConfigurationFixProvider
{
/// <summary>
/// Returns true if the given diagnostic can be configured, suppressed or unsuppressed by this provider.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册