提交 e5f9839b 编写于 作者: M Manish Vasani

Add lightbulb actions to bulk configure default severity for analyzer diagnostics

Fixes #41910
上级 7aa825c6
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.Configuration.ConfigureSeverity;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.Configuration.ConfigureSeverity
{
public abstract partial class AllAnalyzersSeverityConfigurationTests : AbstractSuppressionDiagnosticTest
{
private sealed class CustomDiagnosticAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
id: "XYZ0001",
title: "Title",
messageFormat: "Message",
category: "CustomCategory",
defaultSeverity: DiagnosticSeverity.Info,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
c => c.ReportDiagnostic(Diagnostic.Create(Rule, c.Node.GetLocation())),
SyntaxKind.ClassDeclaration);
}
}
protected override TestWorkspace CreateWorkspaceFromFile(string initialMarkup, TestParameters parameters)
=> TestWorkspace.CreateCSharp(initialMarkup, parameters.parseOptions, parameters.compilationOptions);
protected override string GetLanguage() => LanguageNames.CSharp;
protected override ParseOptions GetScriptOptions() => Options.Script;
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CustomDiagnosticAnalyzer(), new ConfigureSeverityLevelCodeFixProvider());
}
public sealed class SilentConfigurationTests : AllAnalyzersSeverityConfigurationTests
{
/// <summary>
/// Code action ranges:
/// 1. (0 - 4) => Code actions for diagnostic "ID" configuration with severity None, Silent, Suggestion, Warning and Error
/// 2. (5 - 9) => Code actions for diagnostic "Category" configuration with severity None, Silent, Suggestion, Warning and Error
/// 3. (10 - 14) => Code actions for all analyzer diagnostics configuration with severity None, Silent, Suggestion, Warning and Error
/// </summary>
protected override int CodeActionIndex => 11;
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_Empty()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig""></AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RuleExists()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_analyzer_diagnostic.severity = suggestion # Comment
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_analyzer_diagnostic.severity = silent # Comment
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RuleIdEntryExists()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_diagnostic.XYZ0001.severity = suggestion # Comment1
dotnet_diagnostic.category-CustomCategory.severity = warning # Comment2
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_diagnostic.XYZ0001.severity = suggestion # Comment1
dotnet_diagnostic.category-CustomCategory.severity = warning # Comment2
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_InvalidHeader()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.vb]
dotnet_analyzer_diagnostic.severity = suggestion
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.vb]
dotnet_analyzer_diagnostic.severity = suggestion
[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_MaintainExistingEntry()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, input, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_DiagnosticsSuppressed()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.severity = none
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestMissingInRegularAndScriptAsync(input);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_InvalidRule()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.XYZ1111.severity = suggestion
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.XYZ1111.severity = suggestion
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RegexHeaderMatch()
{
// NOTE: Even though we have a regex match, bulk configuration code fix is always applied to all files
// within the editorconfig cone, so it generates a new entry.
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fi*e.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = warning
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fi*e.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = warning
[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RegexHeaderNonMatch()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fii*e.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = warning
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fii*e.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = warning
[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.Configuration.ConfigureSeverity;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.Configuration.ConfigureSeverity
{
public abstract partial class CategoryBasedSeverityConfigurationTests : AbstractSuppressionDiagnosticTest
{
private sealed class CustomDiagnosticAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
id: "XYZ0001",
title: "Title",
messageFormat: "Message",
category: "CustomCategory",
defaultSeverity: DiagnosticSeverity.Info,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
c => c.ReportDiagnostic(Diagnostic.Create(Rule, c.Node.GetLocation())),
SyntaxKind.ClassDeclaration);
}
}
protected override TestWorkspace CreateWorkspaceFromFile(string initialMarkup, TestParameters parameters)
=> TestWorkspace.CreateCSharp(initialMarkup, parameters.parseOptions, parameters.compilationOptions);
protected override string GetLanguage() => LanguageNames.CSharp;
protected override ParseOptions GetScriptOptions() => Options.Script;
internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
new CustomDiagnosticAnalyzer(), new ConfigureSeverityLevelCodeFixProvider());
}
public sealed class SilentConfigurationTests : CategoryBasedSeverityConfigurationTests
{
/// <summary>
/// Code action ranges:
/// 1. (0 - 4) => Code actions for diagnostic "ID" configuration with severity None, Silent, Suggestion, Warning and Error
/// 2. (5 - 9) => Code actions for diagnostic "Category" configuration with severity None, Silent, Suggestion, Warning and Error
/// 3. (10 - 14) => Code actions for all analyzer diagnostics configuration with severity None, Silent, Suggestion, Warning and Error
/// </summary>
protected override int CodeActionIndex => 6;
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_Empty()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig""></AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RuleExists()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = suggestion # Comment
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent # Comment
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RuleIdEntryExists()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_diagnostic.XYZ0001.severity = suggestion # Comment
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.cs]
dotnet_diagnostic.XYZ0001.severity = suggestion # Comment
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_InvalidHeader()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.vb]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = suggestion
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.vb]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = suggestion
[*.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_MaintainExistingEntry()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, input, CodeActionIndex);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_DiagnosticsSuppressed()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.category-CustomCategory.severity = none
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestMissingInRegularAndScriptAsync(input);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_InvalidRule()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.category-XYZ1111Category.severity = suggestion
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*.{vb,cs}]
dotnet_analyzer_diagnostic.category-XYZ1111Category.severity = suggestion
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RegexHeaderMatch()
{
// NOTE: Even though we have a regex match, bulk configuration code fix is always applied to all files
// within the editorconfig cone, so it generates a new entry.
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fi*e.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = warning
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fi*e.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = warning
[*.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
public async Task ConfigureEditorconfig_RegexHeaderNonMatch()
{
var input = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
[|class Program1 { }|]
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fii*e.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = warning
</AnalyzerConfigDocument>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" FilePath=""z:\\Assembly1.csproj"">
<Document FilePath=""z:\\Program/file.cs"">
class Program1 { }
</Document>
<AnalyzerConfigDocument FilePath=""z:\\.editorconfig"">[*am/fii*e.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = warning
[*.cs]
# Default severity for analyzer diagnostics with category 'CustomCategory'
dotnet_analyzer_diagnostic.category-CustomCategory.severity = silent
</AnalyzerConfigDocument>
</Project>
</Workspace>";
await TestInRegularAndScriptAsync(input, expected, CodeActionIndex);
}
}
}
}
......@@ -29,7 +29,7 @@
using Microsoft.VisualStudio.Text.Editor;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.CodeActions.CodeAction;
using CodeFixGroupKey = System.Tuple<Microsoft.CodeAnalysis.Diagnostics.DiagnosticData, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority>;
using CodeFixGroupKey = System.Tuple<Microsoft.CodeAnalysis.Diagnostics.DiagnosticData, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority?>;
using IUIThreadOperationContext = Microsoft.VisualStudio.Utilities.IUIThreadOperationContext;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
......@@ -496,6 +496,9 @@ private ImmutableArray<CodeRefactoring> FilterOnUIThread(ImmutableArray<CodeRefa
private static bool IsTopLevelSuppressionAction(CodeAction action)
=> action is AbstractConfigurationActionWithNestedActions;
private static bool IsBulkConfigurationAction(CodeAction action)
=> (action as AbstractConfigurationActionWithNestedActions)?.IsBulkConfigurationAction == true;
private void AddCodeActions(
Workspace workspace, IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order, CodeFixCollection fixCollection,
......@@ -542,9 +545,7 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map,
ArrayBuilder<CodeFixGroupKey> order)
{
var diag = fix.GetPrimaryDiagnosticData();
var groupKey = new CodeFixGroupKey(diag, fix.Action.Priority);
var groupKey = GetGroupKey(fix);
if (!map.ContainsKey(groupKey))
{
order.Add(groupKey);
......@@ -552,6 +553,17 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
}
map[groupKey].Add(suggestedAction);
static CodeFixGroupKey GetGroupKey(CodeFix fix)
{
var diag = fix.GetPrimaryDiagnosticData();
if (fix.Action is AbstractConfigurationActionWithNestedActions configurationAction)
{
return new CodeFixGroupKey(diag, configurationAction.Priority, configurationAction.AdditionalPriority);
}
return new CodeFixGroupKey(diag, fix.Action.Priority, null);
}
}
/// <summary>
......@@ -612,20 +624,30 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
{
using var nonSuppressionSetsDisposer = ArrayBuilder<SuggestedActionSet>.GetInstance(out var nonSuppressionSets);
using var suppressionSetsDisposer = ArrayBuilder<SuggestedActionSet>.GetInstance(out var suppressionSets);
using var bulkConfigurationActionsDisposer = ArrayBuilder<SuggestedAction>.GetInstance(out var bulkConfigurationActions);
foreach (var diag in order)
foreach (var groupKey in order)
{
var actions = map[diag];
var actions = map[groupKey];
var nonSuppressionActions = actions.Where(a => !IsTopLevelSuppressionAction(a.CodeAction));
AddSuggestedActionsSet(nonSuppressionActions, diag, nonSuppressionSets);
AddSuggestedActionsSet(nonSuppressionActions, groupKey, nonSuppressionSets);
var suppressionActions = actions.Where(a => IsTopLevelSuppressionAction(a.CodeAction) && !IsBulkConfigurationAction(a.CodeAction));
AddSuggestedActionsSet(suppressionActions, groupKey, suppressionSets);
var suppressionActions = actions.Where(a => IsTopLevelSuppressionAction(a.CodeAction));
AddSuggestedActionsSet(suppressionActions, diag, suppressionSets);
bulkConfigurationActions.AddRange(actions.Where(a => IsBulkConfigurationAction(a.CodeAction)));
}
var sets = nonSuppressionSets.ToImmutable();
// Append bulk configuration fixes at the end of suppression/configuration fixes.
if (bulkConfigurationActions.Count > 0)
{
var bulkConfigurationSet = new SuggestedActionSet(PredefinedSuggestedActionCategoryNames.CodeFix, bulkConfigurationActions);
suppressionSets.Add(bulkConfigurationSet);
}
if (suppressionSets.Count > 0)
{
// Wrap the suppression/configuration actions within another top level suggested action
......@@ -694,7 +716,7 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
private static void AddSuggestedActionsSet(
IEnumerable<SuggestedAction> actions,
CodeFixGroupKey diag,
CodeFixGroupKey groupKey,
ArrayBuilder<SuggestedActionSet> sets)
{
foreach (var group in actions.GroupBy(a => a.Priority))
......@@ -702,9 +724,9 @@ SuggestedAction GetSuggestedAction(CodeAction action, CodeFix fix)
var priority = GetSuggestedActionSetPriority(group.Key);
// diagnostic from things like build shouldn't reach here since we don't support LB for those diagnostics
Debug.Assert(diag.Item1.HasTextSpan);
var category = GetFixCategory(diag.Item1.Severity);
sets.Add(new SuggestedActionSet(category, group, priority: priority, applicableToSpan: diag.Item1.GetTextSpan().ToSpan()));
Debug.Assert(groupKey.Item1.HasTextSpan);
var category = GetFixCategory(groupKey.Item1.Severity);
sets.Add(new SuggestedActionSet(category, group, priority: priority, applicableToSpan: groupKey.Item1.GetTextSpan().ToSpan()));
}
}
......
......@@ -21,5 +21,14 @@ protected AbstractConfigurationActionWithNestedActions(ImmutableArray<CodeAction
// Put configurations/suppressions at the end of everything.
internal override CodeActionPriority Priority => CodeActionPriority.None;
/// <summary>
/// Additional priority associated with all configuration and suppression code actions.
/// This allows special code actions such as Bulk configuration to to be at the end of
/// all suppression and configuration actions by having a lower additional priority.
/// </summary>
internal virtual CodeActionPriority AdditionalPriority => CodeActionPriority.Medium;
internal virtual bool IsBulkConfigurationAction => false;
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeActions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.Configuration.ConfigureSeverity
{
internal sealed partial class ConfigureSeverityLevelCodeFixProvider : IConfigurationFixProvider
{
private sealed class TopLevelBulkConfigureSeverityCodeAction : AbstractConfigurationActionWithNestedActions
{
public TopLevelBulkConfigureSeverityCodeAction(ImmutableArray<CodeAction> nestedActions, string? category)
: base(nestedActions,
category != null
? string.Format(FeaturesResources.Configure_severity_for_all_0_analyzers, category)
: FeaturesResources.Configure_severity_for_all_analyzers)
{
// Ensure that 'Category' based bulk configuration actions are shown above
// the 'All analyzer diagnostics' bulk configuration actions.
AdditionalPriority = category != null ? CodeActionPriority.Low : CodeActionPriority.None;
}
internal override CodeActionPriority AdditionalPriority { get; }
internal override bool IsBulkConfigurationAction => true;
}
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
......@@ -12,6 +14,7 @@
using Microsoft.CodeAnalysis.Options.EditorConfig;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.CodeActions.CodeAction;
namespace Microsoft.CodeAnalysis.CodeFixes.Configuration.ConfigureSeverity
......@@ -33,7 +36,7 @@ internal sealed partial class ConfigureSeverityLevelCodeFixProvider : IConfigura
public bool IsFixableDiagnostic(Diagnostic diagnostic)
=> !diagnostic.IsSuppressed && !SuppressionHelpers.IsNotConfigurableDiagnostic(diagnostic);
public FixAllProvider GetFixAllProvider()
public FixAllProvider? GetFixAllProvider()
=> null;
public Task<ImmutableArray<CodeFix>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
......@@ -51,6 +54,8 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
}
var result = ArrayBuilder<CodeFix>.GetInstance();
var anayzerDiagnosticsByCategory = new SortedDictionary<string, ArrayBuilder<Diagnostic>>();
using var disposer = ArrayBuilder<Diagnostic>.GetInstance(out var analyzerDiagnostics);
foreach (var diagnostic in diagnostics)
{
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
......@@ -62,9 +67,49 @@ private static ImmutableArray<CodeFix> GetConfigurations(Project project, IEnume
var codeAction = new TopLevelConfigureSeverityCodeAction(diagnostic, nestedActions.ToImmutableAndFree());
result.Add(new CodeFix(project, codeAction, diagnostic));
// Bulk configuration is only supported for analyzer diagnostics.
if (!SuppressionHelpers.IsCompilerDiagnostic(diagnostic))
{
// Ensure diagnostic has a valid non-empty 'Category' for category based configuration.
if (!string.IsNullOrEmpty(diagnostic.Descriptor.Category))
{
var diagnosticsForCategory = anayzerDiagnosticsByCategory.GetOrAdd(diagnostic.Descriptor.Category, _ => ArrayBuilder<Diagnostic>.GetInstance());
diagnosticsForCategory.Add(diagnostic);
}
analyzerDiagnostics.Add(diagnostic);
}
}
foreach (var (category, diagnosticsWithCategory) in anayzerDiagnosticsByCategory)
{
AddBulkConfigurationCodeFixes(diagnosticsWithCategory.ToImmutableAndFree(), category);
}
if (analyzerDiagnostics.Count > 0)
{
AddBulkConfigurationCodeFixes(analyzerDiagnostics.ToImmutable(), category: null);
}
return result.ToImmutableAndFree();
void AddBulkConfigurationCodeFixes(ImmutableArray<Diagnostic> diagnostics, string? category)
{
var nestedActions = ArrayBuilder<CodeAction>.GetInstance();
foreach (var (name, value) in s_editorConfigSeverityStrings)
{
nestedActions.Add(
new SolutionChangeAction(
name,
solution => category != null
? ConfigurationUpdater.BulkConfigureSeverityAsync(value, category, project, cancellationToken)
: ConfigurationUpdater.BulkConfigureSeverityAsync(value, project, cancellationToken)));
}
var codeAction = new TopLevelBulkConfigureSeverityCodeAction(nestedActions.ToImmutableAndFree(), category);
result.Add(new CodeFix(project, codeAction, diagnostics));
}
}
}
}
......@@ -691,6 +691,12 @@ Do you want to continue?</value>
<data name="Configure_0_code_style" xml:space="preserve">
<value>Configure {0} code style</value>
</data>
<data name="Configure_severity_for_all_0_analyzers" xml:space="preserve">
<value>Configure severity for all '{0}' analyzers</value>
</data>
<data name="Configure_severity_for_all_analyzers" xml:space="preserve">
<value>Configure severity for all analyzers</value>
</data>
<data name="Pending" xml:space="preserve">
<value>&lt;Pending&gt;</value>
</data>
......
......@@ -137,6 +137,16 @@
<target state="translated">Nakonfigurovat závažnost {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Převést na LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Schweregrad "{0}" konfigurieren</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">In LINQ konvertieren</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Configurar la gravedad de {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Convertir a LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Configurer la gravité {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Convertir en LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Configura la gravità di {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Converti in LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">{0} の重要度の構成</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">LINQ に変換</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">{0} 심각도 구성</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">LINQ로 변환</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Konfiguruj ważność {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Konwertuj na składnię LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Configurar severidade de {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Converter para LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">Настройка серьезности {0}</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">Преобразовать в LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">{0} önem derecesini yapılandır</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">LINQ to dönüştürme</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">配置 {0} 严重性</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">转换为 LINQ</target>
......
......@@ -137,6 +137,16 @@
<target state="translated">設定 {0} 嚴重性</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_0_analyzers">
<source>Configure severity for all '{0}' analyzers</source>
<target state="new">Configure severity for all '{0}' analyzers</target>
<note />
</trans-unit>
<trans-unit id="Configure_severity_for_all_analyzers">
<source>Configure severity for all analyzers</source>
<target state="new">Configure severity for all analyzers</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_linq">
<source>Convert to LINQ</source>
<target state="translated">轉換至 LINQ</target>
......
......@@ -696,6 +696,18 @@ static void Main(string[] args)
"Suggestion",
"Warning",
"Error",
"Configure severity for all 'Style' analyzers",
"None",
"Silent",
"Suggestion",
"Warning",
"Error",
"Configure severity for all analyzers",
"None",
"Silent",
"Suggestion",
"Warning",
"Error",
};
VisualStudio.Editor.Verify.CodeActions(expectedItems, ensureExpectedItemsAreOrdered: true);
......
......@@ -51,7 +51,7 @@ internal CodeFix(Project project, CodeAction action, Diagnostic diagnostic)
internal CodeFix(Project project, CodeAction action, ImmutableArray<Diagnostic> diagnostics)
{
Debug.Assert(!diagnostics.IsDefault);
Debug.Assert(!diagnostics.IsDefaultOrEmpty);
Project = project;
Action = action;
Diagnostics = diagnostics;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册