fix(compiler-cli): create LiteralLikeNode for String and Number literal (#27536)

Typescript 3.2 introduced BigInt type, and consequently the
implementation for checkExpressionWorker() in checkers.ts is refactored.

For NumberLiteral and StringLiteral types, 'text' filed must be present
in the Node type, therefore they must be LiteralLikeNode instead of
Node.

PR Close #27536
This commit is contained in:
Keen Yee Liau 2018-12-14 13:40:01 -08:00 committed by Miško Hevery
parent 17e702bf8b
commit 2c9b6c0c1f
4 changed files with 45 additions and 8 deletions

View File

@ -718,13 +718,20 @@ function getBuiltinTypeFromTs(kind: BuiltinType, context: TypeContext): ts.Type
checker.getTypeAtLocation(setParents(<ts.Node>{kind: ts.SyntaxKind.NullKeyword}, node));
break;
case BuiltinType.Number:
const numeric = <ts.Node>{kind: ts.SyntaxKind.NumericLiteral};
const numeric = <ts.LiteralLikeNode>{
kind: ts.SyntaxKind.NumericLiteral,
text: node.getText(),
};
setParents(<any>{kind: ts.SyntaxKind.ExpressionStatement, expression: numeric}, node);
type = checker.getTypeAtLocation(numeric);
break;
case BuiltinType.String:
type = checker.getTypeAtLocation(
setParents(<ts.Node>{kind: ts.SyntaxKind.NoSubstitutionTemplateLiteral}, node));
type = checker.getTypeAtLocation(setParents(
<ts.LiteralLikeNode>{
kind: ts.SyntaxKind.NoSubstitutionTemplateLiteral,
text: node.getText(),
},
node));
break;
case BuiltinType.Undefined:
type = checker.getTypeAtLocation(setParents(

View File

@ -12,7 +12,7 @@ import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockData, M
import {ReflectorHost} from '@angular/language-service/src/reflector_host';
import * as ts from 'typescript';
import {Symbol, SymbolQuery, SymbolTable} from '../../src/diagnostics/symbols';
import {BuiltinType, Symbol, SymbolQuery, SymbolTable} from '../../src/diagnostics/symbols';
import {getSymbolQuery, toSymbolTableFactory} from '../../src/diagnostics/typescript_symbols';
import {CompilerOptions} from '../../src/transformers/api';
import {Directory} from '../mocks';
@ -55,6 +55,29 @@ describe('symbol query', () => {
const symbol = query.getTypeSymbol(unknownType);
expect(symbol).toBeUndefined();
});
it('should return correct built-in types', () => {
const tests: Array<[BuiltinType, boolean, ts.TypeFlags?]> = [
// builtinType, throws, want
[BuiltinType.Any, false, ts.TypeFlags.Any],
[BuiltinType.Boolean, false, ts.TypeFlags.BooleanLiteral],
[BuiltinType.Null, false, ts.TypeFlags.Null],
[BuiltinType.Number, false, ts.TypeFlags.NumberLiteral],
[BuiltinType.String, false, ts.TypeFlags.StringLiteral],
[BuiltinType.Undefined, false, ts.TypeFlags.Undefined],
[BuiltinType.Unbound, true],
[BuiltinType.Other, true],
];
for (const [builtinType, throws, want] of tests) {
if (throws) {
expect(() => query.getBuiltinType(builtinType)).toThrow();
} else {
const symbol = query.getBuiltinType(builtinType);
const got: ts.TypeFlags = (symbol as any).tsType.flags;
expect(got).toBe(want !);
}
}
});
});
describe('toSymbolTableFactory(tsVersion)', () => {

View File

@ -145,9 +145,7 @@ describe('ngc transformer command-line', () => {
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).toHaveBeenCalledWith(
`test.ts(1,9): error TS2305: Module '"` + path.join(basePath, 'empty-deps') +
`"' has no exported member 'MyClass'.` +
'\n');
`test.ts(1,9): error TS2305: Module '"./empty-deps"' has no exported member 'MyClass'.\n`);
expect(exitCode).toEqual(1);
});
@ -874,7 +872,7 @@ describe('ngc transformer command-line', () => {
write('mymodule.ts', `
import {Component, NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
export function foo(): string {
console.log('side-effect');
return 'test';

View File

@ -149,6 +149,15 @@ describe('diagnostics', () => {
});
});
it('should not report an error for sub-types of number', () => {
const code =
` @Component({template: \`<div *ngIf="something === 123"></div>\`}) export class MyComponent { something: 123 | 456; }`;
addCode(code, fileName => {
const diagnostics = ngService.getDiagnostics(fileName);
expectOnlyModuleDiagnostics(diagnostics);
});
});
it('should report a warning if an event results in a callable expression', () => {
const code =
` @Component({template: \`<div (click)="onClick"></div>\`}) export class MyComponent { onClick() { } }`;