[GH-ISSUE #5149] [Feature] Show type names in decoded managed member signatures instead of class:<coded index> #3166

Closed
opened 2026-10-31 00:37:25 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @elricfd on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5149

Before submitting

  • I searched the open and closed issues and pull requests for a related proposal.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This request does not include credentials, private samples, or sensitive target data.

Area

Native analysis or decompilation

Current limitation

Decoded member signatures print class and valuetype operands as raw TypeDefOrRef coded indexes. GetBeatGridAndCuePoints.signature.parameter_types is ["class:7772"]. Decoding: 7772 & 3 = 0 (TypeDef), 7772 >> 2 = 1943, token 0x02000797, which is AnalysisJob (matches the method's AnalysisJob::AnalysisResult field operands). On this type 37 of 63 methods have such a parameter. The result also says signature_resolution: "type-names-v1", which reads as if names are resolved.

Source-derived: src/dotnet/ManagedMemberInspectorCore.ts:569 and :596 format ${"valuetype" | "class"}:${token.value}. The limitations string says class and valuetype operands "keep their encoded TypeDefOrRefOrSpec values", and names are used only for resolved_sha256 (docs/managed-code-analysis.md). Names already appear elsewhere in the same result (member_refs[].parent_name, call_edges[].target_declaring_type).

Observed on rea 6.7.0 with Mixed In Key 11 MixedInKey.exe (SHA-256 b014a00e6f6b80ed9313f68ad3da8f42c2de38f9111582e62145cec63c7da843; rea inspect-managed-members <exe> --type MixedInKey.Audio.AudioAnalyser --json, ran twice).

Use cases

Reading a method signature requires decoding the 2-bit tag by hand and joining to types, which only contains selected types, so references to other types need member_refs or the metadata tables.

Desired outcome and success criteria

parameter_types, return_type and field_type show the resolved full name (with the coded index kept for identity) when the type is readable, and keep today's form where it cannot be resolved (TypeSpec, unsupported forms). Success: the example above reads like class:7772 (AnalysisJob) or just AnalysisJob.

Expected interaction with targets

Read existing files or captured data

Target and scope details (optional)

Read-only, no change in authority.

Verification available so far

I have a prototype or observed results

Verification details (optional)

Observed on the one type; the fraction of unresolvable operands in the whole assembly was not measured.

Alternatives considered

Joining against types and member_refs by hand; works but each caller reimplements the coded-index decode.

Possible direction

Reuse the existing type-name owner that feeds resolved_sha256. Proposal only; output size grows slightly, so measure tokens.

References

docs/managed-code-analysis.md (signature resolution); closed #1832, #1835 and #1837 (signature element decoding).

Originally created by @elricfd on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5149 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related proposal. - [x] I understand the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope) must be reviewed before integration; open questions are welcome here. - [x] This request does not include credentials, private samples, or sensitive target data. ### Area Native analysis or decompilation ### Current limitation Decoded member signatures print class and valuetype operands as raw TypeDefOrRef coded indexes. `GetBeatGridAndCuePoints.signature.parameter_types` is `["class:7772"]`. Decoding: `7772 & 3 = 0` (TypeDef), `7772 >> 2 = 1943`, token `0x02000797`, which is `AnalysisJob` (matches the method's `AnalysisJob::AnalysisResult` field operands). On this type 37 of 63 methods have such a parameter. The result also says `signature_resolution: "type-names-v1"`, which reads as if names are resolved. Source-derived: `src/dotnet/ManagedMemberInspectorCore.ts:569` and `:596` format `${"valuetype" | "class"}:${token.value}`. The limitations string says class and valuetype operands "keep their encoded TypeDefOrRefOrSpec values", and names are used only for `resolved_sha256` (docs/managed-code-analysis.md). Names already appear elsewhere in the same result (`member_refs[].parent_name`, `call_edges[].target_declaring_type`). Observed on rea 6.7.0 with Mixed In Key 11 `MixedInKey.exe` (SHA-256 `b014a00e6f6b80ed9313f68ad3da8f42c2de38f9111582e62145cec63c7da843`; `rea inspect-managed-members <exe> --type MixedInKey.Audio.AudioAnalyser --json`, ran twice). ### Use cases Reading a method signature requires decoding the 2-bit tag by hand and joining to `types`, which only contains selected types, so references to other types need `member_refs` or the metadata tables. ### Desired outcome and success criteria `parameter_types`, `return_type` and `field_type` show the resolved full name (with the coded index kept for identity) when the type is readable, and keep today's form where it cannot be resolved (TypeSpec, unsupported forms). Success: the example above reads like `class:7772 (AnalysisJob)` or just `AnalysisJob`. ### Expected interaction with targets Read existing files or captured data ### Target and scope details (optional) Read-only, no change in authority. ### Verification available so far I have a prototype or observed results ### Verification details (optional) Observed on the one type; the fraction of unresolvable operands in the whole assembly was not measured. ### Alternatives considered Joining against `types` and `member_refs` by hand; works but each caller reimplements the coded-index decode. ### Possible direction Reuse the existing type-name owner that feeds `resolved_sha256`. Proposal only; output size grows slightly, so measure tokens. ### References docs/managed-code-analysis.md (signature resolution); closed #1832, #1835 and #1837 (signature element decoding).
Author
Owner

@XinwangTao commented on GitHub (Oct 19, 2026):

Agree this is a real UX win: asking every consumer to reimplement the 2-bit tag decode is the kind of friction that silently pushes people toward hand-rolled metadata readers instead of using the API. Keeping the coded index alongside the resolved name is the right call — it preserves identity for TypeSpec/generic instantiations and won't break consumers keying on the raw token.

One suggestion: since you plan to reuse the resolved_sha256 name owner, decide explicitly how generic instantiations render (e.g. List`1 vs List<System.String>), because the coded index alone cannot express the type arguments — a stable 'name with type-args-omitted' fallback beats silently dropping them. Keeping today's raw form for unresolvable operands (TypeSpec/unsupported) keeps the contract honest, and the 'signature_resolution: type-names-v1' string should be bumped so consumers can detect the new shape.

<!-- gh-comment-id:6259632935 --> @XinwangTao commented on GitHub (Oct 19, 2026): Agree this is a real UX win: asking every consumer to reimplement the 2-bit tag decode is the kind of friction that silently pushes people toward hand-rolled metadata readers instead of using the API. Keeping the coded index alongside the resolved name is the right call — it preserves identity for TypeSpec/generic instantiations and won't break consumers keying on the raw token. One suggestion: since you plan to reuse the resolved_sha256 name owner, decide explicitly how generic instantiations render (e.g. List\`1<T> vs List<System.String>), because the coded index alone cannot express the type arguments — a stable 'name with type-args-omitted' fallback beats silently dropping them. Keeping today's raw form for unresolvable operands (TypeSpec/unsupported) keeps the contract honest, and the 'signature_resolution: type-names-v1' string should be bumped so consumers can detect the new shape.
Author
Owner

@XinwangTao commented on GitHub (Oct 29, 2026):

Merged via #5309 and this looks exactly like the resolution I was hoping for — the encoded operand is retained alongside the readable name (valuetype:24 (System.SequencePosition)), generics/nesting keep their grammar, unresolvable TypeSpecs stay raw, and the signature_resolution bump to type-names-v2 lets consumers detect the new shape while v1 Evidence remains accepted. Thanks for carrying the breaking-change label and the thorough digest regression work.

<!-- gh-comment-id:6491678166 --> @XinwangTao commented on GitHub (Oct 29, 2026): Merged via #5309 and this looks exactly like the resolution I was hoping for — the encoded operand is retained alongside the readable name (valuetype:24 (System.SequencePosition)), generics/nesting keep their grammar, unresolvable TypeSpecs stay raw, and the signature_resolution bump to type-names-v2 lets consumers detect the new shape while v1 Evidence remains accepted. Thanks for carrying the breaking-change label and the thorough digest regression work.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3166
No description provided.