diff --git a/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts b/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts index 4650929ff9b..4d8553fd52f 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/api/symbols.ts @@ -274,11 +274,6 @@ export interface LetDeclarationSymbol { * The location in the shim file for the identifier of the `@let` declaration. */ localVarLocation: TcbLocation; - - /** - * The location in the shim file of the `@let` declaration's initializer expression. - */ - initializerLocation: TcbLocation; } /** 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 4a4d96c83a2..c41cec20cab 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 @@ -646,9 +646,9 @@ export class SymbolBuilder { return { tsType: nodeValueSymbol.tsType, tsSymbol: nodeValueSymbol.tsSymbol, - initializerLocation: nodeValueSymbol.tcbLocation, kind: SymbolKind.Variable, declaration: variable, + initializerLocation: nodeValueSymbol.tcbLocation, localVarLocation: { tcbPath: this.tcbPath, isShimFile: this.tcbIsShim, @@ -727,7 +727,7 @@ export class SymbolBuilder { return null; } - const nodeValueSymbol = this.getSymbolOfTsNode(node.initializer!); + const nodeValueSymbol = this.getSymbolOfTsNode(node.name); if (nodeValueSymbol === null) { return null; @@ -736,7 +736,6 @@ export class SymbolBuilder { return { tsType: nodeValueSymbol.tsType, tsSymbol: nodeValueSymbol.tsSymbol, - initializerLocation: nodeValueSymbol.tcbLocation, kind: SymbolKind.LetDeclaration, declaration: decl, localVarLocation: { diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts index 98579e5c2f2..f6ad1a64533 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/type_checker__get_symbol_of_template_node_spec.ts @@ -201,12 +201,6 @@ runInEachFileSystem(() => { assertVariableSymbol(symbol); expect(program.getTypeChecker().typeToString(symbol.tsType!)).toEqual('any'); expect(symbol.declaration.name).toEqual('contextFoo'); - - // Ensure we can map the shim locations back to the template - const initializerMapping = templateTypeChecker.getSourceMappingAtTcbLocation( - symbol.initializerLocation, - )!; - expect(initializerMapping.span.toString()).toEqual('bar'); const localVarMapping = templateTypeChecker.getSourceMappingAtTcbLocation( symbol.localVarLocation, )!; @@ -2025,11 +2019,6 @@ runInEachFileSystem(() => { expect(program.getTypeChecker().typeToString(symbol.tsType!)).toEqual('string'); expect(symbol.declaration.name).toEqual('message'); - // Ensure we can map the shim locations back to the template - const initializerMapping = templateTypeChecker.getSourceMappingAtTcbLocation( - symbol.initializerLocation, - )!; - expect(initializerMapping.span.toString()).toEqual(`'The value is ' + value`); const localVarMapping = templateTypeChecker.getSourceMappingAtTcbLocation( symbol.localVarLocation, )!; diff --git a/packages/language-service/src/definitions.ts b/packages/language-service/src/definitions.ts index ebc4442329e..2d7fdbb2040 100644 --- a/packages/language-service/src/definitions.ts +++ b/packages/language-service/src/definitions.ts @@ -172,7 +172,7 @@ export class DefinitionBuilder { }); } } - if (symbol.kind === SymbolKind.Variable || symbol.kind === SymbolKind.LetDeclaration) { + if (symbol.kind === SymbolKind.Variable) { definitions.push( ...this.getDefinitionsForSymbols({tcbLocation: symbol.initializerLocation}), ); @@ -281,7 +281,7 @@ export class DefinitionBuilder { case SymbolKind.Variable: case SymbolKind.LetDeclaration: { definitions.push( - ...this.getTypeDefinitionsForSymbols({tcbLocation: symbol.initializerLocation}), + ...this.getTypeDefinitionsForSymbols({tcbLocation: symbol.localVarLocation}), ); break; } diff --git a/packages/language-service/src/quick_info.ts b/packages/language-service/src/quick_info.ts index 8a812c5e79b..f64cda8e322 100644 --- a/packages/language-service/src/quick_info.ts +++ b/packages/language-service/src/quick_info.ts @@ -148,21 +148,24 @@ export class QuickInfoBuilder { ); } - private getQuickInfoForVariableSymbol(symbol: VariableSymbol): ts.QuickInfo { - const info = this.getQuickInfoFromTypeDefAtLocation(symbol.initializerLocation); - return createQuickInfo( - symbol.declaration.name, - DisplayInfoKind.VARIABLE, - getTextSpanOfNode(this.node), - undefined /* containerName */, - this.typeChecker.typeToString(symbol.tsType), - info?.documentation, - info?.tags, - ); + private getQuickInfoForVariableSymbol(symbol: VariableSymbol): ts.QuickInfo | undefined { + const quickInfo = this.getQuickInfoAtTcbLocation(symbol.localVarLocation); + if (quickInfo === undefined || quickInfo.displayParts === undefined) { + return quickInfo; + } + + for (const part of quickInfo.displayParts) { + if (part.kind === 'localName') { + part.text = symbol.declaration.name; + break; + } + } + + return updateQuickInfoKind(quickInfo, DisplayInfoKind.VARIABLE); } private getQuickInfoForLetDeclarationSymbol(symbol: LetDeclarationSymbol): ts.QuickInfo { - const info = this.getQuickInfoFromTypeDefAtLocation(symbol.initializerLocation); + const info = this.getQuickInfoAtTcbLocation(symbol.localVarLocation); return createQuickInfo( symbol.declaration.name, DisplayInfoKind.LET, diff --git a/packages/language-service/src/utils/display_parts.ts b/packages/language-service/src/utils/display_parts.ts index c85698e1c80..1525505c996 100644 --- a/packages/language-service/src/utils/display_parts.ts +++ b/packages/language-service/src/utils/display_parts.ts @@ -80,7 +80,7 @@ export function getSymbolDisplayInfo( const quickInfo = symbol.kind === SymbolKind.Reference ? getQuickInfoFromTypeDefAtLocation(tsLS, symbol.targetLocation) - : getQuickInfoFromTypeDefAtLocation(tsLS, symbol.initializerLocation); + : getQuickInfoFromTypeDefAtLocation(tsLS, symbol.localVarLocation); return { kind, displayParts, diff --git a/packages/language-service/test/quick_info_spec.ts b/packages/language-service/test/quick_info_spec.ts index dd5ebb9cf45..37a109779d0 100644 --- a/packages/language-service/test/quick_info_spec.ts +++ b/packages/language-service/test/quick_info_spec.ts @@ -372,7 +372,7 @@ describe('quick info', () => { expectedSpanText: 'hero', expectedDisplayString: '(variable) hero: Hero', }); - expect(toText(documentation)).toEqual('The most heroic being.'); + expect(toText(documentation)).toEqual(''); }); it('should work for ReadonlyArray members (#36191)', () => { @@ -387,7 +387,7 @@ describe('quick info', () => { expectQuickInfo({ templateOverride: `
{{na¦me}}
`, expectedSpanText: 'name', - expectedDisplayString: '(variable) name: { readonly name: "name"; }', + expectedDisplayString: '(variable) name: {\n readonly name: "name";\n}', }); }); @@ -409,7 +409,7 @@ describe('quick info', () => { expectQuickInfo({ templateOverride: `
{{\`Hello \${na¦me}\`}}
`, expectedSpanText: 'name', - expectedDisplayString: '(variable) name: { readonly name: "name"; }', + expectedDisplayString: '(variable) name: {\n readonly name: "name";\n}', }); }); @@ -417,7 +417,7 @@ describe('quick info', () => { expectQuickInfo({ templateOverride: `
{{someTag\`Hello \${na¦me}\`}}
`, expectedSpanText: 'name', - expectedDisplayString: '(variable) name: { readonly name: "name"; }', + expectedDisplayString: '(variable) name: {\n readonly name: "name";\n}', }); }); }); @@ -846,7 +846,15 @@ describe('quick info', () => { expectQuickInfo({ templateOverride: `@if (constNames; as al¦iasName) {}`, expectedSpanText: 'aliasName', - expectedDisplayString: '(variable) aliasName: [{ readonly name: "name"; }]', + expectedDisplayString: '(variable) aliasName: [{\n readonly name: "name";\n}]', + }); + }); + + it('if block alias variable narrowed', () => { + expectQuickInfo({ + templateOverride: `@if (signalValue; as al¦iasName) {}`, + expectedSpanText: 'aliasName', + expectedDisplayString: '(variable) aliasName: string | undefined', }); }); @@ -862,7 +870,7 @@ describe('quick info', () => { expectQuickInfo({ templateOverride: `@if (false) {} @else if (constNames; as al¦iasName) {}`, expectedSpanText: 'aliasName', - expectedDisplayString: '(variable) aliasName: [{ readonly name: "name"; }]', + expectedDisplayString: '(variable) aliasName: [{\n readonly name: "name";\n}]', }); }); }); @@ -875,6 +883,14 @@ describe('quick info', () => { expectedDisplayString: `(let) name: "Frodo"`, }); }); + + it('should get quick info for a let declaration initialized with a narrowed property', () => { + expectQuickInfo({ + templateOverride: `@if (signalValue) { @let na¦me = signalValue; {{name}} }`, + expectedSpanText: `@let name = signalValue`, + expectedDisplayString: `(let) name: string`, + }); + }); }); it('should work for object literal with shorthand property declarations', () => {