From 09869af90f88f33cef3937138caa8dd1f308c881 Mon Sep 17 00:00:00 2001 From: ivanwonder Date: Sun, 26 Jan 2020 22:48:11 +0800 Subject: [PATCH] fix(language-service): remove repeated symbol definitions for structural directive (#34847) For the structural directive, the 'path' will contain multiple `BoundDirectivePropertyAst` which depends on the number of directive property in the attribute value(e.g. '*ngFor="let item of []; trackBy: test;"', it has 2 `BoundDirectivePropertyAst`, 'ngForOf' and 'ngForTrackBy'). PR Close #34847 --- packages/language-service/src/locate_symbol.ts | 7 +++++++ packages/language-service/test/definitions_spec.ts | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/language-service/src/locate_symbol.ts b/packages/language-service/src/locate_symbol.ts index d46e542896..f91a315166 100644 --- a/packages/language-service/src/locate_symbol.ts +++ b/packages/language-service/src/locate_symbol.ts @@ -29,6 +29,8 @@ export function locateSymbols(info: AstResult, position: number): SymbolInfo[] { const templatePosition = position - info.template.span.start; // TODO: update `findTemplateAstAt` to use absolute positions. const path = findTemplateAstAt(info.templateAst, templatePosition); + const attribute = findAttribute(info, position); + if (!path.tail) return []; const narrowest = spanOf(path.tail); @@ -38,6 +40,11 @@ export function locateSymbols(info: AstResult, position: number): SymbolInfo[] { toVisit.push(node); } + // For the structural directive, only care about the last template AST. + if (attribute?.name.startsWith('*')) { + toVisit.splice(0, toVisit.length - 1); + } + return toVisit.map(ast => locateSymbol(ast, path, info)) .filter((sym): sym is SymbolInfo => sym !== undefined); } diff --git a/packages/language-service/test/definitions_spec.ts b/packages/language-service/test/definitions_spec.ts index 44c8aaab16..9b0455dd68 100644 --- a/packages/language-service/test/definitions_spec.ts +++ b/packages/language-service/test/definitions_spec.ts @@ -311,7 +311,7 @@ describe('definitions', () => { expect(definitions).toBeDefined(); // The two definitions are setter and getter of 'ngForTrackBy'. - expect(definitions !.length).toBe(4); + expect(definitions !.length).toBe(2); const refFileName = '/node_modules/@angular/common/common.d.ts'; definitions !.forEach(def => { @@ -335,7 +335,7 @@ describe('definitions', () => { expect(textSpan).toEqual(marker); expect(definitions).toBeDefined(); - expect(definitions !.length).toBe(2); + expect(definitions !.length).toBe(1); const refFileName = '/app/parsing-cases.ts'; const def = definitions ![0];