fix(language-service): wrong completions in conditional operator (#37505)
In `a ? b.~{cursor}`, the LS will provide the symbols in the scope of the current template, because the `path.tail` is `falseExp` whose value is `EmptyExpr`, and the span of `falseExp` is wider than the `trueExp`, so the value of `path` should be narrowed. PR Close #37505
This commit is contained in:
parent
adc9d5cdcb
commit
e99bcbb4d4
|
@ -6,11 +6,11 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AST, AstPath as AstPathBase, ASTWithName, ASTWithSource, RecursiveAstVisitor} from '@angular/compiler';
|
||||
import {AST, AstPath as AstPathBase, ASTWithName, ASTWithSource, Interpolation, RecursiveAstVisitor} from '@angular/compiler';
|
||||
|
||||
import {AstType} from './expression_type';
|
||||
import {BuiltinType, Span, Symbol, SymbolTable, TemplateSource} from './types';
|
||||
import {inSpan} from './utils';
|
||||
import {inSpan, isNarrower} from './utils';
|
||||
|
||||
type AstPath = AstPathBase<AST>;
|
||||
|
||||
|
@ -20,7 +20,10 @@ function findAstAt(ast: AST, position: number, excludeEmpty: boolean = false): A
|
|||
visit(ast: AST) {
|
||||
if ((!excludeEmpty || ast.sourceSpan.start < ast.sourceSpan.end) &&
|
||||
inSpan(position, ast.sourceSpan)) {
|
||||
const isNotNarrower = path.length && !isNarrower(ast.span, path[path.length - 1].span);
|
||||
if (!isNotNarrower) {
|
||||
path.push(ast);
|
||||
}
|
||||
ast.visit(this);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +35,14 @@ function findAstAt(ast: AST, position: number, excludeEmpty: boolean = false): A
|
|||
ast = ast.ast;
|
||||
}
|
||||
|
||||
// `Interpolation` is useless here except the `expressions` of it.
|
||||
if (ast instanceof Interpolation) {
|
||||
ast = ast.expressions.filter((_ast: AST) => inSpan(position, _ast.sourceSpan))[0];
|
||||
}
|
||||
|
||||
if (ast) {
|
||||
visitor.visit(ast);
|
||||
}
|
||||
|
||||
return new AstPathBase<AST>(path, position);
|
||||
}
|
||||
|
|
|
@ -832,6 +832,15 @@ describe('completions', () => {
|
|||
// should resolve to transform(value: number, prefix: number): number
|
||||
expectContain(c2, CompletionKind.METHOD, ['toFixed', 'toExponential']);
|
||||
});
|
||||
|
||||
it('should work in the conditional operator', () => {
|
||||
mockHost.override(TEST_TEMPLATE, '{{ title ? title.~{cursor} }}');
|
||||
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
|
||||
const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
|
||||
expectContain(completions, CompletionKind.METHOD, [
|
||||
'trim',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
function expectContain(
|
||||
|
|
Loading…
Reference in New Issue