Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Analyzers prototype proposal #9735

Merged
merged 44 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a59fe1e
Initial demonstration version
JanKrivanek Feb 12, 2024
628394d
Make analyzer test use bootstrap properly (#9733)
JanKrivanek Feb 13, 2024
59ab931
Hook analyzers stats stub
JanKrivanek Feb 13, 2024
92e3795
Fix unit tests by explicitly opting into analysis
JanKrivanek Feb 14, 2024
33c4d2e
Disable build acceleration for MSBuild.Bootstrap
ladipro Feb 15, 2024
b37e495
Make EndToEndTests disposable
ladipro Feb 15, 2024
2db509f
Support running Analyzers.UnitTests from stage1
ladipro Feb 15, 2024
4cdd903
Fix MSBuild.dll casing
ladipro Feb 15, 2024
05450bb
Don't run netfx Analyzer.UnitTests in Windows Core builds
ladipro Feb 16, 2024
7e12ef0
Fix Analyzers.UnitTests on Mac
ladipro Feb 16, 2024
fdda2cd
Renaming changes
JanKrivanek Feb 16, 2024
72749c4
Renaming for clarity (#9754)
JanKrivanek Feb 16, 2024
9314121
Removing unnecessary types
JanKrivanek Feb 20, 2024
886c483
Code move
JanKrivanek Feb 20, 2024
60e01a7
Adjust namespaces
JanKrivanek Feb 20, 2024
b474fa1
Simplify TestEnvironments in EndToEndTests
ladipro Feb 21, 2024
ac76b77
Support for per-project configuration, Acquisition mounting, etc
JanKrivanek Feb 28, 2024
0467261
Add more comments
JanKrivanek Feb 28, 2024
5f9d941
Grace handle double initialization attempts
JanKrivanek Feb 29, 2024
40dd6e0
Fix tests
JanKrivanek Feb 29, 2024
bddef4c
Troubleshoot test, comment
JanKrivanek Feb 29, 2024
296faa9
Reflect PR comments
JanKrivanek Mar 1, 2024
f873eda
Fix build
JanKrivanek Mar 1, 2024
3db5e97
Fix build - proper multitargeting on core builds
JanKrivanek Mar 5, 2024
6021771
Adjust API naming and exposure
JanKrivanek Mar 12, 2024
72f2d51
Merge branch 'main' into exp/build-analyzers
JanKrivanek Mar 18, 2024
178907f
Add forgotten acquisition data sending
JanKrivanek Mar 18, 2024
e178918
Renaming BuildCop to BuildCheck (#9893)
maridematte Mar 19, 2024
0892e86
Renamed a few files missed (#9900)
maridematte Mar 21, 2024
31a2a0e
Add template for custom analyzers (#9789)
YuliiaKovalova Mar 25, 2024
d710e00
Merge branch 'main' into exp/build-analyzers
JanKrivanek Mar 25, 2024
5fab936
Run tests against just-built bootstrap environment
ladipro Apr 3, 2024
9b5b925
Reflecting PR comments
JanKrivanek Apr 4, 2024
d97a611
Add test without analysis
JanKrivanek Apr 4, 2024
e18f00f
Rename tests project
JanKrivanek Apr 4, 2024
368cb08
Force case renaming
JanKrivanek Apr 4, 2024
7025f3a
Simplify GlobalInstance initialization
JanKrivanek Apr 5, 2024
aeb4107
Remove multiple registrations checking
JanKrivanek Apr 5, 2024
01510e2
Reflect on PR feedback
JanKrivanek Apr 5, 2024
1d7c4c6
Apply suggestions from code review
JanKrivanek Apr 5, 2024
25b5f75
Reflect on PR comments
JanKrivanek Apr 5, 2024
aaaafcc
Update src/Build/BuildCheck/API/BuildAnalyzerRule.cs
JanKrivanek Apr 10, 2024
cf29add
Reflect PR comments
JanKrivanek Apr 10, 2024
402f490
Merge branch 'exp/build-analyzers' of https://github.com/dotnet/msbui…
JanKrivanek Apr 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions MSBuild.sln
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MSBuild.VSSetup.Arm64", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.UnitTests.Shared", "src\UnitTests.Shared\Microsoft.Build.UnitTests.Shared.csproj", "{52A0B9C1-23B7-4CCC-B3FC-BDBA1C619E2A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.Analyzers.UnitTests", "src\Analyzers.UnitTests\Microsoft.Build.Analyzers.UnitTests.csproj", "{B18BAE17-D78F-4F89-B7A4-808C05E64D73}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -864,6 +866,30 @@ Global
{52A0B9C1-23B7-4CCC-B3FC-BDBA1C619E2A}.Release|x64.Build.0 = Release|x64
{52A0B9C1-23B7-4CCC-B3FC-BDBA1C619E2A}.Release|x86.ActiveCfg = Release|Any CPU
{52A0B9C1-23B7-4CCC-B3FC-BDBA1C619E2A}.Release|x86.Build.0 = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|ARM64.ActiveCfg = Debug|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|ARM64.Build.0 = Debug|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x64.ActiveCfg = Debug|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x64.Build.0 = Debug|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x86.ActiveCfg = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x86.Build.0 = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|Any CPU.ActiveCfg = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|Any CPU.Build.0 = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|ARM64.ActiveCfg = MachineIndependent|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|ARM64.Build.0 = MachineIndependent|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x64.ActiveCfg = MachineIndependent|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x64.Build.0 = MachineIndependent|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x86.ActiveCfg = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x86.Build.0 = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|Any CPU.Build.0 = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|ARM64.ActiveCfg = Release|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|ARM64.Build.0 = Release|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x64.ActiveCfg = Release|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x64.Build.0 = Release|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x86.ActiveCfg = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
21 changes: 21 additions & 0 deletions eng/BootStrapMSBuild.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project>
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved

<!--
Construct a location of MSBuild bootstrap folder - to be used for deployment and for tests
relying on bootstrapped MSBuild
-->

<PropertyGroup>
<BootstrapDestination>$(ArtifactsBinDir)bootstrap\</BootstrapDestination>
<BootstrapDestination Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'arm64'">$(BootstrapDestination)$(Platform)\</BootstrapDestination>
<BootstrapDestination>$(BootstrapDestination)$(TargetFramework.ToLowerInvariant())\MSBuild\</BootstrapDestination>
</PropertyGroup>

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4'))">
<BootstrapBinaryDestination>$(BootstrapDestination)$(TargetMSBuildToolsVersion)\Bin</BootstrapBinaryDestination>
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<PropertyGroup Condition="!$(TargetFramework.StartsWith('net4'))">
<BootstrapBinaryDestination>$(BootstrapDestination)</BootstrapBinaryDestination>
</PropertyGroup>
</Project>
9 changes: 5 additions & 4 deletions eng/BootStrapMSBuild.targets
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
<Project>

<Import Project="BootStrapMSBuild.props" />
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved

<!--
Copies the binaries of MSBuild to a bootstrap folder so we can rebuild msbuild with itself.
On netcore it performs a directory copy.
On full framework it performs a more involved deployment.
-->

<PropertyGroup>
<BootstrapDestination>$(ArtifactsBinDir)bootstrap\</BootstrapDestination>
<BootstrapDestination Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'arm64'">$(BootstrapDestination)$(Platform)\</BootstrapDestination>
<BootstrapDestination>$(BootstrapDestination)$(TargetFramework.ToLowerInvariant())\MSBuild\</BootstrapDestination>

<BootstrapDependsOn Condition="$(TargetFramework.StartsWith('net4'))">BootstrapFull</BootstrapDependsOn>
<BootstrapDependsOn Condition="!$(TargetFramework.StartsWith('net4'))">BootstrapNetCore</BootstrapDependsOn>

<!-- Needed to ensure that RuntimeTargetsCopyLocalItems is populated for full framework -->
<DisableRuntimeTargets>false</DisableRuntimeTargets>

<!-- Disable build acceleration for this non-standard project. The Bootstrap target must run after any of the dependencies changes. -->
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
</PropertyGroup>

<Target Name="Bootstrap" DependsOnTargets="$(BootstrapDependsOn)"
Expand Down
3 changes: 3 additions & 0 deletions eng/cibuild_bootstrapped_msbuild.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ try {
# Opt into performance logging. https://github.com/dotnet/msbuild/issues/5900
$env:DOTNET_PERFLOG_DIR=$PerfLogDir

# Expose stage 1 path so unit tests can find the bootstrapped MSBuild.
$env:MSBUILD_BOOTSTRAPPED_BINDIR=$Stage1BinDir
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved

# When using bootstrapped MSBuild:
# - Turn off node reuse (so that bootstrapped MSBuild processes don't stay running and lock files)
# - Do run tests
Expand Down
3 changes: 3 additions & 0 deletions eng/cibuild_bootstrapped_msbuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ mv $ArtifactsDir $Stage1Dir
# Ensure that debug bits fail fast, rather than hanging waiting for a debugger attach.
export MSBUILDDONOTLAUNCHDEBUGGER=true

# Expose stage 1 path so unit tests can find the bootstrapped MSBuild.
export MSBUILD_BOOTSTRAPPED_BINDIR="$Stage1Dir/bin"

# Opt into performance logging.
export DOTNET_PERFLOG_DIR=$PerfLogDir

Expand Down
14 changes: 14 additions & 0 deletions src/Analyzers.UnitTests/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

global using NativeMethodsShared = Microsoft.Build.Framework.NativeMethods;

namespace Microsoft.Build.Analyzers.UnitTests;

[System.AttributeUsage(System.AttributeTargets.Assembly)]
internal sealed class BootstrapLocationAttribute(string bootstrapRoot, string bootstrapMsbuildBinaryLocation)
: System.Attribute
{
public string BootstrapRoot { get; } = bootstrapRoot;
public string BootstrapMsbuildBinaryLocation { get; } = bootstrapMsbuildBinaryLocation;
}
48 changes: 48 additions & 0 deletions src/Analyzers.UnitTests/BootstrapRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.UnitTests.Shared;
using Xunit.Abstractions;

#if FEATURE_MSIOREDIST
using Path = Microsoft.IO.Path;
#endif

namespace Microsoft.Build.Analyzers.UnitTests
{
internal static class BootstrapRunner
{
// This should ideally be part of RunnerUtilities - however then we'd need to enforce
// all test projects to import the BootStrapMSBuild.props file and declare the BootstrapLocationAttribute.
// Better solution would be to have a single test utility project - instead of linked code files.
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
public static string ExecBootstrapedMSBuild(string msbuildParameters, out bool successfulExit, bool shellExecute = false, ITestOutputHelper? outputHelper = null)
{
BootstrapLocationAttribute attribute = Assembly.GetExecutingAssembly().GetCustomAttribute<BootstrapLocationAttribute>()
?? throw new InvalidOperationException("This test assembly does not have the BootstrapLocationAttribute");

string binaryFolder = attribute.BootstrapMsbuildBinaryLocation;
string? bindirOverride = Environment.GetEnvironmentVariable("MSBUILD_BOOTSTRAPPED_BINDIR");
if (!string.IsNullOrEmpty(bindirOverride))
{
// The bootstrap environment has moved to another location. Assume the same relative layout and adjust the path.
string relativePath = Path.GetRelativePath(attribute.BootstrapRoot, binaryFolder);
binaryFolder = Path.GetFullPath(relativePath, bindirOverride);
}
#if NET
string pathToExecutable = EnvironmentProvider.GetDotnetExePath()!;
msbuildParameters = Path.Combine(binaryFolder, "MSBuild.dll") + " " + msbuildParameters;
#else
string pathToExecutable =
Path.Combine(binaryFolder, "msbuild.exe");
#endif
return RunnerUtilities.RunProcessAndGetOutput(pathToExecutable, msbuildParameters, out successfulExit, shellExecute, outputHelper);
}
}
}
129 changes: 129 additions & 0 deletions src/Analyzers.UnitTests/EndToEndTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.UnitTests;
using Microsoft.Build.UnitTests.Shared;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.Analyzers.UnitTests
{
public class EndToEndTests : IDisposable
{
private readonly TestEnvironment _env;
public EndToEndTests(ITestOutputHelper output)
{
_env = TestEnvironment.Create(output);

// this is needed to ensure the binary logger does not pollute the environment
_env.WithEnvironmentInvariant();
}

public void Dispose() => _env.Dispose();

[Theory]
[InlineData(true)]
[InlineData(false)]
public void SampleAnalyzerIntegrationTest(bool buildInOutOfProcessNode)
{
string contents = $"""
<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="Hello">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup Condition="$(Test) == true">
<TestProperty>Test</TestProperty>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include=".\FooBar-Copy.csproj" />
</ItemGroup>

<Target Name="Hello">
<Message Importance="High" Condition="$(Test2) == true" Text="XYZABC" />
</Target>

</Project>
""";

string contents2 = $"""
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup Condition="$(Test) == true">
<TestProperty>Test</TestProperty>
</PropertyGroup>

<ItemGroup>
<Reference Include="bin/foo.dll" />
</ItemGroup>

<Target Name="Hello">
<Message Importance="High" Condition="$(Test2) == true" Text="XYZABC" />
</Target>

</Project>
""";
TransientTestFolder workFolder = _env.CreateFolder(createFolder: true);
TransientTestFile projectFile = _env.CreateFile(workFolder, "FooBar.csproj", contents);
TransientTestFile projectFile2 = _env.CreateFile(workFolder, "FooBar-Copy.csproj", contents2);

// var cache = new SimpleProjectRootElementCache();
// ProjectRootElement xml = ProjectRootElement.OpenProjectOrSolution(projectFile.Path, /*unused*/null, /*unused*/null, cache, false /*Not explicitly loaded - unused*/);


TransientTestFile config = _env.CreateFile(workFolder, "editorconfig.json",
/*lang=json,strict*/
"""
{
"BC0101": {
"IsEnabled": true,
"Severity": "Error"
},
"COND0543": {
"IsEnabled": false,
"Severity": "Error",
"EvaluationAnalysisScope": "AnalyzedProjectOnly",
"CustomSwitch": "QWERTY"
},
"BLA": {
"IsEnabled": false
}
}
""");

// OSX links /var into /private, which makes Path.GetTempPath() return "/var..." but Directory.GetCurrentDirectory return "/private/var...".
// This discrepancy breaks path equality checks in analyzers if we pass to MSBuild full path to the initial project.
// TODO: See if there is a way of fixing it in the engine.
_env.SetCurrentDirectory(Path.GetDirectoryName(projectFile.Path));

_env.SetEnvironmentVariable("MSBUILDNOINPROCNODE", buildInOutOfProcessNode ? "1" : "0");
_env.SetEnvironmentVariable("MSBUILDLOGPROPERTIESANDITEMSAFTEREVALUATION", "1");
// string output = RunnerUtilities.ExecMSBuild($"{projectFile.Path} /m:1 -nr:False", out bool success);
string output = BootstrapRunner.ExecBootstrapedMSBuild($"{Path.GetFileName(projectFile.Path)} /m:1 -nr:False -restore -analyze", out bool success);
_env.Output.WriteLine(output);
success.ShouldBeTrue();
// The conflicting outputs warning appears
output.ShouldContain("BC0101");
}
}
}
92 changes: 92 additions & 0 deletions src/Analyzers.UnitTests/Microsoft.Build.Analyzers.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\Shared\FileSystemSources.proj" />
<Import Project="..\Shared\DebuggingSources.proj" />

<PropertyGroup>
<!-- Don't build a netfx version of this unit with dotnet, as the netfx bootstrap layout created with 'dotnet build' is incomplete. -->
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
<TargetFrameworks>$(LatestDotNetCoreForMSBuild)</TargetFrameworks>
<TargetFrameworks Condition="'$(MSBuildRuntimeType)' == 'Full'">$(FullFrameworkTFM);$(TargetFrameworks)</TargetFrameworks>

<PlatformTarget>$(RuntimeOutputPlatformTarget)</PlatformTarget>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RootNamespace>Microsoft.Build.Analyzers.UnitTests</RootNamespace>
<AssemblyName>Microsoft.Build.Analyzers.UnitTests</AssemblyName>
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Build\Microsoft.Build.csproj" />
<ProjectReference Include="..\UnitTests.Shared\Microsoft.Build.UnitTests.Shared.csproj" />
<ProjectReference Include="..\Xunit.NetCore.Extensions\Xunit.NetCore.Extensions.csproj" />
<ProjectReference Include="..\MSBuild.Bootstrap\MSBuild.Bootstrap.csproj">
<Private>false</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Collections.Immutable" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.IO.Redist" Condition="'$(FeatureMSIORedist)' == 'true'" />
<PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" PrivateAssets="all" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Shouldly" />
JanKrivanek marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="System.Net.Http" />
</ItemGroup>

<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
ladipro marked this conversation as resolved.
Show resolved Hide resolved
</ItemGroup>

<ItemGroup>
<Compile Include="..\Shared\FileUtilities.cs">
<Link>Shared\FileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\TempFileUtilities.cs">
<Link>Shared\TempFileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\ErrorUtilities.cs">
<Link>Shared\ErrorUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\EscapingUtilities.cs">
<Link>Shared\EscapingUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\BuildEnvironmentHelper.cs">
<Link>Shared\BuildEnvironmentHelper.cs</Link>
</Compile>
<Compile Include="..\Shared\ProcessExtensions.cs">
<Link>Shared\ProcessExtensions.cs</Link>
</Compile>
<Compile Include="..\Shared\ResourceUtilities.cs">
<Link>Shared\ResourceUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\ExceptionHandling.cs">
<Link>Shared\ExceptionHandling.cs</Link>
</Compile>
<Compile Include="..\Shared\FileUtilitiesRegex.cs">
<Link>Shared\FileUtilitiesRegex.cs</Link>
</Compile>
<Compile Include="..\Shared\UnitTests\AssemblyResources.cs">
<Link>Shared\AssemblyResources.cs</Link>
</Compile>
</ItemGroup>

<ItemGroup>
<None Include="..\Shared\UnitTests\App.config">
<Link>App.config</Link>
<SubType>Designer</SubType>
</None>
<None Include="..\Shared\UnitTests\xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<Import Project="..\..\eng\BootStrapMSBuild.props" />

<ItemGroup>
<AssemblyAttribute Include="Microsoft.Build.Analyzers.UnitTests.BootstrapLocationAttribute">
<_Parameter1>$(ArtifactsBinDir)</_Parameter1>
<_Parameter2>$(BootstrapBinaryDestination)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
</Project>
Loading
Loading