fix(compiler-cli): Refactor getTsTypeFromBuiltinType (#33778)

This commit fixes a few issues with helper method
`getBuiltInTypeFromTsType`.

1. The function is wrongly named. It should be the other way round.
2. The ts.Type returned by the function should not contain any value.
This is because for some data types like Number and String, the
SourceFile (context.node) is not the correct value. Value is never
needed for program correctness in this case.

PR Close #33778
This commit is contained in:
Keen Yee Liau 2019-11-11 16:16:56 -08:00 committed by Alex Rickabaugh
parent 1d3aae6f92
commit cbb1d9f2bb
2 changed files with 24 additions and 49 deletions

View File

@ -94,8 +94,11 @@ class TypeScriptSymbolQuery implements SymbolQuery {
getBuiltinType(kind: BuiltinType): Symbol {
let result = this.typeCache.get(kind);
if (!result) {
const type = getBuiltinTypeFromTs(
kind, {checker: this.checker, node: this.source, program: this.program});
const type = getTsTypeFromBuiltinType(kind, {
checker: this.checker,
node: this.source,
program: this.program,
});
result =
new TypeWrapper(type, {program: this.program, checker: this.checker, node: this.source});
this.typeCache.set(kind, result);
@ -553,7 +556,7 @@ class PipeSymbol implements Symbol {
resultType = getTypeParameterOf(parameterType.tsType, parameterType.name);
break;
default:
resultType = getBuiltinTypeFromTs(BuiltinType.Any, this.context);
resultType = getTsTypeFromBuiltinType(BuiltinType.Any, this.context);
break;
}
break;
@ -580,7 +583,7 @@ class PipeSymbol implements Symbol {
type = this._tsType = this.findTransformMethodType(classSymbol) !;
}
if (!type) {
type = this._tsType = getBuiltinTypeFromTs(BuiltinType.Any, this.context);
type = this._tsType = getTsTypeFromBuiltinType(BuiltinType.Any, this.context);
}
}
return type;
@ -633,62 +636,34 @@ function isSymbolPrivate(s: ts.Symbol): boolean {
return !!s.valueDeclaration && isPrivate(s.valueDeclaration);
}
function getBuiltinTypeFromTs(kind: BuiltinType, context: TypeContext): ts.Type {
let type: ts.Type;
const checker = context.checker;
const node = context.node;
switch (kind) {
function getTsTypeFromBuiltinType(builtinType: BuiltinType, ctx: TypeContext): ts.Type {
let syntaxKind: ts.SyntaxKind;
switch (builtinType) {
case BuiltinType.Any:
type = checker.getTypeAtLocation(setParents(
<ts.Node><any>{
kind: ts.SyntaxKind.AsExpression,
expression: <ts.Node>{kind: ts.SyntaxKind.TrueKeyword},
type: <ts.Node>{kind: ts.SyntaxKind.AnyKeyword}
},
node));
syntaxKind = ts.SyntaxKind.AnyKeyword;
break;
case BuiltinType.Boolean:
type =
checker.getTypeAtLocation(setParents(<ts.Node>{kind: ts.SyntaxKind.TrueKeyword}, node));
syntaxKind = ts.SyntaxKind.BooleanKeyword;
break;
case BuiltinType.Null:
type =
checker.getTypeAtLocation(setParents(<ts.Node>{kind: ts.SyntaxKind.NullKeyword}, node));
syntaxKind = ts.SyntaxKind.NullKeyword;
break;
case BuiltinType.Number:
const numeric = <ts.LiteralLikeNode>{
kind: ts.SyntaxKind.NumericLiteral,
text: node.getText(),
};
setParents(<any>{kind: ts.SyntaxKind.ExpressionStatement, expression: numeric}, node);
type = checker.getTypeAtLocation(numeric);
syntaxKind = ts.SyntaxKind.NumberKeyword;
break;
case BuiltinType.String:
type = checker.getTypeAtLocation(setParents(
<ts.LiteralLikeNode>{
kind: ts.SyntaxKind.NoSubstitutionTemplateLiteral,
text: node.getText(),
},
node));
syntaxKind = ts.SyntaxKind.StringKeyword;
break;
case BuiltinType.Undefined:
type = checker.getTypeAtLocation(setParents(
<ts.Node><any>{
kind: ts.SyntaxKind.VoidExpression,
expression: <ts.Node>{kind: ts.SyntaxKind.NumericLiteral}
},
node));
syntaxKind = ts.SyntaxKind.UndefinedKeyword;
break;
default:
throw new Error(`Internal error, unhandled literal kind ${kind}:${BuiltinType[kind]}`);
throw new Error(
`Internal error, unhandled literal kind ${builtinType}:${BuiltinType[builtinType]}`);
}
return type;
}
function setParents<T extends ts.Node>(node: T, parent: ts.Node): T {
node.parent = parent;
ts.forEachChild(node, child => setParents(child, node));
return node;
const node = ts.createNode(syntaxKind);
node.parent = ctx.node;
return ctx.checker.getTypeAtLocation(node);
}
function spanAt(sourceFile: ts.SourceFile, line: number, column: number): Span|undefined {

View File

@ -53,10 +53,10 @@ describe('symbol query', () => {
const tests: Array<[BuiltinType, boolean, ts.TypeFlags?]> = [
// builtinType, throws, want
[BuiltinType.Any, false, ts.TypeFlags.Any],
[BuiltinType.Boolean, false, ts.TypeFlags.BooleanLiteral],
[BuiltinType.Boolean, false, ts.TypeFlags.Boolean | ts.TypeFlags.Union],
[BuiltinType.Null, false, ts.TypeFlags.Null],
[BuiltinType.Number, false, ts.TypeFlags.NumberLiteral],
[BuiltinType.String, false, ts.TypeFlags.StringLiteral],
[BuiltinType.Number, false, ts.TypeFlags.Number],
[BuiltinType.String, false, ts.TypeFlags.String],
[BuiltinType.Undefined, false, ts.TypeFlags.Undefined],
[BuiltinType.Unbound, true],
[BuiltinType.Other, true],