fix(language-service): correctly type undefined
fixes #13412 closes #13414
This commit is contained in:
parent
9ec0a4e105
commit
3a64ad895a
|
@ -209,22 +209,25 @@ class AstType implements ExpressionVisitor {
|
||||||
|
|
||||||
visitBinary(ast: Binary): Symbol {
|
visitBinary(ast: Binary): Symbol {
|
||||||
// Treat undefined and null as other.
|
// Treat undefined and null as other.
|
||||||
function normalize(kind: BuiltinType): BuiltinType {
|
function normalize(kind: BuiltinType, other: BuiltinType): BuiltinType {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case BuiltinType.Undefined:
|
case BuiltinType.Undefined:
|
||||||
case BuiltinType.Null:
|
case BuiltinType.Null:
|
||||||
return BuiltinType.Other;
|
return normalize(other, BuiltinType.Other);
|
||||||
}
|
}
|
||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
const leftType = this.getType(ast.left);
|
const leftType = this.getType(ast.left);
|
||||||
const rightType = this.getType(ast.right);
|
const rightType = this.getType(ast.right);
|
||||||
const leftKind = normalize(this.query.getTypeKind(leftType));
|
const leftRawKind = this.query.getTypeKind(leftType);
|
||||||
const rightKind = normalize(this.query.getTypeKind(rightType));
|
const rightRawKind = this.query.getTypeKind(rightType);
|
||||||
|
const leftKind = normalize(leftRawKind, rightRawKind);
|
||||||
|
const rightKind = normalize(rightRawKind, leftRawKind);
|
||||||
|
|
||||||
// The following swtich implements operator typing similar to the
|
// The following swtich implements operator typing similar to the
|
||||||
// type production tables in the TypeScript specification.
|
// type production tables in the TypeScript specification.
|
||||||
|
// https://github.com/Microsoft/TypeScript/blob/v1.8.10/doc/spec.md#4.19
|
||||||
const operKind = leftKind << 8 | rightKind;
|
const operKind = leftKind << 8 | rightKind;
|
||||||
switch (ast.operation) {
|
switch (ast.operation) {
|
||||||
case '*':
|
case '*':
|
||||||
|
@ -411,6 +414,8 @@ class AstType implements ExpressionVisitor {
|
||||||
return this.query.getBuiltinType(BuiltinType.Boolean);
|
return this.query.getBuiltinType(BuiltinType.Boolean);
|
||||||
case null:
|
case null:
|
||||||
return this.query.getBuiltinType(BuiltinType.Null);
|
return this.query.getBuiltinType(BuiltinType.Null);
|
||||||
|
case undefined:
|
||||||
|
return this.query.getBuiltinType(BuiltinType.Undefined);
|
||||||
default:
|
default:
|
||||||
switch (typeof ast.value) {
|
switch (typeof ast.value) {
|
||||||
case 'string':
|
case 'string':
|
||||||
|
|
|
@ -141,6 +141,16 @@ describe('diagnostics', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// #13412
|
||||||
|
it('should not report an error for using undefined', () => {
|
||||||
|
const code =
|
||||||
|
` @Component({template: \`<div *ngIf="something === undefined"></div>\`}) export class MyComponent { something = 'foo'; }})`;
|
||||||
|
addCode(code, fileName => {
|
||||||
|
const diagnostics = ngService.getDiagnostics(fileName);
|
||||||
|
onlyModuleDiagnostics(diagnostics);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function addCode(code: string, cb: (fileName: string, content?: string) => void) {
|
function addCode(code: string, cb: (fileName: string, content?: string) => void) {
|
||||||
const fileName = '/app/app.component.ts';
|
const fileName = '/app/app.component.ts';
|
||||||
const originalContent = mockHost.getFileContent(fileName);
|
const originalContent = mockHost.getFileContent(fileName);
|
||||||
|
|
Loading…
Reference in New Issue