Skip to content

Commit c5842d3

Browse files
authored
Fix edit in one project not being reflected in consuming project (#12439)
Don't return Guid.Zero if we can't get the MVID for a module. Instead, iterate the modules in both assemblies; if we don't have an MVID (like for a compilation reference) then consider them not equal. Add test to cover behavior.
1 parent 2d8783f commit c5842d3

File tree

2 files changed

+107
-6
lines changed

2 files changed

+107
-6
lines changed

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,37 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
173173
return true;
174174
}
175175

176-
if (oldSymbol is IAssemblySymbol oldAssembly && newSymbol is IAssemblySymbol newAssembly)
176+
if (oldSymbol is not IAssemblySymbol oldAssembly || newSymbol is not IAssemblySymbol newAssembly)
177177
{
178-
var oldModuleMVIDs = oldAssembly.Modules.Select(GetMVID);
179-
var newModuleMVIDs = newAssembly.Modules.Select(GetMVID);
180-
return oldModuleMVIDs.SequenceEqual(newModuleMVIDs);
178+
return false;
179+
}
180+
181+
// Compare the MVIDs of the modules in each assembly. If they aren't present or don't match we don't consider them equal
182+
var oldModules = oldAssembly.Modules.ToArray();
183+
var newModules = newAssembly.Modules.ToArray();
184+
if (oldModules.Length != newModules.Length)
185+
{
186+
return false;
187+
}
181188

182-
static Guid GetMVID(IModuleSymbol m) => m.GetMetadata()?.GetModuleVersionId() ?? Guid.Empty;
189+
for (int i = 0; i < oldModules.Length; i++)
190+
{
191+
var oldMetadata = oldModules[i].GetMetadata();
192+
var newMetadata = newModules[i].GetMetadata();
193+
194+
if (oldMetadata is null || newMetadata is null)
195+
{
196+
return false;
197+
}
198+
199+
if (oldMetadata.GetModuleVersionId() != newMetadata.GetModuleVersionId())
200+
{
201+
return false;
202+
}
183203
}
184204

185-
return false;
205+
// All module MVIDs matched.
206+
return true;
186207
})))
187208
{
188209
return false;

src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3605,5 +3605,85 @@ public async Task IncrementalCompilation_RerunsGenerator_When_AdditionalFileRena
36053605
var newCouNterSource = result.GeneratedSources.FirstOrDefault(s => s.HintName.Contains("NewCouNter"));
36063606
Assert.Contains("public partial class NewCouNter", newCouNterSource.SourceText.ToString());
36073607
}
3608+
3609+
[Fact, WorkItem("https://github.com/dotnet/razor/issues/12316")]
3610+
public async Task RazorClassLibrary_Change_Updates_DependentProject_WhenReferencedAsCompilation()
3611+
{
3612+
var rclProject = CreateTestProject(new()
3613+
{
3614+
["LibComponent.razor"] = "<p>Library component</p>",
3615+
});
3616+
rclProject = rclProject.WithAssemblyName("RazorClassLibrary");
3617+
3618+
var rclCompilation = await rclProject.GetCompilationAsync();
3619+
var rclDriver = await GetDriverAsync(rclProject);
3620+
var rclRun = RunGenerator(rclCompilation!, ref rclDriver, out var rclOutputCompilation);
3621+
Assert.Empty(rclRun.Diagnostics);
3622+
Assert.Single(rclRun.GeneratedSources); // LibComponent
3623+
3624+
// Explicitly use a CompilationReference
3625+
var rclReference = rclOutputCompilation.ToMetadataReference();
3626+
3627+
// Create the main project that references the RCL and uses its component.
3628+
var mainProject = CreateTestProject(new()
3629+
{
3630+
["Pages/Index.razor"] = "<LibComponent />",
3631+
});
3632+
mainProject = mainProject.AddMetadataReference(rclReference);
3633+
3634+
var mainCompilation = await mainProject.GetCompilationAsync();
3635+
var (mainDriver, mainAdditionalTexts) = await GetDriverWithAdditionalTextAsync(mainProject);
3636+
var mainRun = RunGenerator(mainCompilation!, ref mainDriver);
3637+
Assert.Empty(mainRun.Diagnostics);
3638+
Assert.Single(mainRun.GeneratedSources);
3639+
3640+
// Rename the component in the RCL: LibComponent -> RenamedComponent
3641+
rclProject = CreateTestProject(new()
3642+
{
3643+
["RenamedComponent.razor"] = "<p>Library component</p>",
3644+
}).WithAssemblyName("RazorClassLibrary");
3645+
3646+
rclCompilation = await rclProject.GetCompilationAsync()!;
3647+
rclDriver = await GetDriverAsync(rclProject);
3648+
rclRun = RunGenerator(rclCompilation!, ref rclDriver, out rclOutputCompilation);
3649+
Assert.Empty(rclRun.Diagnostics);
3650+
Assert.Single(rclRun.GeneratedSources); // RenamedComponent
3651+
3652+
var rclReference2 = rclOutputCompilation.ToMetadataReference();
3653+
3654+
// Update main project to point to the new reference (with renamed component).
3655+
mainProject = mainProject.RemoveMetadataReference(rclReference)
3656+
.AddMetadataReference(rclReference2);
3657+
mainCompilation = await mainProject.GetCompilationAsync();
3658+
3659+
// Re-run generator: expect missing component diagnostic (RZ10012).
3660+
mainRun = RunGenerator(mainCompilation!, ref mainDriver);
3661+
var missing = Assert.Single(mainRun.Diagnostics);
3662+
Assert.Equal("RZ10012", missing.Id);
3663+
3664+
// Update main project's Index.razor to use the renamed component.
3665+
var updatedIndex = new TestAdditionalText("Pages/Index.razor", SourceText.From("<RenamedComponent />", Encoding.UTF8));
3666+
mainDriver = mainDriver.ReplaceAdditionalText(
3667+
mainAdditionalTexts.First(t => t.Path.EndsWith("Index.razor", StringComparison.OrdinalIgnoreCase)),
3668+
updatedIndex);
3669+
3670+
// Re-run generator: should compile cleanly again.
3671+
mainRun = RunGenerator(mainCompilation!, ref mainDriver);
3672+
Assert.Empty(mainRun.Diagnostics);
3673+
Assert.Single(mainRun.GeneratedSources);
3674+
3675+
// Update the compilation, which will cause us to re-run.
3676+
RazorEventListener eventListener = new RazorEventListener();
3677+
3678+
mainCompilation = mainCompilation!.WithOptions(mainCompilation.Options.WithModuleName("newMain"));
3679+
mainRun = RunGenerator(mainCompilation!, ref mainDriver);
3680+
Assert.Empty(mainRun.Diagnostics);
3681+
Assert.Single(mainRun.GeneratedSources);
3682+
3683+
// Confirm that the tag helpers from metadata refs _didn't_ re-run
3684+
Assert.Collection(eventListener.Events,
3685+
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
3686+
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
3687+
}
36083688
}
36093689
}

0 commit comments

Comments
 (0)