/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Core/MSBuildTaskTests/SdkIntegrationTests.cs
278 строк
10 KB
Copilot
Embed AnalyzerConfigFiles in binlog (#82741)
25 мар 2026, 12:37
Не верифицирован
25 мар 2026, 12:37
d3fa672
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Basic.CompilerLog.Util; using Microsoft.Build.Logging.StructuredLogger; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.BuildTasks.UnitTests; public sealed class SdkIntegrationTests : IDisposable { public const string NetCoreTfm = "net10.0"; public ITestOutputHelper TestOutputHelper { get; } public TempRoot Temp { get; } public TempDirectory ProjectDir { get; } public ArtifactUploadUtil ArtifactUploadUtil { get; } public SdkIntegrationTests(ITestOutputHelper testOutputHelper) { Assert.NotNull(DotNetSdkTestBase.DotNetInstallDir); TestOutputHelper = testOutputHelper; Temp = new TempRoot(); ProjectDir = Temp.CreateDirectory(); ArtifactUploadUtil = new ArtifactUploadUtil(testOutputHelper); } public void Dispose() { Temp.Dispose(); ArtifactUploadUtil.Dispose(); } public static string GetRoslynTargetsPath() { var p = typeof(SdkIntegrationTests).Assembly.Location!; var dir = Path.GetDirectoryName(p)!; var targets = Path.Combine(dir, "Microsoft.CSharp.Core.targets"); Assert.True(File.Exists(targets)); return dir; } /// <summary> /// Runs the build and returns the path to the binary log file /// </summary> private string RunBuild( string projectFilePath, string? additionalArguments = null, IEnumerable<KeyValuePair<string, string>>? additionalEnvironmentVars = null, bool succeeds = true) { var workingDirectory = Path.GetDirectoryName(projectFilePath)!; ArtifactUploadUtil.AddDirectory(workingDirectory); var args = new StringBuilder(); args.Append("build /bl "); args.Append($"/p:RoslynTargetsPath={GetRoslynTargetsPath()} "); args.Append($"/p:RoslynTasksAssembly={typeof(Csc).Assembly.Location} "); args.Append($"/p:RoslynCompilerType=Custom "); if (additionalArguments is not null) { args.Append(additionalArguments); } var result = ProcessUtilities.Run(DotNetSdkTestBase.DotNetExeName, args.ToString(), workingDirectory, additionalEnvironmentVars); if (succeeds) { Assert.True(result.ExitCode == 0, $"MSBuild failed with exit code {result.ExitCode}: {result.Output}"); } else { Assert.False(result.ExitCode == 0, $"MSBuild failed with exit code {result.ExitCode}: {result.Output}"); } return Path.Combine(workingDirectory, "msbuild.binlog"); } private static List<Compilation> ReadCompilations(string binaryLogPath) { using var reader = BinaryLogReader.Create(binaryLogPath, BasicAnalyzerKind.None); var list = new List<Compilation>(); foreach (var compilerCall in reader.ReadAllCompilerCalls()) { var compilation = reader.ReadCompilationData(compilerCall).GetCompilationAfterGenerators(); list.Add(compilation); } return list; } [ConditionalFact(typeof(DotNetSdkAvailable))] public void Console() { var projectFile = ProjectDir.CreateFile("console.csproj"); projectFile.WriteAllText($""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>{NetCoreTfm}</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project> """); ProjectDir.CreateFile("hello.cs").WriteAllText(""" Console.WriteLine("Hello, World!"); """); var binlogPath = RunBuild(projectFile.Path); var compilations = ReadCompilations(binlogPath); Assert.Single(compilations); Assert.True(compilations[0].SyntaxTrees.Any(x => Path.GetFileName(x.FilePath) == "hello.cs")); ArtifactUploadUtil.SetSucceeded(); } [ConditionalTheory(typeof(DotNetSdkAvailable))] [InlineData(NetCoreTfm, true)] [InlineData("net6.0", true)] [InlineData("netstandard2.0", false)] [InlineData("net472", false)] public void StrongNameWarningCSharp(string tfm, bool expectStrongNameSuppression) { var projectFile = ProjectDir.CreateFile("console.csproj"); projectFile.WriteAllText($""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Library</OutputType> <TargetFramework>{tfm}</TargetFramework> </PropertyGroup> </Project> """); ProjectDir.CreateFile("hello.cs").WriteAllText(""" class C { } """); var binlogPath = RunBuild(projectFile.Path); var compilation = ReadCompilations(binlogPath).Single(); var options = compilation.Options; if (expectStrongNameSuppression) { Assert.True(options.SpecificDiagnosticOptions.TryGetValue("CS8002", out ReportDiagnostic d)); Assert.Equal(ReportDiagnostic.Suppress, d); } else { Assert.False(options.SpecificDiagnosticOptions.TryGetValue("CS8002", out _)); } ArtifactUploadUtil.SetSucceeded(); } [ConditionalTheory(typeof(DotNetSdkAvailable))] [InlineData(NetCoreTfm, true)] [InlineData("net6.0", true)] [InlineData("netstandard2.0", false)] [InlineData("net472", false)] public void StrongNameWarningVisualBasic(string tfm, bool expectStrongNameSuppression) { var projectFile = ProjectDir.CreateFile("console.vbproj"); projectFile.WriteAllText($""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Library</OutputType> <TargetFramework>{tfm}</TargetFramework> </PropertyGroup> </Project> """); ProjectDir.CreateFile("hello.vb").WriteAllText(""" Module M End Module """); var binlogPath = RunBuild(projectFile.Path); var compilation = ReadCompilations(binlogPath).Single(); var options = compilation.Options; if (expectStrongNameSuppression) { Assert.True(options.SpecificDiagnosticOptions.TryGetValue("BC41997", out ReportDiagnostic d)); Assert.Equal(ReportDiagnostic.Suppress, d); } else { Assert.False(options.SpecificDiagnosticOptions.TryGetValue("BC41997", out _)); } ArtifactUploadUtil.SetSucceeded(); } [ConditionalFact(typeof(DotNetSdkAvailable))] [WorkItem("https://github.com/dotnet/roslyn/issues/82721")] public void EditorConfig_EmbeddedInBinlog_Generated() { var projectFile = ProjectDir.CreateFile("console.csproj"); projectFile.WriteAllText($""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>{NetCoreTfm}</TargetFramework> </PropertyGroup> <ItemGroup> <CompilerVisibleProperty Include="RootNamespace" /> </ItemGroup> </Project> """); ProjectDir.CreateFile("c.cs").WriteAllText(""" class C { } """); var binlogPath = RunBuild(projectFile.Path); var build = BinaryLog.ReadBuild(binlogPath); string embeddedText = build.SourceFiles .Single(static f => f.FullPath.EndsWith("GeneratedMSBuildEditorConfig.editorconfig", StringComparison.OrdinalIgnoreCase)) .Text; Assert.Contains("is_global = true", embeddedText); Assert.Contains("build_property.RootNamespace", embeddedText); ArtifactUploadUtil.SetSucceeded(); } [ConditionalFact(typeof(DotNetSdkAvailable))] [WorkItem("https://github.com/dotnet/roslyn/issues/82721")] public void EditorConfig_EmbeddedInBinlog_FromTarget() { string analyzerGlobalConfigText = """ is_global = true some_prop = some_val """; var analyzerGlobalConfig = ProjectDir.CreateFile("analyzer.globalconfig").WriteAllText(analyzerGlobalConfigText); var projectFile = ProjectDir.CreateFile("console.csproj"); projectFile.WriteAllText($""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>{NetCoreTfm}</TargetFramework> </PropertyGroup> <Target Name="AddAnalyzerPackageEditorConfigFile" BeforeTargets="CoreCompile"> <ItemGroup> <EditorConfigFiles Include="{analyzerGlobalConfig.Path}" /> </ItemGroup> </Target> </Project> """); ProjectDir.CreateFile("c.cs").WriteAllText(""" class C { } """); var binlogPath = RunBuild(projectFile.Path); var build = BinaryLog.ReadBuild(binlogPath); string embeddedText = build.SourceFiles .Single(f => f.FullPath.Equals(analyzerGlobalConfig.Path, StringComparison.OrdinalIgnoreCase)) .Text; Assert.Equal(analyzerGlobalConfigText, embeddedText); ArtifactUploadUtil.SetSucceeded(); } }