Skip to content
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

feat(language-service): Add getTypeDefinitionAtPosition (go to type d… #39145

Closed
wants to merge 1 commit into from

Conversation

@atscott
Copy link
Contributor

@atscott atscott commented Oct 6, 2020

…efinition)

This commit adds the implementation for providing "go to type definition"
functionality in the Ivy Language Service.

@atscott atscott requested review from kyliau and ayazhafiz Oct 6, 2020
@atscott atscott self-assigned this Oct 6, 2020
@ngbot ngbot bot added this to the needsTriage milestone Oct 6, 2020
@google-cla google-cla bot added the cla: yes label Oct 6, 2020
@atscott atscott added this to PRs In Review in Ivy Language Service Oct 6, 2020
Copy link
Contributor

@ayazhafiz ayazhafiz left a comment

This is so exciting

packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Show resolved Hide resolved
it('should return nothing for input providers', () => {
const definitions = getTypeDefinitionsAndAssertBoundSpan({
templateOverride: `<test-comp [tcN¦ame]="name"></test-comp>`,
});
expect(definitions).toEqual([]);
Copy link
Contributor

@ayazhafiz ayazhafiz Oct 6, 2020

Wouldn't tcName have a type, namely string?

Copy link
Contributor Author

@atscott atscott Oct 7, 2020

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)

Copy link
Contributor

@ayazhafiz ayazhafiz Oct 7, 2020

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.

Copy link
Contributor Author

@atscott atscott Oct 7, 2020

👍 Done.

kyliau
kyliau approved these changes Oct 7, 2020
Copy link
Contributor

@kyliau kyliau left a comment

minor comments. LGTM overall

packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
}
}

function getDefinitionsForSymbols(
symbols: {shimLocation: ShimLocation}[],
Copy link
Contributor

@kyliau kyliau Oct 7, 2020

Instead of the custom type, why not just pass in the shim locations?

Copy link
Contributor Author

@atscott atscott Oct 7, 2020

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.

packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
@atscott atscott force-pushed the gototypedefinition branch 3 times, most recently from ecdbf2d to d43ea0f Oct 7, 2020
Copy link
Contributor Author

@atscott atscott left a comment

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}[],
Copy link
Contributor Author

@atscott atscott Oct 7, 2020

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.

packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Show resolved Hide resolved
packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
it('should return nothing for input providers', () => {
const definitions = getTypeDefinitionsAndAssertBoundSpan({
templateOverride: `<test-comp [tcN¦ame]="name"></test-comp>`,
});
expect(definitions).toEqual([]);
Copy link
Contributor Author

@atscott atscott Oct 7, 2020

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)

@atscott atscott requested review from ayazhafiz and kyliau Oct 7, 2020
@atscott atscott force-pushed the gototypedefinition branch 3 times, most recently from f0ecc84 to 61d11e5 Oct 7, 2020
return symbols.reduce((result, {shimLocation}) => {
const defs = this.tsLS.getDefinitionAtPosition(
shimLocation.shimPath, shimLocation.positionInShimFile) ??
[];
Copy link
Contributor

@ayazhafiz ayazhafiz Oct 7, 2020

nit: clang format is really weird here, maybe something like

Suggested change
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?

Copy link
Contributor

@ayazhafiz ayazhafiz Oct 7, 2020

Also, can we use map and flatten here rather than creating a new array on each reduce iteration?

Copy link
Contributor Author

@atscott atscott Oct 8, 2020

Done.

switch (symbol.kind) {
case SymbolKind.Template: {
const matches = getDirectiveMatches(
{name: symbol.templateNode.tagName, kind: DirectiveMatchKind.TAG_NAME},
Copy link
Contributor

@ayazhafiz ayazhafiz Oct 7, 2020

can we pass the name and kind as separate params? Constructing an object feels verbose.

Copy link
Contributor Author

@atscott atscott Oct 8, 2020

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 {
Copy link
Contributor

@ayazhafiz ayazhafiz Oct 7, 2020

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.

Copy link
Contributor Author

@atscott atscott Oct 8, 2020

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.

packages/language-service/ivy/utils.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/utils.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/utils.ts Outdated Show resolved Hide resolved
@atscott atscott force-pushed the gototypedefinition branch from 61d11e5 to 4baab21 Oct 8, 2020
@atscott atscott requested a review from ayazhafiz Oct 8, 2020
Copy link
Contributor

@ayazhafiz ayazhafiz left a comment

nice 👍

packages/language-service/ivy/definitions.ts Outdated Show resolved Hide resolved
@atscott atscott force-pushed the gototypedefinition branch from 4baab21 to 29f9779 Oct 9, 2020
kyliau
kyliau approved these changes Oct 9, 2020
packages/language-service/ivy/utils.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/utils.ts Show resolved Hide resolved
packages/language-service/ivy/utils.ts Show resolved Hide resolved
@atscott atscott force-pushed the gototypedefinition branch from 29f9779 to 0ffc386 Oct 9, 2020
…efinition)

This commit adds the implementation for providing "go to type definition"
functionality in the Ivy Language Service.
@atscott atscott force-pushed the gototypedefinition branch from 0ffc386 to 25a4d4f Oct 9, 2020
@atscott atscott closed this in a84976f Oct 9, 2020
@atscott atscott moved this from PRs In Review to Done in Ivy Language Service Oct 9, 2020
@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Nov 9, 2020

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Linked issues

Successfully merging this pull request may close these issues.

None yet

3 participants