fix(language-service): completions after "let x of |" in ngFor (#34473)
This commit fixes a bug in which we do testing for completions. Subsequently, this exposes another bug in our implementation whereby suggestions are not provided in "ngFor" where there should have been. Currently, multiple test cases are grouped together in a single template. This requires the template to be somewhat complete so that test cases that depend on variables declared earlier would pass. Consider the following example: ``` template: ` <div *ngFor="let ~{for-person}person of ~{for-people}people"> <span>Name: {{~{for-interp-person}person.~{for-interp-name}name}}</span> <span>Age: {{person.~{for-interp-age}age}}</span> </div>`, ``` In order to test `~{for-interp-person}`, `people` has to be included after `~{for-people}`. This means the test case for `~{for-people}` is not reflective of the actual use case because the variable is already there! In real case, the expression would be incomplete, and our implementation failed to take that into account. This commit breaks such test into individual tests, and fix the bugs in the underlying implementation. PR Close #34473
This commit is contained in:

committed by
Alex Rickabaugh

parent
fde5067996
commit
ca8b584097
@ -511,7 +511,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
||||
|
||||
if (binding.keyIsVar) {
|
||||
const equalLocation = attr.value.indexOf('=');
|
||||
if (equalLocation >= 0 && valueRelativePosition >= equalLocation) {
|
||||
if (equalLocation > 0 && valueRelativePosition > equalLocation) {
|
||||
// We are after the '=' in a let clause. The valid values here are the members of the
|
||||
// template reference's type parameter.
|
||||
const directiveMetadata = selectorInfo.map.get(selector);
|
||||
@ -531,6 +531,19 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
||||
this.addAttributeValuesToCompletions(binding.expression.ast);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the expression is incomplete, for example *ngFor="let x of |"
|
||||
// binding.expression is null. We could still try to provide suggestions
|
||||
// by looking for symbols that are in scope.
|
||||
const KW_OF = ' of ';
|
||||
const ofLocation = attr.value.indexOf(KW_OF);
|
||||
if (ofLocation > 0 && valueRelativePosition >= ofLocation + KW_OF.length) {
|
||||
const span = new ParseSpan(0, attr.value.length);
|
||||
const offset = attr.sourceSpan.start.offset;
|
||||
const receiver = new ImplicitReceiver(span, span.toAbsolute(offset));
|
||||
const expressionAst = new PropertyRead(span, span.toAbsolute(offset), receiver, '');
|
||||
this.addAttributeValuesToCompletions(expressionAst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user