From 3a86bebbfc8d385ba021313a316d3442e64d5d82 Mon Sep 17 00:00:00 2001 From: Michael Jabbour Date: Thu, 28 Nov 2024 21:13:55 +0100 Subject: [PATCH 1/4] Include language information for headers in the command line This helps analyze headers in C projects as C code. This is needed now that we no longer pass HeaderFileLanguage separately to the analyzer. --- .../CFamily/CmdBuilderTests.cs | 10 +++++----- .../CFamily/VcxProject/FileConfigTests.cs | 12 +++++++++++- .../CFamily/VcxProject/CmdBuilder.cs | 5 +---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs b/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs index eaf1bd6a6..352b49b5d 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs @@ -318,10 +318,10 @@ public void AddOptFromProperties(string input, string output, string cmd) } [TestMethod] - [DataRow("Default", "cpp")] - [DataRow("CompileAsC", "c")] - [DataRow("CompileAsCpp", "cpp")] - public void HeaderFileLang(string compileAs, string lang) + [DataRow("Default", "cpp", "")] + [DataRow("CompileAsC", "c", "/TC ")] + [DataRow("CompileAsCpp", "cpp", "/TP ")] + public void HeaderFileLang(string compileAs, string lang, string cmd) { var cmdBuilder = new CmdBuilder(true); var settingsMock = new Mock(); @@ -329,7 +329,7 @@ public void HeaderFileLang(string compileAs, string lang) cmdBuilder.AddOptFromProperties(settingsMock.Object); - cmdBuilder.GetFullCmd().Should().Be(""); + cmdBuilder.GetFullCmd().Should().Be(cmd); cmdBuilder.HeaderFileLang.Should().Be(lang); } diff --git a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs index be9ff0e45..a5e982f08 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs @@ -185,8 +185,18 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() request = FileConfig.TryGet(testLogger, projectItemMock.Object, "c:\\dummy\\file.h"); // Assert - Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu \"c:\\dummy\\file.h\"", request.CDCommand); + Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TC \"c:\\dummy\\file.h\"", request.CDCommand); Assert.AreEqual("c", request.HeaderFileLanguage); + + // Arrange + projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsCpp"; + + // Act + request = FileConfig.TryGet(testLogger, projectItemMock.Object, "c:\\dummy\\file.h"); + + // Assert + Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TP \"c:\\dummy\\file.h\"", request.CDCommand); + Assert.AreEqual("cpp", request.HeaderFileLanguage); } [TestMethod] diff --git a/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs b/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs index 5774d6170..6fdbf642a 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs @@ -171,10 +171,7 @@ internal void AddOptFromProperties(IVCRulePropertyStorage properties) { HeaderFileLang = (compileAs == "CompileAsC") ? "c" : "cpp"; } - else - { - AddCmdOpt(ConvertCompileAsAndGetLanguage(compileAs)); - } + AddCmdOpt(ConvertCompileAsAndGetLanguage(compileAs)); // Additional options var additionalOptions = properties.GetEvaluatedPropertyValue("AdditionalOptions"); From de4d54c2279817bfdf0c99a8b02e94c6e6a228e8 Mon Sep 17 00:00:00 2001 From: Michael Jabbour Date: Fri, 29 Nov 2024 16:31:46 +0100 Subject: [PATCH 2/4] Drop HeaderFileLanguage since it is no longer passed --- .../CFamily/CmdBuilderTests.cs | 11 ++++------- .../CFamily/VcxProject/FileConfigTests.cs | 4 ---- src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs | 5 ----- src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs | 4 ++-- .../CFamily/VcxProject/IFileConfig.cs | 1 - 5 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs b/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs index 352b49b5d..f24886bc9 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/CmdBuilderTests.cs @@ -314,14 +314,13 @@ public void AddOptFromProperties(string input, string output, string cmd) cmdBuilder.AddOptFromProperties(settingsMock.Object); cmdBuilder.GetFullCmd().Should().Be(cmd); - cmdBuilder.HeaderFileLang.Should().Be(""); } [TestMethod] - [DataRow("Default", "cpp", "")] - [DataRow("CompileAsC", "c", "/TC ")] - [DataRow("CompileAsCpp", "cpp", "/TP ")] - public void HeaderFileLang(string compileAs, string lang, string cmd) + [DataRow("Default", "")] + [DataRow("CompileAsC", "/TC ")] + [DataRow("CompileAsCpp", "/TP ")] + public void HeaderFileLang(string compileAs, string cmd) { var cmdBuilder = new CmdBuilder(true); var settingsMock = new Mock(); @@ -330,7 +329,6 @@ public void HeaderFileLang(string compileAs, string lang, string cmd) cmdBuilder.AddOptFromProperties(settingsMock.Object); cmdBuilder.GetFullCmd().Should().Be(cmd); - cmdBuilder.HeaderFileLang.Should().Be(lang); } [TestMethod] @@ -391,7 +389,6 @@ public void PCHUse() cmdBuilder.AddOptFromProperties(settingsMock.Object); cmdBuilder.GetFullCmd().Should().Be("/Yc\"C:\\pch.h\" "); - cmdBuilder.HeaderFileLang.Should().Be(""); } [TestMethod] diff --git a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs index a5e982f08..587e11f84 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs @@ -139,7 +139,6 @@ public void TryGet_Full_Cmd() // Assert request.Should().NotBeNull(); Assert.AreEqual("\"C:\\path\\cl.exe\" /permissive- /std:c++17 /EHsc /arch:AVX512 /MT /RTCu /Zp8 /TP /DA \"c:\\dummy\\file.cpp\"", request.CDCommand); - Assert.AreEqual("", request.HeaderFileLanguage); Assert.AreEqual("C:\\path\\includeDir1;C:\\path\\includeDir2;C:\\path\\includeDir3;", request.EnvInclude); Assert.AreEqual("c:\\dummy\\file.cpp", request.CDFile); Assert.AreEqual("c:\\foo", request.CDDirectory); @@ -175,7 +174,6 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert request.Should().NotBeNull(); Assert.AreEqual("\"C:\\path\\cl.exe\" /Yu\"pch.h\" /FI\"pch.h\" /EHsc /RTCu \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("cpp", request.HeaderFileLanguage); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsC"; @@ -186,7 +184,6 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TC \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("c", request.HeaderFileLanguage); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsCpp"; @@ -196,7 +193,6 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TP \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("cpp", request.HeaderFileLanguage); } [TestMethod] diff --git a/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs b/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs index 6fdbf642a..fda75c0b4 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/CmdBuilder.cs @@ -39,7 +39,6 @@ internal class CmdBuilder StringBuilder Cmd { get; set; } = new StringBuilder(); bool IsHeader { get; set; } - public string HeaderFileLang { get; set; } = ""; public CmdBuilder(bool isHeader) { @@ -167,10 +166,6 @@ internal void AddOptFromProperties(IVCRulePropertyStorage properties) AddCmdOpt(ConvertStructMemberAlignment(structMemberAlignment)); var compileAs = properties.GetEvaluatedPropertyValue("CompileAs"); - if (IsHeader) - { - HeaderFileLang = (compileAs == "CompileAsC") ? "c" : "cpp"; - } AddCmdOpt(ConvertCompileAsAndGetLanguage(compileAs)); // Additional options diff --git a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs index cdb23dbef..93e11de61 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs @@ -45,6 +45,7 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri // Not supported return null; } + CmdBuilder cmdBuilder = new CmdBuilder(vcFile.ItemType == "ClInclude"); var compilerPath = vcConfig.GetEvaluatedPropertyValue("ClCompilerPath"); @@ -76,7 +77,6 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri CDCommand = cmdBuilder.GetFullCmd(), CDFile = absoluteFilePath, EnvInclude = envINCLUDE, - HeaderFileLanguage = cmdBuilder.HeaderFileLang, }; } @@ -134,7 +134,7 @@ private static IVCRulePropertyStorage GetVcFileSettings(ILogger logger, string a public string CDCommand { get; set; } public string CDFile { get; set; } public string EnvInclude { get; set; } - public string HeaderFileLanguage { get; set; } + #endregion } diff --git a/src/Integration.Vsix/CFamily/VcxProject/IFileConfig.cs b/src/Integration.Vsix/CFamily/VcxProject/IFileConfig.cs index 2f956be6a..874cfe1c3 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/IFileConfig.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/IFileConfig.cs @@ -26,6 +26,5 @@ internal interface IFileConfig string CDCommand { get; } string CDFile { get; } string EnvInclude { get; } - string HeaderFileLanguage { get; } } } From 76f9398745d25cf627df0c9a9f7703feb9b8d8e2 Mon Sep 17 00:00:00 2001 From: Michael Jabbour Date: Fri, 29 Nov 2024 16:49:56 +0100 Subject: [PATCH 3/4] Workaround for identifying header files in the CFamily analyzer Normally, the CFamily analyzer deduces that the file being analyzed is a header when there is no exact match for the file name in the given compilation database. This is a temporary workaround to communicate with the analyzer that the current file is a header file. This helps the analyzer avoid reporting some FPs. See https://sonarsource.atlassian.net/browse/CPP-2743 --- .../CFamily/VcxProject/FileConfigTests.cs | 3 +++ src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs index 587e11f84..8465e4664 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs @@ -174,6 +174,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert request.Should().NotBeNull(); Assert.AreEqual("\"C:\\path\\cl.exe\" /Yu\"pch.h\" /FI\"pch.h\" /EHsc /RTCu \"c:\\dummy\\file.h\"", request.CDCommand); + Assert.AreEqual("non_existent_file", request.CDFile); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsC"; @@ -184,6 +185,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TC \"c:\\dummy\\file.h\"", request.CDCommand); + Assert.AreEqual("non_existent_file", request.CDFile); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsCpp"; @@ -193,6 +195,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TP \"c:\\dummy\\file.h\"", request.CDCommand); + Assert.AreEqual("non_existent_file", request.CDFile); } [TestMethod] diff --git a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs index 93e11de61..1285eb00a 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs @@ -46,7 +46,8 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri return null; } - CmdBuilder cmdBuilder = new CmdBuilder(vcFile.ItemType == "ClInclude"); + var isHeader = vcFile.ItemType == "ClInclude"; + CmdBuilder cmdBuilder = new CmdBuilder(isHeader); var compilerPath = vcConfig.GetEvaluatedPropertyValue("ClCompilerPath"); if (string.IsNullOrEmpty(compilerPath)) @@ -75,7 +76,9 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri { CDDirectory = Path.GetDirectoryName(vcProject.ProjectFile), CDCommand = cmdBuilder.GetFullCmd(), - CDFile = absoluteFilePath, + // A hack to communicate with the CFamily analyzer that this is a header file. + // A long-term solution should be investigated in CPP-5898. + CDFile = isHeader ? "non_existent_file" : absoluteFilePath, EnvInclude = envINCLUDE, }; } From 471a48f2a7b468ab89c7651ce3d1a82b8dbc32dc Mon Sep 17 00:00:00 2001 From: Michael Jabbour Date: Mon, 2 Dec 2024 11:04:40 +0100 Subject: [PATCH 4/4] Revert hack for passing MainFileIsHeader --- .../CFamily/VcxProject/FileConfigTests.cs | 6 +++--- src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs index 8465e4664..7f3434592 100644 --- a/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs +++ b/src/Integration.Vsix.UnitTests/CFamily/VcxProject/FileConfigTests.cs @@ -174,7 +174,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert request.Should().NotBeNull(); Assert.AreEqual("\"C:\\path\\cl.exe\" /Yu\"pch.h\" /FI\"pch.h\" /EHsc /RTCu \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("non_existent_file", request.CDFile); + Assert.AreEqual("c:\\dummy\\file.h", request.CDFile); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsC"; @@ -185,7 +185,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TC \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("non_existent_file", request.CDFile); + Assert.AreEqual("c:\\dummy\\file.h", request.CDFile); // Arrange projectItemConfig.FileConfigProperties["CompileAs"] = "CompileAsCpp"; @@ -195,7 +195,7 @@ public void TryGet_HeaderFileOptions_ReturnsValidConfig() // Assert Assert.AreEqual("\"C:\\path\\cl.exe\" /FI\"FHeader.h\" /Yu\"pch.h\" /EHsc /RTCu /TP \"c:\\dummy\\file.h\"", request.CDCommand); - Assert.AreEqual("non_existent_file", request.CDFile); + Assert.AreEqual("c:\\dummy\\file.h", request.CDFile); } [TestMethod] diff --git a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs index 1285eb00a..93e11de61 100644 --- a/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs +++ b/src/Integration.Vsix/CFamily/VcxProject/FileConfig.cs @@ -46,8 +46,7 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri return null; } - var isHeader = vcFile.ItemType == "ClInclude"; - CmdBuilder cmdBuilder = new CmdBuilder(isHeader); + CmdBuilder cmdBuilder = new CmdBuilder(vcFile.ItemType == "ClInclude"); var compilerPath = vcConfig.GetEvaluatedPropertyValue("ClCompilerPath"); if (string.IsNullOrEmpty(compilerPath)) @@ -76,9 +75,7 @@ public static FileConfig TryGet(ILogger logger, ProjectItem dteProjectItem, stri { CDDirectory = Path.GetDirectoryName(vcProject.ProjectFile), CDCommand = cmdBuilder.GetFullCmd(), - // A hack to communicate with the CFamily analyzer that this is a header file. - // A long-term solution should be investigated in CPP-5898. - CDFile = isHeader ? "non_existent_file" : absoluteFilePath, + CDFile = absoluteFilePath, EnvInclude = envINCLUDE, }; }