diff --git a/.opt-prof.yml b/.opt-prof.yml index ee9d1649fee..38796eed3b8 100644 --- a/.opt-prof.yml +++ b/.opt-prof.yml @@ -57,7 +57,6 @@ stages: cloudBuildResourceName: ComponentBuildUnderTest testLabPoolName: VS-Platform # The test lab pool to run your tests in testMachineCleanUpStrategy: ${{parameters.testMachineCleanUpStrategy}} - testMachineImageName: Windows-11-Enterprise-23H2 visualStudioSigning: Test variables: - name: branchName # The branch in the VS repo the bootstrapper was based on diff --git a/documentation/wiki/ChangeWaves.md b/documentation/wiki/ChangeWaves.md index 304e6b3a8b3..6b88ed66097 100644 --- a/documentation/wiki/ChangeWaves.md +++ b/documentation/wiki/ChangeWaves.md @@ -25,7 +25,7 @@ A wave of features is set to "rotate out" (i.e. become standard functionality) t ## Current Rotation of Change Waves ### 17.14 -- [.SLNX support - use the new parser for .sln and .slnx](https://github.com/dotnet/msbuild/pull/10836) +- ~[.SLNX support - use the new parser for .sln and .slnx](https://github.com/dotnet/msbuild/pull/10836)~ reverted after compat problems discovered - [Support custom culture in RAR](https://github.com/dotnet/msbuild/pull/11000) - [VS Telemetry](https://github.com/dotnet/msbuild/pull/11255) diff --git a/eng/BootStrapMsBuild.targets b/eng/BootStrapMsBuild.targets index d4330ba658d..dcff8617638 100644 --- a/eng/BootStrapMsBuild.targets +++ b/eng/BootStrapMsBuild.targets @@ -35,8 +35,7 @@ <_NuGetRuntimeDependencies Include="%(RuntimeCopyLocalItems.Identity)" Condition="'@(RuntimeCopyLocalItems->Contains('Newtonsoft.Json'))' == 'true'" /> <_NuGetRuntimeDependencies Include="%(RuntimeCopyLocalItems.Identity)" Condition="'@(RuntimeCopyLocalItems->Contains('NuGetSdkResolver'))' == 'true'" /> <_NuGetRuntimeDependencies Include="%(RuntimeCopyLocalItems.Identity)" Condition="'@(RuntimeCopyLocalItems->Contains('Microsoft.Extensions.'))' == 'true'" /> - <_NuGetRuntimeDependencies Include="%(RuntimeCopyLocalItems.Identity)" Condition="'@(RuntimeCopyLocalItems->Contains('Microsoft.VisualStudio.SolutionPersistence'))' == 'true'" /> - + <_NuGetRuntimeDependencies Include="%(RuntimeTargetsCopyLocalItems.Identity)" Condition="'@(RuntimeTargetsCopyLocalItems->Contains('NuGet.'))' == 'true'" /> @@ -49,7 +48,7 @@ - - - - - - - - - - - - - - - - - @(BravoProjectOutputs) - @(CharlieProjectOutputs) - @(DeltaProjectOutputs) - - - - - - - - - - - - - - - Count())' != '3' ` Text='Overall sln outputs must include outputs of each referenced project (there should be 3).' /> - AnyHaveMetadataValue('Identity', '$(StringifiedBravoProjectOutputs)'))' != 'true'` Text='Overall sln outputs must include outputs of normal project build of project B.' /> - AnyHaveMetadataValue('Identity', '$(StringifiedCharlieProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project C.' /> - AnyHaveMetadataValue('Identity', '$(StringifiedDeltaProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project D.' /> - - - """; + "; + const string automaticProjectFileContents = @" + + + + + + + + + + + + + + + + + + + + @(BravoProjectOutputs) + @(CharlieProjectOutputs) + @(DeltaProjectOutputs) + + + + + + + + + + + + + + + Count())' != '3' ` Text='Overall sln outputs must include outputs of each referenced project (there should be 3).' /> + AnyHaveMetadataValue('Identity', '$(StringifiedBravoProjectOutputs)'))' != 'true'` Text='Overall sln outputs must include outputs of normal project build of project B.' /> + AnyHaveMetadataValue('Identity', '$(StringifiedCharlieProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project C.' /> + AnyHaveMetadataValue('Identity', '$(StringifiedDeltaProjectOutputs)'))' != 'true' ` Text='Overall sln outputs must include outputs of normal project build of project D.' /> + +"; #endregion var logger = new MockLogger(output); @@ -1065,13 +1039,11 @@ public void SolutionConfigurationWithDependenciesRelaysItsOutputs() /// /// Test the SolutionProjectGenerator.AddPropertyGroupForSolutionConfiguration method /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestAddPropertyGroupForSolutionConfiguration(bool useNewParser) + [Fact] + public void TestAddPropertyGroupForSolutionConfiguration() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1091,9 +1063,9 @@ public void TestAddPropertyGroupForSolutionConfiguration(bool useNewParser) {A6F99D27-47B9-4EA4-BFC9-25157CBDC281}.Debug|Mixed Platforms.Build.0 = VCConfig1|Win32 EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectRootElement projectXml = ProjectRootElement.Create(); @@ -1140,13 +1112,11 @@ public void TestAddPropertyGroupForSolutionConfiguration(bool useNewParser) /// /// Make sure that BuildProjectInSolution is set to true of the Build.0 entry is in the solution configuration. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionSet(bool useNewParser) + [Fact] + public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionSet() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1161,9 +1131,9 @@ public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionSe {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.Build.0 = CSConfig1|Any CPU EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectRootElement projectXml = ProjectRootElement.Create(); @@ -1186,13 +1156,11 @@ public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionSe /// /// Make sure that BuildProjectInSolution is set to false of the Build.0 entry is in the solution configuration. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionNotSet(bool useNewParser) + [Fact] + public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionNotSet() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1206,9 +1174,9 @@ public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionNo {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Mixed Platforms.ActiveCfg = CSConfig1|Any CPU EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectRootElement projectXml = ProjectRootElement.Create(); @@ -1232,12 +1200,10 @@ public void TestAddPropertyGroupForSolutionConfigurationBuildProjectInSolutionNo /// In this bug, SkipNonexistentProjects was always set to 'Build'. It should be 'Build' for metaprojects and 'True' for everything else. /// The repro below has one of each case. WebProjects can't build so they are set as SkipNonexistentProjects='Build' /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void Regress751742_SkipNonexistentProjects(bool useNewParser) + public void Regress751742_SkipNonexistentProjects() { if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) { @@ -1246,7 +1212,7 @@ public void Regress751742_SkipNonexistentProjects(bool useNewParser) } var solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1266,10 +1232,10 @@ public void Regress751742_SkipNonexistentProjects(bool useNewParser) {A6F99D27-47B9-4EA4-BFC9-25157CBDC281}.Debug|Mixed Platforms.Build.0 = VCConfig1|Win32 EndGlobalSection EndGlobal - """; + "; // We're not passing in a /tv:xx switch, so the solution project will have tools version 2.0 - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + var solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); var instance = SolutionProjectGenerator.Generate(solution, null, ObjectModelHelpers.MSBuildDefaultToolsVersion, _buildEventContext, CreateMockLoggingService())[0]; @@ -1308,13 +1274,11 @@ public void Regress751742_SkipNonexistentProjects(bool useNewParser) /// if set when building a solution, will be specified as the ToolsVersion on the MSBuild task when /// building the projects contained within the solution. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ToolsVersionOverrideShouldBeSpecifiedOnMSBuildTaskInvocations(bool useNewParser) + [Fact] + public void ToolsVersionOverrideShouldBeSpecifiedOnMSBuildTaskInvocations() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1334,10 +1298,10 @@ public void ToolsVersionOverrideShouldBeSpecifiedOnMSBuildTaskInvocations(bool u {A6F99D27-47B9-4EA4-BFC9-25157CBDC281}.Debug|Mixed Platforms.Build.0 = VCConfig1|Win32 EndGlobalSection EndGlobal - """; + "; // We're not passing in a /tv:xx switch, so the solution project will have tools version 2.0 - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, null, ObjectModelHelpers.MSBuildDefaultToolsVersion, _buildEventContext, CreateMockLoggingService()); @@ -1376,44 +1340,42 @@ public void ToolsVersionOverrideShouldBeSpecifiedOnMSBuildTaskInvocations(bool u /// /// Make sure that whatever the solution ToolsVersion is, it gets mapped to all its metaprojs, too. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SolutionWithDependenciesHasCorrectToolsVersionInMetaprojs(bool useNewParser) + [Fact] + public void SolutionWithDependenciesHasCorrectToolsVersionInMetaprojs() { string solutionFileContents = - """ - Microsoft Visual Studio Solution File, Format Version 12.00 - Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ConsoleApplication2', 'ConsoleApplication2\ConsoleApplication2.csproj', '{5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}' - ProjectSection(ProjectDependencies) = postProject - {E0D295A1-CAFA-4E68-9929-468657DAAC6C} = {E0D295A1-CAFA-4E68-9929-468657DAAC6C} - EndProjectSection - EndProject - Project('{F184B08F-C81C-45F6-A57F-5ABD9991F28F}') = 'ConsoleApplication1', 'ConsoleApplication1\ConsoleApplication1.vbproj', '{E0D295A1-CAFA-4E68-9929-468657DAAC6C}' - EndProject - Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Release|Any CPU.Build.0 = Release|Any CPU - {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - EndGlobal - """; + @" +Microsoft Visual Studio Solution File, Format Version 12.00 +Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ConsoleApplication2', 'ConsoleApplication2\ConsoleApplication2.csproj', '{5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}' + ProjectSection(ProjectDependencies) = postProject + {E0D295A1-CAFA-4E68-9929-468657DAAC6C} = {E0D295A1-CAFA-4E68-9929-468657DAAC6C} + EndProjectSection +EndProject +Project('{F184B08F-C81C-45F6-A57F-5ABD9991F28F}') = 'ConsoleApplication1', 'ConsoleApplication1\ConsoleApplication1.vbproj', '{E0D295A1-CAFA-4E68-9929-468657DAAC6C}' +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B97A3C7-3DEE-47A4-870F-5CB6384FE6A4}.Release|Any CPU.Build.0 = Release|Any CPU + {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0D295A1-CAFA-4E68-9929-468657DAAC6C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal + "; // We're not passing in a /tv:xx switch, so the solution project will have tools version 2.0 - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); string[] solutionToolsVersions = { "4.0", ObjectModelHelpers.MSBuildDefaultToolsVersion }; @@ -1447,13 +1409,11 @@ public void SolutionWithDependenciesHasCorrectToolsVersionInMetaprojs(bool useNe /// /// Test the SolutionProjectGenerator.Generate method has its toolset redirected correctly. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ToolsVersionOverrideCausesToolsetRedirect(bool useNewParser) + [Fact] + public void ToolsVersionOverrideCausesToolsetRedirect() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ClassLibrary1', 'ClassLibrary1\ClassLibrary1.csproj', '{6185CC21-BE89-448A-B3C0-D1C27112E595}' @@ -1473,8 +1433,8 @@ public void ToolsVersionOverrideCausesToolsetRedirect(bool useNewParser) {A6F99D27-47B9-4EA4-BFC9-25157CBDC281}.Debug|Mixed Platforms.Build.0 = VCConfig1|Win32 EndGlobalSection EndGlobal - """; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + "; + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); bool caughtException = false; try @@ -1494,13 +1454,11 @@ public void ToolsVersionOverrideCausesToolsetRedirect(bool useNewParser) /// /// Test the SolutionProjectGenerator.AddPropertyGroupForSolutionConfiguration method /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestDisambiguateProjectTargetName(bool useNewParser) + [Fact] + public void TestDisambiguateProjectTargetName() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'Build', 'Build\Build.csproj', '{21397922-C38F-4A0E-B950-77B3FBD51881}' @@ -1520,9 +1478,9 @@ public void TestDisambiguateProjectTargetName(bool useNewParser) HideSolutionNode = FALSE EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, null, null, BuildEventContext.Invalid, CreateMockLoggingService()); @@ -1576,13 +1534,11 @@ public void TestDisambiguateProjectTargetName(bool useNewParser) /// /// Tests the algorithm for choosing default configuration/platform values for solutions /// - /// This test would only work for the old parser. In the new parser SolutionConfigurations are not available, - /// and constructed from projects configurations. [Fact] public void TestConfigurationPlatformDefaults1() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1594,9 +1550,9 @@ public void TestConfigurationPlatformDefaults1() Release|Win32 = Release|Win32 EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = SolutionFile_OldParser_Tests.ParseSolutionHelper(solutionFileContents); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); // These used to exist on the engine, but now need to be passed in explicitly IDictionary globalProperties = new Dictionary(); @@ -1616,13 +1572,11 @@ public void TestConfigurationPlatformDefaults1() /// /// Tests the algorithm for choosing default configuration/platform values for solutions /// - /// This test would only work for the old parser. In the new parser SolutionConfigurations are not available, - /// and constructed from projects configurations. [Fact] public void TestConfigurationPlatformDefaults2() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1632,9 +1586,9 @@ public void TestConfigurationPlatformDefaults2() Other|Win32 = Other|Win32 EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = SolutionFile_OldParser_Tests.ParseSolutionHelper(solutionFileContents); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, null, null, BuildEventContext.Invalid, CreateMockLoggingService()); @@ -1648,12 +1602,10 @@ public void TestConfigurationPlatformDefaults2() /// /// Tests the algorithm for choosing default Venus configuration values for solutions /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void TestVenusConfigurationDefaults(bool useNewParser) + public void TestVenusConfigurationDefaults() { if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) { @@ -1663,13 +1615,13 @@ public void TestVenusConfigurationDefaults(bool useNewParser) Dictionary globalProperties = new Dictionary(); globalProperties["Configuration"] = "Debug"; - ProjectInstance msbuildProject = CreateVenusSolutionProject(globalProperties, useNewParser); + ProjectInstance msbuildProject = CreateVenusSolutionProject(globalProperties); // ASP.NET configuration should match the selected solution configuration Assert.Equal("Debug", msbuildProject.GetPropertyValue("AspNetConfiguration")); globalProperties["Configuration"] = "Release"; - msbuildProject = CreateVenusSolutionProject(globalProperties, useNewParser); + msbuildProject = CreateVenusSolutionProject(globalProperties); Assert.Equal("Release", msbuildProject.GetPropertyValue("AspNetConfiguration")); // Check that the two standard Asp.net configurations are represented on the targets @@ -1680,12 +1632,10 @@ public void TestVenusConfigurationDefaults(bool useNewParser) /// /// Tests that the correct value for TargetFrameworkVersion gets set when creating Venus solutions /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void VenusSolutionDefaultTargetFrameworkVersion(bool useNewParser) + public void VenusSolutionDefaultTargetFrameworkVersion() { if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) { @@ -1694,7 +1644,7 @@ public void VenusSolutionDefaultTargetFrameworkVersion(bool useNewParser) } // v4.0 by default - ProjectInstance msbuildProject = CreateVenusSolutionProject(useNewParser); + ProjectInstance msbuildProject = CreateVenusSolutionProject(); Assert.Equal("v4.0", msbuildProject.GetPropertyValue("TargetFrameworkVersion")); if (FrameworkLocationHelper.PathToDotNetFrameworkV35 == null) @@ -1704,36 +1654,34 @@ public void VenusSolutionDefaultTargetFrameworkVersion(bool useNewParser) } // v3.5 if MSBuildToolsVersion is 3.5 - msbuildProject = CreateVenusSolutionProject("3.5", useNewParser); + msbuildProject = CreateVenusSolutionProject("3.5"); Assert.Equal("v3.5", msbuildProject.GetPropertyValue("TargetFrameworkVersion")); // v2.0 if MSBuildToolsVersion is 2.0 - msbuildProject = CreateVenusSolutionProject("2.0", useNewParser); + msbuildProject = CreateVenusSolutionProject("2.0"); Assert.Equal("v2.0", msbuildProject.GetPropertyValue("TargetFrameworkVersion")); // may be user defined IDictionary globalProperties = new Dictionary(); globalProperties.Add("TargetFrameworkVersion", "userdefined"); - msbuildProject = CreateVenusSolutionProject(globalProperties, useNewParser); + msbuildProject = CreateVenusSolutionProject(globalProperties); Assert.Equal("userdefined", msbuildProject.GetPropertyValue("TargetFrameworkVersion")); } /// /// Tests the algorithm for choosing target framework paths for ResolveAssemblyReferences for Venus /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void TestTargetFrameworkPaths0(bool useNewParser) + public void TestTargetFrameworkPaths0() { if (FrameworkLocationHelper.PathToDotNetFrameworkSdkV20 != null) { IDictionary globalProperties = new Dictionary(); globalProperties.Add("TargetFrameworkVersion", "v2.0"); - ProjectInstance msbuildProject = CreateVenusSolutionProject("2.0", useNewParser); + ProjectInstance msbuildProject = CreateVenusSolutionProject("2.0"); // ToolsVersion is 2.0, TargetFrameworkVersion is v2.0 --> one item pointing to v2.0 Assert.Equal("2.0", msbuildProject.ToolsVersion); @@ -1748,12 +1696,10 @@ public void TestTargetFrameworkPaths0(bool useNewParser) /// /// Tests the algorithm for choosing target framework paths for ResolveAssemblyReferences for Venus /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void TestTargetFrameworkPaths1(bool useNewParser) + public void TestTargetFrameworkPaths1() { if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) { @@ -1761,7 +1707,7 @@ public void TestTargetFrameworkPaths1(bool useNewParser) return; } - ProjectInstance msbuildProject = CreateVenusSolutionProject(useNewParser); + ProjectInstance msbuildProject = CreateVenusSolutionProject(); // ToolsVersion is 4.0, TargetFrameworkVersion is v2.0 --> one item pointing to v2.0 msbuildProject.SetProperty("TargetFrameworkVersion", "v2.0"); @@ -1776,12 +1722,10 @@ public void TestTargetFrameworkPaths1(bool useNewParser) /// /// Tests the algorithm for choosing target framework paths for ResolveAssemblyReferences for Venus /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void TestTargetFrameworkPaths2(bool useNewParser) + public void TestTargetFrameworkPaths2() { if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) { @@ -1789,7 +1733,7 @@ public void TestTargetFrameworkPaths2(bool useNewParser) return; } - ProjectInstance msbuildProject = CreateVenusSolutionProject(useNewParser); + ProjectInstance msbuildProject = CreateVenusSolutionProject(); // ToolsVersion is 4.0, TargetFrameworkVersion is v4.0 --> items for v2.0 and v4.0 msbuildProject.SetProperty("TargetFrameworkVersion", "v4.0"); @@ -1827,13 +1771,11 @@ public void TestTargetFrameworkPaths2(bool useNewParser) /// /// Test the PredictActiveSolutionConfigurationName method /// - /// This test would only work for the old parser. - /// In the new parser SolutionConfigurations are not available, and constructed from projects configurations. [Fact] public void TestPredictSolutionConfigurationName() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1843,9 +1785,9 @@ public void TestPredictSolutionConfigurationName() Debug|Win32 = Debug|Win32 EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = SolutionFile_OldParser_Tests.ParseSolutionHelper(solutionFileContents); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); IDictionary globalProperties = new Dictionary(); @@ -1864,13 +1806,11 @@ public void TestPredictSolutionConfigurationName() /// /// Verifies that the SolutionProjectGenerator will correctly escape project file paths /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SolutionGeneratorEscapingProjectFilePaths(bool useNewParser) + [Fact] + public void SolutionGeneratorEscapingProjectFilePaths() { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{F184B08F-C81C-45F6-A57F-5ABD9991F28F}') = 'ConsoleApplication1', '%abtest\ConsoleApplication1.vbproj', '{AB3413A6-D689-486D-B7F0-A095371B3F13}' @@ -1890,9 +1830,9 @@ public void SolutionGeneratorEscapingProjectFilePaths(bool useNewParser) HideSolutionNode = FALSE EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); // Creating a ProjectRootElement shouldn't affect the ProjectCollection at all Assert.Empty(ProjectCollection.GlobalProjectCollection.LoadedProjects); @@ -1909,10 +1849,8 @@ public void SolutionGeneratorEscapingProjectFilePaths(bool useNewParser) /// /// Verifies that the SolutionProjectGenerator will emit a solution file. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SolutionGeneratorCanEmitSolutions(bool useNewParser) + [Fact] + public void SolutionGeneratorCanEmitSolutions() { string oldValueForMSBuildEmitSolution = Environment.GetEnvironmentVariable("MSBuildEmitSolution"); @@ -1920,7 +1858,7 @@ public void SolutionGeneratorCanEmitSolutions(bool useNewParser) ProjectCollection.GlobalProjectCollection.UnloadAllProjects(); string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{F184B08F-C81C-45F6-A57F-5ABD9991F28F}') = 'ConsoleApplication1', 'ConsoleApplication1\ConsoleApplication1.vbproj', '{AB3413A6-D689-486D-B7F0-A095371B3F13}' @@ -1940,7 +1878,7 @@ public void SolutionGeneratorCanEmitSolutions(bool useNewParser) HideSolutionNode = FALSE EndGlobalSection EndGlobal - """; + "; SolutionFile solution = null; using ProjectCollection collection = new ProjectCollection(); @@ -1949,7 +1887,7 @@ public void SolutionGeneratorCanEmitSolutions(bool useNewParser) { Environment.SetEnvironmentVariable("MSBuildEmitSolution", "1"); - solution = ParseSolutionHelper(solutionFileContents, useNewParser); + solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); // Creating a ProjectRootElement shouldn't affect the ProjectCollection at all Assert.Empty(ProjectCollection.GlobalProjectCollection.LoadedProjects); @@ -1981,18 +1919,16 @@ public void SolutionGeneratorCanEmitSolutions(bool useNewParser) /// Make sure that we output a warning and don't build anything when we're given an invalid /// solution configuration and SkipInvalidConfigurations is set to true. /// - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [Trait("Category", "netcore-osx-failing")] [Trait("Category", "netcore-linux-failing")] - public void TestSkipInvalidConfigurationsCase(bool useNewParser) + public void TestSkipInvalidConfigurationsCase() { string tmpFileName = FileUtilities.GetTemporaryFileName(); string projectFilePath = tmpFileName + ".sln"; - string solutionFileContents = - """ + string solutionContents = + @" Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2005 Project('{E24C65DC-7377-472B-9ABA-BC803B73C61A}') = 'C:\solutions\WebSite2\', '..\..\solutions\WebSite2\', '{F90528C4-6989-4D33-AFE8-F53173597CC2}' @@ -2023,8 +1959,7 @@ public void TestSkipInvalidConfigurationsCase(bool useNewParser) {F90528C4-6989-4D33-AFE8-F53173597CC2}.Debug|Any CPU.ActiveCfg = Debug|.NET {F90528C4-6989-4D33-AFE8-F53173597CC2}.Debug|Any CPU.Build.0 = Debug|.NET EndGlobalSection - EndGlobal - """; + EndGlobal"; try { @@ -2034,7 +1969,7 @@ public void TestSkipInvalidConfigurationsCase(bool useNewParser) globalProperties["Configuration"] = "Nonexistent"; globalProperties["SkipInvalidConfigurations"] = "true"; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionContents.Replace('\'', '"')); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, globalProperties, null, BuildEventContext.Invalid, CreateMockLoggingService()); ProjectInstance msbuildProject = instances[0]; @@ -2238,52 +2173,50 @@ public void BadFrameworkMonkierExpectBuildToFail2() /// Bug indicated that when a target framework version greater than 4.0 was used then the solution project generator would crash. /// this test is to make sure the fix is not regressed. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestTargetFrameworkVersionGreaterThan4(bool useNewParser) + [Fact] + public void TestTargetFrameworkVersionGreaterThan4() { string tmpFileName = FileUtilities.GetTemporaryFileName(); string projectFilePath = tmpFileName + ".sln"; string solutionFileContents = - """ - Microsoft Visual Studio Solution File, Format Version 11.00 - # Visual Studio 2010 - Project('{E24C65DC-7377-472B-9ABA-BC803B73C61A}') = 'WebSite1', '..\WebSite1\', '{6B8F98F2-C976-4029-9321-5CCD73A174DA}' - ProjectSection(WebsiteProperties) = preProject - TargetFrameworkMoniker = '.NETFramework,Version=v4.34' - Debug.AspNetCompiler.VirtualPath = '/WebSite1' - Debug.AspNetCompiler.PhysicalPath = '..\WebSite1\' - Debug.AspNetCompiler.TargetPath = 'PrecompiledWeb\WebSite1\' - Debug.AspNetCompiler.Updateable = 'true' - Debug.AspNetCompiler.ForceOverwrite = 'true' - Debug.AspNetCompiler.FixedNames = 'false' - Debug.AspNetCompiler.Debug = 'True' - Release.AspNetCompiler.VirtualPath = '/WebSite1' - Release.AspNetCompiler.PhysicalPath = '..\WebSite1\' - Release.AspNetCompiler.TargetPath = 'PrecompiledWeb\WebSite1\' - Release.AspNetCompiler.Updateable = 'true' - Release.AspNetCompiler.ForceOverwrite = 'true' - Release.AspNetCompiler.FixedNames = 'false' - Release.AspNetCompiler.Debug = 'False' - VWDPort = '45602' - DefaultWebSiteLanguage = 'Visual Basic' - EndProjectSection - EndProject - Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6B8F98F2-C976-4029-9321-5CCD73A174DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B8F98F2-C976-4029-9321-5CCD73A174DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - EndGlobal - """; + @" +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project('{E24C65DC-7377-472B-9ABA-BC803B73C61A}') = 'WebSite1', '..\WebSite1\', '{6B8F98F2-C976-4029-9321-5CCD73A174DA}' + ProjectSection(WebsiteProperties) = preProject + TargetFrameworkMoniker = '.NETFramework,Version=v4.34' + Debug.AspNetCompiler.VirtualPath = '/WebSite1' + Debug.AspNetCompiler.PhysicalPath = '..\WebSite1\' + Debug.AspNetCompiler.TargetPath = 'PrecompiledWeb\WebSite1\' + Debug.AspNetCompiler.Updateable = 'true' + Debug.AspNetCompiler.ForceOverwrite = 'true' + Debug.AspNetCompiler.FixedNames = 'false' + Debug.AspNetCompiler.Debug = 'True' + Release.AspNetCompiler.VirtualPath = '/WebSite1' + Release.AspNetCompiler.PhysicalPath = '..\WebSite1\' + Release.AspNetCompiler.TargetPath = 'PrecompiledWeb\WebSite1\' + Release.AspNetCompiler.Updateable = 'true' + Release.AspNetCompiler.ForceOverwrite = 'true' + Release.AspNetCompiler.FixedNames = 'false' + Release.AspNetCompiler.Debug = 'False' + VWDPort = '45602' + DefaultWebSiteLanguage = 'Visual Basic' + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B8F98F2-C976-4029-9321-5CCD73A174DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B8F98F2-C976-4029-9321-5CCD73A174DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal + "; try { @@ -2293,9 +2226,7 @@ public void TestTargetFrameworkVersionGreaterThan4(bool useNewParser) globalProperties["Configuration"] = "Release"; globalProperties["SkipInvalidConfigurations"] = "true"; - - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); - + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents.Replace('\'', '"')); using ProjectCollection collection = new ProjectCollection(); collection.RegisterLogger(logger); @@ -2325,16 +2256,14 @@ public void TestTargetFrameworkVersionGreaterThan4(bool useNewParser) /// /// Verifies that when target names are specified they end up in the metaproj. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CustomTargetNamesAreInInMetaproj(bool useNewParser) + [Fact] + public void CustomTargetNamesAreInInMetaproj() { - string solutionFileContents = - """ - Microsoft Visual Studio Solution File, Format Version 12.00 + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper( + @" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" + Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2346,9 +2275,7 @@ public void CustomTargetNamesAreInInMetaproj(bool useNewParser) {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = CSConfig2|Any CPU EndGlobalSection EndGlobal - """; - - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + "); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, null, null, BuildEventContext.Invalid, CreateMockLoggingService(), new List { "One" }); @@ -2377,16 +2304,14 @@ public void CustomTargetNamesAreInInMetaproj(bool useNewParser) /// /// Verifies that disambiguated target names are used when a project name matches a standard solution entry point. /// - [Theory] - [InlineData(false)] - [InlineData(true)] - public void DisambiguatedTargetNamesAreInMetaproj(bool useNewParser) + [Fact] + public void DisambiguatedTargetNamesAreInInMetaproj() { - foreach (string projectName in ProjectInSolution.projectNamesToDisambiguate) + foreach(string projectName in ProjectInSolution.projectNamesToDisambiguate) { - string solutionFileContents = - $$""" - Microsoft Visual Studio Solution File, Format Version 12.00 + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper( + $$""" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{projectName}}", "{{projectName}}.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" EndProject @@ -2401,9 +2326,7 @@ public void DisambiguatedTargetNamesAreInMetaproj(bool useNewParser) {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal - """; - - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + """); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, null, null, BuildEventContext.Invalid, CreateMockLoggingService(), null); @@ -2426,33 +2349,29 @@ public void DisambiguatedTargetNamesAreInMetaproj(bool useNewParser) /// Verifies that illegal user target names (the ones already used internally) don't crash the SolutionProjectGenerator /// [Theory] - [InlineData(false, false)] - [InlineData(true, false)] - [InlineData(false, true)] - [InlineData(true, true)] - public void IllegalUserTargetNamesDoNotThrow(bool forceCaseDifference, bool useNewParser) + [InlineData(false)] + [InlineData(true)] + public void IllegalUserTargetNamesDoNotThrow(bool forceCaseDifference) { - string solutionFileContents = - """ - Microsoft Visual Studio Solution File, Format Version 12.00 + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper( + @" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" + Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal - """; - - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + "); ProjectInstance[] instances; @@ -2507,34 +2426,31 @@ public void AfterTargetsComeFromImport() { string baseDirectory = Guid.NewGuid().ToString("N"); - string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), - """ - Microsoft Visual Studio Solution File, Format Version 12.00 + string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), @" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" + Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal - """); + "); - ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"after.{Path.GetFileName(solutionFilePath)}.targets"), - """ - - + ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"after.{Path.GetFileName(solutionFilePath)}.targets"), @" + + - - """); + "); try { @@ -2566,34 +2482,31 @@ public void BeforeTargetsFromImportCanHookDynamicTarget() { string baseDirectory = Guid.NewGuid().ToString("N"); - string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), - """ - Microsoft Visual Studio Solution File, Format Version 12.00 + string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), @" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" + Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal - """); + "); - ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"after.{Path.GetFileName(solutionFilePath)}.targets"), - """ - - - + ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"after.{Path.GetFileName(solutionFilePath)}.targets"), @" + + + - - """); + "); try { @@ -2644,55 +2557,48 @@ public void DirectorySolutionPropsTest(string projectName, bool enable) string baseDirectory = Guid.NewGuid().ToString("N"); - string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), - """ - Microsoft Visual Studio Solution File, Format Version 12.00 + string solutionFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, $"{Guid.NewGuid():N}.sln"), @" + Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2015 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1.csproj", "{6185CC21-BE89-448A-B3C0-D1C27112E595}" + Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ClassLibrary1"", ""ClassLibrary1.csproj"", ""{6185CC21-BE89-448A-B3C0-D1C27112E595}"" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6185CC21-BE89-448A-B3C0-D1C27112E595}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal - """); + "); - string projectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, projectName), - $$""" - + string projectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, projectName), $@" + - {{expectedPropertyValue}} + {expectedPropertyValue} - - """); + "); if (projectPath.StartsWith("Custom", StringComparison.OrdinalIgnoreCase)) { // If a custom file name was given, create a Directory.Solution.props and Directory.Build.targets to ensure that they aren't imported - ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, "Directory.Solution.props"), - """ - - - This file should not be imported - - - """); - - ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, "Directory.Solution.targets"), - """ - - - This file should not be imported - - - """); + ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, "Directory.Solution.props"), $@" + + + This file should not be imported + + "); + + ObjectModelHelpers.CreateFileInTempProjectDirectory(Path.Combine(baseDirectory, "Directory.Solution.targets"), $@" + + + This file should not be imported + + "); } try @@ -2734,23 +2640,20 @@ public void DirectorySolutionPropsTest(string projectName, bool enable) /// Regression test for https://github.com/dotnet/msbuild/issues/6236 /// [Theory] - [InlineData("http://localhost:8080", false)] - [InlineData("http://localhost:8080", true)] - [InlineData(_longLineString, false)] - [InlineData(_longLineString, true)] - public void AbsolutePathWorksForUnsupportedPaths(string relativePath, bool useNewParser) + [InlineData("http://localhost:8080")] + [InlineData("a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-")] + public void AbsolutePathWorksForUnsupportedPaths(string relativePath) { string solutionFileContents = - $$""" - Microsoft Visual Studio Solution File, Format Version 12.00 - # Visual Studio Version 16 - VisualStudioVersion = 16.0.31025.194 - MinimumVisualStudioVersion = 10.0.40219.1 - Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "WebSite1", "{{relativePath}}", "{96E0707C-2E9C-4704-946F-FA583147737F}" - EndProject - """; + $@" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31025.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project(""{{E24C65DC-7377-472B-9ABA-BC803B73C61A}}"") = ""WebSite1"", ""{relativePath}"", ""{{{{96E0707C-2E9C-4704-946F-FA583147737F}}}}"" +EndProject"; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectInSolution projectInSolution = solution.ProjectsInOrder.ShouldHaveSingleItem(); @@ -2762,25 +2665,25 @@ public void AbsolutePathWorksForUnsupportedPaths(string relativePath, bool useNe /// /// Create a Project derived from a Venus solution /// - private ProjectInstance CreateVenusSolutionProject(bool useNewParser) + private ProjectInstance CreateVenusSolutionProject() { - return CreateVenusSolutionProject(null, null, useNewParser); + return CreateVenusSolutionProject(null, null); } /// /// Create a Project derived from a Venus solution /// - private ProjectInstance CreateVenusSolutionProject(IDictionary globalProperties, bool useNewParser) + private ProjectInstance CreateVenusSolutionProject(IDictionary globalProperties) { - return CreateVenusSolutionProject(globalProperties, null, useNewParser); + return CreateVenusSolutionProject(globalProperties, null); } /// /// Create a Project derived from a Venus solution /// - private ProjectInstance CreateVenusSolutionProject(string toolsVersion, bool useNewParser) + private ProjectInstance CreateVenusSolutionProject(string toolsVersion) { - return CreateVenusSolutionProject(null, toolsVersion, useNewParser); + return CreateVenusSolutionProject(null, toolsVersion); } /// @@ -2789,10 +2692,10 @@ private ProjectInstance CreateVenusSolutionProject(string toolsVersion, bool use /// /// The dictionary of global properties. May be null. /// The ToolsVersion override value. May be null. - private ProjectInstance CreateVenusSolutionProject(IDictionary globalProperties, string toolsVersion, bool useNewParser) + private ProjectInstance CreateVenusSolutionProject(IDictionary globalProperties, string toolsVersion) { string solutionFileContents = - """ + @" Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project('{E24C65DC-7377-472B-9ABA-BC803B73C61A}') = 'C:\solutions\WebSite2\', '..\..\solutions\WebSite2\', '{F90528C4-6989-4D33-AFE8-F53173597CC2}' @@ -2824,9 +2727,9 @@ private ProjectInstance CreateVenusSolutionProject(IDictionary g {F90528C4-6989-4D33-AFE8-F53173597CC2}.Debug|Any CPU.Build.0 = Debug|.NET EndGlobalSection EndGlobal - """; + "; - SolutionFile solution = ParseSolutionHelper(solutionFileContents, useNewParser); + SolutionFile solution = SolutionFile_Tests.ParseSolutionHelper(solutionFileContents); ProjectInstance[] instances = SolutionProjectGenerator.Generate(solution, globalProperties, toolsVersion, BuildEventContext.Invalid, CreateMockLoggingService()); @@ -2873,12 +2776,6 @@ private void AssertProjectItemNameCount(ProjectInstance msbuildProject, string i Assert.Equal(count, itemGroup.Count()); } - private SolutionFile ParseSolutionHelper(string solutionFileContents, bool useNewParser) - { - return useNewParser ? SolutionFile_NewParser_Tests.ParseSolutionHelper(solutionFileContents) : - SolutionFile_OldParser_Tests.ParseSolutionHelper(solutionFileContents); - } - #endregion // Helper Functions } } diff --git a/src/Build.UnitTests/Evaluation/Preprocessor_Tests.cs b/src/Build.UnitTests/Evaluation/Preprocessor_Tests.cs index da04dae2a84..b6b49388ec7 100644 --- a/src/Build.UnitTests/Evaluation/Preprocessor_Tests.cs +++ b/src/Build.UnitTests/Evaluation/Preprocessor_Tests.cs @@ -933,6 +933,7 @@ This import was added implicitly because the Project element's Sdk attribute spe } [Fact] + [ActiveIssue("https://github.com/dotnet/msbuild/issues/11498")] public void SdkResolverItemsAndPropertiesAreInPreprocessedOutput() { using (TestEnvironment env = TestEnvironment.Create()) diff --git a/src/Build.UnitTests/Graph/GetCompatiblePlatformGraph_Tests.cs b/src/Build.UnitTests/Graph/GetCompatiblePlatformGraph_Tests.cs index d6344240f1a..b941649ad74 100644 --- a/src/Build.UnitTests/Graph/GetCompatiblePlatformGraph_Tests.cs +++ b/src/Build.UnitTests/Graph/GetCompatiblePlatformGraph_Tests.cs @@ -402,14 +402,14 @@ public void SolutionWithoutAllConfigurations() // Slashes here (and in the .slnf) are hardcoded as backslashes intentionally to support the common case. TransientTestFile solutionFile = testEnvironment.CreateFile(folder, "SimpleProject.sln", - """ + @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29326.124 MinimumVisualStudioVersion = 10.0.40219.1 - Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Project1", "1\1\1.csproj", "{79B5EBA6-5D27-4976-BC31-14422245A59A}" + Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Project1"", ""1\1\1.csproj"", ""{79B5EBA6-5D27-4976-BC31-14422245A59A}"" EndProject - Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "2", "2\2\2.proj", "{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}" + Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""2"", ""2\2\2.proj"", ""{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -434,7 +434,7 @@ public void SolutionWithoutAllConfigurations() SolutionGuid = {DE7234EC-0C4D-4070-B66A-DCF1B4F0CFEF} EndGlobalSection EndGlobal - """); + "); ProjectCollection projectCollection = testEnvironment.CreateProjectCollection().Collection; MockLogger logger = new(); diff --git a/src/Build.UnitTests/Graph/GraphLoadedFromSolution_tests.cs b/src/Build.UnitTests/Graph/GraphLoadedFromSolution_tests.cs index 6d535479b1e..431ea412875 100644 --- a/src/Build.UnitTests/Graph/GraphLoadedFromSolution_tests.cs +++ b/src/Build.UnitTests/Graph/GraphLoadedFromSolution_tests.cs @@ -59,8 +59,7 @@ public void GraphConstructionFailsOnNonExistentSolution() new ProjectGraph("nonExistent.sln"); }); - exception.Message.ShouldContain("The project file could not be loaded."); - exception.Message.ShouldContain("Could not find file"); + exception.Message.ShouldContain("The project file could not be loaded. Could not find file"); } [Fact] @@ -647,6 +646,28 @@ IEnumerable GetIncomingEdgeItemsToNode(ProjectGraphNode nod } } + [Fact] + public void GraphConstructionShouldThrowOnMissingSolutionDependencies() + { + var solutionContents = SolutionFileBuilder.FromGraphEdges( + _env, + new Dictionary { { 1, null }, { 2, null } }, + new[] { ("1", new[] { Guid.NewGuid().ToString("B") }) }).BuildSolution(); + + var solutionFile = _env.CreateFile( + "solution.sln", + solutionContents) + .Path; + + var exception = Should.Throw( + () => + { + new ProjectGraph(solutionFile); + }); + + exception.Message.ShouldContain("but a project with this GUID was not found in the .SLN file"); + } + private static bool IsSolutionItemReference(ProjectItemInstance edgeItem) { return edgeItem.ItemType == GraphBuilder.SolutionItemReference; diff --git a/src/Build/Construction/ProjectRootElement.cs b/src/Build/Construction/ProjectRootElement.cs index cc416e5d409..eee48e9f667 100644 --- a/src/Build/Construction/ProjectRootElement.cs +++ b/src/Build/Construction/ProjectRootElement.cs @@ -176,6 +176,14 @@ internal ProjectRootElement(XmlReader xmlReader, ProjectRootElementCacheBase pro ProjectParser.Parse(document, this); } + private readonly bool _isEphemeral = false; + + private ProjectRootElement(ProjectRootElementCacheBase projectRootElementCache, NewProjectFileOptions projectFileOptions, bool isEphemeral) + : this(projectRootElementCache, projectFileOptions) + { + _isEphemeral = isEphemeral; + } + /// /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later. /// Leaves the project dirty, indicating there are unsaved changes. @@ -321,6 +329,8 @@ public override string Condition /// public ICollection Imports => new ReadOnlyCollection(GetAllChildrenOfType()); + internal bool IsEphemeral => _isEphemeral; + /// /// Get a read-only collection of the child property groups, if any. /// Does not include any that may not be at the root, i.e. inside Choose elements. @@ -712,6 +722,18 @@ internal ProjectExtensionsElement ProjectExtensions internal string LastDirtyReason => _dirtyReason == null ? null : String.Format(CultureInfo.InvariantCulture, _dirtyReason, _dirtyParameter); + /// + /// Initialize an in-memory empty ProjectRootElement instance that CANNOT be saved later. + /// The ProjectRootElement will not be marked dirty. + /// Uses the global project collection. + /// + internal static ProjectRootElement CreateEphemeral(ProjectRootElementCacheBase projectRootElementCache) + { + ErrorUtilities.VerifyThrowArgumentNull(projectRootElementCache); + + return new ProjectRootElement(projectRootElementCache, Project.DefaultNewProjectTemplateOptions, isEphemeral: true); + } + /// /// Initialize an in-memory, empty ProjectRootElement instance that can be saved later. /// Uses the global project collection. @@ -1817,6 +1839,11 @@ internal override void VerifyThrowInvalidOperationAcceptableLocation(ProjectElem /// internal sealed override void MarkDirty(string reason, string param) { + if (_isEphemeral) + { + return; + } + if (Link != null) { RootLink.MarkDirty(reason, param); diff --git a/src/Build/Construction/Solution/SolutionFile.cs b/src/Build/Construction/Solution/SolutionFile.cs index 63ce5b9dcee..b549e97da5a 100644 --- a/src/Build/Construction/Solution/SolutionFile.cs +++ b/src/Build/Construction/Solution/SolutionFile.cs @@ -193,7 +193,7 @@ internal int VisualStudioVersion internal bool UseNewParser => ShouldUseNewParser(_solutionFile); - internal static bool ShouldUseNewParser(string solutionFile) => ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_14) || FileUtilities.IsSolutionXFilename(solutionFile); + internal static bool ShouldUseNewParser(string solutionFile) => FileUtilities.IsSolutionXFilename(solutionFile); /// /// All projects in this solution, in the order they appeared in the solution file @@ -221,10 +221,6 @@ internal string FullPath set { - if (ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_14) && string.IsNullOrEmpty(value)) - { - throw new ArgumentNullException(nameof(FullPath)); - } // Should already be canonicalized to a full path ErrorUtilities.VerifyThrowInternalRooted(value); // To reduce code duplication, this should be diff --git a/src/Build/Definition/Project.cs b/src/Build/Definition/Project.cs index 1348a7cffcc..2401d4935a1 100644 --- a/src/Build/Definition/Project.cs +++ b/src/Build/Definition/Project.cs @@ -2257,7 +2257,7 @@ public override IList Imports foreach (ResolvedImport import in _data.ImportClosure) { - if (import.ImportingElement != null) // Exclude outer project itself + if (import.ImportingElement != null && !import.ImportedProject.IsEphemeral) // Exclude outer project itself and SDK-resolver synthesized imports { imports.Add(import); } @@ -2280,7 +2280,7 @@ public override IList ImportsIncludingDuplicates foreach (var import in _data.ImportClosureWithDuplicates) { - if (import.ImportingElement != null) // Exclude outer project itself + if (import.ImportingElement != null && !import.ImportedProject.IsEphemeral) // Exclude outer project itself and SDK-resolver synthesized imports { imports.Add(import); } diff --git a/src/Build/Evaluation/Evaluator.cs b/src/Build/Evaluation/Evaluator.cs index e285a948aa4..cba4152a3fc 100644 --- a/src/Build/Evaluation/Evaluator.cs +++ b/src/Build/Evaluation/Evaluator.cs @@ -1931,7 +1931,7 @@ private ProjectRootElement CreateProjectForSdkResult(SdkResult sdkResult) ProjectRootElement InnerCreate(string _, ProjectRootElementCacheBase __) { - ProjectRootElement project = ProjectRootElement.Create(); + ProjectRootElement project = ProjectRootElement.CreateEphemeral(_projectRootElementCache); project.FullPath = projectPath; if (sdkResult.PropertiesToAdd?.Any() == true)