Skip to content

Commit 52d04f9

Browse files
TheLartiansPerryvw
authored andcommitted
check origin for standard library types (#468)
* detect global console * added test * actually check if type is a DOM declaration * refactor helper methods * check standard library type origins * revert for constructors * check constructors again and assume lib for no valueDeclaration * make program protected
1 parent 7b9ecbb commit 52d04f9

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

src/LuaTransformer.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export class LuaTransformer {
4747

4848
private checker: ts.TypeChecker;
4949
protected options: CompilerOptions;
50+
protected program: ts.Program;
51+
5052
private isModule: boolean;
5153

5254
private currentSourceFile?: ts.SourceFile;
@@ -68,6 +70,7 @@ export class LuaTransformer {
6870
public constructor(program: ts.Program, options: CompilerOptions) {
6971
this.checker = program.getTypeChecker();
7072
this.options = options;
73+
this.program = program;
7174
this.isStrict = this.options.alwaysStrict || (this.options.strict && this.options.alwaysStrict !== false) ||
7275
(this.isModule && this.options.target && this.options.target >= ts.ScriptTarget.ES2015);
7376

@@ -3113,7 +3116,7 @@ export class LuaTransformer {
31133116
}
31143117

31153118
const expressionType = this.checker.getTypeAtLocation(node.expression);
3116-
if (expressionType.symbol && expressionType.symbol.escapedName === "SymbolConstructor") {
3119+
if (tsHelper.isStandardLibraryType(expressionType, "SymbolConstructor", this.program)) {
31173120
return this.transformLuaLibFunction(LuaLibFeature.Symbol, node, ...parameters);
31183121
}
31193122

@@ -3132,27 +3135,27 @@ export class LuaTransformer {
31323135
// If the function being called is of type owner.func, get the type of owner
31333136
const ownerType = this.checker.getTypeAtLocation(node.expression.expression);
31343137

3135-
if (ownerType.symbol && ownerType.symbol.escapedName === "Math") {
3138+
if (tsHelper.isStandardLibraryType(ownerType, "Math", this.program)) {
31363139
return this.transformMathCallExpression(node);
31373140
}
31383141

3139-
if (ownerType.symbol && ownerType.symbol.escapedName === "StringConstructor") {
3142+
if (tsHelper.isStandardLibraryType(ownerType, "Console", this.program)) {
3143+
return this.transformConsoleCallExpression(node);
3144+
}
3145+
3146+
if (tsHelper.isStandardLibraryType(ownerType, "StringConstructor", this.program)) {
31403147
return tstl.createCallExpression(
31413148
this.transformStringExpression(node.expression.name),
31423149
this.transformArguments(node.arguments),
31433150
node
31443151
);
31453152
}
31463153

3147-
if (ownerType.symbol && ownerType.symbol.escapedName === "ObjectConstructor") {
3154+
if (tsHelper.isStandardLibraryType(ownerType, "ObjectConstructor", this.program)) {
31483155
return this.transformObjectCallExpression(node);
31493156
}
31503157

3151-
if (ownerType.symbol && ownerType.symbol.escapedName === "Console") {
3152-
return this.transformConsoleCallExpression(node);
3153-
}
3154-
3155-
if (ownerType.symbol && ownerType.symbol.escapedName === "SymbolConstructor") {
3158+
if (tsHelper.isStandardLibraryType(ownerType, "SymbolConstructor", this.program)) {
31563159
return this.transformSymbolCallExpression(node);
31573160
}
31583161

@@ -3317,9 +3320,11 @@ export class LuaTransformer {
33173320

33183321
// Catch math expressions
33193322
if (ts.isIdentifier(node.expression)) {
3320-
if (node.expression.escapedText === "Math") {
3323+
const ownerType = this.checker.getTypeAtLocation(node.expression);
3324+
3325+
if (tsHelper.isStandardLibraryType(ownerType, "Math", this.program)) {
33213326
return this.transformMathExpression(node.name);
3322-
} else if (node.expression.escapedText === "Symbol") {
3327+
} else if (tsHelper.isStandardLibraryType(ownerType, "Symbol", this.program)) {
33233328
// Pull in Symbol lib
33243329
this.importLuaLibFeature(LuaLibFeature.Symbol);
33253330
}

src/TSHelper.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ export class TSHelper {
297297
return node.parent === undefined || ts.isExpressionStatement(node.parent) || ts.isForStatement(node.parent);
298298
}
299299

300-
public static isInGlobalScope(node: ts.FunctionDeclaration): boolean {
300+
public static isInGlobalScope(node: ts.Node): boolean {
301301
let parent = node.parent;
302302
while (parent !== undefined) {
303303
if (ts.isBlock(parent)) {
@@ -687,6 +687,20 @@ export class TSHelper {
687687
return firstDeclaration === node;
688688
}
689689

690+
public static isStandardLibraryDeclaration(declaration: ts.Declaration, program: ts.Program): boolean {
691+
const source = declaration.getSourceFile();
692+
if (!source) { return false; }
693+
return program.isSourceFileDefaultLibrary(source);
694+
}
695+
696+
public static isStandardLibraryType(type: ts.Type, name: string, program: ts.Program): boolean {
697+
const symbol = type.symbol;
698+
if (!symbol || symbol.escapedName !== name) { return false; }
699+
const declaration = symbol.valueDeclaration;
700+
if(!declaration) { return true; } // assume to be lib function if no valueDeclaration exists
701+
return this.isStandardLibraryDeclaration(declaration, program);
702+
}
703+
690704
public static isEnumMember(enumDeclaration: ts.EnumDeclaration, value: ts.Expression): [boolean, ts.PropertyName] {
691705
if (ts.isIdentifier(value)) {
692706
const enumMember = enumDeclaration.members.find(m => ts.isIdentifier(m.name) && m.name.text === value.text);

test/unit/console.spec.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Expect, Test, TestCase, IgnoreTest, FocusTest } from "alsatian";
1+
import { Expect, Test, TestCase } from "alsatian";
22
import * as util from "../src/util";
33

44
export class ConsoleTests {
@@ -45,4 +45,23 @@ export class ConsoleTests {
4545
Expect(lua).toBe(expected);
4646
}
4747

48+
@Test("console.differentiation")
49+
public testConsoleDifferentiation(): void {
50+
// Transpile
51+
const result = util.transpileExecuteAndReturnExport(`
52+
export class Console {
53+
test() { return 42; }
54+
}
55+
56+
function test() {
57+
const console = new Console();
58+
return console.test();
59+
}
60+
61+
export const result = test();
62+
`, "result");
63+
Expect(result).toBe(42);
64+
}
65+
66+
4867
}

0 commit comments

Comments
 (0)