Skip to content

Commit 0284f91

Browse files
ark120202Perryvw
authored andcommitted
Assume files with imports to be modules (#776)
1 parent 10ff5f7 commit 0284f91

File tree

7 files changed

+63
-98
lines changed

7 files changed

+63
-98
lines changed

src/transformation/context/context.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as ts from "typescript";
22
import { CompilerOptions, LuaTarget } from "../../CompilerOptions";
33
import * as lua from "../../LuaAST";
44
import { unwrapVisitorResult } from "../utils/lua-ast";
5-
import { isFileModule } from "../utils/typescript";
65
import { ExpressionLikeNode, ObjectVisitor, StatementLikeNode, VisitorMap } from "./visitors";
76

87
export interface EmitResolver {
@@ -23,7 +22,7 @@ export class TransformationContext {
2322

2423
public readonly options: CompilerOptions = this.program.getCompilerOptions();
2524
public readonly luaTarget = this.options.luaTarget ?? LuaTarget.LuaJIT;
26-
public readonly isModule = isFileModule(this.sourceFile);
25+
public readonly isModule = ts.isExternalModule(this.sourceFile);
2726
public readonly isStrict =
2827
(this.options.alwaysStrict ?? this.options.strict) ||
2928
(this.isModule && this.options.target !== undefined && this.options.target >= ts.ScriptTarget.ES2015);

src/transformation/utils/export.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { TransformationContext } from "../context";
44
import { createModuleLocalNameIdentifier } from "../visitors/namespace";
55
import { createExportsIdentifier } from "./lua-ast";
66
import { getSymbolInfo } from "./symbols";
7-
import { findFirstNodeAbove, isFileModule } from "./typescript";
7+
import { findFirstNodeAbove } from "./typescript";
88

99
export function hasDefaultExportModifier(node: ts.Node): boolean {
1010
return (node.modifiers ?? []).some(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword);
@@ -75,17 +75,8 @@ export function getExportedSymbolsFromScope(
7575
context: TransformationContext,
7676
scope: ts.SourceFile | ts.ModuleDeclaration
7777
): ts.Symbol[] {
78-
if (ts.isSourceFile(scope) && !isFileModule(scope)) {
79-
return [];
80-
}
81-
82-
let scopeSymbol = context.checker.getSymbolAtLocation(scope);
83-
if (scopeSymbol === undefined) {
84-
// TODO: Necessary?
85-
scopeSymbol = context.checker.getTypeAtLocation(scope).getSymbol();
86-
}
87-
88-
if (scopeSymbol === undefined || scopeSymbol.exports === undefined) {
78+
const scopeSymbol = context.checker.getSymbolAtLocation(ts.isSourceFile(scope) ? scope : scope.name);
79+
if (scopeSymbol?.exports === undefined) {
8980
return [];
9081
}
9182

src/transformation/utils/typescript/index.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,11 @@
11
import * as ts from "typescript";
22
import { TransformationContext } from "../../context";
3-
import { isDeclaration } from "./nodes";
43

54
export * from "./nodes";
65
export * from "./types";
76

87
// TODO: Move to separate files?
98

10-
export function isFileModule(sourceFile: ts.SourceFile): boolean {
11-
return sourceFile.statements.some(isStatementExported);
12-
}
13-
14-
function isStatementExported(statement: ts.Statement): boolean {
15-
if (ts.isExportAssignment(statement) || ts.isExportDeclaration(statement)) {
16-
return true;
17-
}
18-
if (ts.isVariableStatement(statement)) {
19-
return statement.declarationList.declarations.some(
20-
declaration => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0
21-
);
22-
}
23-
return isDeclaration(statement) && (ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export) !== 0;
24-
}
25-
269
export function hasExportEquals(sourceFile: ts.SourceFile): boolean {
2710
return sourceFile.statements.some(node => ts.isExportAssignment(node) && node.isExportEquals);
2811
}

src/transformation/utils/typescript/nodes.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,6 @@ export function isAmbientNode(node: ts.Declaration): boolean {
1616
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Ambient) !== 0;
1717
}
1818

19-
export function isDeclaration(node: ts.Node): node is ts.Declaration {
20-
return (
21-
ts.isEnumDeclaration(node) ||
22-
ts.isClassDeclaration(node) ||
23-
ts.isExportDeclaration(node) ||
24-
ts.isImportDeclaration(node) ||
25-
ts.isMethodDeclaration(node) ||
26-
ts.isModuleDeclaration(node) ||
27-
ts.isFunctionDeclaration(node) ||
28-
ts.isVariableDeclaration(node) ||
29-
ts.isInterfaceDeclaration(node) ||
30-
ts.isTypeAliasDeclaration(node) ||
31-
ts.isNamespaceExportDeclaration(node)
32-
);
33-
}
34-
3519
export function isInDestructingAssignment(node: ts.Node): boolean {
3620
return (
3721
node.parent &&

test/translation/__snapshots__/transformation.spec.ts.snap

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,23 @@ end"
126126
`;
127127

128128
exports[`Transformation (modulesImportAll) 1`] = `
129-
"local Test = require(\\"test\\")
130-
local ____ = Test"
129+
"local ____exports = {}
130+
local Test = require(\\"test\\")
131+
local ____ = Test
132+
return ____exports"
131133
`;
132134

133135
exports[`Transformation (modulesImportNamed) 1`] = `
134-
"local ____test = require(\\"test\\")
136+
"local ____exports = {}
137+
local ____test = require(\\"test\\")
135138
local TestClass = ____test.TestClass
136-
local ____ = TestClass"
139+
local ____ = TestClass
140+
return ____exports"
137141
`;
138142

139143
exports[`Transformation (modulesImportNamedSpecialChars) 1`] = `
140-
"local ____kebab_2Dmodule = require(\\"kebab-module\\")
144+
"local ____exports = {}
145+
local ____kebab_2Dmodule = require(\\"kebab-module\\")
141146
local TestClass1 = ____kebab_2Dmodule.TestClass1
142147
local ____dollar_24module = require(\\"dollar$module\\")
143148
local TestClass2 = ____dollar_24module.TestClass2
@@ -151,17 +156,21 @@ local ____ = TestClass1
151156
local ____ = TestClass2
152157
local ____ = TestClass3
153158
local ____ = TestClass4
154-
local ____ = TestClass5"
159+
local ____ = TestClass5
160+
return ____exports"
155161
`;
156162

157163
exports[`Transformation (modulesImportRenamed) 1`] = `
158-
"local ____test = require(\\"test\\")
164+
"local ____exports = {}
165+
local ____test = require(\\"test\\")
159166
local RenamedClass = ____test.TestClass
160-
local ____ = RenamedClass"
167+
local ____ = RenamedClass
168+
return ____exports"
161169
`;
162170

163171
exports[`Transformation (modulesImportRenamedSpecialChars) 1`] = `
164-
"local ____kebab_2Dmodule = require(\\"kebab-module\\")
172+
"local ____exports = {}
173+
local ____kebab_2Dmodule = require(\\"kebab-module\\")
165174
local RenamedClass1 = ____kebab_2Dmodule.TestClass
166175
local ____dollar_24module = require(\\"dollar$module\\")
167176
local RenamedClass2 = ____dollar_24module.TestClass
@@ -175,10 +184,15 @@ local ____ = RenamedClass1
175184
local ____ = RenamedClass2
176185
local ____ = RenamedClass3
177186
local ____ = RenamedClass4
178-
local ____ = RenamedClass5"
187+
local ____ = RenamedClass5
188+
return ____exports"
179189
`;
180190

181-
exports[`Transformation (modulesImportWithoutFromClause) 1`] = `"require(\\"test\\")"`;
191+
exports[`Transformation (modulesImportWithoutFromClause) 1`] = `
192+
"local ____exports = {}
193+
require(\\"test\\")
194+
return ____exports"
195+
`;
182196

183197
exports[`Transformation (modulesNamespaceExport) 1`] = `
184198
"local ____exports = {}
@@ -244,6 +258,8 @@ end"
244258
`;
245259

246260
exports[`Transformation (unusedDefaultWithNamespaceImport) 1`] = `
247-
"local x = require(\\"module\\")
248-
local ____ = x"
261+
"local ____exports = {}
262+
local x = require(\\"module\\")
263+
local ____ = x
264+
return ____exports"
249265
`;

test/transpile/__snapshots__/project.spec.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ return ____exports
1515
Object {
1616
"name": "index.lua",
1717
"text": "--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
18+
local ____exports = {}
1819
local ____otherFile = require(\\"otherFile\\")
1920
local getNumber = ____otherFile.getNumber
2021
local myNumber = getNumber(nil)
2122
SetAPIValue(myNumber * 5)
23+
return ____exports
2224
",
2325
},
2426
]

test/unit/hoisting.spec.ts

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -243,55 +243,45 @@ test.each([
243243
});
244244

245245
test("Import hoisting (named)", () => {
246-
const importCode = `
247-
const bar = foo;
248-
import {foo} from "myMod";`;
249-
const luaHeader = `
250-
package.loaded["myMod"] = {foo = "foobar"}
251-
${util.transpileString(importCode)}`;
252-
const tsHeader = "declare const bar: any;";
253-
const code = "return bar;";
254-
expect(util.transpileAndExecute(code, undefined, luaHeader, tsHeader)).toBe("foobar");
246+
util.testBundle`
247+
export const result = foo;
248+
import { foo } from "./module";
249+
`
250+
.addExtraFile("module.ts", "export const foo = true;")
251+
.expectToEqual({ result: true });
255252
});
256253

257254
test("Import hoisting (namespace)", () => {
258-
const importCode = `
259-
const bar = myMod.foo;
260-
import * as myMod from "myMod";`;
261-
const luaHeader = `
262-
package.loaded["myMod"] = {foo = "foobar"}
263-
${util.transpileString(importCode)}`;
264-
const tsHeader = "declare const bar: any;";
265-
const code = "return bar;";
266-
expect(util.transpileAndExecute(code, undefined, luaHeader, tsHeader)).toBe("foobar");
255+
util.testBundle`
256+
export const result = module.foo;
257+
import * as module from "./module";
258+
`
259+
.addExtraFile("module.ts", "export const foo = true;")
260+
.expectToEqual({ result: true });
267261
});
268262

269263
test("Import hoisting (side-effect)", () => {
270-
const importCode = `
271-
const bar = foo;
272-
import "myMod";`;
273-
const luaHeader = `
274-
package.loaded["myMod"] = {_ = (function() foo = "foobar" end)()}
275-
${util.transpileString(importCode)}`;
276-
const tsHeader = "declare const bar: any;";
277-
const code = "return bar;";
278-
expect(util.transpileAndExecute(code, undefined, luaHeader, tsHeader)).toBe("foobar");
264+
util.testBundle`
265+
export const result = (globalThis as any).result;
266+
import "./module";
267+
`
268+
.addExtraFile("module.ts", "(globalThis as any).result = true; export {};")
269+
.expectToEqual({ result: true });
279270
});
280271

281272
test("Import hoisted before function", () => {
282-
const importCode = `
283-
let bar: any;
284-
import {foo} from "myMod";
273+
util.testBundle`
274+
export let result: any;
275+
285276
baz();
286277
function baz() {
287-
bar = foo;
288-
}`;
289-
const luaHeader = `
290-
package.loaded["myMod"] = {foo = "foobar"}
291-
${util.transpileString(importCode)}`;
292-
const tsHeader = "declare const bar: any;";
293-
const code = "return bar;";
294-
expect(util.transpileAndExecute(code, undefined, luaHeader, tsHeader)).toBe("foobar");
278+
result = foo;
279+
}
280+
281+
import { foo } from "./module";
282+
`
283+
.addExtraFile("module.ts", "export const foo = true;")
284+
.expectToEqual({ result: true });
295285
});
296286

297287
test("Hoisting Shorthand Property", () => {

0 commit comments

Comments
 (0)