Generate ID strings directly from metadata instead of the type system,
so callers holding only a MetadataFile and an EntityHandle do not need
to materialize a compilation first, and raw metadata names survive
verbatim. GetIdString(IEntity) stays as a thin wrapper over the new
implementation, keeping the published entity-based entry point intact.
The implementation is validated by a differential suite comparing every
symbol of a test corpus against Roslyn's GetDocumentationCommentId.
Corners pinned by those tests: generic arguments distribute to their
nesting level (Outer{A}.Inner{B}), op_CheckedExplicit carries the
~ReturnType suffix like the other conversion operators, and custom
modifiers are ignored like Roslyn ignores them (a virtual method's 'in'
parameter is modreq(InAttribute) but documented as T@). Array shapes
use the spec's lowerbound:size notation, covered by a hand-built
module, since C# cannot express non-default array bounds in signatures.
Assisted-by: Claude:claude-fable-5:Claude Code