diff --git a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Design.targets b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Design.targets index a08b453e177d..5d9f5a2e0058 100644 --- a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Design.targets +++ b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Design.targets @@ -4,6 +4,7 @@ $(CollectUpToDateCheckInputDesignTimeDependsOn); ResolveStaticWebAssetsConfiguration; ResolveProjectStaticWebAssets; + ResolveReferencedProjectsStaticWebAssetsConfiguration; CollectStaticWebAssetInputsDesignTime; @@ -61,6 +62,7 @@ + diff --git a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.References.targets b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.References.targets index 2ce47328997a..20537de45e73 100644 --- a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.References.targets +++ b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.References.targets @@ -46,14 +46,42 @@ Copyright (c) .NET Foundation. All rights reserved. + + + <_StaticWebAssetDesignTimeProjectReference Include="@(_MSBuildProjectReferenceExistent)" /> + + + + + + + + <_ReferenceManifestPath Include="@(_ReferencedProjectsConfiguration->'%(BuildManifestPath)')" Condition="'%(_ReferencedProjectsConfiguration.BuildManifestPath)' != ''" /> + <_ReferenceManifestPath Include="@(_ReferencedProjectsConfiguration->'%(EndpointsBuildManifestPath)')" Condition="'%(_ReferencedProjectsConfiguration.EndpointsBuildManifestPath)' != ''" /> + + <_ReferenceManifestPath Include="@(_DesignTimeReferencedProjectsConfiguration->'%(BuildManifestPath)')" Condition="'%(_DesignTimeReferencedProjectsConfiguration.BuildManifestPath)' != ''" /> + <_ReferenceManifestPath Include="@(_DesignTimeReferencedProjectsConfiguration->'%(EndpointsBuildManifestPath)')" Condition="'%(_DesignTimeReferencedProjectsConfiguration.EndpointsBuildManifestPath)' != ''" /> $(StaticWebAssetsAdditionalPublishPropertiesToRemove) $([System.IO.Path]::GetFullPath('$(StaticWebAssetBuildManifestPath)')) + $([System.IO.Path]::GetFullPath('$(StaticWebAssetEndpointsBuildManifestPath)')) diff --git a/test/Microsoft.NET.Sdk.StaticWebAssets.Tests/StaticWebAssetsDesignTimeTest.cs b/test/Microsoft.NET.Sdk.StaticWebAssets.Tests/StaticWebAssetsDesignTimeTest.cs index 5b57ef2b2c53..e139ea06073f 100644 --- a/test/Microsoft.NET.Sdk.StaticWebAssets.Tests/StaticWebAssetsDesignTimeTest.cs +++ b/test/Microsoft.NET.Sdk.StaticWebAssets.Tests/StaticWebAssetsDesignTimeTest.cs @@ -51,8 +51,9 @@ public void CollectUpToDateCheckInputOutputsDesignTime_ReportsAddedFiles() var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt"); new FileInfo(outputFilePath).Should().Exist(); var outputFiles = File.ReadAllLines(outputFilePath); - outputFiles.Should().ContainSingle(); - Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json"); + outputFiles.Should().HaveCount(2); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json"); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json"); } [Fact] @@ -86,8 +87,9 @@ public void CollectUpToDateCheckInputOutputsDesignTime_ReportsRemovedFiles_Once( var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt"); new FileInfo(outputFilePath).Should().Exist(); var outputFiles = File.ReadAllLines(outputFilePath); - outputFiles.Should().ContainSingle(); - Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json"); + outputFiles.Should().HaveCount(2); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json"); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json"); } [Fact] @@ -105,7 +107,7 @@ public void CollectUpToDateCheckInputOutputsDesignTime_IncludesReferencedProject var msbuild = CreateMSBuildCommand( ProjectDirectory, "AppWithP2PReference", - "ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime"); + "ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;ResolveReferencedProjectsStaticWebAssetsConfiguration;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime"); msbuild.ExecuteWithoutRestore("/p:DesignTimeBuild=true", "/p:BuildingInsideVisualStudio=true", "/bl:design.binlog").Should().Pass(); @@ -113,14 +115,51 @@ public void CollectUpToDateCheckInputOutputsDesignTime_IncludesReferencedProject var inputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCInput.txt"); new FileInfo(inputFilePath).Should().Exist(); var inputFiles = File.ReadAllLines(inputFilePath); - inputFiles.Should().HaveCount(1); + inputFiles.Should().HaveCount(2); + inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.json")); + inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.endpoints.json")); + + var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt"); + new FileInfo(outputFilePath).Should().Exist(); + var outputFiles = File.ReadAllLines(outputFilePath); + outputFiles.Should().HaveCount(2); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json"); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json"); + } + + [Fact] + public void CollectUpToDateCheckInputOutputsDesignTime_IncludesReferencedProjectsManifests_OnInitialLoad() + { + // This test verifies the timing bug fix: referenced project manifest paths must be available + // in the FUTDC inputs even before a full build has occurred (i.e., on initial VS load). + // Arrange + var testAsset = "RazorAppWithP2PReference"; + ProjectDirectory = AddIntrospection(CreateAspNetSdkTestAsset(testAsset)); + + var build = CreateBuildCommand(ProjectDirectory, "AppWithP2PReference"); + + var msbuild = CreateMSBuildCommand( + ProjectDirectory, + "AppWithP2PReference", + "ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;ResolveReferencedProjectsStaticWebAssetsConfiguration;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime"); + + // Run design-time targets WITHOUT a prior full build to simulate initial VS project load + msbuild.ExecuteWithoutRestore("/p:DesignTimeBuild=true", "/p:BuildingInsideVisualStudio=true", "/bl:design.binlog").Should().Pass(); + + // The referenced project manifest paths must be tracked as inputs, even without a prior build + var inputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCInput.txt"); + new FileInfo(inputFilePath).Should().Exist(); + var inputFiles = File.ReadAllLines(inputFilePath); + inputFiles.Should().HaveCount(2); inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.json")); + inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.endpoints.json")); var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt"); new FileInfo(outputFilePath).Should().Exist(); var outputFiles = File.ReadAllLines(outputFilePath); - outputFiles.Should().ContainSingle(); - Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json"); + outputFiles.Should().HaveCount(2); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json"); + outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json"); } private static MSBuildCommand CreateMSBuildCommand(TestAsset testAsset, string relativeProjectPath, string targets)