Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SonarAnalysisContextBase refactoring #6915

Expand Up @@ -53,9 +53,9 @@ protected SonarAnalysisContextBase(SonarAnalysisContext analysisContext, TContex
/// <param name="tree">Tree to decide on. Can be null for Symbol-based and Compilation-based scenarios. And we want to analyze those too.</param>
/// <param name="generatedCodeRecognizer">When set, generated trees are analyzed only when language-specific 'analyzeGeneratedCode' configuration property is also set.</param>
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)));

/// <summary>
/// Reads configuration from SonarProjectConfig.xml file and caches the result for scope of this analysis.
Expand All @@ -79,7 +79,7 @@ public ProjectConfigReader ProjectConfiguration()
/// <summary>
/// Reads the properties from the SonarLint.xml file and caches the result for the scope of this analysis.
/// </summary>
public SonarLintXmlReader SonarLintFile()
public SonarLintXmlReader SonarLintXml()
{
if (Options.SonarLintXml() is { } sonarLintXml)
{
Expand Down Expand Up @@ -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<string> CreateUnchangedFilesHashSet() =>
ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, ProjectConfiguration().AnalysisConfig?.UnchangedFiles() ?? Array.Empty<string>());
Expand Down
Expand Up @@ -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);
});
}
Expand Down
Expand Up @@ -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<string>() : str.Split(',');
Expand Down
Expand Up @@ -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");
Expand Down
Expand Up @@ -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();
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}

Expand All @@ -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<InvalidOperationException>()
.WithMessage("File 'SonarLint.xml' has been added as an AdditionalFile but could not be read and parsed.");
Expand Down
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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);
}

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down