Skip to content

Commit 060ff0d

Browse files
authored
Ensure ApplicationPart attributes are added during incremental builds (dotnet/razor#686)
Fixes https://github.com/aspnet/AspNetCore/issues/11315\n\nCommit migrated from dotnet/razor@1a7a74b
1 parent c16d55c commit 060ff0d

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets

+10-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,16 @@ Copyright (c) .NET Foundation. All rights reserved.
6767
OutputFile="$(_MvcApplicationPartAttributeGeneratedFile)"
6868
Condition="'@(_ApplicationPartAssemblyNames->Count())' != '0'" />
6969

70-
<ItemGroup Condition="'@(_ApplicationPartAssemblyNames->Count())' != '0'">
70+
<!--
71+
If the generated attribute file exists, but no assembly names were discovered,
72+
it suggests that the assembly references were changed to no longer point to MVC.
73+
In this case, delete the file so that future incremental builds can no longer pick it up.
74+
-->
75+
<Delete
76+
File="$(_MvcApplicationPartAttributeGeneratedFile)"
77+
Condition="'@(_ApplicationPartAssemblyNames->Count())' == '0' AND Exists('$(_MvcApplicationPartAttributeGeneratedFile)')" />
78+
79+
<ItemGroup Condition="Exists('$(_MvcApplicationPartAttributeGeneratedFile)')">
7180
<Compile Remove="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'!='F#'" />
7281
<Compile Include="$(_MvcApplicationPartAttributeGeneratedFile)" Condition="'$(Language)'!='F#'" />
7382

src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/ApplicationPartDiscoveryIntegrationTest.cs

+29
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ private async Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute(MS
3434

3535
Assert.FileExists(result, IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs");
3636
Assert.FileContains(result, Path.Combine(IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs"), "[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")]");
37+
Assert.AssemblyHasAttribute(result, Path.Combine(OutputPath, "AppWithP2PReference.dll"), "Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute");
3738
}
3839

3940
[Fact]
@@ -69,6 +70,33 @@ public async Task BuildIncrementalism_WhenApplicationPartAttributeIsGenerated()
6970

7071
Assert.FileExists(result, generatedAttributeFile);
7172
Assert.Equal(thumbPrint, GetThumbPrint(generatedAttributeFile));
73+
Assert.AssemblyHasAttribute(result, Path.Combine(OutputPath, "AppWithP2PReference.dll"), "Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute");
74+
}
75+
76+
// Regression test for https://github.com/aspnet/AspNetCore/issues/11315
77+
[Fact]
78+
[InitializeTestProject("AppWithP2PReference", additionalProjects: "ClassLibrary")]
79+
public async Task BuildIncrementalism_CausingRecompilation_WhenApplicationPartAttributeIsGenerated()
80+
{
81+
var result = await DotnetMSBuild("Build");
82+
83+
Assert.BuildPassed(result);
84+
85+
var generatedAttributeFile = Path.Combine(IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs");
86+
Assert.FileExists(result, generatedAttributeFile);
87+
Assert.FileContains(result, generatedAttributeFile, "[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")]");
88+
89+
var thumbPrint = GetThumbPrint(generatedAttributeFile);
90+
91+
// Touch a file in the main app which should call recompilation, but not the Mvc discovery tasks to re-run.
92+
File.AppendAllText(Path.Combine(Project.DirectoryPath, "Program.cs"), " ");
93+
result = await DotnetMSBuild("Build");
94+
95+
Assert.BuildPassed(result);
96+
97+
Assert.FileExists(result, generatedAttributeFile);
98+
Assert.Equal(thumbPrint, GetThumbPrint(generatedAttributeFile));
99+
Assert.AssemblyHasAttribute(result, Path.Combine(OutputPath, "AppWithP2PReference.dll"), "Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute");
72100
}
73101

74102
[Fact]
@@ -88,6 +116,7 @@ public async Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttributeToNo
88116

89117
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvcFSharp.MvcApplicationPartsAssemblyInfo.fs");
90118
Assert.FileContains(result, Path.Combine(IntermediateOutputPath, "SimpleMvcFSharp.MvcApplicationPartsAssemblyInfo.fs"), "<assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")>");
119+
Assert.AssemblyHasAttribute(result, Path.Combine(OutputPath, "SimpleMvcFSharp.dll"), "Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute");
91120
}
92121

93122
[Fact]

src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/Assert.cs

+30
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,36 @@ private static IEnumerable<string> GetDeclaredTypeNames(string assemblyPath)
507507
}
508508
}
509509

510+
public static void AssemblyHasAttribute(MSBuildResult result, string assemblyPath, string fullTypeName)
511+
{
512+
if (result == null)
513+
{
514+
throw new ArgumentNullException(nameof(result));
515+
}
516+
517+
assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath));
518+
519+
var typeNames = GetAssemblyAttributes(assemblyPath);
520+
Assert.Contains(fullTypeName, typeNames);
521+
}
522+
523+
private static IEnumerable<string> GetAssemblyAttributes(string assemblyPath)
524+
{
525+
using (var file = File.OpenRead(assemblyPath))
526+
{
527+
var peReader = new PEReader(file);
528+
var metadataReader = peReader.GetMetadataReader();
529+
return metadataReader.CustomAttributes.Where(t => !t.IsNil).Select(t =>
530+
{
531+
var attribute = metadataReader.GetCustomAttribute(t);
532+
var constructor = metadataReader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
533+
var type = metadataReader.GetTypeReference((TypeReferenceHandle)constructor.Parent);
534+
535+
return metadataReader.GetString(type.Namespace) + "." + metadataReader.GetString(type.Name);
536+
}).ToArray();
537+
}
538+
}
539+
510540
private abstract class MSBuildXunitException : Xunit.Sdk.XunitException
511541
{
512542
protected MSBuildXunitException(MSBuildResult result)

0 commit comments

Comments
 (0)