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

Autocompletion in expression contexts #39727

Closed
wants to merge 1 commit into from

Conversation

alxhub
Copy link
Member

@alxhub alxhub commented Nov 17, 2020

No description provided.

@google-cla google-cla bot added the cla: yes label Nov 17, 2020
@alxhub alxhub force-pushed the ngtsc/ls/autocomplete-6 branch 4 times, most recently from 04691c8 to 199194e Compare November 18, 2020 20:27
@jessicajaniuk jessicajaniuk added the area: compiler Issues related to `ngc`, Angular's template compiler label Dec 1, 2020
@ngbot ngbot bot added this to the needsTriage milestone Dec 1, 2020
@alxhub alxhub force-pushed the ngtsc/ls/autocomplete-6 branch 2 times, most recently from fc65434 to 62f9518 Compare December 3, 2020 22:01
@alxhub alxhub marked this pull request as ready for review December 3, 2020 22:34
@pullapprove pullapprove bot requested a review from kyliau December 3, 2020 22:34
@alxhub alxhub added action: review The PR is still awaiting reviews from at least one requested reviewer target: minor This PR is targeted for the next minor release labels Dec 4, 2020
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Dec 4, 2020
@alxhub alxhub requested review from atscott and removed request for kyliau December 7, 2020 18:23
@pullapprove pullapprove bot requested a review from kyliau December 7, 2020 18:23
* autocompletion at that point in the expression, if such a location exists.
*/
getExpressionCompletionLocation(
expr: PropertyRead|SafePropertyRead|MethodCall|SafeMethodCall,
Copy link
Contributor

Choose a reason for hiding this comment

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

What about KeyedRead/KeyedWrite/PropertyWrite?

Copy link
Member Author

Choose a reason for hiding this comment

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

KeyedRead and KeyedWrite are non-trivial - the key is itself an expression, meaning we won't target the KeyedRead but rather a LiteralPrimitive (if a string literal key is used) within the KeyedRead. It's possible to support these forms, but I want to get the 99% case working first.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added support / a test for PropertyWrite, since it's nearly identical to PropertyRead.

@@ -79,4 +83,52 @@ export class CompletionEngine {
this.globalCompletionCache.set(context, completion);
return completion;
}

getExpressionCompletionLocation(expr: PropertyRead|PropertyWrite|MethodCall|
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm actually a bit curious about this method in general. Shouldn't TTC#getSymbolAtLocation return this same information?

Edit: Ah, I see that you use getEnd whereas the getSymbolAtLocation uses getStart. Maybe there's some more nuance to this as well that I don't see immediately.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think there's any nuance with getStart() vs getEnd(). TTC#getSymbolOfNode() would almost certainly work in the cases supported by this PR. But something more complex liked KeyedRead may require a completion location that's specifically inside of the quoted key string, for example, which getSymbolOfNode() isn't obligated to provide.

We could add to getSymbolOfNode()'s contract that it provides autocompletion-compatible locations where necessary, but I think a separate method is probably preferable.

// Safe navigation operations are a little more complex, and involve a ternary. Completion
// happens in the "true" case of the ternary.
const ternaryExpr = findFirstMatchingNode(this.tcb, {
filter: ts.isParenthesizedExpression,
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a little weird that you're using parenthesized expression as the filter here. I think this should actually be ts.isConditionalExpression based on the check below.

Copy link
Member Author

Choose a reason for hiding this comment

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

getSymbolOfTemplateExpression does something similar - it looks for any node with the given span, then unwraps any parenthesized expression. I'm relying on the fact that all ternaries are parenthesized.

@@ -28,6 +29,9 @@ export class CompletionEngine {
*/
private globalCompletionCache = new Map<TmplAstTemplate|null, GlobalCompletion>();

private expressionCompletionCache =
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have any concerns about memory "leak" since we are not invalidating cache entries?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, because the entire CompletionEngine is thrown away on a template change.

/**
* Analogue for `ts.LanguageService.getCompletionEntrySymbol`.
*/
getCompletionEntrySymbol(name: string): ts.Symbol|undefined {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can omit this method. I looked at the TypeScript language service,getCompletionEntryDetails is the main API for completions. Besides, I don't think we have a use case for the ts.Symbol right now. The symbol will be discarded at the LSP boundary.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm going to leave it in here, but can do a separate PR to remove all the getCompletionSymbol operations.

packages/language-service/ivy/completions.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/language_service.ts Outdated Show resolved Hide resolved
packages/language-service/ivy/completions.ts Outdated Show resolved Hide resolved
const {ngLS, fileName, cursor} =
setup(`{{name.f¦}}`, `name!: {first: string; last: string;};`);
const completions = ngLS.getCompletionsAtPosition(fileName, cursor, /* options */ undefined);
expectContain(completions, ts.ScriptElementKind.memberVariableElement, ['first']);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should have a test that lists out all the results.
In the past, we've had unexpected completion results because we only check what's expected to be there, but not results that are not supposed to be there.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done - switched to expectAll.

@kyliau kyliau added action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Dec 7, 2020
@alxhub alxhub force-pushed the ngtsc/ls/autocomplete-6 branch 3 times, most recently from 52eb6a2 to defa59b Compare December 8, 2020 20:33
@alxhub alxhub removed the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Dec 8, 2020
@alxhub alxhub added the action: merge The PR is ready for merge by the caretaker label Dec 8, 2020
This commit adds support to the Language Service for autocompletion within
expression contexts. Specifically, this is auto completion of property reads
and method calls, both in normal and safe-navigational forms.
@mhevery
Copy link
Contributor

mhevery commented Dec 9, 2020

presubmit

@pullapprove pullapprove bot removed the area: compiler Issues related to `ngc`, Angular's template compiler label Dec 9, 2020
@ngbot ngbot bot removed this from the Backlog milestone Dec 9, 2020
@alxhub alxhub closed this in 93a8326 Dec 10, 2020
zarend pushed a commit to zarend/angular that referenced this pull request Dec 11, 2020
…gular#39727)

This commit adds support to the Language Service for autocompletion within
expression contexts. Specifically, this is auto completion of property reads
and method calls, both in normal and safe-navigational forms.

PR Close angular#39727
@angular-automatic-lock-bot
Copy link

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 Jan 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants