-
Notifications
You must be signed in to change notification settings - Fork 26.6k
feat(language-service): Add getTypeDefinitionAtPosition (go to type d… #39145
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so exciting
it('should return nothing for input providers', () => { | ||
const definitions = getTypeDefinitionsAndAssertBoundSpan({ | ||
templateOverride: `<test-comp [tcN¦ame]="name"></test-comp>`, | ||
}); | ||
expect(definitions).toEqual([]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't tcName
have a type, namely string
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually just the behavior of the ts language service itself for primitives. However, if I set the type to String
rather than string
, I do get definitions from the lib.es2015.core.d.ts
, lib.es5.d.ts
, etc. I think this case is generally covered in the new test that Keen requested (go to type definition of toLowerCase
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. I think it would be worth reworking this test to use a value that has a go-to-definition type, because I think the test title "should return nothing for input providers" is incorrect - in general we do want to return something for input providers, when there is something to return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comments. LGTM overall
} | ||
} | ||
|
||
function getDefinitionsForSymbols( | ||
symbols: {shimLocation: ShimLocation}[], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the custom type, why not just pass in the shim locations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes calling the function easier. I would otherwise have to map
all the symbols before passing them in. I also can't use the Symbol
type because some don't have shimLocation
at the top level. If you feel strongly about this, I can change it.
ecdbf2d
to
d43ea0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PTAL. I had to make some adjustments to the getDirectiveMatches
to allow matching compound selectors that included the tag name.
} | ||
} | ||
|
||
function getDefinitionsForSymbols( | ||
symbols: {shimLocation: ShimLocation}[], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes calling the function easier. I would otherwise have to map
all the symbols before passing them in. I also can't use the Symbol
type because some don't have shimLocation
at the top level. If you feel strongly about this, I can change it.
it('should return nothing for input providers', () => { | ||
const definitions = getTypeDefinitionsAndAssertBoundSpan({ | ||
templateOverride: `<test-comp [tcN¦ame]="name"></test-comp>`, | ||
}); | ||
expect(definitions).toEqual([]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually just the behavior of the ts language service itself for primitives. However, if I set the type to String
rather than string
, I do get definitions from the lib.es2015.core.d.ts
, lib.es5.d.ts
, etc. I think this case is generally covered in the new test that Keen requested (go to type definition of toLowerCase
)
f0ecc84
to
61d11e5
Compare
return symbols.reduce((result, {shimLocation}) => { | ||
const defs = this.tsLS.getDefinitionAtPosition( | ||
shimLocation.shimPath, shimLocation.positionInShimFile) ?? | ||
[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: clang format is really weird here, maybe something like
return symbols.reduce((result, {shimLocation}) => { | |
const defs = this.tsLS.getDefinitionAtPosition( | |
shimLocation.shimPath, shimLocation.positionInShimFile) ?? | |
[]; | |
return symbols.reduce((result, {shimLocation}) => { | |
const {shimPath, positionInShimFile} = shimLocation; | |
const defs = this.tsLS.getDefinitionAtPosition(shimPath, positionInShimFile) ?? []; |
to make it a bit more linear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, can we use map and flatten here rather than creating a new array on each reduce iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
switch (symbol.kind) { | ||
case SymbolKind.Template: { | ||
const matches = getDirectiveMatches( | ||
{name: symbol.templateNode.tagName, kind: DirectiveMatchKind.TAG_NAME}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we pass the name and kind as separate params? Constructing an object feels verbose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored this into two totally separate functions. This was feeling a little bit like a code smell the way it was.
}, [] as ts.DefinitionInfo[]); | ||
} | ||
|
||
private getSymbolAndNodeAtPosition(fileName: string, position: number): DefinitionMeta { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usages of this function return value unpack symbol
and node
and check that both are defined before moving on, so I think it would be better to make the return type DefinitionMeta|undefined
. I think this would make it clearer that the metadata is either entirely defined with a symbol and node, or not at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I have a WIP branch that distinguish between templateInfo
is undefined
vs if the node/symbol lookup failed so I just extracted the templateInfo
getter out of this function.
61d11e5
to
4baab21
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice 👍
4baab21
to
29f9779
Compare
29f9779
to
0ffc386
Compare
…efinition) This commit adds the implementation for providing "go to type definition" functionality in the Ivy Language Service.
0ffc386
to
25a4d4f
Compare
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
…efinition)
This commit adds the implementation for providing "go to type definition"
functionality in the Ivy Language Service.