diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs
index e6f2ff25f68..90889c8ffd0 100644
--- a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs
@@ -53,9 +53,9 @@ protected SonarAnalysisContextBase(SonarAnalysisContext analysisContext, TContex
/// Tree to decide on. Can be null for Symbol-based and Compilation-based scenarios. And we want to analyze those too.
/// When set, generated trees are analyzed only when language-specific 'analyzeGeneratedCode' configuration property is also set.
public bool ShouldAnalyzeTree(SyntaxTree tree, GeneratedCodeRecognizer generatedCodeRecognizer) =>
- SonarLintFile() is var sonarLintReader
- && (generatedCodeRecognizer is null || sonarLintReader.AnalyzeGeneratedCode(Compilation.Language) || !tree.IsGenerated(generatedCodeRecognizer, Compilation))
- && (tree is null || (!IsUnchanged(tree) && ShouldAnalyzeFile(sonarLintReader, tree.FilePath)));
+ SonarLintXml() is var sonarLintXml
+ && (generatedCodeRecognizer is null || sonarLintXml.AnalyzeGeneratedCode(Compilation.Language) || !tree.IsGenerated(generatedCodeRecognizer, Compilation))
+ && (tree is null || (!IsUnchanged(tree) && !IsExcluded(sonarLintXml, tree.FilePath)));
///
/// Reads configuration from SonarProjectConfig.xml file and caches the result for scope of this analysis.
@@ -79,7 +79,7 @@ public ProjectConfigReader ProjectConfiguration()
///
/// Reads the properties from the SonarLint.xml file and caches the result for the scope of this analysis.
///
- public SonarLintXmlReader SonarLintFile()
+ public SonarLintXmlReader SonarLintXml()
{
if (Options.SonarLintXml() is { } sonarLintXml)
{
@@ -121,10 +121,12 @@ public bool HasMatchingScope(DiagnosticDescriptor descriptor)
descriptor.CustomTags.Contains(tag);
}
- private bool ShouldAnalyzeFile(SonarLintXmlReader sonarLintXml, string filePath) =>
- ProjectConfiguration().ProjectType != ProjectType.Unknown // Not SonarLint context, NuGet or Scanner <= 5.0
- || (FileInclusionCache.GetValue(Compilation, _ => new()) is var cache
- && cache.GetOrAdd(filePath, _ => IsFileIncluded(sonarLintXml, filePath)));
+ private bool IsExcluded(SonarLintXmlReader sonarLintXml, string filePath) =>
+ // If ProjectType is not 'Unknown' it means we are in S4NET context and all files are analyzed.
+ // If ProjectType is 'Unknown' then we are in SonarLint or NuGet context and we need to check if the file has been excluded from analysis through SonarLint.xml.
+ ProjectConfiguration().ProjectType == ProjectType.Unknown
+ && FileInclusionCache.GetValue(Compilation, _ => new()) is var cache
+ && !cache.GetOrAdd(filePath, _ => IsFileIncluded(sonarLintXml, filePath));
private ImmutableHashSet CreateUnchangedFilesHashSet() =>
ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, ProjectConfiguration().AnalysisConfig?.UnchangedFiles() ?? Array.Empty());
diff --git a/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs b/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs
index cb3d06010dd..46f7ea5533a 100644
--- a/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs
+++ b/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs
@@ -32,7 +32,7 @@ protected sealed override void Initialize(SonarAnalysisContext context)
context.RegisterCompilationStartAction(
c =>
{
- ParameterLoader.SetParameterValues(this, c.SonarLintFile());
+ ParameterLoader.SetParameterValues(this, c.SonarLintXml());
parameterContext.ExecutePostponedActions(c);
});
}
diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs
index 77cfddc9c1e..3f9af7d7d45 100644
--- a/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs
@@ -100,8 +100,8 @@ private static SonarLintXml ParseContent(SourceText sonarLintXml)
private string ReadSettingsProperty(string property) =>
sonarLintXml is { Settings: { } settings }
- ? settings.Where(x => x.Key.Equals(property)).Select(x => x.Value).FirstOrDefault()
- : string.Empty;
+ ? settings.Where(x => x.Key.Equals(property)).Select(x => x.Value).FirstOrDefault()
+ : null;
private static string[] ReadCommaSeparatedArray(string str) =>
string.IsNullOrEmpty(str) ? Array.Empty() : str.Split(',');
diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/UtilityAnalyzerBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/UtilityAnalyzerBase.cs
index 65627b91f2f..c2508a645c2 100644
--- a/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/UtilityAnalyzerBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/UtilityAnalyzerBase.cs
@@ -60,7 +60,7 @@ protected void ReadParameters(SonarCompilationStartAnalysisContext context)
}
if (context.Options.SonarLintXml() != null && !string.IsNullOrEmpty(outPath))
{
- var sonarLintXml = context.SonarLintFile();
+ var sonarLintXml = context.SonarLintXml();
IgnoreHeaderComments = sonarLintXml.IgnoreHeaderComments(context.Compilation.Language);
AnalyzeGeneratedCode = sonarLintXml.AnalyzeGeneratedCode(context.Compilation.Language);
OutPath = Path.Combine(outPath, context.Compilation.Language == LanguageNames.CSharp ? "output-cs" : "output-vbnet");
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs
index f527dd092a9..bc44a11477e 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs
@@ -179,7 +179,7 @@ public void SonarLintFile_LoadsExpectedValues(string language)
var analyzerLanguage = language == "cs" ? AnalyzerLanguage.CSharp : AnalyzerLanguage.VisualBasic;
var (compilation, _) = CreateDummyCompilation(analyzerLanguage, "ExtraEmptyFile");
var options = AnalysisScaffolding.CreateOptions($"ResourceTests\\SonarLintXml\\All_properties_{language}\\SonarLint.xml");
- var sut = CreateSut(compilation, options).SonarLintFile();
+ var sut = CreateSut(compilation, options).SonarLintXml();
sut.IgnoreHeaderComments(analyzerLanguage.LanguageName).Should().BeTrue();
sut.AnalyzeGeneratedCode(analyzerLanguage.LanguageName).Should().BeFalse();
@@ -204,8 +204,8 @@ public void SonarLintFile_UsesCachedValue()
var options = AnalysisScaffolding.CreateOptions("ResourceTests\\SonarLintXml\\All_properties_cs\\SonarLint.xml");
var firstSut = CreateSut(options);
var secondSut = CreateSut(options);
- var firstFile = firstSut.SonarLintFile();
- var secondFile = secondSut.SonarLintFile();
+ var firstFile = firstSut.SonarLintXml();
+ var secondFile = secondSut.SonarLintXml();
secondFile.Should().BeSameAs(firstFile);
}
@@ -215,8 +215,8 @@ public void SonarLintFile_WhenFileChanges_RebuildsCache()
{
var firstOptions = AnalysisScaffolding.CreateOptions("ResourceTests\\SonarLintXml\\All_properties_cs\\SonarLint.xml");
var secondOptions = AnalysisScaffolding.CreateOptions("ResourceTests\\SonarLintXml\\All_properties_vbnet\\SonarLint.xml");
- var firstFile = CreateSut(firstOptions).SonarLintFile();
- var secondFile = CreateSut(secondOptions).SonarLintFile();
+ var firstFile = CreateSut(firstOptions).SonarLintXml();
+ var secondFile = CreateSut(secondOptions).SonarLintXml();
secondFile.Should().NotBeSameAs(firstFile);
}
@@ -229,14 +229,14 @@ public void SonarLintFile_WhenFileChanges_RebuildsCache()
[DataRow("path//SonarLint.xmla")] // different extension
public void SonarLintFile_WhenAdditionalFileNotPresent_ReturnsDefaultValues(string folder)
{
- var sut = CreateSut(AnalysisScaffolding.CreateOptions(folder)).SonarLintFile();
+ var sut = CreateSut(AnalysisScaffolding.CreateOptions(folder)).SonarLintXml();
CheckSonarLintXmlDefaultValues(sut);
}
[TestMethod]
public void SonarLintFile_WhenInvalidXml_ReturnsDefaultValues()
{
- var sut = CreateSut(AnalysisScaffolding.CreateOptions("ResourceTests\\SonarLintXml\\Invalid_Xml\\SonarLint.xml")).SonarLintFile();
+ var sut = CreateSut(AnalysisScaffolding.CreateOptions("ResourceTests\\SonarLintXml\\Invalid_Xml\\SonarLint.xml")).SonarLintXml();
CheckSonarLintXmlDefaultValues(sut);
}
@@ -245,7 +245,7 @@ public void SonarLintFile_WhenFileIsMissing_ThrowException()
{
var sut = CreateSut(AnalysisScaffolding.CreateOptions("ThisPathDoesNotExist\\SonarLint.xml"));
- sut.Invoking(x => x.SonarLintFile())
+ sut.Invoking(x => x.SonarLintXml())
.Should()
.Throw()
.WithMessage("File 'SonarLint.xml' has been added as an AdditionalFile but could not be read and parsed.");
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs
index fb9a2ff026c..5d599cd21c9 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs
@@ -41,7 +41,7 @@ public void SetParameterValues_WithInvalidSonarLintPath_DoesNotPopulateParameter
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(3); // Default value
@@ -57,7 +57,7 @@ public void SetParameterValues_WithValidSonarLintPath_PopulatesProperties(string
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(1); // Value from the xml file
@@ -71,7 +71,7 @@ public void SetParameterValues_SonarLintFileWithIntParameterType_PopulatesProper
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(1); // Value from the xml file
@@ -87,7 +87,7 @@ public void SetParameterValues_SonarLintFileWithStringParameterType_PopulatesPro
var analyzer = new EnumNameShouldFollowRegex(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.FlagsEnumNamePattern.Should().Be(parameterValue); // value from XML file
@@ -103,7 +103,7 @@ public void SetParameterValues_SonarLintFileWithBooleanParameterType_PopulatesPr
var analyzer = new CheckFileLicense(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.IsRegularExpression.Should().Be(parameterValue); // value from XML file
@@ -117,7 +117,7 @@ public void SetParameterValues_SonarLintFileWithoutRuleParameters_DoesNotPopulat
var analyzer = new LineLength(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(200); // Default value
@@ -149,7 +149,7 @@ public void SetParameterValues_CalledTwiceAfterChangeInConfigFile_UpdatesPropert
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
analyzer.Maximum.Should().Be(maxValue);
// Modify the in-memory additional file
@@ -159,7 +159,7 @@ public void SetParameterValues_CalledTwiceAfterChangeInConfigFile_UpdatesPropert
var modifiedFilePath = TestHelper.WriteFile(TestContext, "SonarLint.xml", modifiedSonarLintXml);
compilation = CreateCompilationWithOption(modifiedFilePath);
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
analyzer.Maximum.Should().Be(maxValue);
}
@@ -174,7 +174,7 @@ public void SetParameterValues_WithMalformedXml_DoesNotPopulateProperties(string
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(3); // Default value
@@ -190,7 +190,7 @@ public void SetParameterValues_SonarLintFileWithStringInsteadOfIntParameterType_
var analyzer = new ExpressionComplexity(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.Maximum.Should().Be(3); // Default value
@@ -206,7 +206,7 @@ public void SetParameterValues_SonarLintFileWithStringInsteadOfBooleanParameterT
var analyzer = new CheckFileLicense(); // Cannot use mock because we use reflection to find properties.
// Act
- ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintFile());
+ ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml());
// Assert
analyzer.IsRegularExpression.Should().BeFalse(); // Default value