Package reusable cDAC usage graph analyzer - #132234
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 95c4aedd-f09e-42d7-8c9f-f439297576a6
|
Azure Pipelines: Successfully started running 4 pipeline(s). 12 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
|
Azure Pipelines: Successfully started running 4 pipeline(s). 12 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR packages the existing cDAC usage graph analyzer for reuse by making its analysis entrypoints configurable (contracts project path + registration type), updating the CLI and tests accordingly, and expanding registration discovery to cover default-valued struct registrations.
Changes:
- Replace the CoreCLR-rooted analysis entrypoint with
UsageGraphAnalysisOptions(project path, registration type name, source root, optional output directory). - Update the CLI pipeline and tests to use the configurable analysis options and project-loading APIs.
- Extend contract registration discovery to recognize
default(T)returns in registration factories.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tools/CdacUsageGraph/tests/CdacUsageGraph.Tests/UsageWalkerIntegrationTests.cs | Updates integration test to run analysis via configurable options and explicit contracts project path. |
| src/native/managed/cdac/tools/CdacUsageGraph/tests/CdacUsageGraph.Tests/DataTypeIndexTests.cs | Updates parser call sites and adds a test covering default-valued struct registration discovery. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/UsageGraphAnalyzer.cs | Introduces UsageGraphAnalysisOptions and updates public analyzer entrypoint to accept options. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Docs/DocGenerator.cs | Minor descriptor-key parsing tweak (LastIndexOf('.')). |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Docs/DocDescriptorOverrides.cs | Minor descriptor-key validation tweak (LastIndexOf('.')). |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Docs/DocDescriptorMeanings.cs | Minor descriptor-key validation tweak (LastIndexOf('.')). |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Discovery/ContractRegistrationParser.cs | Makes registration discovery configurable and adds handling for default(T) returns. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Compilation/CdacCompilationLoader.cs | Replaces root-based loading with explicit LoadProject(projectPath). |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Commands.cs | Updates CLI wiring to construct and pass UsageGraphAnalysisOptions. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/CdacUsageGraph.csproj | Renames assembly, switches to $(CDacTfm), enables packing, and updates Roslyn package version properties. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/AnalysisPipeline.cs | Refactors pipeline to use UsageGraphAnalysisOptions, including output-dir handling. |
| src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/AnalysisOptions.cs | Removes old CLI-only AnalysisOptions record in favor of shared analysis options. |
| src/native/managed/cdac/tests/UsageTests/UsageGraphFixture.cs | Updates usage tests to use UsageGraphAnalysisOptions with explicit project + registration type. |
| src/native/managed/cdac/tests/UsageTests/Microsoft.Diagnostics.DataContractReader.Usage.Tests.csproj | Removes JsonSerializerIsReflectionEnabledByDefault override from the test project. |
| foreach (IDefaultValueOperation defaultValue in inv.Descendants().OfType<IDefaultValueOperation>()) | ||
| { | ||
| if (defaultValue.Type is INamedTypeSymbol impl && | ||
| comparer.Equals(impl.ContainingAssembly, compilation.Assembly) && | ||
| compilation.IsAssignableTo(impl, iface) && | ||
| compilation.IsAssignableTo(impl, iContract)) | ||
| { | ||
| registrations.Add(new ContractRegistration( | ||
| new ContractVersion(new ContractInterface(iface.Name), version), | ||
| iface, | ||
| impl, | ||
| impl.InstanceConstructors.Single( | ||
| candidate => candidate.Parameters.Length == 0))); | ||
| } | ||
| } |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 95c4aedd-f09e-42d7-8c9f-f439297576a6
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Discovery/ContractRegistrationParser.cs:97
- The default-value registration path treats any
default(T)as a concrete implementation and then assumes it can obtain a parameterless constructor. For reference types,default(T)isnull(not an instance) andInstanceConstructors.Single(...)can throw if there is no parameterless ctor, so this can either mis-record registrations or crash analysis.
Restrict this path to value-type implementations (structs) and avoid Single throwing on unexpected shapes.
foreach (IDefaultValueOperation defaultValue in inv.Descendants().OfType<IDefaultValueOperation>())
{
if (defaultValue.Type is INamedTypeSymbol impl &&
comparer.Equals(impl.ContainingAssembly, compilation.Assembly) &&
compilation.IsAssignableTo(impl, iface) &&
Record the ManagedTypeSource layout fallback discovered through generic ContractRegistry lookups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 95c4aedd-f09e-42d7-8c9f-f439297576a6
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 40 out of 40 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/UsageGraphAnalyzer.cs:17
- This introduces new public API surface (
UsageGraphAnalyzer.Analyze(UsageGraphAnalysisOptions)andUsageGraphAnalysisOptions). Per repo process, new public APIs need a linked issue with theapi-approvedlabel; if this isn’t yet approved, keep the APIinternaluntil the approval is in place.
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Discovery/ContractRegistrationParser.cs:97 default(T)registrations can yieldIDefaultValueOperationwhereTypeis the interface itself (e.g.,default(ITest)), which would makeimpl.InstanceConstructors.Single(...)throw (interfaces have no instance constructors). The default-value path should be constrained to value-type implementations (or otherwise ensure a parameterless ctor exists) before adding a registration.
Stop traversal at the generated LayoutSet helper so its ManagedTypeSource fallback is not attributed to every IData consumer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 95c4aedd-f09e-42d7-8c9f-f439297576a6
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/native/managed/cdac/tests/UsageTests/Microsoft.Diagnostics.DataContractReader.Usage.Tests.csproj:6
- This project is the only cDAC test project that no longer disables reflection-based
System.Text.Jsonserialization by default. Other cDAC projects keepJsonSerializerIsReflectionEnabledByDefaultset tofalse(e.g. src/native/managed/cdac/tests/DumpTests/Microsoft.Diagnostics.DataContractReader.DumpTests.csproj:8). Consider restoring it here to keep the same runtime behavior/coverage across the cDAC test suite.
<PropertyGroup>
<TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework>
<Nullable>enable</Nullable>
<IsTestProject>true</IsTestProject>
<AssemblyName>Microsoft.Diagnostics.DataContractReader.Usage.Tests</AssemblyName>
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Discovery/ContractRegistrationParser.cs:97
- The default-value registration discovery treats any
default(T)found under aRegister<IFace>invocation as an implementation type and then unconditionally callsimpl.InstanceConstructors.Single(...). This can (1) incorrectly treat reference-typedefault(T)(which isnull) as a registration and (2) throw if the default is target-typed to an interface/abstract type (no instance constructors). Restrict this path to value-type implementations and only add a registration when a parameterless ctor symbol is available.
foreach (IDefaultValueOperation defaultValue in inv.Descendants().OfType<IDefaultValueOperation>())
{
if (defaultValue.Type is INamedTypeSymbol impl &&
comparer.Equals(impl.ContainingAssembly, compilation.Assembly) &&
compilation.IsAssignableTo(impl, iface) &&
compilation.IsAssignableTo(impl, iContract))
{
registrations.Add(new ContractRegistration(
new ContractVersion(new ContractInterface(iface.Name), version),
iface,
impl,
impl.InstanceConstructors.Single(
candidate => candidate.Parameters.Length == 0)));
}
Summary
Testing
CdacUsageGraph.Tests(85 passed)Microsoft.Diagnostics.DataContractReader.Usage.Tests(4 passed)