Skip to content

feat(utilities): TypeDeclarationInfo.GetFullyQualifiedMetadataName + GetFullyQualifiedName - #156

Merged
github-actions[bot] merged 1 commit into
mainfrom
claude/metadata-name-caching-assertions
Jul 6, 2026
Merged

feat(utilities): TypeDeclarationInfo.GetFullyQualifiedMetadataName + GetFullyQualifiedName#156
github-actions[bot] merged 1 commit into
mainfrom
claude/metadata-name-caching-assertions

Conversation

@ANcpLua

@ANcpLua ANcpLua commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Completes the TypeDeclarationInfo round-trip surface (From → emit → re-resolve):

GetFullyQualifiedMetadataName()

Reconstructs the CLR metadata name from the cached snapshot — Deep.Outer\1+Middle+Inner`1— so a later pipeline stage can re-resolve the liveINamedTypeSymbolviaCompilation.GetTypeByMetadataNamewithout ever retaining the original symbol (which would break incremental caching). Round-trip test: the returned name resolves back to the original symbol underSymbolEqualityComparer`.

GetFullyQualifiedName()

The global::Deep.Outer<T>.Middle.Inner<U> reference for emitting self-references from generated code. Compile-test proves the reference is valid inside the partial wrapper opened by BeginDeclaration (where the type parameters are in scope).

Scope note (honest reduction)

The cachability-assertion helper originally pitched for this arc already existsGeneratorResult.IsCached() in the Testing package is the run-twice, all-steps-cached, forbidden-types one-liner, more complete than what was proposed. Nothing to add there.

Verification

Status: complete-and-verified. Publishes as 2.2.35 via auto-bump; qyl gets one consolidated bump 2.2.33 → 2.2.35 after indexing.

🤖 Generated with Claude Code

GetFullyQualifiedMetadataName() reconstructs the CLR metadata name
(Deep.Outer`1+Middle+Inner`1) from the cached snapshot so later pipeline
stages can re-resolve the live symbol via Compilation.GetTypeByMetadataName
without retaining the original ISymbol.

GetFullyQualifiedName() yields the global::-qualified C# reference with type
parameter names (global::Deep.Outer<T>.Middle.Inner<U>) for emitting
self-references inside the generated partial, where those parameters are in
scope.

Note: the cachability-assertion feature originally planned for this arc
already exists as GeneratorResult.IsCached() — scope reduced to what was
actually missing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions
github-actions Bot merged commit c18e2b8 into main Jul 6, 2026
3 of 4 checks passed
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0451e7b6-24cf-4d0d-af15-6e98129cbbe4

📥 Commits

Reviewing files that changed from the base of the PR and between 671c1bf and 4053a38.

⛔ Files ignored due to path filters (2)
  • .claude/TASK.md is excluded by none and included by none
  • README.md is excluded by none and included by none
📒 Files selected for processing (2)
  • src/ANcpLua.Roslyn.Utilities/Models/TypeDeclarationInfo.cs
  • tests/ANcpLua.Roslyn.Utilities.Testing.Tests/TypeDeclarationInfoTests.cs

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting


Summary by CodeRabbit

  • New Features

    • Improved generation of fully qualified type names, including better handling of nested and generic types.
    • Added support for consistent global::-prefixed type references and metadata-style names.
  • Bug Fixes

    • Fixed type-name generation for generic arity so nested types resolve more reliably.
    • Improved correctness of generated references used in compiled output.

Walkthrough

Adds a shared GetArity helper for generic parameter counting in TypeDeclarationInfo, implements GetFullyQualifiedMetadataName() and GetFullyQualifiedName() to produce CLR metadata names and global::-qualified C# type references, and adds corresponding unit tests with a shared CreateCompilation test helper.

Changes

Fully-qualified name generation

Layer / File(s) Summary
Shared arity helper
src/ANcpLua.Roslyn.Utilities/Models/TypeDeclarationInfo.cs
Adds GetArity (comma-count-based) and refactors AppendHintNameLevel to use it instead of an inline loop.
Metadata name construction
src/ANcpLua.Roslyn.Utilities/Models/TypeDeclarationInfo.cs
Implements GetFullyQualifiedMetadataName() joining containing-type levels with +, and updates AppendMetadataNameLevel to encode backtick arity via GetArity.
Display name construction
src/ANcpLua.Roslyn.Utilities/Models/TypeDeclarationInfo.cs
Implements GetFullyQualifiedName() producing a global::-aliased type reference from containing types' and the target type's DisplayName.
Tests and shared compilation helper
tests/ANcpLua.Roslyn.Utilities.Testing.Tests/TypeDeclarationInfoTests.cs
Adds round-trip, simple-shape, nested-generic, global-namespace, and generated-code compilation tests for both new methods; introduces CreateCompilation helper and refactors GetType to use it.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

Not applicable — this change is a self-contained refactor/implementation within a single class and its tests, without multi-component orchestration.


Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4053a38179

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

builder.Append(Namespace).Append('.');

foreach (var containing in ContainingTypes.AsImmutableArray())
builder.Append(containing.DisplayName).Append('.');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve outer generic parameters in self references

For a legal nested generic such as partial class Outer<T> { partial class Inner<T> { } } (CS0693 warning only), this appends the containing clause as Outer<T>, so GetFullyQualifiedName() returns global::N.Outer<T>.Inner<T>. Inside the generated Inner<T> partial, T resolves to the inner parameter, making the reference Outer<inner T>.Inner<inner T> rather than the current Outer<outer T>.Inner<inner T>; the documented public {info.GetFullyQualifiedName()} Self() => this; pattern then fails to compile. The helper needs to avoid qualifying through shadowed generic containers or explicitly reject/document that case.

Useful? React with 👍 / 👎.

Comment on lines +184 to +185
if (Namespace is not null)
builder.Append(Namespace).Append('.');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit metadata namespaces without C# escapes

When the source namespace needs escaping, such as namespace @class { partial class C { } }, Namespace is stored as the C# display text so BeginDeclaration can re-emit it. Reusing that value here produces @class.C, but Compilation.GetTypeByMetadataName expects the CLR metadata namespace class.C, so the advertised round-trip returns null for these legal declarations. Build the metadata name from namespace metadata segments rather than the display string.

Useful? React with 👍 / 👎.

builder.Append('+');
}

AppendMetadataNameLevel(builder, Name, GenericParameterClause);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use metadata names for file-local types

For file-local declarations such as file class Hidden, Roslyn gives the symbol a synthesized metadata name while Name remains only Hidden. Reconstructing the lookup key from the source name here makes GetFullyQualifiedMetadataName() return Hidden/N.Hidden, so Compilation.GetTypeByMetadataName(...) cannot resolve the original file-local symbol despite the new round-trip contract. Store and append INamedTypeSymbol.MetadataName separately from the source name used for emitted declarations.

Useful? React with 👍 / 👎.

github-actions Bot pushed a commit that referenced this pull request Jul 6, 2026
….2.35 round-trip surface) (#157)

Arc A (#155 → 2.2.34): warnings-as-errors gate armed, zero-warning build.
Arc B (#156 → 2.2.35): GetFullyQualifiedMetadataName + GetFullyQualifiedName.
Both indexed on nuget.org; qyl bumped 2.2.33 → 2.2.35 in qyl#494.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant