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:
parent
17e702bf8b
commit
2c9b6c0c1f
|
@ -718,13 +718,20 @@ function getBuiltinTypeFromTs(kind: BuiltinType, context: TypeContext): ts.Type
|
||||||
checker.getTypeAtLocation(setParents(<ts.Node>{kind: ts.SyntaxKind.NullKeyword}, node));
|
checker.getTypeAtLocation(setParents(<ts.Node>{kind: ts.SyntaxKind.NullKeyword}, node));
|
||||||
break;
|
break;
|
||||||
case BuiltinType.Number:
|
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);
|
setParents(<any>{kind: ts.SyntaxKind.ExpressionStatement, expression: numeric}, node);
|
||||||
type = checker.getTypeAtLocation(numeric);
|
type = checker.getTypeAtLocation(numeric);
|
||||||
break;
|
break;
|
||||||
case BuiltinType.String:
|
case BuiltinType.String:
|
||||||
type = checker.getTypeAtLocation(
|
type = checker.getTypeAtLocation(setParents(
|
||||||
setParents(<ts.Node>{kind: ts.SyntaxKind.NoSubstitutionTemplateLiteral}, node));
|
<ts.LiteralLikeNode>{
|
||||||
|
kind: ts.SyntaxKind.NoSubstitutionTemplateLiteral,
|
||||||
|
text: node.getText(),
|
||||||
|
},
|
||||||
|
node));
|
||||||
break;
|
break;
|
||||||
case BuiltinType.Undefined:
|
case BuiltinType.Undefined:
|
||||||
type = checker.getTypeAtLocation(setParents(
|
type = checker.getTypeAtLocation(setParents(
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockData, M
|
||||||
import {ReflectorHost} from '@angular/language-service/src/reflector_host';
|
import {ReflectorHost} from '@angular/language-service/src/reflector_host';
|
||||||
import * as ts from 'typescript';
|
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 {getSymbolQuery, toSymbolTableFactory} from '../../src/diagnostics/typescript_symbols';
|
||||||
import {CompilerOptions} from '../../src/transformers/api';
|
import {CompilerOptions} from '../../src/transformers/api';
|
||||||
import {Directory} from '../mocks';
|
import {Directory} from '../mocks';
|
||||||
|
@ -55,6 +55,29 @@ describe('symbol query', () => {
|
||||||
const symbol = query.getTypeSymbol(unknownType);
|
const symbol = query.getTypeSymbol(unknownType);
|
||||||
expect(symbol).toBeUndefined();
|
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)', () => {
|
describe('toSymbolTableFactory(tsVersion)', () => {
|
||||||
|
|
|
@ -145,9 +145,7 @@ describe('ngc transformer command-line', () => {
|
||||||
|
|
||||||
const exitCode = main(['-p', basePath], errorSpy);
|
const exitCode = main(['-p', basePath], errorSpy);
|
||||||
expect(errorSpy).toHaveBeenCalledWith(
|
expect(errorSpy).toHaveBeenCalledWith(
|
||||||
`test.ts(1,9): error TS2305: Module '"` + path.join(basePath, 'empty-deps') +
|
`test.ts(1,9): error TS2305: Module '"./empty-deps"' has no exported member 'MyClass'.\n`);
|
||||||
`"' has no exported member 'MyClass'.` +
|
|
||||||
'\n');
|
|
||||||
expect(exitCode).toEqual(1);
|
expect(exitCode).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -874,7 +872,7 @@ describe('ngc transformer command-line', () => {
|
||||||
write('mymodule.ts', `
|
write('mymodule.ts', `
|
||||||
import {Component, NgModule} from '@angular/core';
|
import {Component, NgModule} from '@angular/core';
|
||||||
import {RouterModule} from '@angular/router';
|
import {RouterModule} from '@angular/router';
|
||||||
|
|
||||||
export function foo(): string {
|
export function foo(): string {
|
||||||
console.log('side-effect');
|
console.log('side-effect');
|
||||||
return 'test';
|
return 'test';
|
||||||
|
|
|
@ -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', () => {
|
it('should report a warning if an event results in a callable expression', () => {
|
||||||
const code =
|
const code =
|
||||||
` @Component({template: \`<div (click)="onClick"></div>\`}) export class MyComponent { onClick() { } }`;
|
` @Component({template: \`<div (click)="onClick"></div>\`}) export class MyComponent { onClick() { } }`;
|
||||||
|
|
Loading…
Reference in New Issue