Skip to content

Map TypeAlias doc links to the underlying C# type#4573

Open
pepone wants to merge 1 commit intoicerpc:mainfrom
pepone:fix/doc-comment-typealias-link
Open

Map TypeAlias doc links to the underlying C# type#4573
pepone wants to merge 1 commit intoicerpc:mainfrom
pepone:fix/doc-comment-typealias-link

Conversation

@pepone
Copy link
Copy Markdown
Member

@pepone pepone commented Apr 30, 2026

Fix #4494

Fix icerpc#4494

For inline @link to a TypeAlias, emit <see cref="MappedType"/> when the
mapped type is non-generic, or <c>MappedType</c> (XML-escaped) when it
is generic — closed generics like IList<string> have no valid C# cref
form, so a clickable link isn't possible. For @see, emit <seealso/>
only for non-generic mapped types and skip generic ones.

Add typealias coverage to DocumentationTests.slice for non-generic,
sequence, dictionary, and result mappings.
Copilot AI review requested due to automatic review settings April 30, 2026 11:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the Slice-to-C# documentation generator so doc-comment links that target typealias entities resolve (when possible) to the aliased underlying C# type, and expands the documentation Slice test inputs to exercise these cases.

Changes:

  • Map inline {@link TypeAlias} to the underlying mapped C# type, emitting <see cref="..."/> for non-generic mappings and <c>...</c> for generic mappings.
  • Map @see TypeAlias to <seealso/> only for non-generic underlying mappings; skip generic mappings.
  • Extend DocumentationTests.slice with additional typealias/link scenarios (string, sequence, dictionary, result).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/ZeroC.Slice.Generator/DocCommentFormatter.cs Adjusts how @link/@see are formatted for TypeAlias targets by mapping them to the underlying C# type.
tests/IceRpc.Slice.Generator.Tests/DocumentationTests.slice Adds Slice definitions and doc comments that reference type aliases to validate the new link formatting behavior.

Comment on lines +63 to 65
ResolvedCommentLink { Entity: TypeAlias alias } => FormatTypeAliasInline(alias, currentNamespace),
ResolvedCommentLink r => $"""<see cref="{FormatEntityCref(r.Entity, currentNamespace)}" />""",
UnresolvedCommentLink u => $"<c>{CommentTag.XmlEscape(u.Identifier)}</c>",
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

The <see cref="..." /> emitted for resolved inline links interpolates FormatEntityCref(...) directly into an XML attribute value without XML-escaping. Since FormatEntityCref can incorporate cs::type (and namespace strings), this can produce malformed XML doc comments when the type/namespace contains characters like &, <, > or ". Escape the cref value (e.g., via CommentTag.XmlEscape(...)) before splicing it into the <see/> tag, or switch to generating this tag through CommentTag to ensure consistent escaping.

Copilot uses AI. Check for mistakes.
string mapped = alias.UnderlyingType.Type.ToTypeString(currentNamespace);
return mapped.Contains('<', StringComparison.Ordinal)
? $"<c>{CommentTag.XmlEscape(mapped)}</c>"
: $"""<see cref="{mapped}" />""";
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

For non-generic type-alias mappings, this emits <see cref="{mapped}" /> without XML-escaping mapped. ToTypeString can return strings influenced by cs::type, so special XML characters could break the doc comment. Escape mapped before inserting it into the cref attribute (the generic branch already escapes via XmlEscape).

Suggested change
: $"""<see cref="{mapped}" />""";
: $"""<see cref="{CommentTag.XmlEscape(mapped)}" />""";

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@InsertCreativityHere InsertCreativityHere left a comment

Choose a reason for hiding this comment

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

Looks good to me!

Comment on lines +24 to +34
/// Returns the {@link UserName} for the active user.
getName() -> UserName

/// Returns a {@link UserList} of active user names.
getNames() -> UserList

/// Returns a {@link UserMap} keyed by user name.
getSessions() -> UserMap

/// Returns a {@link UserResult} containing the session or an error message.
getResult() -> UserResult
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Feel free to keep the separate methods if you want. But, you could also accomplish the exact same testing with a single operation

    /// Returns the {@link UserName} for the active user.
    /// This does not return a {@link UserList}, or a {@link UserMap}, or even a {@link UserResult}.
    getName() -> UserName

Unless there's some oddity in the C# code-generator I'm unaware of, there really shouldn't be any difference between these things.

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.

[Audit-Low] DocCommentFormatter.FormatEntityCref doesn't escape name/…

3 participants