diff --git a/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs b/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs
index adf692b344b..3813f713e83 100644
--- a/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs
+++ b/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs
@@ -22,12 +22,16 @@ namespace SonarAnalyzer.CFG.Helpers
{
public static class RoslynHelper
{
+ public const int VS2017MajorVersion = 2;
public const int MinimalSupportedMajorVersion = 3;
public static bool IsRoslynCfgSupported(int minimalVersion = MinimalSupportedMajorVersion) =>
- typeof(SemanticModel).Assembly.GetName().Version.Major >= minimalVersion;
+ !IsVersionLessThan(minimalVersion);
public static Type FlowAnalysisType(string typeName) =>
typeof(SemanticModel).Assembly.GetType("Microsoft.CodeAnalysis.FlowAnalysis." + typeName);
+
+ public static bool IsVersionLessThan(int minimalVersion = MinimalSupportedMajorVersion) =>
+ typeof(SemanticModel).Assembly.GetName().Version.Major < minimalVersion;
}
}
diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/AnalysisWarningAnalyzerBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/AnalysisWarningAnalyzerBase.cs
index 75054efae67..256612afd7c 100644
--- a/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/AnalysisWarningAnalyzerBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Rules/Utilities/AnalysisWarningAnalyzerBase.cs
@@ -28,7 +28,8 @@ public abstract class AnalysisWarningAnalyzerBase : UtilityAnalyzerBase
private const string DiagnosticId = "S9999-warning";
private const string Title = "Analysis Warning generator";
- protected virtual int MinimalSupportedRoslynVersion => RoslynHelper.MinimalSupportedMajorVersion; // For testing
+ protected virtual int VS2017MajorVersion => RoslynHelper.VS2017MajorVersion; // For testing
+ protected virtual int MinimalSupportedRoslynVersion => RoslynHelper.MinimalSupportedMajorVersion; // For testing
protected AnalysisWarningAnalyzerBase() : base(DiagnosticId, Title) { }
@@ -36,21 +37,36 @@ protected sealed override void Initialize(SonarAnalysisContext context) =>
context.RegisterCompilationAction(c =>
{
var parameter = ReadParameters(c);
- if (parameter.IsAnalyzerEnabled && !RoslynHelper.IsRoslynCfgSupported(MinimalSupportedRoslynVersion)) // MsBuild 15 is bound with Roslyn 2.x, where Roslyn CFG is not available.
+ if (!parameter.IsAnalyzerEnabled || parameter.OutPath is null)
{
- // This can be removed after we bump Microsoft.CodeAnalysis references to 3.0 or higher.
- var path = Path.GetFullPath(Path.Combine(parameter.OutPath, "../../AnalysisWarnings.MsBuild.json"));
- if (!File.Exists(path))
+ return;
+ }
+
+ var path = Path.GetFullPath(Path.Combine(parameter.OutPath, "../../AnalysisWarnings.MsBuild.json"));
+ if (!File.Exists(path))
+ {
+ // This can be removed after we bump Microsoft.CodeAnalysis references to 2.0 or higher. MsBuild 14 is bound with Roslyn 1.x.
+ if (RoslynHelper.IsVersionLessThan(VS2017MajorVersion))
{
- try
- {
- File.WriteAllText(path, """[{"text": "Analysis using MsBuild 14 and 15 build tools is deprecated. Please update your pipeline to MsBuild 16 or higher."}]""");
- }
- catch
- {
- // Nothing to do here. Two compilations running on two different processes are unlikely to lock each other out on a small file write.
- }
+ WriteAllText(path, "The analysis using MsBuild 14 is no longer supported and the analysis with MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher.");
+ }
+ // This can be removed after we bump Microsoft.CodeAnalysis references to 3.0 or higher. MsBuild 15 is bound with Roslyn 2.x.
+ else if (RoslynHelper.IsVersionLessThan(MinimalSupportedRoslynVersion))
+ {
+ WriteAllText(path, "The analysis using MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher.");
}
}
});
+
+ private static void WriteAllText(string path, string text)
+ {
+ try
+ {
+ File.WriteAllText(path, $$"""[{"text": "{{text}}"}]""");
+ }
+ catch
+ {
+ // Nothing to do here. Two compilations running on two different processes are unlikely to lock each other out on a small file write.
+ }
+ }
}
diff --git a/analyzers/tests/SonarAnalyzer.Test/Rules/Utilities/AnalysisWarningAnalyzerTest.cs b/analyzers/tests/SonarAnalyzer.Test/Rules/Utilities/AnalysisWarningAnalyzerTest.cs
index f6681dcad22..ab55580203c 100644
--- a/analyzers/tests/SonarAnalyzer.Test/Rules/Utilities/AnalysisWarningAnalyzerTest.cs
+++ b/analyzers/tests/SonarAnalyzer.Test/Rules/Utilities/AnalysisWarningAnalyzerTest.cs
@@ -37,37 +37,54 @@ public class AnalysisWarningAnalyzerTest
[DataRow(LanguageNames.CSharp, false)]
[DataRow(LanguageNames.VisualBasic, true)]
[DataRow(LanguageNames.VisualBasic, false)]
- public void SupportedRoslyn(string languageName, bool isAnalyzerEnabled)
+ public void AnalysisWarning_MSBuildSupportedScenario_NoWarning(string languageName, bool isAnalyzerEnabled)
{
- var expectedPath = ExecuteAnalyzer(languageName, isAnalyzerEnabled, RoslynHelper.MinimalSupportedMajorVersion); // Using production value that is lower than our UT Roslyn version
+ var expectedPath = ExecuteAnalyzer(languageName, isAnalyzerEnabled, RoslynHelper.VS2017MajorVersion, RoslynHelper.MinimalSupportedMajorVersion); // Using production value that is lower than our UT Roslyn version
File.Exists(expectedPath).Should().BeFalse("Analysis warning file should not be generated.");
}
[DataTestMethod]
[DataRow(LanguageNames.CSharp)]
[DataRow(LanguageNames.VisualBasic)]
- public void OldRoslyn(string languageName)
+ public void AnalysisWarning_MSBuild14UnsupportedScenario_GenerateWarning(string languageName)
{
- var expectedPath = ExecuteAnalyzer(languageName, true, 1000); // Requiring too high Roslyn version => we're under unsupported scenario
+ var expectedPath = ExecuteAnalyzer(languageName, true, 1000, 1001); // Requiring too high Roslyn version => we're under unsupported scenario
File.Exists(expectedPath).Should().BeTrue();
- File.ReadAllText(expectedPath).Should().Be("""[{"text": "Analysis using MsBuild 14 and 15 build tools is deprecated. Please update your pipeline to MsBuild 16 or higher."}]""");
+ File.ReadAllText(expectedPath).Should().Be("""[{"text": "The analysis using MsBuild 14 is no longer supported and the analysis with MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher."}]""");
+ }
+
+ [DataTestMethod]
+ [DataRow(LanguageNames.CSharp)]
+ [DataRow(LanguageNames.VisualBasic)]
+ public void AnalysisWarning_MSBuild15DeprecatedScenario_GenerateWarning(string languageName)
+ {
+ var expectedPath = ExecuteAnalyzer(languageName, true, RoslynHelper.VS2017MajorVersion, 1000); // Requiring too high Roslyn version => we're under unsupported scenario
+ File.Exists(expectedPath).Should().BeTrue();
+ File.ReadAllText(expectedPath).Should().Be("""[{"text": "The analysis using MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher."}]""");
+ }
+ [DataTestMethod]
+ [DataRow(LanguageNames.CSharp)]
+ [DataRow(LanguageNames.VisualBasic)]
+ public void AnalysisWarning_LockFile_PathShouldBeReused(string languageName)
+ {
+ var expectedPath = ExecuteAnalyzer(languageName, true, RoslynHelper.VS2017MajorVersion, 1000);
// Lock file and run it for 2nd time
using var lockedFile = new FileStream(expectedPath, FileMode.Open, FileAccess.Write, FileShare.None);
- ExecuteAnalyzer(languageName, true, 1000).Should().Be(expectedPath, "path should be reused and analyzer should not fail");
+ ExecuteAnalyzer(languageName, true, RoslynHelper.VS2017MajorVersion, 1000).Should().Be(expectedPath, "path should be reused and analyzer should not fail");
}
[DataTestMethod]
[DataRow(LanguageNames.CSharp)]
[DataRow(LanguageNames.VisualBasic)]
- public void FileExceptions_AreIgnored(string languageName)
+ public void AnalysisWarning_FileExceptions_AreIgnored(string languageName)
{
// This will not create the output directory, causing an exception in the File.WriteAllText(...)
- var expectedPath = ExecuteAnalyzer(languageName, true, 1000, false); // Requiring too high Roslyn version => we're under unsupported scenario
+ var expectedPath = ExecuteAnalyzer(languageName, true, 500, 1000, false); // Requiring too high Roslyn version => we're under unsupported scenario
File.Exists(expectedPath).Should().BeFalse();
}
- private string ExecuteAnalyzer(string languageName, bool isAnalyzerEnabled, int minimalSupportedRoslynVersion, bool createDirectory = true)
+ private string ExecuteAnalyzer(string languageName, bool isAnalyzerEnabled, int vs2017MajorVersion, int minimalSupportedRoslynVersion, bool createDirectory = true)
{
var language = AnalyzerLanguage.FromName(languageName);
var analysisOutPath = TestHelper.TestPath(TestContext, @$"{languageName}\.sonarqube\out");
@@ -78,8 +95,8 @@ private string ExecuteAnalyzer(string languageName, bool isAnalyzerEnabled, int
}
UtilityAnalyzerBase analyzer = language.LanguageName switch
{
- LanguageNames.CSharp => new TestAnalysisWarningAnalyzer_CS(isAnalyzerEnabled, minimalSupportedRoslynVersion, projectOutPath),
- LanguageNames.VisualBasic => new TestAnalysisWarningAnalyzer_VB(isAnalyzerEnabled, minimalSupportedRoslynVersion, projectOutPath),
+ LanguageNames.CSharp => new TestAnalysisWarningAnalyzer_CS(isAnalyzerEnabled, vs2017MajorVersion, minimalSupportedRoslynVersion, projectOutPath),
+ LanguageNames.VisualBasic => new TestAnalysisWarningAnalyzer_VB(isAnalyzerEnabled, vs2017MajorVersion, minimalSupportedRoslynVersion, projectOutPath),
_ => throw new UnexpectedLanguageException(language)
};
new VerifierBuilder().AddAnalyzer(() => analyzer).AddSnippet(string.Empty).VerifyNoIssueReported(); // Nothing to analyze, just make it run
@@ -90,11 +107,13 @@ private sealed class TestAnalysisWarningAnalyzer_CS : CS.AnalysisWarningAnalyzer
{
private readonly bool isAnalyzerEnabled;
private readonly string outPath;
+ protected override int VS2017MajorVersion { get; }
protected override int MinimalSupportedRoslynVersion { get; }
- public TestAnalysisWarningAnalyzer_CS(bool isAnalyzerEnabled, int minimalSupportedRoslynVersion, string outPath)
+ public TestAnalysisWarningAnalyzer_CS(bool isAnalyzerEnabled, int vs2017MajorVersion, int minimalSupportedRoslynVersion, string outPath)
{
this.isAnalyzerEnabled = isAnalyzerEnabled;
+ VS2017MajorVersion = vs2017MajorVersion;
MinimalSupportedRoslynVersion = minimalSupportedRoslynVersion;
this.outPath = outPath;
}
@@ -107,11 +126,13 @@ private sealed class TestAnalysisWarningAnalyzer_VB : VB.AnalysisWarningAnalyzer
{
private readonly bool isAnalyzerEnabled;
private readonly string outPath;
+ protected override int VS2017MajorVersion { get; }
protected override int MinimalSupportedRoslynVersion { get; }
- public TestAnalysisWarningAnalyzer_VB(bool isAnalyzerEnabled, int minimalSupportedRoslynVersion, string outPath)
+ public TestAnalysisWarningAnalyzer_VB(bool isAnalyzerEnabled, int vs2017MajorVersion, int minimalSupportedRoslynVersion, string outPath)
{
this.isAnalyzerEnabled = isAnalyzerEnabled;
+ VS2017MajorVersion = vs2017MajorVersion;
MinimalSupportedRoslynVersion = minimalSupportedRoslynVersion;
this.outPath = outPath;
}
diff --git a/its/projects/Roslyn.1.3.1/OldRoslyn.cs b/its/projects/Roslyn.1.3.2/OldRoslyn.cs
similarity index 100%
rename from its/projects/Roslyn.1.3.1/OldRoslyn.cs
rename to its/projects/Roslyn.1.3.2/OldRoslyn.cs
diff --git a/its/projects/Roslyn.1.3.2/Roslyn.1.3.2.csproj b/its/projects/Roslyn.1.3.2/Roslyn.1.3.2.csproj
new file mode 100644
index 00000000000..f9041192003
--- /dev/null
+++ b/its/projects/Roslyn.1.3.2/Roslyn.1.3.2.csproj
@@ -0,0 +1,11 @@
+
+
+
+ net48
+
+
+
+
+
+
+
diff --git a/its/projects/Roslyn.1.3.1/Roslyn.1.3.1.sln b/its/projects/Roslyn.1.3.2/Roslyn.1.3.2.sln
similarity index 88%
rename from its/projects/Roslyn.1.3.1/Roslyn.1.3.1.sln
rename to its/projects/Roslyn.1.3.2/Roslyn.1.3.2.sln
index 264db477dc7..cc74993e5aa 100644
--- a/its/projects/Roslyn.1.3.1/Roslyn.1.3.1.sln
+++ b/its/projects/Roslyn.1.3.2/Roslyn.1.3.2.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32811.315
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roslyn.1.3.1", "Roslyn.1.3.1.csproj", "{151E9036-31F1-481F-BBCE-6C663F21EB31}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roslyn.1.3.2", "Roslyn.1.3.2.csproj", "{151E9036-31F1-481F-BBCE-6C663F21EB31}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/its/projects/Roslyn.1.3.2/packages.lock.json b/its/projects/Roslyn.1.3.2/packages.lock.json
new file mode 100644
index 00000000000..bfdf68d3392
--- /dev/null
+++ b/its/projects/Roslyn.1.3.2/packages.lock.json
@@ -0,0 +1,21 @@
+{
+ "version": 1,
+ "dependencies": {
+ ".NETFramework,Version=v4.8": {
+ "Microsoft.CodeDom.Providers.DotNetCompilerPlatform": {
+ "type": "Direct",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "7G2GcPc9aveqUa2t1a4OZmfs4RqSlalpHC94KILFswIDLCTGrser0ymXi7TnUI5gAIHhfn2dEjpIb5taxPWU5g==",
+ "dependencies": {
+ "Microsoft.Net.Compilers": "1.3.2"
+ }
+ },
+ "Microsoft.Net.Compilers": {
+ "type": "Transitive",
+ "resolved": "1.3.2",
+ "contentHash": "usbCzvNYmSWTdlsJM8FYm1NgGPdM+njnBzerAn3xKGy4/prztHcofq7CMiO7Lb0AK71jXKUzmUuW9Fc0cIzdbQ=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/its/projects/Roslyn.2.4.0/OldRoslyn.cs b/its/projects/Roslyn.2.4.0/OldRoslyn.cs
new file mode 100644
index 00000000000..aa524e74323
--- /dev/null
+++ b/its/projects/Roslyn.2.4.0/OldRoslyn.cs
@@ -0,0 +1,7 @@
+namespace Roslyn
+{
+ public class OldRoslyn
+ {
+ // Nothing to see here
+ }
+}
diff --git a/its/projects/Roslyn.1.3.1/Roslyn.1.3.1.csproj b/its/projects/Roslyn.2.4.0/Roslyn.2.4.0.csproj
similarity index 72%
rename from its/projects/Roslyn.1.3.1/Roslyn.1.3.1.csproj
rename to its/projects/Roslyn.2.4.0/Roslyn.2.4.0.csproj
index 7bd0c451241..5f04cb99e30 100644
--- a/its/projects/Roslyn.1.3.1/Roslyn.1.3.1.csproj
+++ b/its/projects/Roslyn.2.4.0/Roslyn.2.4.0.csproj
@@ -1,11 +1,11 @@
-
+
net48
-
+
diff --git a/its/projects/Roslyn.2.4.0/Roslyn.2.4.0.sln b/its/projects/Roslyn.2.4.0/Roslyn.2.4.0.sln
new file mode 100644
index 00000000000..c92130659f6
--- /dev/null
+++ b/its/projects/Roslyn.2.4.0/Roslyn.2.4.0.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32811.315
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roslyn.2.4.0", "Roslyn.2.4.0.csproj", "{151E9036-31F1-481F-BBCE-6C663F21EB31}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {151E9036-31F1-481F-BBCE-6C663F21EB31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {151E9036-31F1-481F-BBCE-6C663F21EB31}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {151E9036-31F1-481F-BBCE-6C663F21EB31}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {151E9036-31F1-481F-BBCE-6C663F21EB31}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0E15ED11-FF3B-4CCE-8940-EFE27FCC42FD}
+ EndGlobalSection
+EndGlobal
diff --git a/its/projects/Roslyn.1.3.1/packages.lock.json b/its/projects/Roslyn.2.4.0/packages.lock.json
similarity index 100%
rename from its/projects/Roslyn.1.3.1/packages.lock.json
rename to its/projects/Roslyn.2.4.0/packages.lock.json
diff --git a/its/src/test/java/com/sonar/it/csharp/AnalysisWarningsTest.java b/its/src/test/java/com/sonar/it/csharp/AnalysisWarningsTest.java
index aad6f18021d..ff6bbdf14c4 100644
--- a/its/src/test/java/com/sonar/it/csharp/AnalysisWarningsTest.java
+++ b/its/src/test/java/com/sonar/it/csharp/AnalysisWarningsTest.java
@@ -56,10 +56,18 @@ void analysisWarningsImport() throws IOException {
}
@Test
- void analysisWarnings_OldRoslyn() throws IOException {
- BuildResult buildResult = Tests.analyzeProject(temp, "Roslyn.1.3.1");
+ void analysisWarnings_MSBuild14() throws IOException {
+ BuildResult buildResult = Tests.analyzeProject(temp, "Roslyn.1.3.2");
Ce.Task task = TestUtils.getAnalysisWarningsTask(ORCHESTRATOR, buildResult);
assertThat(task.getStatus()).isEqualTo(Ce.TaskStatus.SUCCESS);
- assertThat(task.getWarningsList()).containsExactly("Analysis using MsBuild 14 and 15 build tools is deprecated. Please update your pipeline to MsBuild 16 or higher.");
+ assertThat(task.getWarningsList()).containsExactly("The analysis using MsBuild 14 is no longer supported and the analysis with MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher.");
+ }
+
+ @Test
+ void analysisWarnings_MSBuild15() throws IOException {
+ BuildResult buildResult = Tests.analyzeProject(temp, "Roslyn.2.4.0");
+ Ce.Task task = TestUtils.getAnalysisWarningsTask(ORCHESTRATOR, buildResult);
+ assertThat(task.getStatus()).isEqualTo(Ce.TaskStatus.SUCCESS);
+ assertThat(task.getWarningsList()).containsExactly("The analysis using MsBuild 15 is deprecated. Please update your pipeline to MsBuild 16 or higher.");
}
}