Skip to content

Commit 0499cf9

Browse files
ark120202Perryvw
authored andcommitted
Support JSON source files (#411)
* Support JSON source files * Add temporary workaround for .json module resolving * Rename mainFileName option to avoid conflicts with other pull request
1 parent 6ad63ec commit 0499cf9

File tree

5 files changed

+69
-26
lines changed

5 files changed

+69
-26
lines changed

src/Compiler.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ const defaultCompilerOptions: CompilerOptions = {
8989
};
9090

9191
export function createStringCompilerProgram(
92-
input: string, options: CompilerOptions = defaultCompilerOptions): ts.Program {
93-
92+
input: string, options: CompilerOptions = defaultCompilerOptions, filePath = "file.ts"): ts.Program {
9493
const compilerHost = {
9594
directoryExists: () => true,
9695
fileExists: (fileName): boolean => true,
@@ -100,8 +99,8 @@ export function createStringCompilerProgram(
10099
getDirectories: () => [],
101100
getNewLine: () => "\n",
102101

103-
getSourceFile: (filename: string, languageVersion) => {
104-
if (filename === "file.ts") {
102+
getSourceFile: (filename: string) => {
103+
if (filename === filePath) {
105104
return ts.createSourceFile(filename, input, ts.ScriptTarget.Latest, false);
106105
}
107106
if (filename.indexOf(".d.ts") !== -1) {
@@ -126,15 +125,16 @@ export function createStringCompilerProgram(
126125
// Don't write output
127126
writeFile: (name, text, writeByteOrderMark) => undefined,
128127
};
129-
return ts.createProgram(["file.ts"], options, compilerHost);
128+
return ts.createProgram([filePath], options, compilerHost);
130129
}
131130

132131
export function transpileString(
133132
str: string,
134133
options: CompilerOptions = defaultCompilerOptions,
135-
ignoreDiagnostics = false
134+
ignoreDiagnostics = false,
135+
filePath = "file.ts"
136136
): string {
137-
const program = createStringCompilerProgram(str, options);
137+
const program = createStringCompilerProgram(str, options, filePath);
138138

139139
if (!ignoreDiagnostics) {
140140
const diagnostics = ts.getPreEmitDiagnostics(program);
@@ -148,7 +148,7 @@ export function transpileString(
148148

149149
const transpiler = new LuaTranspiler(program);
150150

151-
const result = transpiler.transpileSourceFile(program.getSourceFile("file.ts"));
151+
const result = transpiler.transpileSourceFile(program.getSourceFile(filePath));
152152

153153
return result.trim();
154154
}

src/LuaTransformer.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,27 +93,41 @@ export class LuaTransformer {
9393
// TODO make all other methods private???
9494
public transformSourceFile(node: ts.SourceFile): [tstl.Block, Set<LuaLibFeature>] {
9595
this.setupState();
96-
this.pushScope(ScopeType.File, node);
9796

9897
this.currentSourceFile = node;
99-
this.isModule = tsHelper.isFileModule(node);
10098

101-
const statements = this.performHoisting(this.transformStatements(node.statements));
102-
this.popScope();
99+
let statements: tstl.Statement[] = [];
100+
if (node.flags & ts.NodeFlags.JsonFile) {
101+
this.isModule = false;
103102

104-
if (this.isModule) {
105-
statements.unshift(
106-
tstl.createVariableDeclarationStatement(
107-
tstl.createIdentifier("exports"),
108-
tstl.createBinaryExpression(
103+
const statement = node.statements[0];
104+
if (!statement || !ts.isExpressionStatement(statement)) {
105+
throw TSTLErrors.InvalidJsonFileContent(node);
106+
}
107+
108+
statements.push(tstl.createReturnStatement([this.transformExpression(statement.expression)]));
109+
} else {
110+
this.pushScope(ScopeType.File, node);
111+
112+
this.isModule = tsHelper.isFileModule(node);
113+
statements = this.performHoisting(this.transformStatements(node.statements));
114+
115+
this.popScope();
116+
117+
if (this.isModule) {
118+
statements.unshift(
119+
tstl.createVariableDeclarationStatement(
109120
tstl.createIdentifier("exports"),
110-
tstl.createTableExpression(),
111-
tstl.SyntaxKind.OrOperator
112-
)));
113-
statements.push(
114-
tstl.createReturnStatement(
115-
[tstl.createIdentifier("exports")]
116-
));
121+
tstl.createBinaryExpression(
122+
tstl.createIdentifier("exports"),
123+
tstl.createTableExpression(),
124+
tstl.SyntaxKind.OrOperator
125+
)));
126+
statements.push(
127+
tstl.createReturnStatement(
128+
[tstl.createIdentifier("exports")]
129+
));
130+
}
117131
}
118132

119133
return [tstl.createBlock(statements, node), this.luaLibFeatureSet];
@@ -3675,7 +3689,7 @@ export class LuaTransformer {
36753689
}
36763690

36773691
private pathToLuaRequirePath(filePath: string): string {
3678-
return filePath.replace(new RegExp("\\\\|\/", "g"), ".");
3692+
return filePath.replace(new RegExp("\\\\|\/", "g"), ".").replace(/\.json$/, '');
36793693
}
36803694

36813695
private shouldExportIdentifier(identifier: tstl.Identifier | tstl.Identifier[]): boolean {

src/TSTLErrors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,6 @@ export class TSTLErrors {
141141
node
142142
);
143143
}
144+
145+
public static InvalidJsonFileContent = (node: ts.Node) => new TranspileError("Invalid JSON file content", node);
144146
}

test/src/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function transpileString(str: string, options?: CompilerOptions, ignoreDi
3131
}
3232
}
3333

34-
function executeLua(luaStr: string, withLib = true): any {
34+
export function executeLua(luaStr: string, withLib = true): any {
3535
if (withLib) {
3636
luaStr = minimalTestLib + luaStr;
3737
}

test/unit/json.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Expect, Test, TestCase } from "alsatian";
2+
import { transpileString } from "../../src/Compiler";
3+
import { TranspileError } from "../../src/TranspileError";
4+
import * as util from "../src/util";
5+
6+
export class JsonTests {
7+
@Test("JSON")
8+
@TestCase("0")
9+
@TestCase('""')
10+
@TestCase("[]")
11+
@TestCase('[1, "2", []]')
12+
@TestCase('{ "a": "b" }')
13+
@TestCase('{ "a": { "b": "c" } }')
14+
public json(json: string): void {
15+
const lua = transpileString(json, { resolveJsonModule: true, noHeader: true }, false, "file.json")
16+
.replace(/^return (.+);$/s, "return JSONStringify($1);");
17+
18+
const result = util.executeLua(lua);
19+
Expect(JSON.parse(result)).toEqual(JSON.parse(json));
20+
}
21+
22+
@Test("Empty JSON")
23+
public emptyJson(): void {
24+
Expect(() => transpileString("", { resolveJsonModule: true, noHeader: true }, false, "file.json"))
25+
.toThrowError(TranspileError, "Invalid JSON file content");
26+
}
27+
}

0 commit comments

Comments
 (0)