From 2ebaa51514f327d7d79ca54c4ba30d121fdd029e Mon Sep 17 00:00:00 2001 From: ivanwonder Date: Mon, 2 Dec 2019 15:22:07 +0800 Subject: [PATCH] fix(language-service): bug of accessing a string index signature using dot notation (#34177) PR Close #34177 --- packages/language-service/src/typescript_symbols.ts | 13 +++++++++---- packages/language-service/test/diagnostics_spec.ts | 8 ++++++++ .../test/project/app/parsing-cases.ts | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/language-service/src/typescript_symbols.ts b/packages/language-service/src/typescript_symbols.ts index 7928cfcf78..52c1d74201 100644 --- a/packages/language-service/src/typescript_symbols.ts +++ b/packages/language-service/src/typescript_symbols.ts @@ -308,6 +308,10 @@ class TypeWrapper implements Symbol { } } +class StringIndexTypeWrappr extends TypeWrapper { + public readonly type = new TypeWrapper(this.tsType, this.context); +} + class SymbolWrapper implements Symbol { private symbol: ts.Symbol; private _members?: SymbolTable; @@ -506,10 +510,11 @@ class SymbolTableWrapper implements SymbolTable { // obj.stringIndex // equivalent to obj['stringIndex']; // // In this case, return the type indexed by an arbitrary string key. - const symbol = this.stringIndexType.getSymbol(); - if (symbol) { - return new SymbolWrapper(symbol, this.context, this.stringIndexType); - } + + // if stringIndexType is js primitive type(e.g. 'string'), the Symbol is undefined; + // and In AstType.resolvePropertyRead method, the Symbol.type should get the right type. + // so I add a new Symbol type, 'StringIndexTypeWrappr' + return new StringIndexTypeWrappr(this.stringIndexType, this.context); } return undefined; diff --git a/packages/language-service/test/diagnostics_spec.ts b/packages/language-service/test/diagnostics_spec.ts index 283c6345de..0f84ab7e36 100644 --- a/packages/language-service/test/diagnostics_spec.ts +++ b/packages/language-service/test/diagnostics_spec.ts @@ -172,6 +172,14 @@ describe('diagnostics', () => { expect(diags[0].messageText) .toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`); }); + + it('should not produce errors with dot notation if stringIndexType is js primitive type', + () => { + mockHost.override(TEST_TEMPLATE, ` + {{primitiveType.test}}`); + const diags = ngLS.getDiagnostics(TEST_TEMPLATE); + expect(diags.length).toBe(0); + }); }); }); diff --git a/packages/language-service/test/project/app/parsing-cases.ts b/packages/language-service/test/project/app/parsing-cases.ts index 6050caa0b1..35db9e8269 100644 --- a/packages/language-service/test/project/app/parsing-cases.ts +++ b/packages/language-service/test/project/app/parsing-cases.ts @@ -192,6 +192,7 @@ export class TemplateReference { tupleArray: [string, Hero] = ['test', this.hero]; league: Hero[][] = [this.heroes]; heroesByName: {[name: string]: Hero} = {}; + primitiveType: {[name: string]: string} = {}; anyValue: any; myClick(event: any) {} }