Skip to content

Expose getJSDocCommentsAndTags #53627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 24, 2023
Merged

Expose getJSDocCommentsAndTags #53627

merged 5 commits into from
Apr 24, 2023

Conversation

Gerrit0
Copy link
Contributor

@Gerrit0 Gerrit0 commented Apr 2, 2023

As discussed in the TS Discord, TypeDoc is now relying on this internal function in order parse comments more closely to TypeScript's parsing.

Fixes #45197

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Apr 2, 2023
@typescript-bot
Copy link
Collaborator

The TypeScript team hasn't accepted the linked issue #45197. If you can get it accepted, this PR will have a better chance of being reviewed.

@sandersn sandersn self-assigned this Apr 12, 2023
@sandersn sandersn requested review from sandersn and jakebailey April 12, 2023 17:05
Copy link
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

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

I don't have any problem doing this, but, I don't know if we should bother trying to move all of the code. Frankly, we've been bad at sorting out public from non-public and I'm not sure there's a benefit of trying at the moment...

@@ -8507,6 +8507,7 @@ declare namespace ts {
function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined;
function getDecorators(node: HasDecorators): readonly Decorator[] | undefined;
function getModifiers(node: HasModifiers): readonly Modifier[] | undefined;
function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): readonly (JSDoc | JSDocTag)[];
Copy link
Member

Choose a reason for hiding this comment

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

Do we have noCache anywhere else in the public code? Is this useful externally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I must not have been paying much attention, didn't mean to expose that parameter externally, I don't think it should be used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved it back to utilities.ts, and avoided exposing noCache externally, which unfortunately required either an extra function, or an overload and disabling a rule.

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

Needs some documentation that explains why you'd use this lower-level function (which will also help me understand why this change is needed).

@@ -956,6 +961,52 @@ export function getModifiers(node: HasModifiers): readonly Modifier[] | undefine
}
}

export function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): readonly (JSDoc | JSDocTag)[] {
Copy link
Member

Choose a reason for hiding this comment

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

This function is wrapped in the language service as getCommentHavingNodes, for declarations only.

This function needs at least two kinds of documentation:

  1. Why use it instead of getJSDocTags? They both look for multiple relevant comments, but getJSDocTags only returns tags that apply, not the entire comment. Does non-local comment text ever make sense [1]? Are the non-local comments useful in some way besides comments+tags? Would a caller need to know that one tag was part of a local comment and another was part of a non-local one?
  2. What do the parameters mean and what preconditions are there for their use? Specifically:
    • Internally, getJSDocCommentsAndTags is called from two places; the first verifies canHaveJSDoc(hostNode) and the second passes only declarations. So I think this only works on specific kinds of node, or maybe on any node, but might hurt performance due to deoptimisation.
    • getJSDocTagsNoCache is labelled internal but find-all-refs doesn't find anything. Why wouldn't you want caching?

[1] eg

/**
 * Function documentation, non-local to x, but shouldn't be needed, right?
 * @param x non-local documentation for x, in a tag
 */
function f(/** also local, so maybe this is needed? */x) { }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. It should be used when you want documentation for a node, personally, getJSDocTags is something I never see myself using, because if I want documentation for something, I want all related documentation, not only documentation that's nested within a tag. getJSDocTags would return nothing of use whatsoever for non-parameters/type parameters... I have no idea why you'd use that function, and was surprised it was exposed while this more useful version was not.
  2. I experimented with changing this to accept a Declaration rather than Node, and while TypeDoc is fine with that signature, getJSDocTypeParameterTagsWorker isn't (InferTypeNode and JSDocTemplateTag)
  3. Caching - I removed noCache and the other noCache parameters from functions that call this with that parameter, and found that getJSDocOverrideTagNoCache is public, but that looks like a mistake, the other getJSDoc*Tag functions all use the cache. The real user of all of this is getJSDocModifierFlagsNoCache, which is ultimately used by __debugModifierFlags in enableDebugInfo... not familiar enough with the compiler to say if these ought to be cleaned up.

@Gerrit0 Gerrit0 requested review from sandersn and jakebailey April 16, 2023 00:32
@jakebailey
Copy link
Member

Given this is now just a plain de-internalizing, this seems okay to me if the API seems reasonable, but I think @sandersn or @rbuckton know more here.

@sandersn
Copy link
Member

I think it's probably fine, even though the function is still pretty complex for the simplish uses I think most people will want it for.

@Gerrit0 specifically it sounds like you're only interested in the jsdoc comment text. Would a function with no lookup loop work for you? Maybe a signature like getJSDocComments: (hostNode: Node) => JSDoc | undefined

It's easier to expose getJSDocCommentsAndTags, so probably not worthwhile making a new function, but I am curious about your exact needs.

@Gerrit0
Copy link
Contributor Author

Gerrit0 commented Apr 21, 2023

Yes, that would work for me (mostly, should return readonly JSDoc[] to be able to handle JSDoc @overload)

If you think that's a better solution, I'd be happy to give implementing that a shot.

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

Let's expose what we have, but rewrite the explanation.

@@ -4181,7 +4181,31 @@ export function canHaveJSDoc(node: Node): node is HasJSDoc {
}
}

/** @internal */
/**
* Gets either the {@link JSDoc} object or {@link JSDocTag} providing documentation for the provided node.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Gets either the {@link JSDoc} object or {@link JSDocTag} providing documentation for the provided node.
* Gets an array of each {@link JSDoc} object or {@link JSDocTag} that documents the provided node at every position that related JSDoc could exist.

Comment on lines 4202 to 4203
*
* @param hostNode node to get the associated JSDoc comment for.
Copy link
Member

Choose a reason for hiding this comment

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

This is redundant, so please delete it.

* const a = 0
* /**
* * Entire JSDoc will be returned for `b`
* * JSDocTag will be returned for `c`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* * JSDocTag will be returned for `c`
* @param c JSDocTag will be returned for `c`

/** @internal */
/**
* Gets either the {@link JSDoc} object or {@link JSDocTag} providing documentation for the provided node.
* A {@link JSDoc} object will be returned if an entire comment is associated with this node. This is always
Copy link
Member

Choose a reason for hiding this comment

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

I would replace this paragraph with the one below:

This function checks multiple locations for JSDoc comments that apply to a host node. At each location, the whole comment may apply to the node, or only a specific tag in the comment. In the first case, location adds the entire {@link JSDoc} object. In the second case, it adds the applicable {@link JSDocTag}.

For example, a JSDoc comment before a parameter adds the entire {@link JSDoc}. But a `@param` tag on the parent function only adds the {@link JSDocTag} for the `@param`.

(writing probably needs to be rewrapped)

@Gerrit0 Gerrit0 requested a review from sandersn April 21, 2023 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Add a way to get JSDoc comment text
4 participants