tsdoc icon indicating copy to clipboard operation
tsdoc copied to clipboard

RFC: Normalized form for standard TSDoc tags

Open octogonz opened this issue 7 years ago • 8 comments

Consider this example:

/**
 * Adds two numbers together.
 *
 * @remarks
 * This method is part of the {@link core-libary/Math | Math subsystem}.
 *
 * @param x - The first number to add
 * @param y - The second number to add
 * @returns The sum of `x` and `y`
 *
 * @beta
 */
function add(x: number, y: number): number;

Is the ordering of tags important? Would this be legal:

/**
 * @beta
 * @returns The sum of `x` and `y`
 * @param y - The second number to add
 * @param x - The first number to add
 * Adds two numbers together.
 *
 * @remarks
 * This method is part of the {@link core-libary/Math | Math subsystem}.
 */
function add(x: number, y: number): number;

What about this?

/**
 * @beta @returns The sum of `x` and `y`
 * @param y - The second number to add @param x - The first number to add
 * Adds two numbers together. @remarks This method is part of 
 * the {@link core-libary/Math | Math subsystem}.
 */
function add(x: number, y: number): number;

Some questions:

  1. If it's not legal, what's the best way to specify which orders are allowable?
  2. What should the parser do with ambiguous orderings?
  3. Should the TSDoc library include an operation for normalizing an AST?

octogonz avatar Mar 23 '18 02:03 octogonz

TypeDoc currently has a related issue where the order of tags can interfere with how the tags are processed. This is caused because TypeDoc takes any text following the tag as the tag text so putting a tag like @internal before the documentation text doesn't work by default.

/**
 * @internal
 * Without the plugin, this comment does not show up in the
 * docs because it's removed by typedoc tag processing
 */

See the single-line-tags plugin

aciccarello avatar Mar 23 '18 19:03 aciccarello

I think any text should belong to the preceding tag, even if it is delimitted by new lines. If no tag precedes the text, the text is considered being the description. If the description is desired somewhere else within the comment, the @descr or @description tag should be used.

tenry92 avatar Jun 04 '18 17:06 tenry92

@iansan5653 raised this question again in https://github.com/microsoft/tsdoc/issues/201:

Thanks for the info. Maybe we should introduce some notion of tags that typically form a group? For example, all @param tags (and maybe @returns) should be grouped together. All of the modifier tags should probably be grouped as well since they don't have any content.

Now that we've established an inventory of standard tags, maybe it's a good time to revisit this topic. Let's try to propose a "normalized" doc comment format that is aesthetically pleasing. This can serve as a spec for any rewriting that is (optionally) performed by the TSDocEmitter.renderComment() API.

Something like this:

  /**
   * The summary comes first.
   *
   * @remarks
   * The `@remarks` tag always goes on its own line.  It appears immediately after the summary.
   *
   * @example
   * Other blocks appear after `@remarks` preserving their original input ordering,
   * except that similar blocks are grouped together.  For example, additional `@example`
   * blocks are reordered to appear immediately after the first `@example` block.
   *
   * @throws {@link MySpecialError}
   *
   * If a block's syntax accepts special content on the same line, then a blank line 
   * should be skipped before the rest of the content.
   *
   * @param x - The parameters and return value are always the last block tags,
   * so they will be visually closer to the function signature.
   *
   * @param y - If the parameters and return value descriptions are all single paragraphs
   * less than 3 lines, then we can compress them by omitting newlines between the blocks.
   *
   * @returns 
   * The `@returns` section comes after the parameters. Then modifier tags come last.
   * Modifiers tags are grouped onto a single line (with wrapping) and preserve their 
   * original input ordering.
   *
   * @beta @override @sealed
   */

What do you think?

@rbuckton @EisenbergEffect @D4N14L FYI

octogonz avatar Dec 09 '19 23:12 octogonz

And here's an example of "compressed" param/returns:

  /**
   * The summary comes first.
   *
   * @remarks
   * The `@remarks` tag always goes on its own line.  It appears immediately after the summary.
   *
   * @param x - the horizontal offset
   * @param y - the vertical offset
   * @returns `true` if anything changed, `false` otherwise
   *
   * @beta @override @sealed
   */

octogonz avatar Dec 09 '19 23:12 octogonz

It seems odd to me that @throws is before @params / @returns, otherwise this looks reasonable to me and how I would write it naturally.


Broken tag: @rbuckton FYI

Gerrit0 avatar Dec 10 '19 00:12 Gerrit0

Good points, thanks @Gerrit0 !

octogonz avatar Dec 10 '19 04:12 octogonz

To me, I feel like intuitively most users will want to describe the parameters first (before @example or @throws) because the function parameters are arguably the firs thing you're looking for when you are reading the source directly. That being said, I think your justification of putting them as close as possible to the function signature does have some merit - it would just take some getting used to.

I like putting all the modifier tags on the same line - that feels right.

I don't think I agree with this:

If a block's syntax accepts special content on the same line, then a blank line should be skipped before the rest of the content.

To me, this makes it look like the information is detached from the tag - I think it should immediately follow:

/**
   * @throws {@link MySpecialError}
   * The block content should always start on the line immediately following the
   * block's opening tag.
   */

In general, how do we define which tags should have content start immediately following the tag (@param, @returns) and which ones should have content start on the next line (@remarks, @throws, @example)? Intuitively, @remarks does this because it's always going to have paragraph-like content, while @example and @throws feel like they should do this because they might have titles (for @example that's a potential result of the discussion in #20). I'm not sure how to formally make that distinction though.

iansan5653 avatar Dec 11 '19 05:12 iansan5653

Did someone make any progress on this in the last 4 years? 😸

For @example I'd say: There should be no fixed position. Examples should be able to be included where they are actually needed. This can be in the summary, or in the remarks, or in the privateRemarks.

Maybe even @example in combination with param or return can make sense sometimes (?). Didn't have a use for that screnario so far, but maybe someone else has.

benneq avatar Apr 14 '23 12:04 benneq