Skip to content

Add jsdoc member names: Class#method #44150

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 8 commits into from
May 21, 2021
Merged

Conversation

sandersn
Copy link
Member

@sandersn sandersn commented May 18, 2021

This PR adds support for jsdoc instance references of the form Class#method. Right now, these are parsed only inside of @see and @link tags, but they could probably be allowed other places fairly simply.

Additional fixes

  1. Allow find-all-refs (and related services like goto-def) on all parts of an entity name. Previously in @see {A.B.c}, only c worked. Now all 3 do.
  2. Put missing space into @link quick info for links with unresolved entities. I think I was going to follow up with a general fix that proved too ambitious and forgot the ad-hoc fix until now.

Implementation notes

  1. The parser and scanner now have a rescanPrivateIdentifier, which breaks up #id into two tokens, # id. This is the main way to get the new HashToken out of the scanner, but scanJsDocToken now also returns HashToken instead of Unknown. My first attempt just reused PrivateIdentifier, but this gave bad spans for find-all-refs. I also think that always scanning # as part of a private identifier ties that token too tightly to private identifiers, so when # gets used for other things, it'll probably make sense to invert the scanner's behaviour and provide a rescanHash function when private identifiers are desired.
  2. resolveJSDocInstanceReference is recursive, then delegates to resolveEntityName whenever it encounters a normal EntityName like K.x in, for example, K.x#m. However, when K.x doesn't resolve, it also tries K.prototype.x. That's because both K#x and K.x are supported inside @see/@link as synonyms of K.prototype.x. This fallback is inefficient, but only happens in services when find-all-refs is requested for @see/@link, and only performs redundant work for chained entity names like A.B.c which should actually be A#B#c.

Fixes #43594

sandersn added 3 commits May 17, 2021 10:01
A couple of mixed, nested references don't work yet.
The scanner+parser interaction is wrong, the parser consumes one too
many spaces, and the checker+services code needs a little cleanup.
1. I decided that correctly parsing a#b.c, an entity name containing an
instance reference, is not worth the work.
2. I made the scanner, at least the jsdoc part, emit a # token, and
provided a reScanPrivateIdentifier in order to convert #a to # a.
3. I cleaned up the code in the checker.
2. Unrelated: I added a missing space in linkPart display.
@typescript-bot typescript-bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone labels May 18, 2021
@sandersn
Copy link
Member Author

@DanielRosenwasser @amcasey I added you because you've had good opinions about usability in the past. Feel free to skip the implementation.

@andrewbranch @elibarzilay I heard you like parsing....

const entityName = parseEntityName(/* allowReservedWords*/ false);
const p2 = getNodePos();
let entityName: EntityName | JSDocInstanceReference = parseEntityName(/* allowReservedWords*/ false);
while (token() === SyntaxKind.PrivateIdentifier) {
Copy link
Member

@DanielRosenwasser DanielRosenwasser May 19, 2021

Choose a reason for hiding this comment

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

while?

What does Foo#Bar#Baz parse as?

Copy link
Member Author

Choose a reason for hiding this comment

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

A left-deep JSDocInstanceReference tree: ((Foo#Bar)#Baz)

? parseEntityName(/*allowReservedWords*/ true)
: undefined;
if (name) {
while(token() === SyntaxKind.PrivateIdentifier) {
Copy link
Member

Choose a reason for hiding this comment

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

Huh, the linter really doesn’t make you do this?

Suggested change
while(token() === SyntaxKind.PrivateIdentifier) {
while (token() === SyntaxKind.PrivateIdentifier) {

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, it used to. I'm not sure why it didn't complain this time.

@@ -2251,6 +2254,14 @@ namespace ts {
return token;
}

function reScanPrivateIdentifier(): SyntaxKind {
Copy link
Member

Choose a reason for hiding this comment

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

I know the various reScan functions don’t all have perfectly comparable behavior, but it seems like the general naming convention is naming it for what you want, not what you currently have: “I currently have token X, but have reason to believe that could be interpreted as token Y, so to re-scan X as Y, I call reScanY.”

The naming convention is clearly bad when read like that, but diverging from it is probably worse. I would either conform, naming this reScanHashToken, or be totally explicit, naming it reScanPrivateIdentifierAsHashToken.

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, I just confused myself. I will reverse it.

@sandersn sandersn changed the title Add jsdoc instance references: Class#method Add jsdoc member names: Class#method May 20, 2021
@sandersn sandersn merged commit 0864237 into master May 21, 2021
@sandersn sandersn deleted the add-jsdoc-instance-references branch May 21, 2021 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@link and @see should support Class#method syntax
4 participants