|
|
@@ -1,618 +1,618 @@
|
|
|
-<?xml version="1.0" encoding="utf-8"?>
|
|
|
-<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
|
-
|
|
|
- <!--
|
|
|
- This file contains targets to integrate SonarQube and MSBuild.
|
|
|
-
|
|
|
- The targets will produce an output folder structure containing information required by the sonar-scanner.
|
|
|
-
|
|
|
- A subdirectory will be created for each MSBuild project. Information about the project
|
|
|
- will be written to a file called "ProjectInfo.xml". Additional files may also be written
|
|
|
- containing information required by different analyzers. In particular, a file will be written
|
|
|
- containing the list of files in the project that should be analyzed by the sonar-scanner.
|
|
|
-
|
|
|
- The output will only be produced if the property $(SonarQubeTempPath) and is specified.
|
|
|
- $(SonarQubeTempPath) is the root folder under which per-analysis output should be written.
|
|
|
-
|
|
|
- Excluding projects and files from SonarQube analysis
|
|
|
- ****************************************************
|
|
|
- Individual projects can excluded from SonarQube analysis by setting the property $(SonarQubeExclude) e.g.
|
|
|
-
|
|
|
- <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
-
|
|
|
- Individual files can be excluded from analysis by setting the <SonarQubeExclude> metadata item e.g.
|
|
|
-
|
|
|
- <Compile Include="Logger.cs">
|
|
|
- <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
- </Compile>
|
|
|
-
|
|
|
- Project is also excluded if it's recognized as a Fakes or a Temp project. These projects are auto-generated.
|
|
|
-
|
|
|
- Test projects
|
|
|
- *************
|
|
|
- The analysis performed by SonarQube varies depending on whether a project is a test project or not.
|
|
|
-
|
|
|
- A project can be explicitly marked as being a test or product project by setting the property $(SonarQubeTestProject) e.g.
|
|
|
-
|
|
|
- <SonarQubeTestProject>true</SonarQubeTestProject>
|
|
|
-
|
|
|
- If $(SonarQubeTestProject) is not set explicitly then the project is categorized as a Test project if:
|
|
|
- * Is a Fakes or a Temp project explicitly marked as SonarQubeExclude=false
|
|
|
- * Has one of the expected test project GUIDs ("3AC096D0-A1C2-E12C-1390-A8335801FDAB" or legacy "82A7F48D-3B50-4B1E-B82E-3ADA8210C358").
|
|
|
- * Has a TestContainer project capability.
|
|
|
- * References a known unit test related assembly.
|
|
|
- * Deprecated: Project name matches "sonar.msbuild.testProjectPattern" parameter. Use SonarQubeTestProject=true instead.
|
|
|
-
|
|
|
- Otherwise it is a Product project.
|
|
|
-
|
|
|
- Supplying analysis setting in a project file
|
|
|
- ********************************************
|
|
|
- Project-level analysis settings can be specified in a project file using following
|
|
|
- syntax:
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <SonarQubeSetting Include="sonar.my.analysis.setting">
|
|
|
- <Value>42</Value>
|
|
|
- </SonarQubeSetting>
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- Settings specified in the project file will override those specified on the SonarQube server.
|
|
|
-
|
|
|
- Specifying additional types of file to be analysed
|
|
|
- **************************************************
|
|
|
-
|
|
|
- The Scanner for MSBuild will automatically collect all of the common
|
|
|
- file types that can be analysed by the various Sonar language plugins
|
|
|
- (e.g. C# files, TypeScript, TSQL, C++ include and source files etc).
|
|
|
- The full list of item types that will be included for analysis is
|
|
|
- specified in $(SQAnalysisFileItemTypes) property below.
|
|
|
-
|
|
|
- If you have any additional item types that you want to have analyzed,
|
|
|
- you can specify them setting the property $(SQAdditionalAnalysisFileItemTypes)
|
|
|
- in the project being analysed e.g.
|
|
|
-
|
|
|
- <SQAdditionalAnalysisFileItemTypes>MyCustomFileType1;MyCustomFileType</SQAdditionalAnalysisFileItemTypes>
|
|
|
-
|
|
|
- Specific handling of Razor builds
|
|
|
- **************************************************
|
|
|
- During the compilation of an SDK-style MSBuild project with Razor, MSBuild executes 2 build targets:
|
|
|
- CoreCompile to compile the main code and RazorCoreCompile to compile ".cshtml" view files.
|
|
|
- Since it is not possible to execute one target more than once, there's a logic that prevents RazorCoreCompile
|
|
|
- from overriding output files from CoreCompile step:
|
|
|
- * CoreCompile produces output files in directory "X", where X represents project specific unique number.
|
|
|
- * Directory "X" with CoreCompile results is renamed to "X.tmp" before RazorCoreCompile and new empty directory "X" is prepared.
|
|
|
- * RazorCoreCompile produces its output to the current directory "X".
|
|
|
- * Directory "X" with Razor output is renamed to "X.Razor".
|
|
|
- * Directory "X.tmp" with original output is renamed back to "X".
|
|
|
--->
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- SonarQube MSBuild Integration implementation logic -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Note: where possible, these targets avoid taking dependencies on specific
|
|
|
- managed or C++- targets e.g. they use
|
|
|
- "AfterTargets='Build'" which is general rather than
|
|
|
- "AfterTargets='CoreCompile'" which is specific to managed projects.
|
|
|
- -->
|
|
|
-
|
|
|
- <!-- Safeguard against importing this .targets file multiple times -->
|
|
|
- <PropertyGroup>
|
|
|
- <SonarQubeTargetsImported>true</SonarQubeTargetsImported>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!-- Set defaults if explicit values have not been provided -->
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
- <SonarQubeConfigPath Condition=" $(SonarQubeConfigPath) == '' ">$(SonarQubeTempPath)\conf</SonarQubeConfigPath>
|
|
|
- <SonarQubeOutputPath Condition=" $(SonarQubeOutputPath) == '' ">$(SonarQubeTempPath)\out</SonarQubeOutputPath>
|
|
|
-
|
|
|
- <!-- Specify the ItemGroups to be analyzed -->
|
|
|
- <SQAnalysisFileItemTypes Condition=" $(SQAnalysisFileItemTypes) == '' ">AndroidEnvironment;AndroidJavaSource;AndroidResource;ApplicationDefinition;Build;ClCompile;ClInclude;Compile;Content;DeploymentExtensionConfiguration;EmbeddedResource;EntityDeploy;None;Page;PostDeploy;PRIResource;PreDeploy;RefactorLog;Resource;Script;ScriptCode;TypeScriptCompile;$(SQAdditionalAnalysisFileItemTypes)</SQAnalysisFileItemTypes>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Using tasks -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTempPath) != '' AND $(SonarQubeBuildTasksAssemblyFile) == '' ">
|
|
|
- <!-- Assume that the tasks assembly is in the same location as this targets file
|
|
|
- or in a parent directory unless another location has already been specified. -->
|
|
|
- <SonarQubeBuildTasksAssemblyFile>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), SonarScanner.MSBuild.Tasks.dll))\SonarScanner.MSBuild.Tasks.dll</SonarQubeBuildTasksAssemblyFile>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!-- Unescape the paths to work around the issue "MSBuild 4.0 UsingTask cannot have a path with parentheses".
|
|
|
- See https://connect.microsoft.com/VisualStudio/feedback/details/713690/msbuild-4-0-usingtask-cannot-have-a-path-with-parentheses -->
|
|
|
- <UsingTask TaskName="WriteProjectConfigFile" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="WriteProjectInfoFile" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="IsTestFileByName" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="IsTestByReference" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="GetAnalyzerSettings" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="MakeUniqueDir" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
- <UsingTask TaskName="WriteZeroLengthFiles" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Targets -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
-
|
|
|
- <Target Name="SkippingSonarQubeAnalysis" BeforeTargets="Build"
|
|
|
- Condition=" $(SonarQubeTempPath) == '' ">
|
|
|
- <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Skipping dumping compile outputs because SonarQubeTempPath has not been specified" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="FailIfLowerThanMSBuild14"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) != '14.0' AND $(MSBuildToolsVersion) != '15.0' AND $(MSBuildToolsVersion) != 'Current'"
|
|
|
- BeforeTargets="Build">
|
|
|
- <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Current MSBuildToolsVersion: $(MSBuildToolsVersion)" />
|
|
|
- <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Current MSBuildAssemblyVersion: $(MSBuildAssemblyVersion)" />
|
|
|
- <Error Text="SonarQube analysis is only supported with MSBuild 14 or later." />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="SonarResolveReferencesMsBuild14"
|
|
|
- AfterTargets="ResolveAssemblyReferences"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) == '14.0'">
|
|
|
- <ItemGroup>
|
|
|
- <SonarResolvedReferences Include="@(%(ReferencePath.FusionName))" />
|
|
|
- </ItemGroup>
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="SonarResolveReferences"
|
|
|
- AfterTargets="FindReferenceAssembliesForReferences"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) != '14.0'">
|
|
|
- <ItemGroup>
|
|
|
- <SonarResolvedReferences Include="@(%(ReferencePathWithRefAssemblies.FusionName))" />
|
|
|
- </ItemGroup>
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Categorize as a product or test project -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- This target is a utility target: it won't be executed unless a target that depends on it is executed. -->
|
|
|
- <Target Name="SonarCategoriseProject"
|
|
|
- DependsOnTargets="SonarResolveReferencesMsBuild14;SonarResolveReferences"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
-
|
|
|
- <Message Text="Sonar: ($(MSBuildProjectFile)) Categorizing project as test or product code..." />
|
|
|
- <Message Condition="$(SonarQubeTestProject) != ''" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) SonarQubeTestProject has been set explicitly to $(SonarQubeTestProject)." />
|
|
|
-
|
|
|
- <!-- Fakes detection -->
|
|
|
- <PropertyGroup>
|
|
|
- <IsFakesProject Condition="$(AssemblyName.EndsWith('.fakes', System.StringComparison.OrdinalIgnoreCase))">true</IsFakesProject>
|
|
|
- </PropertyGroup>
|
|
|
- <!-- Before deciding to exclude or tag as test such a project, make sure it is not a legitimate project that happens to be called something.fakes
|
|
|
- In this case, we require from the user to explicitely state whether the project is to be analyzed/considered a test project -->
|
|
|
- <PropertyGroup Condition="$(IsFakesProject) == 'true' and $(SonarQubeExclude) == ''">
|
|
|
- <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
- </PropertyGroup>
|
|
|
- <PropertyGroup Condition="$(IsFakesProject) == 'true' and $(SonarQubeTestProject) == ''">
|
|
|
- <SonarQubeTestProject>true</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(IsFakesProject) == 'true' and $(SonarQubeExclude) == 'true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is a temporary project generated by Microsoft Fakes and will be ignored." />
|
|
|
-
|
|
|
- <!-- Temporary project detection -->
|
|
|
- <!-- Some kinds of project have logic to trigger additional special builds based on the same project file
|
|
|
- e.g. WPF projects build a temporary assembly before the main compilation takes place.
|
|
|
- We only want to analyze the "normal" build of the project, so we should turn off analysis for the known cases. -->
|
|
|
- <PropertyGroup>
|
|
|
- <!-- Special case 1: WPF projects call the task Windows.GenerateTemporaryTargetAssembly in PresentationBuildTasks. -->
|
|
|
- <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('.tmp_proj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
- <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('_wpftmp.csproj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
- <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('_wpftmp.vbproj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <PropertyGroup Condition="$(IsTempProject) == 'true' AND $(SonarQubeExclude)==''" >
|
|
|
- <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(IsTempProject) == 'true' AND $(SonarQubeExclude)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is a temporary project and will be excluded." />
|
|
|
-
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
- <!-- The MS Test project type guid -->
|
|
|
- <SonarQubeMsTestProjectTypeGuid>3AC096D0-A1C2-E12C-1390-A8335801FDAB</SonarQubeMsTestProjectTypeGuid>
|
|
|
- <tmpSonarHasMSTestProjectTypeGuid Condition=" $(ProjectTypeGuids.ToUpperInvariant().Contains('$(SonarQubeMsTestProjectTypeGuid)')) ">true</tmpSonarHasMSTestProjectTypeGuid>
|
|
|
- <SonarQubeTestProject Condition=" $(tmpSonarHasMSTestProjectTypeGuid)=='true' ">true</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(tmpSonarHasMSTestProjectTypeGuid)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the MSTest project type guid -> test project." />
|
|
|
-
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
- <!-- The legacy Service tag added by the Test Explorer window -->
|
|
|
- <tmpSQServiceList>@(Service)</tmpSQServiceList>
|
|
|
- <tmpSonarHasServiceTag Condition="$(tmpSQServiceList.ToUpperInvariant().Contains('{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}')) ">true</tmpSonarHasServiceTag>
|
|
|
- <SonarQubeTestProject Condition="$(tmpSonarHasServiceTag)=='true'">true</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(tmpSonarHasServiceTag)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the legacy Test Explorer Service tag {82A7F48D-3B50-4B1E-B82E-3ADA8210C358} -> test project." />
|
|
|
-
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
- <!-- The ProjectCapability for test projects -->
|
|
|
- <tmpSQProjectCapabilities>@(ProjectCapability)</tmpSQProjectCapabilities>
|
|
|
- <tmpSonarHasTestContainerCapability Condition="$(tmpSQProjectCapabilities.ToUpperInvariant().Contains('TESTCONTAINER')) ">true</tmpSonarHasTestContainerCapability>
|
|
|
- <SonarQubeTestProject Condition="$(tmpSonarHasTestContainerCapability)=='true'">true</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(tmpSonarHasTestContainerCapability)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the ProjectCapability 'TestContainer' -> test project." />
|
|
|
-
|
|
|
- <IsTestByReference Condition=" $(SonarQubeTestProject) == '' "
|
|
|
- References="@(SonarResolvedReferences)">
|
|
|
- <Output TaskParameter="TestReference" PropertyName="tmpSonarTestReferenceResult" />
|
|
|
- </IsTestByReference>
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
- <SonarQubeTestProject Condition="$(tmpSonarTestReferenceResult)!=''">true</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(tmpSonarTestReferenceResult)!=''" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is evaluated as a test project based on the '$(tmpSonarTestReferenceResult)' reference." />
|
|
|
-
|
|
|
- <!-- If we haven't already determined whether the project is a test project then check its path/name against the regular expression in the config file -->
|
|
|
- <IsTestFileByName Condition=" $(SonarQubeTestProject) == '' "
|
|
|
- AnalysisConfigDir="$(SonarQubeConfigPath)"
|
|
|
- FullFilePath="$(MSBuildProjectFullPath)">
|
|
|
- <Output TaskParameter="IsTest" PropertyName="tmpSonarIsTestFileByNameResult" />
|
|
|
- </IsTestFileByName>
|
|
|
-
|
|
|
- <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
- <SonarQubeTestProject>$(tmpSonarIsTestFileByNameResult)</SonarQubeTestProject>
|
|
|
- </PropertyGroup>
|
|
|
- <Message Condition="$(tmpSonarIsTestFileByNameResult)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is evaluated as a test project based on the project name." />
|
|
|
-
|
|
|
- <Message Importance="normal" Condition="$(SonarQubeTestProject)=='false'" Text="Sonar: ($(MSBuildProjectFile)) categorized as MAIN project (production code)." />
|
|
|
- <Message Importance="normal" Condition="$(SonarQubeTestProject)=='true'" Text="Sonar: ($(MSBuildProjectFile)) categorized as TEST project (test code)." />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Calculate the set of files to be analyzed -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- This target is a utility target: it won't be executed unless a target that
|
|
|
- depends on it is executed.
|
|
|
- -->
|
|
|
- <Target Name="SonarWriteFilesToAnalyze"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
-
|
|
|
- <!-- Include all of contents of the specified item groups, but exclude
|
|
|
- any that have the metadata 'SonarQubeExclude' set, or that are auto-generated -->
|
|
|
- <ItemGroup Condition="('$(SQAnalysisFileItemTypes)' != '')">
|
|
|
- <SonarQubeAnalysisFileItems Include="$(SQAnalysisFileItemTypes)" />
|
|
|
- <SonarQubeAnalysisFiles Include="@(%(SonarQubeAnalysisFileItems.Identity))" />
|
|
|
- <SonarQubeAnalysisFiles Remove="@(SonarQubeAnalysisFiles)" Condition=" %(SonarQubeAnalysisFiles.SonarQubeExclude) == 'true' OR %(SonarQubeAnalysisFiles.AutoGen) == 'true' OR %(SonarQubeAnalysisFiles.FullPath) == '$(TargetFrameworkMonikerAssemblyAttributesPath)'" />
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <!-- Exclude items under the intermediate output folder e.g. XAML files that are auto-generated on build -->
|
|
|
- <PropertyGroup>
|
|
|
- <!-- Calculate the full path to the base intermediate folder -->
|
|
|
- <SQFullIntermediateOutputPath>$([System.IO.Path]::Combine($(MSBuildProjectDirectory),$(BaseIntermediateOutputPath)))</SQFullIntermediateOutputPath>
|
|
|
- </PropertyGroup>
|
|
|
- <ItemGroup>
|
|
|
- <!-- Remove based on absolute path -->
|
|
|
- <SQIntermediateFiles Include="$(SQFullIntermediateOutputPath)**\*.*" />
|
|
|
- <!-- Remove based on relative path -->
|
|
|
- <SQIntermediateFiles Include="$(BaseIntermediateOutputPath)**\*.*" />
|
|
|
- <SonarQubeAnalysisFiles Remove="@(SQIntermediateFiles)" />
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <!-- Set a property indicating whether there are any files to analyze -->
|
|
|
- <AnalysisFilesExist Condition=" @(SonarQubeAnalysisFiles) != '' ">true</AnalysisFilesExist>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!-- Write the list of files -->
|
|
|
- <PropertyGroup>
|
|
|
- <!-- Set the file name for the list file -->
|
|
|
- <AnalysisFileList>$(ProjectSpecificConfDir)\FilesToAnalyze.txt</AnalysisFileList>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <Message Condition="$(AnalysisFilesExist)!='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) No files were found to analyse" />
|
|
|
- <Message Condition="$(AnalysisFilesExist)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) Number of files to analyse: @(SonarQubeAnalysisFiles->Count()). The list of files to be analyzed is in $(AnalysisFileList)." />
|
|
|
-
|
|
|
- <!-- Write out a list of files to analyze that will be passed to the sonar-scanner -->
|
|
|
- <WriteLinesToFile Condition=" $(AnalysisFilesExist) == 'true' "
|
|
|
- File="$(AnalysisFileList)"
|
|
|
- Lines="%(SonarQubeAnalysisFiles.FullPath)"
|
|
|
- Overwrite="false"
|
|
|
- Encoding="utf-8" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="SonarCreateProjectSpecificDirs" BeforeTargets="OverrideRoslynCodeAnalysisProperties;SonarWriteProjectData;SonarWriteFilesToAnalyze" Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Create the project-specific directories for conf and out -->
|
|
|
-
|
|
|
- <!-- Create folder with unique name in the .sonarqube/out/ folder -->
|
|
|
- <MakeUniqueDir Path="$(SonarQubeOutputPath)">
|
|
|
- <Output TaskParameter="UniquePath" PropertyName="ProjectSpecificOutDir" />
|
|
|
- <Output TaskParameter="UniqueName" PropertyName="UniqueName" />
|
|
|
- </MakeUniqueDir>
|
|
|
- <!-- Create .sonarqube/conf/ sub-folder with the same unique name -->
|
|
|
- <PropertyGroup>
|
|
|
- <ProjectSpecificConfDir>$(SonarQubeConfigPath)\$(UniqueName)</ProjectSpecificConfDir>
|
|
|
- </PropertyGroup>
|
|
|
- <MakeDir Directories="$(ProjectSpecificConfDir)" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- SonarWriteProjectData has to be invoked after the Build target, so it can pick up the results for C++ projects. -->
|
|
|
- <Target Name="InvokeSonarWriteProjectData_NonRazorProject"
|
|
|
- DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze;SonarCreateProjectSpecificDirs"
|
|
|
- AfterTargets="Build"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND ('@(RazorCompile)'=='' OR ('@(RazorCompile)'!='' AND '$(UseRazorSourceGenerator)'=='true')) ">
|
|
|
- <CallTarget Targets="SonarWriteProjectData" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="InvokeSonarWriteProjectData_RazorProject"
|
|
|
- DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze;SonarCreateProjectSpecificDirs"
|
|
|
- BeforeTargets="SonarPrepareRazorProjectCodeAnalysis"
|
|
|
- AfterTargets="CoreCompile"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND '@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false') ">
|
|
|
- <CallTarget Targets="SonarWriteProjectData" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="SonarWriteProjectData" >
|
|
|
- <PropertyGroup>
|
|
|
- <SonarErrorLogExists Condition=" $(SonarErrorLog) != '' AND $([System.IO.File]::Exists($(SonarErrorLog))) == 'true' ">true</SonarErrorLogExists>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <SonarReportFilePath Condition= "$(SonarErrorLogExists) == 'true'" Include="$(SonarErrorLog)" />
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <SonarQubeSetting Include="sonar.$(SQLanguage).roslyn.reportFilePaths" Condition=" @(SonarReportFilePath) != '' ">
|
|
|
- <!-- Join the paths with | -->
|
|
|
- <!-- This delimiter needs to be the same as PropertiesFileGenerator.RoslynReportPathsDelimiter -->
|
|
|
- <Value>@(SonarReportFilePath->'%(identity)','|')</Value>
|
|
|
- </SonarQubeSetting>
|
|
|
- <SonarQubeSetting Include="sonar.$(SQLanguage).analyzer.projectOutPaths" Condition= "$(SonarErrorLogExists) == 'true'">
|
|
|
- <Value>$(ProjectSpecificOutDir)</Value>
|
|
|
- </SonarQubeSetting>
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <!-- Record the list of files as an analysis result -->
|
|
|
- <ItemGroup Condition=" $(AnalysisFilesExist) == 'true' ">
|
|
|
- <AnalysisResults Include="$(AnalysisFileList)">
|
|
|
- <Id>FilesToAnalyze</Id>
|
|
|
- </AnalysisResults>
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <CallTarget Targets="FixUpTestProjectOutputs" />
|
|
|
-
|
|
|
- <WriteProjectInfoFile ProjectName="$(MSBuildProjectName)"
|
|
|
- FullProjectPath="$(MSBuildProjectFullPath)"
|
|
|
- ProjectLanguage="$(Language)"
|
|
|
- ProjectGuid="$(ProjectGuid)"
|
|
|
- SolutionConfigurationContents="$(CurrentSolutionConfigurationContents)"
|
|
|
- IsTest="$(SonarQubeTestProject)"
|
|
|
- IsExcluded="$(SonarQubeExclude)"
|
|
|
- AnalysisResults="@(AnalysisResults)"
|
|
|
- AnalysisSettings="@(SonarQubeSetting)"
|
|
|
- OutputFolder="$(ProjectSpecificOutDir)"
|
|
|
- CodePage="$(CodePage)"
|
|
|
- Configuration="$(Configuration)"
|
|
|
- Platform="$(Platform)"
|
|
|
- TargetFramework="$(TargetFramework)" />
|
|
|
-
|
|
|
- <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Project processed successfully" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!--
|
|
|
- Set the Razor specific error log properties.
|
|
|
- Move the results of the core compilation to a temporary folder to prevent RazorCoreCompilation from overriding its content.
|
|
|
- The contents will be moved back in SonarFinishRazorProjectCodeAnalysis target.
|
|
|
- -->
|
|
|
- <Target Name="SonarPrepareRazorProjectCodeAnalysis" BeforeTargets="RazorCoreCompile" AfterTargets="CoreCompile" Condition="'@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false')" >
|
|
|
- <PropertyGroup Condition=" $(SonarErrorLog) != '' ">
|
|
|
- <!-- https://github.com/SonarSource/sonar-scanner-msbuild/issues/1015 Respect user-provided value. When set, users should provide unique path for each build (project and target framework). -->
|
|
|
- <RazorSonarErrorLogName Condition=" $(RazorCompilationErrorLog) == '' ">Issues$(RazorTargetNameSuffix).json</RazorSonarErrorLogName>
|
|
|
- <RazorCompilationErrorLog Condition=" $(RazorSonarErrorLogName) != '' ">$(ProjectSpecificOutDir)\$(RazorSonarErrorLogName)</RazorCompilationErrorLog>
|
|
|
- <ErrorLog>$(RazorCompilationErrorLog)</ErrorLog>
|
|
|
- <!-- Keep the path so that we could set SonarQubeSetting with sonar.language.roslyn.reportFilePaths -->
|
|
|
- <RazorSonarErrorLog>$(RazorCompilationErrorLog)</RazorSonarErrorLog>
|
|
|
- </PropertyGroup>
|
|
|
- <PropertyGroup>
|
|
|
- <SonarTemporaryProjectSpecificOutDir>$(ProjectSpecificOutDir).tmp</SonarTemporaryProjectSpecificOutDir>
|
|
|
- </PropertyGroup>
|
|
|
- <ItemGroup>
|
|
|
- <CoreCompileOutFiles Include="$(ProjectSpecificOutDir)\**\*.*"/>
|
|
|
- </ItemGroup>
|
|
|
- <Move
|
|
|
- SourceFiles="@(CoreCompileOutFiles)"
|
|
|
- DestinationFolder="$(SonarTemporaryProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
- <Message Importance="high" Text="Sonar: Preparing for Razor compilation, moved files (@(CoreCompileOutFiles)) to $(SonarTemporaryProjectSpecificOutDir)." />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- In case of Razor compilation the output files generated during the core compilation step are already moved into a temporary folder.
|
|
|
- This target renames output directories to their final state and creates the ProjectInfo.xml for them.
|
|
|
- -->
|
|
|
- <Target Name="SonarFinishRazorProjectCodeAnalysis" AfterTargets="RazorCoreCompile;InvokeSonarWriteProjectData_RazorProject" Condition=" $(SonarTemporaryProjectSpecificOutDir) != '' AND '@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false') ">
|
|
|
- <PropertyGroup>
|
|
|
- <RazorSonarProjectSpecificOutDir>$(ProjectSpecificOutDir).Razor</RazorSonarProjectSpecificOutDir>
|
|
|
- <RazorSonarProjectInfo>$(RazorSonarProjectSpecificOutDir)\ProjectInfo.xml</RazorSonarProjectInfo>
|
|
|
- </PropertyGroup>
|
|
|
- <ItemGroup>
|
|
|
- <RazorCompilationOutFiles Include="$(ProjectSpecificOutDir)\**\*.*"/>
|
|
|
- <SonarTempFiles Include="$(SonarTemporaryProjectSpecificOutDir)\**\*.*"/>
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <!-- Move main and Razor results to their final location. -->
|
|
|
- <Move
|
|
|
- SourceFiles="@(RazorCompilationOutFiles)"
|
|
|
- DestinationFolder="$(RazorSonarProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
- <Message Importance="high" Text="Sonar: After Razor compilation, moved files (@(RazorCompilationOutFiles)) to $(RazorSonarProjectSpecificOutDir)." />
|
|
|
-
|
|
|
- <Move
|
|
|
- SourceFiles="@(SonarTempFiles)"
|
|
|
- DestinationFolder="$(ProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
- <Message Importance="high" Text="Sonar: After Razor compilation, moved files (@(SonarTempFiles)) to $(ProjectSpecificOutDir) and will remove the temporary folder." />
|
|
|
- <RemoveDir Directories="$(SonarTemporaryProjectSpecificOutDir)" />
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <!-- This overwrites the previously set 'RazorSonarErrorLog' in 'SonarPrepareRazorProjectCodeAnalysis'
|
|
|
- if 'RazorSonarErrorLogName' is set, which means 'RazorCompilationErrorLog' was null.
|
|
|
- The condition is a bit difficult to follow, it would be easier to change it or also add "$(RazorSonarErrorLog) != ''" -->
|
|
|
- <RazorSonarErrorLog Condition=" $(RazorSonarErrorLogName) != '' ">$(RazorSonarProjectSpecificOutDir)\$(RazorSonarErrorLogName)</RazorSonarErrorLog>
|
|
|
- <RazorSonarErrorLogExists Condition=" $(RazorSonarErrorLog) != '' AND $([System.IO.File]::Exists($(RazorSonarErrorLog))) == 'true' ">true</RazorSonarErrorLogExists>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <RazorSonarReportFilePath Condition= "$(RazorSonarErrorLogExists) == 'true'" Include="$(RazorSonarErrorLog)" />
|
|
|
- <RazorSonarQubeSetting Include="sonar.$(SQLanguage).roslyn.reportFilePaths" Condition=" @(RazorSonarReportFilePath) != '' ">
|
|
|
- <!-- Join the paths with | -->
|
|
|
- <!-- This delimiter needs to be the same as PropertiesFileGenerator.RoslynReportPathsDelimiter -->
|
|
|
- <Value>@(RazorSonarReportFilePath->'%(identity)','|')</Value>
|
|
|
- </RazorSonarQubeSetting>
|
|
|
- <RazorSonarQubeSetting Include="sonar.$(SQLanguage).analyzer.projectOutPaths" Condition= "$(RazorSonarErrorLogExists) == 'true'">
|
|
|
- <Value>$(RazorSonarProjectSpecificOutDir)</Value>
|
|
|
- </RazorSonarQubeSetting>
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <!-- Create the ProjectInfo.xml for the Razor part. -->
|
|
|
- <WriteProjectInfoFile ProjectName="$(MSBuildProjectName)"
|
|
|
- FullProjectPath="$(MSBuildProjectFullPath)"
|
|
|
- ProjectLanguage="$(Language)"
|
|
|
- ProjectGuid="$(ProjectGuid)"
|
|
|
- SolutionConfigurationContents="$(CurrentSolutionConfigurationContents)"
|
|
|
- IsTest="$(SonarQubeTestProject)"
|
|
|
- IsExcluded="$(SonarQubeExclude)"
|
|
|
- AnalysisResults="@(AnalysisResults)"
|
|
|
- AnalysisSettings="@(RazorSonarQubeSetting)"
|
|
|
- OutputFolder="$(RazorSonarProjectSpecificOutDir)"
|
|
|
- CodePage="$(CodePage)"
|
|
|
- Configuration="$(Configuration)"
|
|
|
- Platform="$(Platform)"
|
|
|
- TargetFramework="$(TargetFramework)" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="FixUpTestProjectOutputs" Condition="$(SonarQubeTestProject)=='true'" >
|
|
|
- <Message Importance="low" Text="Sonar: ($(MSBuildProjectFile)) Fixing up test project outputs..." />
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <!-- Select specific metrics files that should not be uploaded for test files.
|
|
|
- Assumption: these files will be in a sub-folder under the project-specific output folder. -->
|
|
|
- <SQTestMetricFiles Include="$(ProjectSpecificOutDir)\*\metrics.pb" />
|
|
|
- <SQTestMetricFiles Include="$(ProjectSpecificOutDir)\*\token-cpd.pb" />
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <Message Importance="low" Text="Sonar: ($(MSBuildProjectFile)) Selected test metric file: @(SQTestMetricFiles)" />
|
|
|
- <WriteZeroLengthFiles FullFilePaths="@(SQTestMetricFiles)" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Code analysis -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Implementation notes:
|
|
|
-
|
|
|
- We want to override any code analysis-related properties that are set in the
|
|
|
- project file. To do this, we need to execute our targets at the correct
|
|
|
- point in the build.
|
|
|
-
|
|
|
- Note that both the FxCop and Roslyn targets use a property called "CodeAnalysisRuleSet".
|
|
|
- The FxCop targets use this value directly. However, the Roslyn targets use it
|
|
|
- as input to the "ResolveCodeAnalysisRuleSet" target, which sets the property
|
|
|
- "ResolvedCodeAnalysisRuleset".
|
|
|
-
|
|
|
- We override the property "ResolveCodeAnalysisRuleSet" with the path to our Roslyn ruleset.
|
|
|
- -->
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <SQLanguage Condition="$(Language) == 'C#'">cs</SQLanguage>
|
|
|
- <SQLanguage Condition="$(Language) == 'VB'">vbnet</SQLanguage>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Roslyn analysis section -->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- Override VS2019 properties to make sure analysis runs in the scanner build.
|
|
|
- We need to run before BeforeCompile that executes _ComputeSkipAnalyzers target.
|
|
|
- We don't need to override this for excluded projects. -->
|
|
|
- <Target Name="SonarOverrideRunAnalyzers"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' AND $(SonarQubeExclude) != 'true' "
|
|
|
- BeforeTargets="BeforeCompile">
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <RunAnalyzers>true</RunAnalyzers>
|
|
|
- <RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
|
|
- </PropertyGroup>
|
|
|
- </Target>
|
|
|
-
|
|
|
- <!-- Set the properties required to run Roslyn analysis as part of the build.
|
|
|
- Analysis is controlled by the following properties:
|
|
|
- ResolvedCodeAnalysisRuleSet - the full path to the ruleset to use
|
|
|
- ErrorLog and RazorCompilationErrorLog - the file path for the error reporting file
|
|
|
-
|
|
|
- We want to run after the core "ResolveCodeAnalysisRuleSet" target which assigns a value to "ResolvedCodeAnalysisRuleSet".
|
|
|
-
|
|
|
- Conditions:
|
|
|
- * project is excluded -> turn off Roslyn analysis
|
|
|
- * project is a test project and parameter sonar.dotnet.excludeTestProjects=true -> run only metrics rules
|
|
|
- * otherwise, use the analyzer settings loaded from the config file (removing any existing analyzers)
|
|
|
- -->
|
|
|
- <Target Name="OverrideRoslynCodeAnalysisProperties"
|
|
|
- Condition=" $(SonarQubeTempPath) != '' "
|
|
|
- DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze"
|
|
|
- AfterTargets="ResolveCodeAnalysisRuleSet"
|
|
|
- BeforeTargets="CoreCompile">
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <!-- Make sure no warnings are treated as errors -->
|
|
|
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
|
|
- <WarningsAsErrors></WarningsAsErrors>
|
|
|
-
|
|
|
- <!-- The Roslyn analyzers output messages with different warning levels. This is tied to the diagnostic severity and currently
|
|
|
- is translated as follows - error: 0, warning: 1, info: 4. To avoid issues being missed override the warning level by setting it to max tolerance.-->
|
|
|
- <WarningLevel>4</WarningLevel>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <CallTarget Targets="SetRoslynCodeAnalysisProperties" Condition="$(SonarQubeExclude) != 'true'" />
|
|
|
- </Target>
|
|
|
-
|
|
|
- <Target Name="SetRoslynCodeAnalysisProperties">
|
|
|
-
|
|
|
- <!-- Fetch the relevant settings from the config file -->
|
|
|
- <GetAnalyzerSettings AnalysisConfigDir="$(SonarQubeConfigPath)"
|
|
|
- Language="$(SQLanguage)"
|
|
|
- CurrentProjectDirectoryPath="$(MSBuildProjectDirectory)"
|
|
|
- OriginalAnalyzers="@(Analyzer)"
|
|
|
- OriginalAdditionalFiles="@(AdditionalFiles)"
|
|
|
- OriginalRulesetFilePath="$(ResolvedCodeAnalysisRuleset)"
|
|
|
- ProjectSpecificConfigDirectory="$(ProjectSpecificConfDir)"
|
|
|
- IsTestProject="$(SonarQubeTestProject)">
|
|
|
- <Output TaskParameter="RuleSetFilePath" PropertyName="SQRuleSetFilePath" />
|
|
|
- <Output TaskParameter="AnalyzerFilePaths" ItemName="SQAnalyzerFilePaths" />
|
|
|
- <Output TaskParameter="AdditionalFilePaths" ItemName="SQAdditionalFiles" />
|
|
|
- </GetAnalyzerSettings>
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <!-- https://github.com/SonarSource/sonar-scanner-msbuild/issues/1015 Respect user-provided value. When set, users should provide unique path for each build (project and target framework). -->
|
|
|
- <!-- https://jira.sonarsource.com/browse/SONARMSBRU-211 - the full path should be unique per project and target framework. -->
|
|
|
- <ErrorLog Condition=" $(ErrorLog) == '' ">$(ProjectSpecificOutDir)\Issues.json</ErrorLog>
|
|
|
- <!-- Keep the path so that we could set SonarQubeSetting with sonar.language.roslyn.reportFilePaths -->
|
|
|
- <SonarErrorLog>$(ErrorLog)</SonarErrorLog>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <PropertyGroup>
|
|
|
- <ResolvedCodeAnalysisRuleSet>$(SQRuleSetFilePath)</ResolvedCodeAnalysisRuleSet>
|
|
|
- <SonarProjectOutFolderFilePath>$(ProjectSpecificConfDir)\ProjectOutFolderPath.txt</SonarProjectOutFolderFilePath>
|
|
|
- </PropertyGroup>
|
|
|
-
|
|
|
- <!--SonarProjectOutFolderFilePath is generated only for backward compatibility with CSharp and VBNet analyzers before 8.20 -->
|
|
|
- <WriteLinesToFile File="$(SonarProjectOutFolderFilePath)" Lines="$(ProjectSpecificOutDir)" Overwrite="true" />
|
|
|
-
|
|
|
- <WriteProjectConfigFile ConfigDir="$(ProjectSpecificConfDir)"
|
|
|
- AnalysisConfigPath="$(SonarQubeConfigPath)\SonarQubeAnalysisConfig.xml"
|
|
|
- ProjectPath="$(MSBuildProjectFullPath)"
|
|
|
- FilesToAnalyzePath ="$(AnalysisFileList)"
|
|
|
- OutPath="$(ProjectSpecificOutDir)"
|
|
|
- IsTest="$(SonarQubeTestProject)"
|
|
|
- TargetFramework="$(TargetFramework)">
|
|
|
- <Output TaskParameter="ProjectConfigFilePath" PropertyName="SonarProjectConfigFilePath" />
|
|
|
- </WriteProjectConfigFile>
|
|
|
-
|
|
|
- <ItemGroup>
|
|
|
- <!-- Clear the original set of analyzers and additional files -->
|
|
|
- <Analyzer Remove="@(Analyzer)" />
|
|
|
- <AdditionalFiles Remove="@(AdditionalFiles)" />
|
|
|
-
|
|
|
- <!-- Use the set of analyzers and additional files calculated by the GetAnalyzerSettings task -->
|
|
|
- <Analyzer Include="@(SQAnalyzerFilePaths)" />
|
|
|
- <AdditionalFiles Include="@(SQAdditionalFiles)" />
|
|
|
- <AdditionalFiles Include="$(SonarProjectConfigFilePath)" />
|
|
|
- <AdditionalFiles Include="$(SonarProjectOutFolderFilePath)" />
|
|
|
- </ItemGroup>
|
|
|
-
|
|
|
- <Message Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) Analysis configured successfully with $(SonarProjectConfigFilePath)." />
|
|
|
- </Target>
|
|
|
- <!-- **************************************************************************** -->
|
|
|
- <!-- End of Roslyn analysis section-->
|
|
|
- <!-- **************************************************************************** -->
|
|
|
-
|
|
|
-</Project>
|
|
|
+<?xml version="1.0" encoding="utf-8"?>
|
|
|
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
|
+
|
|
|
+ <!--
|
|
|
+ This file contains targets to integrate SonarQube and MSBuild.
|
|
|
+
|
|
|
+ The targets will produce an output folder structure containing information required by the sonar-scanner.
|
|
|
+
|
|
|
+ A subdirectory will be created for each MSBuild project. Information about the project
|
|
|
+ will be written to a file called "ProjectInfo.xml". Additional files may also be written
|
|
|
+ containing information required by different analyzers. In particular, a file will be written
|
|
|
+ containing the list of files in the project that should be analyzed by the sonar-scanner.
|
|
|
+
|
|
|
+ The output will only be produced if the property $(SonarQubeTempPath) and is specified.
|
|
|
+ $(SonarQubeTempPath) is the root folder under which per-analysis output should be written.
|
|
|
+
|
|
|
+ Excluding projects and files from SonarQube analysis
|
|
|
+ ****************************************************
|
|
|
+ Individual projects can excluded from SonarQube analysis by setting the property $(SonarQubeExclude) e.g.
|
|
|
+
|
|
|
+ <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
+
|
|
|
+ Individual files can be excluded from analysis by setting the <SonarQubeExclude> metadata item e.g.
|
|
|
+
|
|
|
+ <Compile Include="Logger.cs">
|
|
|
+ <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
+ </Compile>
|
|
|
+
|
|
|
+ Project is also excluded if it's recognized as a Fakes or a Temp project. These projects are auto-generated.
|
|
|
+
|
|
|
+ Test projects
|
|
|
+ *************
|
|
|
+ The analysis performed by SonarQube varies depending on whether a project is a test project or not.
|
|
|
+
|
|
|
+ A project can be explicitly marked as being a test or product project by setting the property $(SonarQubeTestProject) e.g.
|
|
|
+
|
|
|
+ <SonarQubeTestProject>true</SonarQubeTestProject>
|
|
|
+
|
|
|
+ If $(SonarQubeTestProject) is not set explicitly then the project is categorized as a Test project if:
|
|
|
+ * Is a Fakes or a Temp project explicitly marked as SonarQubeExclude=false
|
|
|
+ * Has one of the expected test project GUIDs ("3AC096D0-A1C2-E12C-1390-A8335801FDAB" or legacy "82A7F48D-3B50-4B1E-B82E-3ADA8210C358").
|
|
|
+ * Has a TestContainer project capability.
|
|
|
+ * References a known unit test related assembly.
|
|
|
+ * Deprecated: Project name matches "sonar.msbuild.testProjectPattern" parameter. Use SonarQubeTestProject=true instead.
|
|
|
+
|
|
|
+ Otherwise it is a Product project.
|
|
|
+
|
|
|
+ Supplying analysis setting in a project file
|
|
|
+ ********************************************
|
|
|
+ Project-level analysis settings can be specified in a project file using following
|
|
|
+ syntax:
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <SonarQubeSetting Include="sonar.my.analysis.setting">
|
|
|
+ <Value>42</Value>
|
|
|
+ </SonarQubeSetting>
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ Settings specified in the project file will override those specified on the SonarQube server.
|
|
|
+
|
|
|
+ Specifying additional types of file to be analysed
|
|
|
+ **************************************************
|
|
|
+
|
|
|
+ The Scanner for MSBuild will automatically collect all of the common
|
|
|
+ file types that can be analysed by the various Sonar language plugins
|
|
|
+ (e.g. C# files, TypeScript, TSQL, C++ include and source files etc).
|
|
|
+ The full list of item types that will be included for analysis is
|
|
|
+ specified in $(SQAnalysisFileItemTypes) property below.
|
|
|
+
|
|
|
+ If you have any additional item types that you want to have analyzed,
|
|
|
+ you can specify them setting the property $(SQAdditionalAnalysisFileItemTypes)
|
|
|
+ in the project being analysed e.g.
|
|
|
+
|
|
|
+ <SQAdditionalAnalysisFileItemTypes>MyCustomFileType1;MyCustomFileType</SQAdditionalAnalysisFileItemTypes>
|
|
|
+
|
|
|
+ Specific handling of Razor builds
|
|
|
+ **************************************************
|
|
|
+ During the compilation of an SDK-style MSBuild project with Razor, MSBuild executes 2 build targets:
|
|
|
+ CoreCompile to compile the main code and RazorCoreCompile to compile ".cshtml" view files.
|
|
|
+ Since it is not possible to execute one target more than once, there's a logic that prevents RazorCoreCompile
|
|
|
+ from overriding output files from CoreCompile step:
|
|
|
+ * CoreCompile produces output files in directory "X", where X represents project specific unique number.
|
|
|
+ * Directory "X" with CoreCompile results is renamed to "X.tmp" before RazorCoreCompile and new empty directory "X" is prepared.
|
|
|
+ * RazorCoreCompile produces its output to the current directory "X".
|
|
|
+ * Directory "X" with Razor output is renamed to "X.Razor".
|
|
|
+ * Directory "X.tmp" with original output is renamed back to "X".
|
|
|
+-->
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- SonarQube MSBuild Integration implementation logic -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Note: where possible, these targets avoid taking dependencies on specific
|
|
|
+ managed or C++- targets e.g. they use
|
|
|
+ "AfterTargets='Build'" which is general rather than
|
|
|
+ "AfterTargets='CoreCompile'" which is specific to managed projects.
|
|
|
+ -->
|
|
|
+
|
|
|
+ <!-- Safeguard against importing this .targets file multiple times -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <SonarQubeTargetsImported>true</SonarQubeTargetsImported>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!-- Set defaults if explicit values have not been provided -->
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
+ <SonarQubeConfigPath Condition=" $(SonarQubeConfigPath) == '' ">$(SonarQubeTempPath)\conf</SonarQubeConfigPath>
|
|
|
+ <SonarQubeOutputPath Condition=" $(SonarQubeOutputPath) == '' ">$(SonarQubeTempPath)\out</SonarQubeOutputPath>
|
|
|
+
|
|
|
+ <!-- Specify the ItemGroups to be analyzed -->
|
|
|
+ <SQAnalysisFileItemTypes Condition=" $(SQAnalysisFileItemTypes) == '' ">AndroidEnvironment;AndroidJavaSource;AndroidResource;ApplicationDefinition;Build;ClCompile;ClInclude;Compile;Content;DeploymentExtensionConfiguration;EmbeddedResource;EntityDeploy;None;Page;PostDeploy;PRIResource;PreDeploy;RefactorLog;Resource;Script;ScriptCode;TypeScriptCompile;$(SQAdditionalAnalysisFileItemTypes)</SQAnalysisFileItemTypes>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Using tasks -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTempPath) != '' AND $(SonarQubeBuildTasksAssemblyFile) == '' ">
|
|
|
+ <!-- Assume that the tasks assembly is in the same location as this targets file
|
|
|
+ or in a parent directory unless another location has already been specified. -->
|
|
|
+ <SonarQubeBuildTasksAssemblyFile>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), SonarScanner.MSBuild.Tasks.dll))\SonarScanner.MSBuild.Tasks.dll</SonarQubeBuildTasksAssemblyFile>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!-- Unescape the paths to work around the issue "MSBuild 4.0 UsingTask cannot have a path with parentheses".
|
|
|
+ See https://connect.microsoft.com/VisualStudio/feedback/details/713690/msbuild-4-0-usingtask-cannot-have-a-path-with-parentheses -->
|
|
|
+ <UsingTask TaskName="WriteProjectConfigFile" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="WriteProjectInfoFile" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="IsTestFileByName" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="IsTestByReference" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="GetAnalyzerSettings" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="MakeUniqueDir" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+ <UsingTask TaskName="WriteZeroLengthFiles" AssemblyFile="$([MSBUILD]::Unescape($(SonarQubeBuildTasksAssemblyFile)))" />
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Targets -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+
|
|
|
+ <Target Name="SkippingSonarQubeAnalysis" BeforeTargets="Build"
|
|
|
+ Condition=" $(SonarQubeTempPath) == '' ">
|
|
|
+ <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Skipping dumping compile outputs because SonarQubeTempPath has not been specified" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="FailIfLowerThanMSBuild14"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) != '14.0' AND $(MSBuildToolsVersion) != '15.0' AND $(MSBuildToolsVersion) != 'Current'"
|
|
|
+ BeforeTargets="Build">
|
|
|
+ <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Current MSBuildToolsVersion: $(MSBuildToolsVersion)" />
|
|
|
+ <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Current MSBuildAssemblyVersion: $(MSBuildAssemblyVersion)" />
|
|
|
+ <Error Text="SonarQube analysis is only supported with MSBuild 14 or later." />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="SonarResolveReferencesMsBuild14"
|
|
|
+ AfterTargets="ResolveAssemblyReferences"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) == '14.0'">
|
|
|
+ <ItemGroup>
|
|
|
+ <SonarResolvedReferences Include="@(%(ReferencePath.FusionName))" />
|
|
|
+ </ItemGroup>
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="SonarResolveReferences"
|
|
|
+ AfterTargets="FindReferenceAssembliesForReferences"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND $(MSBuildToolsVersion) != '14.0'">
|
|
|
+ <ItemGroup>
|
|
|
+ <SonarResolvedReferences Include="@(%(ReferencePathWithRefAssemblies.FusionName))" />
|
|
|
+ </ItemGroup>
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Categorize as a product or test project -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- This target is a utility target: it won't be executed unless a target that depends on it is executed. -->
|
|
|
+ <Target Name="SonarCategoriseProject"
|
|
|
+ DependsOnTargets="SonarResolveReferencesMsBuild14;SonarResolveReferences"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
+
|
|
|
+ <Message Text="Sonar: ($(MSBuildProjectFile)) Categorizing project as test or product code..." />
|
|
|
+ <Message Condition="$(SonarQubeTestProject) != ''" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) SonarQubeTestProject has been set explicitly to $(SonarQubeTestProject)." />
|
|
|
+
|
|
|
+ <!-- Fakes detection -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <IsFakesProject Condition="$(AssemblyName.EndsWith('.fakes', System.StringComparison.OrdinalIgnoreCase))">true</IsFakesProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <!-- Before deciding to exclude or tag as test such a project, make sure it is not a legitimate project that happens to be called something.fakes
|
|
|
+ In this case, we require from the user to explicitely state whether the project is to be analyzed/considered a test project -->
|
|
|
+ <PropertyGroup Condition="$(IsFakesProject) == 'true' and $(SonarQubeExclude) == ''">
|
|
|
+ <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
+ </PropertyGroup>
|
|
|
+ <PropertyGroup Condition="$(IsFakesProject) == 'true' and $(SonarQubeTestProject) == ''">
|
|
|
+ <SonarQubeTestProject>true</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(IsFakesProject) == 'true' and $(SonarQubeExclude) == 'true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is a temporary project generated by Microsoft Fakes and will be ignored." />
|
|
|
+
|
|
|
+ <!-- Temporary project detection -->
|
|
|
+ <!-- Some kinds of project have logic to trigger additional special builds based on the same project file
|
|
|
+ e.g. WPF projects build a temporary assembly before the main compilation takes place.
|
|
|
+ We only want to analyze the "normal" build of the project, so we should turn off analysis for the known cases. -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- Special case 1: WPF projects call the task Windows.GenerateTemporaryTargetAssembly in PresentationBuildTasks. -->
|
|
|
+ <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('.tmp_proj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
+ <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('_wpftmp.csproj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
+ <IsTempProject Condition="$(MSBuildProjectFile.EndsWith('_wpftmp.vbproj', System.StringComparison.OrdinalIgnoreCase))">true</IsTempProject>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <PropertyGroup Condition="$(IsTempProject) == 'true' AND $(SonarQubeExclude)==''" >
|
|
|
+ <SonarQubeExclude>true</SonarQubeExclude>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(IsTempProject) == 'true' AND $(SonarQubeExclude)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is a temporary project and will be excluded." />
|
|
|
+
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
+ <!-- The MS Test project type guid -->
|
|
|
+ <SonarQubeMsTestProjectTypeGuid>3AC096D0-A1C2-E12C-1390-A8335801FDAB</SonarQubeMsTestProjectTypeGuid>
|
|
|
+ <tmpSonarHasMSTestProjectTypeGuid Condition=" $(ProjectTypeGuids.ToUpperInvariant().Contains('$(SonarQubeMsTestProjectTypeGuid)')) ">true</tmpSonarHasMSTestProjectTypeGuid>
|
|
|
+ <SonarQubeTestProject Condition=" $(tmpSonarHasMSTestProjectTypeGuid)=='true' ">true</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(tmpSonarHasMSTestProjectTypeGuid)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the MSTest project type guid -> test project." />
|
|
|
+
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
+ <!-- The legacy Service tag added by the Test Explorer window -->
|
|
|
+ <tmpSQServiceList>@(Service)</tmpSQServiceList>
|
|
|
+ <tmpSonarHasServiceTag Condition="$(tmpSQServiceList.ToUpperInvariant().Contains('{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}')) ">true</tmpSonarHasServiceTag>
|
|
|
+ <SonarQubeTestProject Condition="$(tmpSonarHasServiceTag)=='true'">true</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(tmpSonarHasServiceTag)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the legacy Test Explorer Service tag {82A7F48D-3B50-4B1E-B82E-3ADA8210C358} -> test project." />
|
|
|
+
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
+ <!-- The ProjectCapability for test projects -->
|
|
|
+ <tmpSQProjectCapabilities>@(ProjectCapability)</tmpSQProjectCapabilities>
|
|
|
+ <tmpSonarHasTestContainerCapability Condition="$(tmpSQProjectCapabilities.ToUpperInvariant().Contains('TESTCONTAINER')) ">true</tmpSonarHasTestContainerCapability>
|
|
|
+ <SonarQubeTestProject Condition="$(tmpSonarHasTestContainerCapability)=='true'">true</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(tmpSonarHasTestContainerCapability)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project has the ProjectCapability 'TestContainer' -> test project." />
|
|
|
+
|
|
|
+ <IsTestByReference Condition=" $(SonarQubeTestProject) == '' "
|
|
|
+ References="@(SonarResolvedReferences)">
|
|
|
+ <Output TaskParameter="TestReference" PropertyName="tmpSonarTestReferenceResult" />
|
|
|
+ </IsTestByReference>
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
+ <SonarQubeTestProject Condition="$(tmpSonarTestReferenceResult)!=''">true</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(tmpSonarTestReferenceResult)!=''" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is evaluated as a test project based on the '$(tmpSonarTestReferenceResult)' reference." />
|
|
|
+
|
|
|
+ <!-- If we haven't already determined whether the project is a test project then check its path/name against the regular expression in the config file -->
|
|
|
+ <IsTestFileByName Condition=" $(SonarQubeTestProject) == '' "
|
|
|
+ AnalysisConfigDir="$(SonarQubeConfigPath)"
|
|
|
+ FullFilePath="$(MSBuildProjectFullPath)">
|
|
|
+ <Output TaskParameter="IsTest" PropertyName="tmpSonarIsTestFileByNameResult" />
|
|
|
+ </IsTestFileByName>
|
|
|
+
|
|
|
+ <PropertyGroup Condition=" $(SonarQubeTestProject) == '' ">
|
|
|
+ <SonarQubeTestProject>$(tmpSonarIsTestFileByNameResult)</SonarQubeTestProject>
|
|
|
+ </PropertyGroup>
|
|
|
+ <Message Condition="$(tmpSonarIsTestFileByNameResult)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) project is evaluated as a test project based on the project name." />
|
|
|
+
|
|
|
+ <Message Importance="normal" Condition="$(SonarQubeTestProject)=='false'" Text="Sonar: ($(MSBuildProjectFile)) categorized as MAIN project (production code)." />
|
|
|
+ <Message Importance="normal" Condition="$(SonarQubeTestProject)=='true'" Text="Sonar: ($(MSBuildProjectFile)) categorized as TEST project (test code)." />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Calculate the set of files to be analyzed -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- This target is a utility target: it won't be executed unless a target that
|
|
|
+ depends on it is executed.
|
|
|
+ -->
|
|
|
+ <Target Name="SonarWriteFilesToAnalyze"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
+
|
|
|
+ <!-- Include all of contents of the specified item groups, but exclude
|
|
|
+ any that have the metadata 'SonarQubeExclude' set, or that are auto-generated -->
|
|
|
+ <ItemGroup Condition="('$(SQAnalysisFileItemTypes)' != '')">
|
|
|
+ <SonarQubeAnalysisFileItems Include="$(SQAnalysisFileItemTypes)" />
|
|
|
+ <SonarQubeAnalysisFiles Include="@(%(SonarQubeAnalysisFileItems.Identity))" />
|
|
|
+ <SonarQubeAnalysisFiles Remove="@(SonarQubeAnalysisFiles)" Condition=" %(SonarQubeAnalysisFiles.SonarQubeExclude) == 'true' OR %(SonarQubeAnalysisFiles.AutoGen) == 'true' OR %(SonarQubeAnalysisFiles.FullPath) == '$(TargetFrameworkMonikerAssemblyAttributesPath)'" />
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <!-- Exclude items under the intermediate output folder e.g. XAML files that are auto-generated on build -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- Calculate the full path to the base intermediate folder -->
|
|
|
+ <SQFullIntermediateOutputPath>$([System.IO.Path]::Combine($(MSBuildProjectDirectory),$(BaseIntermediateOutputPath)))</SQFullIntermediateOutputPath>
|
|
|
+ </PropertyGroup>
|
|
|
+ <ItemGroup>
|
|
|
+ <!-- Remove based on absolute path -->
|
|
|
+ <SQIntermediateFiles Include="$(SQFullIntermediateOutputPath)**\*.*" />
|
|
|
+ <!-- Remove based on relative path -->
|
|
|
+ <SQIntermediateFiles Include="$(BaseIntermediateOutputPath)**\*.*" />
|
|
|
+ <SonarQubeAnalysisFiles Remove="@(SQIntermediateFiles)" />
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- Set a property indicating whether there are any files to analyze -->
|
|
|
+ <AnalysisFilesExist Condition=" @(SonarQubeAnalysisFiles) != '' ">true</AnalysisFilesExist>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!-- Write the list of files -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- Set the file name for the list file -->
|
|
|
+ <AnalysisFileList>$(ProjectSpecificConfDir)\FilesToAnalyze.txt</AnalysisFileList>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <Message Condition="$(AnalysisFilesExist)!='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) No files were found to analyse" />
|
|
|
+ <Message Condition="$(AnalysisFilesExist)=='true'" Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) Number of files to analyse: @(SonarQubeAnalysisFiles->Count()). The list of files to be analyzed is in $(AnalysisFileList)." />
|
|
|
+
|
|
|
+ <!-- Write out a list of files to analyze that will be passed to the sonar-scanner -->
|
|
|
+ <WriteLinesToFile Condition=" $(AnalysisFilesExist) == 'true' "
|
|
|
+ File="$(AnalysisFileList)"
|
|
|
+ Lines="%(SonarQubeAnalysisFiles.FullPath)"
|
|
|
+ Overwrite="false"
|
|
|
+ Encoding="utf-8" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="SonarCreateProjectSpecificDirs" BeforeTargets="OverrideRoslynCodeAnalysisProperties;SonarWriteProjectData;SonarWriteFilesToAnalyze" Condition=" $(SonarQubeTempPath) != '' ">
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Create the project-specific directories for conf and out -->
|
|
|
+
|
|
|
+ <!-- Create folder with unique name in the .sonarqube/out/ folder -->
|
|
|
+ <MakeUniqueDir Path="$(SonarQubeOutputPath)">
|
|
|
+ <Output TaskParameter="UniquePath" PropertyName="ProjectSpecificOutDir" />
|
|
|
+ <Output TaskParameter="UniqueName" PropertyName="UniqueName" />
|
|
|
+ </MakeUniqueDir>
|
|
|
+ <!-- Create .sonarqube/conf/ sub-folder with the same unique name -->
|
|
|
+ <PropertyGroup>
|
|
|
+ <ProjectSpecificConfDir>$(SonarQubeConfigPath)\$(UniqueName)</ProjectSpecificConfDir>
|
|
|
+ </PropertyGroup>
|
|
|
+ <MakeDir Directories="$(ProjectSpecificConfDir)" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- SonarWriteProjectData has to be invoked after the Build target, so it can pick up the results for C++ projects. -->
|
|
|
+ <Target Name="InvokeSonarWriteProjectData_NonRazorProject"
|
|
|
+ DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze;SonarCreateProjectSpecificDirs"
|
|
|
+ AfterTargets="Build"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND ('@(RazorCompile)'=='' OR ('@(RazorCompile)'!='' AND '$(UseRazorSourceGenerator)'=='true')) ">
|
|
|
+ <CallTarget Targets="SonarWriteProjectData" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="InvokeSonarWriteProjectData_RazorProject"
|
|
|
+ DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze;SonarCreateProjectSpecificDirs"
|
|
|
+ BeforeTargets="SonarPrepareRazorProjectCodeAnalysis"
|
|
|
+ AfterTargets="CoreCompile"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND '@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false') ">
|
|
|
+ <CallTarget Targets="SonarWriteProjectData" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="SonarWriteProjectData" >
|
|
|
+ <PropertyGroup>
|
|
|
+ <SonarErrorLogExists Condition=" $(SonarErrorLog) != '' AND $([System.IO.File]::Exists($(SonarErrorLog))) == 'true' ">true</SonarErrorLogExists>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <SonarReportFilePath Condition= "$(SonarErrorLogExists) == 'true'" Include="$(SonarErrorLog)" />
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <SonarQubeSetting Include="sonar.$(SQLanguage).roslyn.reportFilePaths" Condition=" @(SonarReportFilePath) != '' ">
|
|
|
+ <!-- Join the paths with | -->
|
|
|
+ <!-- This delimiter needs to be the same as PropertiesFileGenerator.RoslynReportPathsDelimiter -->
|
|
|
+ <Value>@(SonarReportFilePath->'%(identity)','|')</Value>
|
|
|
+ </SonarQubeSetting>
|
|
|
+ <SonarQubeSetting Include="sonar.$(SQLanguage).analyzer.projectOutPaths" Condition= "$(SonarErrorLogExists) == 'true'">
|
|
|
+ <Value>$(ProjectSpecificOutDir)</Value>
|
|
|
+ </SonarQubeSetting>
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <!-- Record the list of files as an analysis result -->
|
|
|
+ <ItemGroup Condition=" $(AnalysisFilesExist) == 'true' ">
|
|
|
+ <AnalysisResults Include="$(AnalysisFileList)">
|
|
|
+ <Id>FilesToAnalyze</Id>
|
|
|
+ </AnalysisResults>
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <CallTarget Targets="FixUpTestProjectOutputs" />
|
|
|
+
|
|
|
+ <WriteProjectInfoFile ProjectName="$(MSBuildProjectName)"
|
|
|
+ FullProjectPath="$(MSBuildProjectFullPath)"
|
|
|
+ ProjectLanguage="$(Language)"
|
|
|
+ ProjectGuid="$(ProjectGuid)"
|
|
|
+ SolutionConfigurationContents="$(CurrentSolutionConfigurationContents)"
|
|
|
+ IsTest="$(SonarQubeTestProject)"
|
|
|
+ IsExcluded="$(SonarQubeExclude)"
|
|
|
+ AnalysisResults="@(AnalysisResults)"
|
|
|
+ AnalysisSettings="@(SonarQubeSetting)"
|
|
|
+ OutputFolder="$(ProjectSpecificOutDir)"
|
|
|
+ CodePage="$(CodePage)"
|
|
|
+ Configuration="$(Configuration)"
|
|
|
+ Platform="$(Platform)"
|
|
|
+ TargetFramework="$(TargetFramework)" />
|
|
|
+
|
|
|
+ <Message Importance="high" Text="Sonar: ($(MSBuildProjectFile)) Project processed successfully" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!--
|
|
|
+ Set the Razor specific error log properties.
|
|
|
+ Move the results of the core compilation to a temporary folder to prevent RazorCoreCompilation from overriding its content.
|
|
|
+ The contents will be moved back in SonarFinishRazorProjectCodeAnalysis target.
|
|
|
+ -->
|
|
|
+ <Target Name="SonarPrepareRazorProjectCodeAnalysis" BeforeTargets="RazorCoreCompile" AfterTargets="CoreCompile" Condition="'@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false')" >
|
|
|
+ <PropertyGroup Condition=" $(SonarErrorLog) != '' ">
|
|
|
+ <!-- https://github.com/SonarSource/sonar-scanner-msbuild/issues/1015 Respect user-provided value. When set, users should provide unique path for each build (project and target framework). -->
|
|
|
+ <RazorSonarErrorLogName Condition=" $(RazorCompilationErrorLog) == '' ">Issues$(RazorTargetNameSuffix).json</RazorSonarErrorLogName>
|
|
|
+ <RazorCompilationErrorLog Condition=" $(RazorSonarErrorLogName) != '' ">$(ProjectSpecificOutDir)\$(RazorSonarErrorLogName)</RazorCompilationErrorLog>
|
|
|
+ <ErrorLog>$(RazorCompilationErrorLog)</ErrorLog>
|
|
|
+ <!-- Keep the path so that we could set SonarQubeSetting with sonar.language.roslyn.reportFilePaths -->
|
|
|
+ <RazorSonarErrorLog>$(RazorCompilationErrorLog)</RazorSonarErrorLog>
|
|
|
+ </PropertyGroup>
|
|
|
+ <PropertyGroup>
|
|
|
+ <SonarTemporaryProjectSpecificOutDir>$(ProjectSpecificOutDir).tmp</SonarTemporaryProjectSpecificOutDir>
|
|
|
+ </PropertyGroup>
|
|
|
+ <ItemGroup>
|
|
|
+ <CoreCompileOutFiles Include="$(ProjectSpecificOutDir)\**\*.*"/>
|
|
|
+ </ItemGroup>
|
|
|
+ <Move
|
|
|
+ SourceFiles="@(CoreCompileOutFiles)"
|
|
|
+ DestinationFolder="$(SonarTemporaryProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
+ <Message Importance="high" Text="Sonar: Preparing for Razor compilation, moved files (@(CoreCompileOutFiles)) to $(SonarTemporaryProjectSpecificOutDir)." />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- In case of Razor compilation the output files generated during the core compilation step are already moved into a temporary folder.
|
|
|
+ This target renames output directories to their final state and creates the ProjectInfo.xml for them.
|
|
|
+ -->
|
|
|
+ <Target Name="SonarFinishRazorProjectCodeAnalysis" AfterTargets="RazorCoreCompile;InvokeSonarWriteProjectData_RazorProject" Condition=" $(SonarTemporaryProjectSpecificOutDir) != '' AND '@(RazorCompile)'!='' AND ('$(UseRazorSourceGenerator)'=='' OR '$(UseRazorSourceGenerator)'=='false') ">
|
|
|
+ <PropertyGroup>
|
|
|
+ <RazorSonarProjectSpecificOutDir>$(ProjectSpecificOutDir).Razor</RazorSonarProjectSpecificOutDir>
|
|
|
+ <RazorSonarProjectInfo>$(RazorSonarProjectSpecificOutDir)\ProjectInfo.xml</RazorSonarProjectInfo>
|
|
|
+ </PropertyGroup>
|
|
|
+ <ItemGroup>
|
|
|
+ <RazorCompilationOutFiles Include="$(ProjectSpecificOutDir)\**\*.*"/>
|
|
|
+ <SonarTempFiles Include="$(SonarTemporaryProjectSpecificOutDir)\**\*.*"/>
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <!-- Move main and Razor results to their final location. -->
|
|
|
+ <Move
|
|
|
+ SourceFiles="@(RazorCompilationOutFiles)"
|
|
|
+ DestinationFolder="$(RazorSonarProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
+ <Message Importance="high" Text="Sonar: After Razor compilation, moved files (@(RazorCompilationOutFiles)) to $(RazorSonarProjectSpecificOutDir)." />
|
|
|
+
|
|
|
+ <Move
|
|
|
+ SourceFiles="@(SonarTempFiles)"
|
|
|
+ DestinationFolder="$(ProjectSpecificOutDir)\%(RecursiveDir)" />
|
|
|
+ <Message Importance="high" Text="Sonar: After Razor compilation, moved files (@(SonarTempFiles)) to $(ProjectSpecificOutDir) and will remove the temporary folder." />
|
|
|
+ <RemoveDir Directories="$(SonarTemporaryProjectSpecificOutDir)" />
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- This overwrites the previously set 'RazorSonarErrorLog' in 'SonarPrepareRazorProjectCodeAnalysis'
|
|
|
+ if 'RazorSonarErrorLogName' is set, which means 'RazorCompilationErrorLog' was null.
|
|
|
+ The condition is a bit difficult to follow, it would be easier to change it or also add "$(RazorSonarErrorLog) != ''" -->
|
|
|
+ <RazorSonarErrorLog Condition=" $(RazorSonarErrorLogName) != '' ">$(RazorSonarProjectSpecificOutDir)\$(RazorSonarErrorLogName)</RazorSonarErrorLog>
|
|
|
+ <RazorSonarErrorLogExists Condition=" $(RazorSonarErrorLog) != '' AND $([System.IO.File]::Exists($(RazorSonarErrorLog))) == 'true' ">true</RazorSonarErrorLogExists>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <RazorSonarReportFilePath Condition= "$(RazorSonarErrorLogExists) == 'true'" Include="$(RazorSonarErrorLog)" />
|
|
|
+ <RazorSonarQubeSetting Include="sonar.$(SQLanguage).roslyn.reportFilePaths" Condition=" @(RazorSonarReportFilePath) != '' ">
|
|
|
+ <!-- Join the paths with | -->
|
|
|
+ <!-- This delimiter needs to be the same as PropertiesFileGenerator.RoslynReportPathsDelimiter -->
|
|
|
+ <Value>@(RazorSonarReportFilePath->'%(identity)','|')</Value>
|
|
|
+ </RazorSonarQubeSetting>
|
|
|
+ <RazorSonarQubeSetting Include="sonar.$(SQLanguage).analyzer.projectOutPaths" Condition= "$(RazorSonarErrorLogExists) == 'true'">
|
|
|
+ <Value>$(RazorSonarProjectSpecificOutDir)</Value>
|
|
|
+ </RazorSonarQubeSetting>
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <!-- Create the ProjectInfo.xml for the Razor part. -->
|
|
|
+ <WriteProjectInfoFile ProjectName="$(MSBuildProjectName)"
|
|
|
+ FullProjectPath="$(MSBuildProjectFullPath)"
|
|
|
+ ProjectLanguage="$(Language)"
|
|
|
+ ProjectGuid="$(ProjectGuid)"
|
|
|
+ SolutionConfigurationContents="$(CurrentSolutionConfigurationContents)"
|
|
|
+ IsTest="$(SonarQubeTestProject)"
|
|
|
+ IsExcluded="$(SonarQubeExclude)"
|
|
|
+ AnalysisResults="@(AnalysisResults)"
|
|
|
+ AnalysisSettings="@(RazorSonarQubeSetting)"
|
|
|
+ OutputFolder="$(RazorSonarProjectSpecificOutDir)"
|
|
|
+ CodePage="$(CodePage)"
|
|
|
+ Configuration="$(Configuration)"
|
|
|
+ Platform="$(Platform)"
|
|
|
+ TargetFramework="$(TargetFramework)" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="FixUpTestProjectOutputs" Condition="$(SonarQubeTestProject)=='true'" >
|
|
|
+ <Message Importance="low" Text="Sonar: ($(MSBuildProjectFile)) Fixing up test project outputs..." />
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <!-- Select specific metrics files that should not be uploaded for test files.
|
|
|
+ Assumption: these files will be in a sub-folder under the project-specific output folder. -->
|
|
|
+ <SQTestMetricFiles Include="$(ProjectSpecificOutDir)\*\metrics.pb" />
|
|
|
+ <SQTestMetricFiles Include="$(ProjectSpecificOutDir)\*\token-cpd.pb" />
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <Message Importance="low" Text="Sonar: ($(MSBuildProjectFile)) Selected test metric file: @(SQTestMetricFiles)" />
|
|
|
+ <WriteZeroLengthFiles FullFilePaths="@(SQTestMetricFiles)" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Code analysis -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Implementation notes:
|
|
|
+
|
|
|
+ We want to override any code analysis-related properties that are set in the
|
|
|
+ project file. To do this, we need to execute our targets at the correct
|
|
|
+ point in the build.
|
|
|
+
|
|
|
+ Note that both the FxCop and Roslyn targets use a property called "CodeAnalysisRuleSet".
|
|
|
+ The FxCop targets use this value directly. However, the Roslyn targets use it
|
|
|
+ as input to the "ResolveCodeAnalysisRuleSet" target, which sets the property
|
|
|
+ "ResolvedCodeAnalysisRuleset".
|
|
|
+
|
|
|
+ We override the property "ResolveCodeAnalysisRuleSet" with the path to our Roslyn ruleset.
|
|
|
+ -->
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <SQLanguage Condition="$(Language) == 'C#'">cs</SQLanguage>
|
|
|
+ <SQLanguage Condition="$(Language) == 'VB'">vbnet</SQLanguage>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Roslyn analysis section -->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- Override VS2019 properties to make sure analysis runs in the scanner build.
|
|
|
+ We need to run before BeforeCompile that executes _ComputeSkipAnalyzers target.
|
|
|
+ We don't need to override this for excluded projects. -->
|
|
|
+ <Target Name="SonarOverrideRunAnalyzers"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' AND $(SonarQubeExclude) != 'true' "
|
|
|
+ BeforeTargets="BeforeCompile">
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <RunAnalyzers>true</RunAnalyzers>
|
|
|
+ <RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
|
|
+ </PropertyGroup>
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <!-- Set the properties required to run Roslyn analysis as part of the build.
|
|
|
+ Analysis is controlled by the following properties:
|
|
|
+ ResolvedCodeAnalysisRuleSet - the full path to the ruleset to use
|
|
|
+ ErrorLog and RazorCompilationErrorLog - the file path for the error reporting file
|
|
|
+
|
|
|
+ We want to run after the core "ResolveCodeAnalysisRuleSet" target which assigns a value to "ResolvedCodeAnalysisRuleSet".
|
|
|
+
|
|
|
+ Conditions:
|
|
|
+ * project is excluded -> turn off Roslyn analysis
|
|
|
+ * project is a test project and parameter sonar.dotnet.excludeTestProjects=true -> run only metrics rules
|
|
|
+ * otherwise, use the analyzer settings loaded from the config file (removing any existing analyzers)
|
|
|
+ -->
|
|
|
+ <Target Name="OverrideRoslynCodeAnalysisProperties"
|
|
|
+ Condition=" $(SonarQubeTempPath) != '' "
|
|
|
+ DependsOnTargets="SonarCategoriseProject;SonarWriteFilesToAnalyze"
|
|
|
+ AfterTargets="ResolveCodeAnalysisRuleSet"
|
|
|
+ BeforeTargets="CoreCompile">
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- Make sure no warnings are treated as errors -->
|
|
|
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
|
|
+ <WarningsAsErrors></WarningsAsErrors>
|
|
|
+
|
|
|
+ <!-- The Roslyn analyzers output messages with different warning levels. This is tied to the diagnostic severity and currently
|
|
|
+ is translated as follows - error: 0, warning: 1, info: 4. To avoid issues being missed override the warning level by setting it to max tolerance.-->
|
|
|
+ <WarningLevel>4</WarningLevel>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <CallTarget Targets="SetRoslynCodeAnalysisProperties" Condition="$(SonarQubeExclude) != 'true'" />
|
|
|
+ </Target>
|
|
|
+
|
|
|
+ <Target Name="SetRoslynCodeAnalysisProperties">
|
|
|
+
|
|
|
+ <!-- Fetch the relevant settings from the config file -->
|
|
|
+ <GetAnalyzerSettings AnalysisConfigDir="$(SonarQubeConfigPath)"
|
|
|
+ Language="$(SQLanguage)"
|
|
|
+ CurrentProjectDirectoryPath="$(MSBuildProjectDirectory)"
|
|
|
+ OriginalAnalyzers="@(Analyzer)"
|
|
|
+ OriginalAdditionalFiles="@(AdditionalFiles)"
|
|
|
+ OriginalRulesetFilePath="$(ResolvedCodeAnalysisRuleset)"
|
|
|
+ ProjectSpecificConfigDirectory="$(ProjectSpecificConfDir)"
|
|
|
+ IsTestProject="$(SonarQubeTestProject)">
|
|
|
+ <Output TaskParameter="RuleSetFilePath" PropertyName="SQRuleSetFilePath" />
|
|
|
+ <Output TaskParameter="AnalyzerFilePaths" ItemName="SQAnalyzerFilePaths" />
|
|
|
+ <Output TaskParameter="AdditionalFilePaths" ItemName="SQAdditionalFiles" />
|
|
|
+ </GetAnalyzerSettings>
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <!-- https://github.com/SonarSource/sonar-scanner-msbuild/issues/1015 Respect user-provided value. When set, users should provide unique path for each build (project and target framework). -->
|
|
|
+ <!-- https://jira.sonarsource.com/browse/SONARMSBRU-211 - the full path should be unique per project and target framework. -->
|
|
|
+ <ErrorLog Condition=" $(ErrorLog) == '' ">$(ProjectSpecificOutDir)\Issues.json</ErrorLog>
|
|
|
+ <!-- Keep the path so that we could set SonarQubeSetting with sonar.language.roslyn.reportFilePaths -->
|
|
|
+ <SonarErrorLog>$(ErrorLog)</SonarErrorLog>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <PropertyGroup>
|
|
|
+ <ResolvedCodeAnalysisRuleSet>$(SQRuleSetFilePath)</ResolvedCodeAnalysisRuleSet>
|
|
|
+ <SonarProjectOutFolderFilePath>$(ProjectSpecificConfDir)\ProjectOutFolderPath.txt</SonarProjectOutFolderFilePath>
|
|
|
+ </PropertyGroup>
|
|
|
+
|
|
|
+ <!--SonarProjectOutFolderFilePath is generated only for backward compatibility with CSharp and VBNet analyzers before 8.20 -->
|
|
|
+ <WriteLinesToFile File="$(SonarProjectOutFolderFilePath)" Lines="$(ProjectSpecificOutDir)" Overwrite="true" />
|
|
|
+
|
|
|
+ <WriteProjectConfigFile ConfigDir="$(ProjectSpecificConfDir)"
|
|
|
+ AnalysisConfigPath="$(SonarQubeConfigPath)\SonarQubeAnalysisConfig.xml"
|
|
|
+ ProjectPath="$(MSBuildProjectFullPath)"
|
|
|
+ FilesToAnalyzePath ="$(AnalysisFileList)"
|
|
|
+ OutPath="$(ProjectSpecificOutDir)"
|
|
|
+ IsTest="$(SonarQubeTestProject)"
|
|
|
+ TargetFramework="$(TargetFramework)">
|
|
|
+ <Output TaskParameter="ProjectConfigFilePath" PropertyName="SonarProjectConfigFilePath" />
|
|
|
+ </WriteProjectConfigFile>
|
|
|
+
|
|
|
+ <ItemGroup>
|
|
|
+ <!-- Clear the original set of analyzers and additional files -->
|
|
|
+ <Analyzer Remove="@(Analyzer)" />
|
|
|
+ <AdditionalFiles Remove="@(AdditionalFiles)" />
|
|
|
+
|
|
|
+ <!-- Use the set of analyzers and additional files calculated by the GetAnalyzerSettings task -->
|
|
|
+ <Analyzer Include="@(SQAnalyzerFilePaths)" />
|
|
|
+ <AdditionalFiles Include="@(SQAdditionalFiles)" />
|
|
|
+ <AdditionalFiles Include="$(SonarProjectConfigFilePath)" />
|
|
|
+ <AdditionalFiles Include="$(SonarProjectOutFolderFilePath)" />
|
|
|
+ </ItemGroup>
|
|
|
+
|
|
|
+ <Message Importance="normal" Text="Sonar: ($(MSBuildProjectFile)) Analysis configured successfully with $(SonarProjectConfigFilePath)." />
|
|
|
+ </Target>
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+ <!-- End of Roslyn analysis section-->
|
|
|
+ <!-- **************************************************************************** -->
|
|
|
+
|
|
|
+</Project>
|