From 47e446cc3d5b80e6d722e6b14a238a628671747e Mon Sep 17 00:00:00 2001 From: Joey Robichaud Date: Mon, 6 Jul 2020 14:46:27 -0700 Subject: [PATCH] Filter analyzers by project language before running --- src/Analyzers/AnalyzerFormatter.cs | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Analyzers/AnalyzerFormatter.cs b/src/Analyzers/AnalyzerFormatter.cs index 7af5930820..6cd013c06a 100644 --- a/src/Analyzers/AnalyzerFormatter.cs +++ b/src/Analyzers/AnalyzerFormatter.cs @@ -16,6 +16,8 @@ namespace Microsoft.CodeAnalysis.Tools.Analyzers { internal class AnalyzerFormatter : ICodeFormatter { + private static readonly ImmutableArray _supportedLanguages = ImmutableArray.Create(LanguageNames.CSharp, LanguageNames.VisualBasic); + private readonly string _name; private readonly IAnalyzerInformationProvider _informationProvider; private readonly IAnalyzerRunner _runner; @@ -42,6 +44,10 @@ internal class AnalyzerFormatter : ICodeFormatter CancellationToken cancellationToken) { var (analyzers, fixers) = _informationProvider.GetAnalyzersAndFixers(solution, formatOptions, logger); + if (analyzers.IsEmpty && fixers.IsEmpty) + { + return solution; + } var analysisStopwatch = Stopwatch.StartNew(); logger.LogTrace(Resources.Running_0_analysis, _name); @@ -148,13 +154,13 @@ static void LogDiagnosticLocations(Solution solution, IEnumerable di } // Build maps between diagnostic id and the associated analyzers and codefixes - var analyzersById = CreateAnalyzerMap(reportedDiagnostics, allAnalyzers); + var analyzersByIdAndLanguage = CreateAnalyzerMap(reportedDiagnostics, allAnalyzers); var fixersById = CreateFixerMap(reportedDiagnostics, allCodefixes); // We need to run each codefix iteratively so ensure that all diagnostics are found and fixed. foreach (var diagnosticId in reportedDiagnostics) { - var analyzers = analyzersById[diagnosticId]; + var analyzersByLanguage = analyzersByIdAndLanguage[diagnosticId]; var codefixes = fixersById[diagnosticId]; // If there is no codefix, there is no reason to run analysis again. @@ -173,6 +179,7 @@ static void LogDiagnosticLocations(Solution solution, IEnumerable di continue; } + var analyzers = analyzersByLanguage[project.Language]; await _runner.RunCodeAnalysisAsync(result, analyzers, project, formattablePaths, severity, logger, cancellationToken).ConfigureAwait(false); } @@ -193,13 +200,18 @@ static void LogDiagnosticLocations(Solution solution, IEnumerable di return solution; - static ImmutableDictionary> CreateAnalyzerMap( + static ImmutableDictionary>> CreateAnalyzerMap( ImmutableArray diagnosticIds, ImmutableArray analyzers) { return diagnosticIds.ToImmutableDictionary( id => id, - id => analyzers.Where(analyzer => analyzer.SupportedDiagnostics.Any(diagnostic => diagnostic.Id == id)).ToImmutableArray()); + id => _supportedLanguages.ToImmutableDictionary( + language => language, + language => analyzers + .Where(analyzer => DoesAnalyzerSupportLanguage(analyzer, language)) + .Where(analyzer => analyzer.SupportedDiagnostics.Any(diagnostic => diagnostic.Id == id)) + .ToImmutableArray())); } static ImmutableDictionary> CreateFixerMap( @@ -226,7 +238,9 @@ static void LogDiagnosticLocations(Solution solution, IEnumerable di { var analyzers = ImmutableArray.CreateBuilder(); - foreach (var analyzer in allAnalyzers) + // Filter analyzers by project's language + var filteredAnalyzer = allAnalyzers.Where(analyzer => DoesAnalyzerSupportLanguage(analyzer, project.Language)); + foreach (var analyzer in filteredAnalyzer) { // Always run naming style analyzers because we cannot determine potential severity. // The reported diagnostics will be filtered by severity when they are run. @@ -248,5 +262,13 @@ static void LogDiagnosticLocations(Solution solution, IEnumerable di return projectAnalyzers.ToImmutableDictionary(); } + + private static bool DoesAnalyzerSupportLanguage(DiagnosticAnalyzer analyzer, string language) + { + return analyzer.GetType() + .GetCustomAttributes(typeof(DiagnosticAnalyzerAttribute), true) + .OfType() + .Any(attribute => attribute.Languages.Contains(language)); + } } }