Skip to content

Commit f47e024

Browse files
authored
[Backport][10.0.2xx] Add suppressor support for dotnet format (#51697)
2 parents 3bfa303 + 869beec commit f47e024

File tree

6 files changed

+82
-2
lines changed

6 files changed

+82
-2
lines changed

src/BuiltInTools/dotnet-format/Analyzers/AnalyzerFormatter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,13 @@ internal static async Task<ImmutableDictionary<ProjectId, ImmutableArray<Diagnos
315315
.Where(analyzer => DoesAnalyzerSupportLanguage(analyzer, project.Language));
316316
foreach (var analyzer in filteredAnalyzer)
317317
{
318+
// Allow suppressors unconditionally
319+
if (analyzer is DiagnosticSuppressor suppressor)
320+
{
321+
analyzers.Add(suppressor);
322+
continue;
323+
}
324+
318325
// Filter by excluded diagnostics
319326
if (!excludeDiagnostics.IsEmpty &&
320327
analyzer.SupportedDiagnostics.All(descriptor => excludeDiagnostics.Contains(descriptor.Id)))

src/BuiltInTools/dotnet-format/Analyzers/CodeStyleInformationProvider.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,29 @@ public ImmutableDictionary<ProjectId, AnalyzersAndFixers> GetAnalyzersAndFixers(
3333
.Select(path => new AnalyzerFileReference(path, analyzerAssemblyLoader));
3434

3535
var analyzersByLanguage = new Dictionary<string, AnalyzersAndFixers>();
36+
37+
// We need AnalyzerReferenceInformationProvider to get all project suppressors
38+
var referenceProvider = new AnalyzerReferenceInformationProvider();
39+
var perProjectAnalyzersAndFixers = referenceProvider.GetAnalyzersAndFixers(workspace, solution, formatOptions, logger);
40+
3641
return solution.Projects
3742
.ToImmutableDictionary(
3843
project => project.Id,
3944
project =>
4045
{
4146
if (!analyzersByLanguage.TryGetValue(project.Language, out var analyzersAndFixers))
4247
{
43-
var analyzers = references.SelectMany(reference => reference.GetAnalyzers(project.Language)).ToImmutableArray();
48+
var analyzers = ImmutableArray.CreateBuilder<DiagnosticAnalyzer>();
49+
analyzers.AddRange(references.SelectMany(reference => reference.GetAnalyzers(project.Language)));
4450
var codeFixes = AnalyzerFinderHelpers.LoadFixers(references.Select(reference => reference.GetAssembly()), project.Language);
45-
analyzersAndFixers = new AnalyzersAndFixers(analyzers, codeFixes);
51+
52+
// Add project suppressors to featured analyzers
53+
if (perProjectAnalyzersAndFixers.TryGetValue(project.Id, out var thisProjectAnalyzersAndFixers))
54+
{
55+
analyzers.AddRange(thisProjectAnalyzersAndFixers.Analyzers.OfType<DiagnosticSuppressor>());
56+
}
57+
58+
analyzersAndFixers = new AnalyzersAndFixers(analyzers.ToImmutableArray(), codeFixes);
4659
analyzersByLanguage.Add(project.Language, analyzersAndFixers);
4760
}
4861

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
root = true
2+
3+
[*.cs]
4+
dotnet_diagnostic.IDE0051.severity = warning # Remove unused private member
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using UnityEngine;
3+
4+
namespace for_code_formatter
5+
{
6+
class Program : MonoBehaviour
7+
{
8+
// This method should trigger IDE0051 (remove unused private member) in a regular project.
9+
// But given we simulate a Unity MonoBehavior and we include Microsoft.Unity.Analyzers nuget,
10+
// given Update is a well-known Unity message, this IDE0051 should be suppressed by USP0003.
11+
// see https://github.com/microsoft/Microsoft.Unity.Analyzers/blob/main/doc/USP0003.md
12+
void Update()
13+
{
14+
15+
}
16+
}
17+
}
18+
19+
namespace UnityEngine
20+
{
21+
public class MonoBehaviour
22+
{
23+
// This is a placeholder for the Unity MonoBehaviour class.
24+
// In a real Unity project, this would be part of the Unity engine.
25+
}
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Library</OutputType>
5+
<TargetFramework>netstandard2.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Unity.Analyzers" Version="1.22.0" />
10+
</ItemGroup>
11+
12+
</Project>

test/dotnet-format.UnitTests/CodeFormatterTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public class CodeFormatterTests
3939
private static readonly string s_generatorSolutionPath = Path.Combine("for_code_formatter", "generator_solution");
4040
private static readonly string s_generatorSolutionFileName = "generator_solution.sln";
4141

42+
private static readonly string s_suppressorProjectPath = Path.Combine("for_code_formatter", "suppressor_project");
43+
private static readonly string s_suppressorProjectFilePath = Path.Combine(s_suppressorProjectPath, "suppressor_project.csproj");
44+
4245
private static string[] EmptyFilesList => Array.Empty<string>();
4346

4447
private Regex FindFormattingLogLine => new Regex(@"((.*)\(\d+,\d+\): (.*))\r|((.*)\(\d+,\d+\): (.*))");
@@ -627,6 +630,21 @@ await TestFormatWorkspaceAsync(
627630
}
628631
}
629632

633+
[MSBuildFact]
634+
public async Task SuppressorsHandledInProject()
635+
{
636+
await TestFormatWorkspaceAsync(
637+
s_suppressorProjectFilePath,
638+
include: EmptyFilesList,
639+
exclude: EmptyFilesList,
640+
includeGenerated: false,
641+
expectedExitCode: 0,
642+
expectedFilesFormatted: 0,
643+
expectedFileCount: 3,
644+
codeStyleSeverity: DiagnosticSeverity.Warning,
645+
fixCategory: FixCategory.CodeStyle);
646+
}
647+
630648
internal async Task<string> TestFormatWorkspaceAsync(
631649
string workspaceFilePath,
632650
string[] include,

0 commit comments

Comments
 (0)