Skip to content

Commit d751cbe

Browse files
[cDAC] Pack DataGenerator as analyzer asset in Abstractions nupkg (#128903)
> [!NOTE] > This PR description was AI-generated with GitHub Copilot CLI. ## Summary Packs the cDAC source generator (`Microsoft.Diagnostics.DataContractReader.DataGenerator`) as an analyzer asset inside the `Microsoft.Diagnostics.DataContractReader.Abstractions` transport NuGet package, so downstream consumers pick the generator up automatically via `PackageReference` — no in-repo `ProjectReference` to the generator csproj required. ## Changes - **Moved** `src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/` → `src/native/managed/cdac/gen/`. The repo-wide `Directory.Build.props` auto-detects projects under `gen/` and sets `IsGeneratorProject=true`, which imports `eng/generatorProjects.targets` (providing the `GetAnalyzerPackFiles` target that `PackAsAnalyzer="true"` relies on). - **Wired** the generator into `Abstractions.csproj` via `<ProjectReference ... ReferenceOutputAssembly="false" PackAsAnalyzer="true" />`. The compiled generator dll ships under `analyzers/dotnet/cs/` in the transport nupkg. - **Cleanup** in the generator csproj: dropped `IsSourceProject=false` and `EnforceExtendedAnalyzerRules=true` overrides that are now redundant under the `gen/` convention. - **Updated** `Contracts.csproj` and `DataGeneratorTests.csproj` `ProjectReference` paths to the new location. ## Generator bug fixes (uncovered by external `PackageReference` consumption) 1. `LayoutPair` / `TypeNameResolver` emission gate used `GetTypeByMetadataName(...) is null`, which suppressed emission whenever the type was *present in metadata* even if **not accessible** to the current compilation (internal type in a referenced assembly without `InternalsVisibleTo`). Replaced with an `IsSymbolAccessibleWithin` check so external consumers get their own internal copy generated. 2. The singular `GetTypeByMetadataName` returns null on cross-assembly duplicates (more than one referenced assembly exposes the same internal helper). Switched to plural `GetTypesByMetadataName` + `Any(accessible)` so the gate behaves correctly in that case. These bugs do not affect the in-repo `Contracts` build (it has `InternalsVisibleTo` to itself and sees a single copy), only external `PackageReference` consumers. ## Validation - In-repo cDAC build and `DataGeneratorTests` continue to use the generator via `ProjectReference OutputItemType="Analyzer"` (unchanged behavior). - Abstractions nupkg now contains `analyzers/dotnet/cs/Microsoft.Diagnostics.DataContractReader.DataGenerator.dll`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5341027 commit d751cbe

13 files changed

Lines changed: 47 additions & 11 deletions

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Microsoft.Diagnostics.DataContractReader.Abstractions.csproj

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,19 @@
1111
<InvariantGlobalization>true</InvariantGlobalization>
1212
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
1313
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<!--
17+
Pack the cDAC source generator into this transport package as an
18+
analyzer asset. Anyone who PackageReferences the Abstractions package
19+
(in particular downstream cDAC consumers writing their own [CdacType]
20+
partial classes).
21+
22+
ReferenceOutputAssembly=false because we don't link the generator at
23+
runtime; only its compiled output flows in the nupkg.
24+
-->
25+
<ProjectReference Include="..\gen\Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj"
26+
ReferenceOutputAssembly="false"
27+
PackAsAnalyzer="true" />
28+
</ItemGroup>
1429
</Project>

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Microsoft.Diagnostics.DataContractReader.Contracts.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<ProjectReference Include="..\Microsoft.Diagnostics.DataContractReader.Abstractions\Microsoft.Diagnostics.DataContractReader.Abstractions.csproj" GlobalPropertiesToRemove="RuntimeIdentifier" />
2121

2222
<!-- Wire the cdac source generator as a Roslyn analyzer. -->
23-
<ProjectReference Include="..\Microsoft.Diagnostics.DataContractReader.DataGenerator\Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj"
23+
<ProjectReference Include="..\gen\Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj"
2424
OutputItemType="Analyzer"
2525
ReferenceOutputAssembly="false" />
2626
</ItemGroup>

src/native/managed/cdac/cdac.slnx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<Project Path="Microsoft.Diagnostics.DataContractReader.Contracts/Microsoft.Diagnostics.DataContractReader.Contracts.csproj" />
1010
<Project Path="Microsoft.Diagnostics.DataContractReader/Microsoft.Diagnostics.DataContractReader.csproj" />
1111
<Project Path="Microsoft.Diagnostics.DataContractReader.Legacy/Microsoft.Diagnostics.DataContractReader.Legacy.csproj" />
12-
<Project Path="Microsoft.Diagnostics.DataContractReader.DataGenerator/Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj" />
12+
<Project Path="gen/Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj" />
1313
<Project Path="mscordaccore_universal/mscordaccore_universal.csproj" />
1414
</Folder>
1515
<Folder Name="/tests/">

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/CdacGenerator.cs renamed to src/native/managed/cdac/gen/CdacGenerator.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3636
// one helper is present but the other is not.
3737
IncrementalValueProvider<(bool EmitLayoutSet, bool EmitTypeNameResolver)> shouldEmitHelpers = context.CompilationProvider
3838
.Select(static (compilation, _) => (
39-
EmitLayoutSet: compilation.GetTypeByMetadataName(LayoutSetSource.FullyQualifiedName) is null,
40-
EmitTypeNameResolver: compilation.GetTypeByMetadataName(TypeNameResolverSource.FullyQualifiedName) is null));
39+
EmitLayoutSet: !IsTypeAccessible(compilation, LayoutSetSource.FullyQualifiedName),
40+
EmitTypeNameResolver: !IsTypeAccessible(compilation, TypeNameResolverSource.FullyQualifiedName)));
4141

4242
context.RegisterSourceOutput(shouldEmitHelpers, static (ctx, flags) =>
4343
{
@@ -67,4 +67,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
6767
context.RegisterSourceOutput(models, static (spc, model) =>
6868
spc.AddSource(Emitter.HintNameFor(model), SourceText.From(Emitter.Emit(model), Encoding.UTF8)));
6969
}
70+
71+
/// <summary>
72+
/// Returns true if the consuming compilation can already see a usable
73+
/// <paramref name="metadataName"/> (declared here, or in a referenced assembly
74+
/// and accessible).
75+
/// </summary>
76+
private static bool IsTypeAccessible(Compilation compilation, string metadataName)
77+
{
78+
foreach (INamedTypeSymbol type in compilation.GetTypesByMetadataName(metadataName))
79+
{
80+
if (compilation.IsSymbolAccessibleWithin(type, compilation.Assembly))
81+
{
82+
return true;
83+
}
84+
}
85+
86+
return false;
87+
}
7088
}

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/Emitter.cs renamed to src/native/managed/cdac/gen/Emitter.cs

File renamed without changes.

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/EquatableArray.cs renamed to src/native/managed/cdac/gen/EquatableArray.cs

File renamed without changes.

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/IsExternalInit.cs renamed to src/native/managed/cdac/gen/IsExternalInit.cs

File renamed without changes.

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/LayoutSetSource.cs renamed to src/native/managed/cdac/gen/LayoutSetSource.cs

File renamed without changes.

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj renamed to src/native/managed/cdac/gen/Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3+
<!--
4+
cDAC source generator. Lives under gen/ so the auto-detect rule in
5+
Directory.Build.props sets IsGeneratorProject=true, which imports
6+
eng/generatorProjects.targets (defines GetAnalyzerPackFiles, used by
7+
PackAsAnalyzer="true" in consuming packages).
8+
-->
39
<PropertyGroup>
410
<TargetFramework>netstandard2.0</TargetFramework>
511
<RootNamespace>Microsoft.Diagnostics.DataContractReader.DataGenerator</RootNamespace>
612
<Nullable>enable</Nullable>
713
<IsRoslynComponent>true</IsRoslynComponent>
8-
<!-- Generator ships inline with the consuming assembly; not a standalone package. -->
14+
<!-- Generator does not ship on its own; flows inside the Abstractions
15+
transport package as an analyzer asset and is linked directly by
16+
Contracts via ProjectReference OutputItemType="Analyzer". -->
917
<IsShipping>false</IsShipping>
1018
<IsPackable>false</IsPackable>
11-
<!-- Opt out of the repo-wide source-project flag so the DownlevelLibraryImportGenerator
12-
isn't applied to this netstandard2.0 generator project (it would emit duplicate
13-
polyfills for InteropServices types it doesn't actually need). -->
14-
<IsSourceProject>false</IsSourceProject>
1519
<AnalyzerLanguage>cs</AnalyzerLanguage>
16-
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
1720
</PropertyGroup>
1821

1922
<ItemGroup>

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.DataGenerator/Model.cs renamed to src/native/managed/cdac/gen/Model.cs

File renamed without changes.

0 commit comments

Comments
 (0)