diff --git a/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts b/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts index b23cc76b07..af72642041 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts @@ -155,8 +155,24 @@ export interface ReferenceSymbol { */ declaration: TmplAstReference; - /** The location in the shim file of a variable that holds the type of the local ref. */ - shimLocation: ShimLocation; + /** + * The location in the shim file of a variable that holds the type of the local ref. + * For example, a reference declaration like the following: + * ``` + * var _t1 = document.createElement('div'); + * var _t2 = _t1; // This is the reference declaration + * ``` + * This `targetLocation` is `[_t1 variable declaration].getStart()`. + */ + targetLocation: ShimLocation; + + /** + * The location in the TCB for the identifier node in the reference variable declaration. + * For example, given a variable declaration statement for a template reference: + * `var _t2 = _t1`, this location is `[_t2 node].getStart()`. This location can + * be used to find references to the variable within the template. + */ + referenceVarLocation: ShimLocation; } /** @@ -185,8 +201,16 @@ export interface VariableSymbol { */ declaration: TmplAstVariable; - /** The location in the shim file of a variable that holds the type of the template variable. */ - shimLocation: ShimLocation; + /** + * The location in the shim file for the identifier that was declared for the template variable. + */ + localVarLocation: ShimLocation; + + /** + * The location in the shim file for the initializer node of the variable that represents the + * template variable. + */ + initializerLocation: ShimLocation; } /** diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts index 91cc032ae4..df08a4016f 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/template_symbol_builder.ts @@ -13,7 +13,7 @@ import {AbsoluteFsPath} from '../../file_system'; import {ClassDeclaration} from '../../reflection'; import {ComponentScopeReader} from '../../scope'; import {isAssignment} from '../../util/src/typescript'; -import {DirectiveSymbol, DomBindingSymbol, ElementSymbol, ExpressionSymbol, InputBindingSymbol, OutputBindingSymbol, ReferenceSymbol, Symbol, SymbolKind, TemplateSymbol, TsNodeSymbolInfo, TypeCheckableDirectiveMeta, VariableSymbol} from '../api'; +import {DirectiveSymbol, DomBindingSymbol, ElementSymbol, ExpressionSymbol, InputBindingSymbol, OutputBindingSymbol, ReferenceSymbol, ShimLocation, Symbol, SymbolKind, TemplateSymbol, TsNodeSymbolInfo, TypeCheckableDirectiveMeta, VariableSymbol} from '../api'; import {ExpressionIdentifier, findAllMatchingNodes, findFirstMatchingNode, hasExpressionIdentifier} from './comments'; import {TemplateData} from './context'; @@ -303,7 +303,17 @@ export class SymbolBuilder { return null; } - return {...expressionSymbol, kind: SymbolKind.Variable, declaration: variable}; + return { + tsType: expressionSymbol.tsType, + tsSymbol: expressionSymbol.tsSymbol, + initializerLocation: expressionSymbol.shimLocation, + kind: SymbolKind.Variable, + declaration: variable, + localVarLocation: { + shimPath: this.shimPath, + positionInShimFile: this.getShimPositionForNode(node.name), + } + }; } private getSymbolOfReference(ref: TmplAstReference): ReferenceSymbol|null { @@ -331,13 +341,19 @@ export class SymbolBuilder { return null; } + const referenceVarShimLocation: ShimLocation = { + shimPath: this.shimPath, + positionInShimFile: this.getShimPositionForNode(node), + }; if (target instanceof TmplAstTemplate || target instanceof TmplAstElement) { return { - ...symbol, - tsSymbol: symbol.tsSymbol, kind: SymbolKind.Reference, + tsSymbol: symbol.tsSymbol, + tsType: symbol.tsType, target, declaration: ref, + targetLocation: symbol.shimLocation, + referenceVarLocation: referenceVarShimLocation, }; } else { if (!ts.isClassDeclaration(target.directive.ref.node)) { @@ -345,11 +361,13 @@ export class SymbolBuilder { } return { - ...symbol, kind: SymbolKind.Reference, tsSymbol: symbol.tsSymbol, + tsType: symbol.tsType, declaration: ref, target: target.directive.ref.node, + targetLocation: symbol.shimLocation, + referenceVarLocation: referenceVarShimLocation, }; } } diff --git a/packages/language-service/ivy/definitions.ts b/packages/language-service/ivy/definitions.ts index 5e59d651fe..de0b8ce78a 100644 --- a/packages/language-service/ivy/definitions.ts +++ b/packages/language-service/ivy/definitions.ts @@ -90,7 +90,8 @@ export class DefinitionBuilder { }); } if (symbol.kind === SymbolKind.Variable) { - definitions.push(...this.getDefinitionsForSymbols(symbol)); + definitions.push( + ...this.getDefinitionsForSymbols({shimLocation: symbol.initializerLocation})); } return definitions; } @@ -135,9 +136,11 @@ export class DefinitionBuilder { return [...bindingDefs, ...directiveDefs]; } case SymbolKind.Reference: + return this.getTypeDefinitionsForSymbols({shimLocation: symbol.targetLocation}); case SymbolKind.Expression: - case SymbolKind.Variable: return this.getTypeDefinitionsForSymbols(symbol); + case SymbolKind.Variable: + return this.getTypeDefinitionsForSymbols({shimLocation: symbol.initializerLocation}); } } diff --git a/packages/language-service/ivy/display_parts.ts b/packages/language-service/ivy/display_parts.ts index aff731fbf6..0844fe6a81 100644 --- a/packages/language-service/ivy/display_parts.ts +++ b/packages/language-service/ivy/display_parts.ts @@ -56,7 +56,9 @@ export function getDisplayInfo( const displayParts = createDisplayParts( symbol.declaration.name, kind, /* containerName */ undefined, typeChecker.typeToString(symbol.tsType)); - const documentation = getDocumentationFromTypeDefAtLocation(tsLS, symbol.shimLocation); + const documentation = symbol.kind === SymbolKind.Reference ? + getDocumentationFromTypeDefAtLocation(tsLS, symbol.targetLocation) : + getDocumentationFromTypeDefAtLocation(tsLS, symbol.initializerLocation); return { kind, displayParts, diff --git a/packages/language-service/ivy/quick_info.ts b/packages/language-service/ivy/quick_info.ts index 0079bc0e2f..32d99e65fd 100644 --- a/packages/language-service/ivy/quick_info.ts +++ b/packages/language-service/ivy/quick_info.ts @@ -80,14 +80,14 @@ export class QuickInfoBuilder { } private getQuickInfoForVariableSymbol(symbol: VariableSymbol): ts.QuickInfo { - const documentation = this.getDocumentationFromTypeDefAtLocation(symbol.shimLocation); + const documentation = this.getDocumentationFromTypeDefAtLocation(symbol.initializerLocation); return createQuickInfo( symbol.declaration.name, DisplayInfoKind.VARIABLE, getTextSpanOfNode(this.node), undefined /* containerName */, this.typeChecker.typeToString(symbol.tsType), documentation); } private getQuickInfoForReferenceSymbol(symbol: ReferenceSymbol): ts.QuickInfo { - const documentation = this.getDocumentationFromTypeDefAtLocation(symbol.shimLocation); + const documentation = this.getDocumentationFromTypeDefAtLocation(symbol.targetLocation); return createQuickInfo( symbol.declaration.name, DisplayInfoKind.REFERENCE, getTextSpanOfNode(this.node), undefined /* containerName */, this.typeChecker.typeToString(symbol.tsType), documentation); @@ -235,4 +235,4 @@ export function createQuickInfo( displayParts, documentation, }; -} \ No newline at end of file +}