diff --git a/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs b/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs index a5041d55fd6..e596bc05e8a 100644 --- a/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs +++ b/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Xml; using Microsoft.Build.Construction; using Microsoft.Build.Definition; using Microsoft.Build.Evaluation; @@ -137,6 +138,40 @@ public void SdkResolverCanReturnNoPaths(bool includePropertiesAndItems) _logger.WarningCount.ShouldBe(0); } + [Fact] + public void SuccessfullyEvaluatesSdkResultWithPropertiesForNullProjectRootElement() + { + Dictionary propertiesToAdd = null; + Dictionary itemsToAdd = null; + + CreateMockSdkResultPropertiesAndItems(out propertiesToAdd, out itemsToAdd); + + var projectOptions = SdkUtilities.CreateProjectOptionsWithResolver(new SdkUtilities.ConfigurableMockSdkResolver( + new Build.BackEnd.SdkResolution.SdkResult( + new SdkReference("TestPropsAndItemsFromResolverSdk", null, null), + Enumerable.Empty(), + version: null, + propertiesToAdd, + itemsToAdd, + warnings: null))); + + string projectContent = @" + + + "; + + string projectPath = Path.Combine(_testFolder, "project.proj"); + File.WriteAllText(projectPath, projectContent); + + using XmlReader xmlReader = XmlReader.Create(projectPath); + + projectOptions.ProjectCollection = _projectCollection; + + // Creating project from XmlReader results in null ProjectRootElement on Evaluation phase. + // In that case project created for SdkResult properties and items is given a unique file name {Guid}.SdkResolver.{propertiesAndItemsHash}.proj in the current directory + Project.FromXmlReader(xmlReader, projectOptions); + } + [Theory] [InlineData(true, true)] [InlineData(true, false)] diff --git a/src/Build/Evaluation/Evaluator.cs b/src/Build/Evaluation/Evaluator.cs index cba4152a3fc..ebd4e1a7383 100644 --- a/src/Build/Evaluation/Evaluator.cs +++ b/src/Build/Evaluation/Evaluator.cs @@ -1926,8 +1926,13 @@ private ProjectRootElement CreateProjectForSdkResult(SdkResult sdkResult) propertiesAndItemsHash = hash.ToHashCode(); #endif - // Generate a unique filename for the generated project for each unique set of properties and items. - string projectPath = _projectRootElement.FullPath + ".SdkResolver." + propertiesAndItemsHash + ".proj"; + // Generate a unique filename for the generated project for each unique set of properties and items that ends like ".SdkResolver.{propertiesAndItemsHash}.proj". + // _projectRootElement.FullPath can be null. This can be in the case when Project is created from XmlReader. For that case we generate filename like "{Guid}.SdkResolver.{propertiesAndItemsHash}.proj in the current directory. + // Otherwise the project is in the same directory as _projectRootElement and has a name of the same project and ends like ".SdkResolver.{propertiesAndItemsHash}.proj". + string projectNameEnding = $".SdkResolver.{propertiesAndItemsHash}.proj"; + string projectPath = _projectRootElement.FullPath != null ? + _projectRootElement.FullPath + projectNameEnding : + FileUtilities.NormalizePath(Guid.NewGuid() + projectNameEnding); ProjectRootElement InnerCreate(string _, ProjectRootElementCacheBase __) {