Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,13 @@ internal static async Task<ImmutableDictionary<ProjectId, ImmutableArray<Diagnos
.Where(analyzer => DoesAnalyzerSupportLanguage(analyzer, project.Language));
foreach (var analyzer in filteredAnalyzer)
{
// Allow suppressors unconditionally
if (analyzer is DiagnosticSuppressor suppressor)
{
analyzers.Add(suppressor);
continue;
}

// Filter by excluded diagnostics
if (!excludeDiagnostics.IsEmpty &&
analyzer.SupportedDiagnostics.All(descriptor => excludeDiagnostics.Contains(descriptor.Id)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,29 @@ public ImmutableDictionary<ProjectId, AnalyzersAndFixers> GetAnalyzersAndFixers(
.Select(path => new AnalyzerFileReference(path, analyzerAssemblyLoader));

var analyzersByLanguage = new Dictionary<string, AnalyzersAndFixers>();

// We need AnalyzerReferenceInformationProvider to get all project suppressors
var referenceProvider = new AnalyzerReferenceInformationProvider();
var perProjectAnalyzersAndFixers = referenceProvider.GetAnalyzersAndFixers(workspace, solution, formatOptions, logger);

return solution.Projects
.ToImmutableDictionary(
project => project.Id,
project =>
{
if (!analyzersByLanguage.TryGetValue(project.Language, out var analyzersAndFixers))
{
var analyzers = references.SelectMany(reference => reference.GetAnalyzers(project.Language)).ToImmutableArray();
var analyzers = ImmutableArray.CreateBuilder<DiagnosticAnalyzer>();
analyzers.AddRange(references.SelectMany(reference => reference.GetAnalyzers(project.Language)));
var codeFixes = AnalyzerFinderHelpers.LoadFixers(references.Select(reference => reference.GetAssembly()), project.Language);
analyzersAndFixers = new AnalyzersAndFixers(analyzers, codeFixes);

// Add project suppressors to featured analyzers
if (perProjectAnalyzersAndFixers.TryGetValue(project.Id, out var thisProjectAnalyzersAndFixers))
{
analyzers.AddRange(thisProjectAnalyzersAndFixers.Analyzers.OfType<DiagnosticSuppressor>());
}

analyzersAndFixers = new AnalyzersAndFixers(analyzers.ToImmutableArray(), codeFixes);
analyzersByLanguage.Add(project.Language, analyzersAndFixers);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
root = true

[*.cs]
dotnet_diagnostic.IDE0051.severity = warning # Remove unused private member
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using UnityEngine;

namespace for_code_formatter
{
class Program : MonoBehaviour
{
// This method should trigger IDE0051 (remove unused private member) in a regular project.
// But given we simulate a Unity MonoBehavior and we include Microsoft.Unity.Analyzers nuget,
// given Update is a well-known Unity message, this IDE0051 should be suppressed by USP0003.
// see https://github.com/microsoft/Microsoft.Unity.Analyzers/blob/main/doc/USP0003.md
void Update()
{

}
}
}

namespace UnityEngine
{
public class MonoBehaviour
{
// This is a placeholder for the Unity MonoBehaviour class.
// In a real Unity project, this would be part of the Unity engine.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Unity.Analyzers" Version="1.22.0" />
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions test/dotnet-format.UnitTests/CodeFormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class CodeFormatterTests
private static readonly string s_generatorSolutionPath = Path.Combine("for_code_formatter", "generator_solution");
private static readonly string s_generatorSolutionFileName = "generator_solution.sln";

private static readonly string s_suppressorProjectPath = Path.Combine("for_code_formatter", "suppressor_project");
private static readonly string s_suppressorProjectFilePath = Path.Combine(s_suppressorProjectPath, "suppressor_project.csproj");

private static string[] EmptyFilesList => Array.Empty<string>();

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

[MSBuildFact]
public async Task SuppressorsHandledInProject()
{
await TestFormatWorkspaceAsync(
s_suppressorProjectFilePath,
include: EmptyFilesList,
exclude: EmptyFilesList,
includeGenerated: false,
expectedExitCode: 0,
expectedFilesFormatted: 0,
expectedFileCount: 3,
codeStyleSeverity: DiagnosticSeverity.Warning,
fixCategory: FixCategory.CodeStyle);
}

internal async Task<string> TestFormatWorkspaceAsync(
string workspaceFilePath,
string[] include,
Expand Down
Loading