Skip to content

Commit

Permalink
fix(compiler-cli): create LiteralLikeNode for String and Number liter…
Browse files Browse the repository at this point in the history
…al (#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
  • Loading branch information
Keen Yee Liau authored and mhevery committed Dec 18, 2018
1 parent 17e702b commit 2c9b6c0
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
13 changes: 10 additions & 3 deletions packages/compiler-cli/src/diagnostics/typescript_symbols.ts
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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)', () => {
Expand Down
6 changes: 2 additions & 4 deletions packages/compiler-cli/test/ngc_spec.ts
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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);
}); });


Expand Down Expand Up @@ -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';
Expand Down
9 changes: 9 additions & 0 deletions packages/language-service/test/diagnostics_spec.ts
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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() { } }`;
Expand Down

0 comments on commit 2c9b6c0

Please sign in to comment.