From f1589d56c7961658d391bce501b0a85ff3102860 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Mon, 13 Mar 2023 14:46:15 +0100 Subject: [PATCH 1/9] Refactor ShouldAnalyzeTree refactor shouldAnalyzeTree method --- .../AnalysisContext/SonarAnalysisContextBase.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index e6f2ff25f68..812ff972d12 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))); + ReadSonarLintXml() is var sonarLint + && (generatedCodeRecognizer is null || sonarLint.AnalyzeGeneratedCode || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) + && (tree is null || ShouldAnalyzeFile(sonarLint, tree)); /// /// Reads configuration from SonarProjectConfig.xml file and caches the result for scope of this analysis. @@ -121,7 +121,10 @@ public bool HasMatchingScope(DiagnosticDescriptor descriptor) descriptor.CustomTags.Contains(tag); } - private bool ShouldAnalyzeFile(SonarLintXmlReader sonarLintXml, string filePath) => + private bool ShouldAnalyzeFile(SonarLintXmlReader sonarLintXml, SyntaxTree tree) => + !IsUnchanged(tree) && IsInSonarLintContextAndIncluded(sonarLintXml, tree.FilePath); + + private bool IsInSonarLintContextAndIncluded(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))); From ec036806dbb6b8bb83276c42931e75d184a5cd5e Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Mon, 13 Mar 2023 15:03:07 +0100 Subject: [PATCH 2/9] rename method that read sonarlintxml --- .../AnalysisContext/SonarAnalysisContextBase.cs | 2 +- .../SonarAnalysisContextBaseTest.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index 812ff972d12..ce78b55d4d9 100644 --- a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs @@ -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 ReadSonarLintXml() { if (Options.SonarLintXml() is { } sonarLintXml) { diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs index f527dd092a9..31e0620dfbf 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).ReadSonarLintXml(); 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.ReadSonarLintXml(); + var secondFile = secondSut.ReadSonarLintXml(); 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).ReadSonarLintXml(); + var secondFile = CreateSut(secondOptions).ReadSonarLintXml(); 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)).ReadSonarLintXml(); 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")).ReadSonarLintXml(); 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.ReadSonarLintXml()) .Should() .Throw() .WithMessage("File 'SonarLint.xml' has been added as an AdditionalFile but could not be read and parsed."); From cf4d9b1d40f30916ee691ace3510463fc65c7b86 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 12:17:40 +0100 Subject: [PATCH 3/9] fix rebase problem --- .../ParametrizedDiagnosticAnalyzer.cs | 2 +- .../Helpers/ParameterLoaderTest.cs | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs b/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs index cb3d06010dd..21315fb11e3 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.ReadSonarLintXml()); parameterContext.ExecutePostponedActions(c); }); } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Helpers/ParameterLoaderTest.cs index fb9a2ff026c..4ff8a20c640 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); 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.ReadSonarLintXml()); 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // 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.ReadSonarLintXml()); // Assert analyzer.IsRegularExpression.Should().BeFalse(); // Default value From 255bf4a4313c676eb2b5f7248ea575c76156c015 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 13:04:56 +0100 Subject: [PATCH 4/9] return null instead of empty string --- .../src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs index 77cfddc9c1e..0b802f7bba3 100644 --- a/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs +++ b/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs @@ -101,7 +101,7 @@ 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; + : null; private static string[] ReadCommaSeparatedArray(string str) => string.IsNullOrEmpty(str) ? Array.Empty() : str.Split(','); From 042f41a541768c5980cfde20af053d5ca7317e47 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 13:05:39 +0100 Subject: [PATCH 5/9] fix indent in method --- .../src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/SonarLintXmlReader.cs index 0b802f7bba3..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() - : null; + ? 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(','); From 37e016eeed64d85f07466c4c735dd8625b86b738 Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 14:11:31 +0100 Subject: [PATCH 6/9] Apply comments --- .../SonarAnalysisContextBase.cs | 16 ++++++-------- .../ParametrizedDiagnosticAnalyzer.cs | 2 +- .../SonarAnalysisContextBaseTest.cs | 16 +++++++------- .../Helpers/ParameterLoaderTest.cs | 22 +++++++++---------- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index ce78b55d4d9..e781ca08688 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) => - ReadSonarLintXml() is var sonarLint - && (generatedCodeRecognizer is null || sonarLint.AnalyzeGeneratedCode || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) - && (tree is null || ShouldAnalyzeFile(sonarLint, tree)); + SonarLintXml() is var sonarLintXml + && (generatedCodeRecognizer is null || sonarLintXml.AnalyzeGeneratedCode || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) + && (tree is null || (!IsUnchanged(tree) && FileIsIncludedInAnalysis(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 ReadSonarLintXml() + public SonarLintXmlReader SonarLintXml() { if (Options.SonarLintXml() is { } sonarLintXml) { @@ -121,11 +121,9 @@ public bool HasMatchingScope(DiagnosticDescriptor descriptor) descriptor.CustomTags.Contains(tag); } - private bool ShouldAnalyzeFile(SonarLintXmlReader sonarLintXml, SyntaxTree tree) => - !IsUnchanged(tree) && IsInSonarLintContextAndIncluded(sonarLintXml, tree.FilePath); - - private bool IsInSonarLintContextAndIncluded(SonarLintXmlReader sonarLintXml, string filePath) => - ProjectConfiguration().ProjectType != ProjectType.Unknown // Not SonarLint context, NuGet or Scanner <= 5.0 + private bool FileIsIncludedInAnalysis(SonarLintXmlReader sonarLintXml, string filePath) => + ProjectConfiguration().ProjectType != ProjectType.Unknown // If ProjectType != 'Unknown' we are in S4NET context and all files are analyzed. + // If ProjectType == '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. || (FileInclusionCache.GetValue(Compilation, _ => new()) is var cache && cache.GetOrAdd(filePath, _ => IsFileIncluded(sonarLintXml, filePath))); diff --git a/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs b/analyzers/src/SonarAnalyzer.Common/DiagnosticAnalyzer/ParametrizedDiagnosticAnalyzer.cs index 21315fb11e3..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.ReadSonarLintXml()); + ParameterLoader.SetParameterValues(this, c.SonarLintXml()); parameterContext.ExecutePostponedActions(c); }); } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/AnalysisContext/SonarAnalysisContextBaseTest.cs index 31e0620dfbf..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).ReadSonarLintXml(); + 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.ReadSonarLintXml(); - var secondFile = secondSut.ReadSonarLintXml(); + 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).ReadSonarLintXml(); - var secondFile = CreateSut(secondOptions).ReadSonarLintXml(); + 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)).ReadSonarLintXml(); + 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")).ReadSonarLintXml(); + 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.ReadSonarLintXml()) + 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 4ff8a20c640..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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + 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.ReadSonarLintXml()); + ParameterLoader.SetParameterValues(analyzer, compilation.SonarLintXml()); // Assert analyzer.IsRegularExpression.Should().BeFalse(); // Default value From ed9357c98894473e0010676de624bc53d08b1a9d Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 14:40:15 +0100 Subject: [PATCH 7/9] put comment in a better position --- .../AnalysisContext/SonarAnalysisContextBase.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index e781ca08688..10fa0142bfb 100644 --- a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs @@ -122,8 +122,10 @@ public bool HasMatchingScope(DiagnosticDescriptor descriptor) } private bool FileIsIncludedInAnalysis(SonarLintXmlReader sonarLintXml, string filePath) => - ProjectConfiguration().ProjectType != ProjectType.Unknown // If ProjectType != 'Unknown' we are in S4NET context and all files are analyzed. - // If ProjectType == '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. + // If ProjectType != 'Unknown' we are in S4NET context and all files are analyzed. + // If ProjectType == '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))); From 73cbdcf0eb53ebabca1f365ff92f48727ad4e7ac Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 15:53:23 +0100 Subject: [PATCH 8/9] rename mathod and condition --- .../AnalysisContext/SonarAnalysisContextBase.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index 10fa0142bfb..318b432f20d 100644 --- a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs @@ -55,7 +55,7 @@ protected SonarAnalysisContextBase(SonarAnalysisContext analysisContext, TContex public bool ShouldAnalyzeTree(SyntaxTree tree, GeneratedCodeRecognizer generatedCodeRecognizer) => SonarLintXml() is var sonarLintXml && (generatedCodeRecognizer is null || sonarLintXml.AnalyzeGeneratedCode || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) - && (tree is null || (!IsUnchanged(tree) && FileIsIncludedInAnalysis(sonarLintXml, tree.FilePath))); + && (tree is null || (!IsUnchanged(tree) && !IsExcluded(sonarLintXml, tree.FilePath))); /// /// Reads configuration from SonarProjectConfig.xml file and caches the result for scope of this analysis. @@ -121,13 +121,12 @@ public bool HasMatchingScope(DiagnosticDescriptor descriptor) descriptor.CustomTags.Contains(tag); } - private bool FileIsIncludedInAnalysis(SonarLintXmlReader sonarLintXml, string filePath) => - // If ProjectType != 'Unknown' we are in S4NET context and all files are analyzed. - // If ProjectType == '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 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()); From 828a16b8391e5bcf0fcb19df89c219ee3fb427cf Mon Sep 17 00:00:00 2001 From: mary-georgiou-sonarsource Date: Wed, 15 Mar 2023 16:15:55 +0100 Subject: [PATCH 9/9] fix issue from rebasing --- .../AnalysisContext/SonarAnalysisContextBase.cs | 2 +- .../SonarAnalyzer.Common/Rules/Utilities/UtilityAnalyzerBase.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs index 318b432f20d..90889c8ffd0 100644 --- a/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/AnalysisContext/SonarAnalysisContextBase.cs @@ -54,7 +54,7 @@ protected SonarAnalysisContextBase(SonarAnalysisContext analysisContext, TContex /// When set, generated trees are analyzed only when language-specific 'analyzeGeneratedCode' configuration property is also set. public bool ShouldAnalyzeTree(SyntaxTree tree, GeneratedCodeRecognizer generatedCodeRecognizer) => SonarLintXml() is var sonarLintXml - && (generatedCodeRecognizer is null || sonarLintXml.AnalyzeGeneratedCode || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) + && (generatedCodeRecognizer is null || sonarLintXml.AnalyzeGeneratedCode(Compilation.Language) || !tree.IsGenerated(generatedCodeRecognizer, Compilation)) && (tree is null || (!IsUnchanged(tree) && !IsExcluded(sonarLintXml, tree.FilePath))); /// 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");