From 904c26be17fa5a6a07e3ab84c0a7dbb5a1a2e67c Mon Sep 17 00:00:00 2001 From: Lolleko Date: Fri, 12 Oct 2018 15:39:06 +0200 Subject: [PATCH 1/3] Generated declarations and exposed API --- package.json | 2 ++ src/Compiler.ts | 53 +++++++++++++++++++++++++++++++++++++++++ src/tstl.ts | 25 ++++++++++++++++++++ test/src/util.ts | 61 ++++++------------------------------------------ tsconfig.json | 3 ++- 5 files changed, 89 insertions(+), 55 deletions(-) create mode 100644 src/tstl.ts diff --git a/package.json b/package.json index b37192df9..38dfd524e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "tstl", "transpiler" ], + "main": "dist/tstl.js", + "types" : "dist/tstl.d.ts", "scripts": { "build": "tsc -p tsconfig.json && npm run build-lualib", "build-lualib": "ts-node ./build_lualib.ts", diff --git a/src/Compiler.ts b/src/Compiler.ts index 7d01f0ea9..0ffa8fa61 100644 --- a/src/Compiler.ts +++ b/src/Compiler.ts @@ -177,6 +177,59 @@ export function createTranspiler(checker: ts.TypeChecker, return luaTargetTranspiler; } +const libSource = fs.readFileSync(path.join(path.dirname(require.resolve("typescript")), "lib.es6.d.ts")).toString(); + +export function transpileString(str: string, + options: CompilerOptions = { + luaLibImport: LuaLibImportKind.Require, + luaTarget: LuaTarget.Lua53, + }): string { + const compilerHost = { + directoryExists: () => true, + fileExists: (fileName): boolean => true, + getCanonicalFileName: fileName => fileName, + getCurrentDirectory: () => "", + getDefaultLibFileName: () => "lib.es6.d.ts", + getDirectories: () => [], + getNewLine: () => "\n", + + getSourceFile: (filename, languageVersion) => { + if (filename === "file.ts") { + return ts.createSourceFile(filename, str, ts.ScriptTarget.Latest, false); + } + if (filename === "lib.es6.d.ts") { + return ts.createSourceFile(filename, libSource, ts.ScriptTarget.Latest, false); + } + return undefined; + }, + + readFile: () => "", + + useCaseSensitiveFileNames: () => false, + // Don't write output + writeFile: (name, text, writeByteOrderMark) => null, + }; + const program = ts.createProgram(["file.ts"], options, compilerHost); + + const result = createTranspiler(program.getTypeChecker(), + options, + program.getSourceFile("file.ts")).transpileSourceFile(); + return result.trim(); +} + +export function transpileFile(filePath: string): string { + const program = ts.createProgram([filePath], {}); + const checker = program.getTypeChecker(); + + // Output errors + const diagnostics = ts.getPreEmitDiagnostics(program).filter(diag => diag.code !== 6054); + diagnostics.forEach(diagnostic => console.log(`${ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")}`)); + + const options: ts.CompilerOptions = { luaLibImport: "none" }; + const result = createTranspiler(checker, options, program.getSourceFile(filePath)).transpileSourceFile(); + return result.trim(); +} + function reportDiagnostic(diagnostic: ts.Diagnostic): void { if (diagnostic.file) { const { line, character } = diff --git a/src/tstl.ts b/src/tstl.ts new file mode 100644 index 000000000..bc74f494a --- /dev/null +++ b/src/tstl.ts @@ -0,0 +1,25 @@ +export { + CompilerOptions, + parseCommandLine +} from "./CommandLineParser"; + +export { + compile, + compileFilesWithOptions, + createTranspiler, + transpileFile, + transpileString, + watchWithOptions +} from "./Compiler"; + +export {LuaTranspiler51} from "./targets/Transpiler.51"; +export {LuaTranspiler52} from "./targets/Transpiler.52"; +export {LuaTranspiler53} from "./targets/Transpiler.53"; +export {LuaTranspilerJIT} from "./targets/Transpiler.JIT"; + +export { + LuaLibFeature, + LuaLibImportKind, + LuaTarget, + LuaTranspiler +} from "./Transpiler"; diff --git a/test/src/util.ts b/test/src/util.ts index a7dce9101..38e2cd2e9 100644 --- a/test/src/util.ts +++ b/test/src/util.ts @@ -4,61 +4,14 @@ import * as ts from "typescript"; import { Expect } from "alsatian"; import { CompilerOptions } from "../../src/CommandLineParser"; -import { createTranspiler } from "../../src/Compiler"; +import { createTranspiler, transpileString } from "../../src/Compiler"; import { LuaLibImportKind, LuaTarget, LuaTranspiler } from "../../src/Transpiler"; import {lauxlib, lua, lualib, to_jsstring, to_luastring } from "fengari"; -const fs = require("fs"); - -const libSource = fs.readFileSync(path.join(path.dirname(require.resolve("typescript")), "lib.es6.d.ts")).toString(); - -export function transpileString(str: string, options: CompilerOptions = { luaLibImport: LuaLibImportKind.Require, luaTarget: LuaTarget.Lua53 }): string { - const compilerHost = { - directoryExists: () => true, - fileExists: (fileName): boolean => true, - getCanonicalFileName: fileName => fileName, - getCurrentDirectory: () => "", - getDefaultLibFileName: () => "lib.es6.d.ts", - getDirectories: () => [], - getNewLine: () => "\n", - - getSourceFile: (filename, languageVersion) => { - if (filename === "file.ts") { - return ts.createSourceFile(filename, str, ts.ScriptTarget.Latest, false); - } - if (filename === "lib.es6.d.ts") { - return ts.createSourceFile(filename, libSource, ts.ScriptTarget.Latest, false); - } - return undefined; - }, - - readFile: () => "", - - useCaseSensitiveFileNames: () => false, - // Don't write output - writeFile: (name, text, writeByteOrderMark) => null, - }; - const program = ts.createProgram(["file.ts"], options, compilerHost); - - const result = createTranspiler(program.getTypeChecker(), - options, - program.getSourceFile("file.ts")).transpileSourceFile(); - return result.trim(); -} - -export function transpileFile(filePath: string): string { - const program = ts.createProgram([filePath], {}); - const checker = program.getTypeChecker(); +import * as fs from "fs"; - // Output errors - const diagnostics = ts.getPreEmitDiagnostics(program).filter(diag => diag.code !== 6054); - diagnostics.forEach(diagnostic => console.log(`${ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")}`)); - - const options: ts.CompilerOptions = { luaLibImport: "none" }; - const result = createTranspiler(checker, options, program.getSourceFile(filePath)).transpileSourceFile(); - return result.trim(); -} +export { transpileString }; export function executeLua(luaStr: string, withLib = true): any { if (withLib) { @@ -91,7 +44,7 @@ export function executeLua(luaStr: string, withLib = true): any { } } -export function expectCodeEqual(code1: string, code2: string) { +export function expectCodeEqual(code1: string, code2: string): void { // Trim leading/trailing whitespace let c1 = code1.trim(); let c2 = code2.trim(); @@ -104,14 +57,14 @@ export function expectCodeEqual(code1: string, code2: string) { } // Get a mock transpiler to use for testing -export function makeTestTranspiler(target: LuaTarget = LuaTarget.Lua53) { +export function makeTestTranspiler(target: LuaTarget = LuaTarget.Lua53): LuaTranspiler { return createTranspiler({} as ts.TypeChecker, { luaLibImport: "none", luaTarget: target } as any, { statements: [] } as any as ts.SourceFile); } -export function transpileAndExecute(ts: string): any { - return executeLua(transpileString(ts)); +export function transpileAndExecute(tsStr: string): any { + return executeLua(transpileString(tsStr)); } const jsonlib = fs.readFileSync("test/src/json.lua") + "\n"; diff --git a/tsconfig.json b/tsconfig.json index 1d2eb76cc..09ebff3e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,11 @@ "alwaysStrict" : true, "outDir": "./dist/", "rootDir": "./src/", + "declaration": true, "sourceMap": true, "experimentalDecorators": true, "target": "es6", "module": "commonjs" }, - "exclude": ["test/**/*", "build_lualib.ts", "src/lualib"] + "exclude": ["test/**/*", "build_lualib.ts", "src/lualib", "dist/**/*"] } From 3559f91d075b135116484f763348bfb89115a16c Mon Sep 17 00:00:00 2001 From: Lolleko Date: Sat, 13 Oct 2018 16:57:42 +0200 Subject: [PATCH 2/3] Refactoring into more files --- package.json | 4 +-- src/CommandLineParser.ts | 20 +++++------ src/Compiler.ts | 34 +++---------------- src/CompilerOptions.ts | 7 ++++ src/LuaLibFeatures.ts | 0 src/TSHelper.ts | 2 +- src/Transpiler.ts | 6 ++-- src/TranspilerFactory.ts | 33 ++++++++++++++++++ src/tstl.ts | 12 +++++-- test/src/util.ts | 6 ++-- test/unit/cli.spec.ts | 4 +-- .../configuration/mixed/index.spec.ts | 19 ++++++----- 12 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 src/CompilerOptions.ts create mode 100644 src/LuaLibFeatures.ts create mode 100644 src/TranspilerFactory.ts diff --git a/package.json b/package.json index 38dfd524e..e401dcab6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "transpiler" ], "main": "dist/tstl.js", - "types" : "dist/tstl.d.ts", + "types": "dist/tstl.d.ts", "scripts": { "build": "tsc -p tsconfig.json && npm run build-lualib", "build-lualib": "ts-node ./build_lualib.ts", @@ -43,7 +43,7 @@ "node": ">=8.5.0" }, "dependencies": { - "typescript": "^2.9.2", + "typescript": "2.9.2", "yargs": "^12.0.1" }, "devDependencies": { diff --git a/src/CommandLineParser.ts b/src/CommandLineParser.ts index 7fac341a9..a743d66ad 100644 --- a/src/CommandLineParser.ts +++ b/src/CommandLineParser.ts @@ -1,23 +1,15 @@ +import { CompilerOptions } from "./CompilerOptions"; + import * as fs from "fs"; import * as path from "path"; import * as ts from "typescript"; import * as yargs from "yargs"; -export interface CompilerOptions extends ts.CompilerOptions { - addHeader?: boolean; - luaTarget?: string; - luaLibImport?: string; -} - -export interface ParsedCommandLine extends ts.ParsedCommandLine { +interface ParsedCommandLine extends ts.ParsedCommandLine { options: CompilerOptions; } -export class CLIError extends Error { - -} - -export interface YargsOptions { +interface YargsOptions { [key: string]: yargs.Options; } @@ -42,6 +34,10 @@ export const optionDeclarations: YargsOptions = { }, }; +class CLIError extends Error { + +} + /** * Removes defaults from the arguments. * Returns a tuple where [0] is a copy of the options without defaults and [1] is the extracted defaults. diff --git a/src/Compiler.ts b/src/Compiler.ts index 0ffa8fa61..b15c3850f 100644 --- a/src/Compiler.ts +++ b/src/Compiler.ts @@ -2,12 +2,11 @@ import * as fs from "fs"; import * as path from "path"; import * as ts from "typescript"; -import { CompilerOptions, parseCommandLine } from "./CommandLineParser"; -import { LuaTranspiler51 } from "./targets/Transpiler.51"; -import { LuaTranspiler52 } from "./targets/Transpiler.52"; -import { LuaTranspiler53 } from "./targets/Transpiler.53"; -import { LuaTranspilerJIT } from "./targets/Transpiler.JIT"; -import { LuaLibImportKind, LuaTarget, LuaTranspiler } from "./Transpiler"; +import { parseCommandLine } from "./CommandLineParser"; +import { CompilerOptions } from "./CompilerOptions"; +import { LuaLibImportKind, LuaTarget } from "./Transpiler"; + +import { createTranspiler } from "./TranspilerFactory"; export function compile(argv: string[]): void { const commandLine = parseCommandLine(argv); @@ -154,29 +153,6 @@ function emitFilesAndReportErrors(program: ts.Program): number { return 0; } -export function createTranspiler(checker: ts.TypeChecker, - options: CompilerOptions, - sourceFile: ts.SourceFile): LuaTranspiler { - let luaTargetTranspiler: LuaTranspiler; - const target = options.luaTarget ? options.luaTarget.toLowerCase() : ""; - switch (target) { - case LuaTarget.Lua51: - luaTargetTranspiler = new LuaTranspiler51(checker, options, sourceFile); - break; - case LuaTarget.Lua52: - luaTargetTranspiler = new LuaTranspiler52(checker, options, sourceFile); - break; - case LuaTarget.Lua53: - luaTargetTranspiler = new LuaTranspiler53(checker, options, sourceFile); - break; - default: - luaTargetTranspiler = new LuaTranspilerJIT(checker, options, sourceFile); - break; - } - - return luaTargetTranspiler; -} - const libSource = fs.readFileSync(path.join(path.dirname(require.resolve("typescript")), "lib.es6.d.ts")).toString(); export function transpileString(str: string, diff --git a/src/CompilerOptions.ts b/src/CompilerOptions.ts new file mode 100644 index 000000000..e40291aa0 --- /dev/null +++ b/src/CompilerOptions.ts @@ -0,0 +1,7 @@ +import * as ts from "typescript"; + +export interface CompilerOptions extends ts.CompilerOptions { + addHeader?: boolean; + luaTarget?: string; + luaLibImport?: string; +} diff --git a/src/LuaLibFeatures.ts b/src/LuaLibFeatures.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/TSHelper.ts b/src/TSHelper.ts index 210410d27..0a437e094 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -48,7 +48,7 @@ export class TSHelper { // Vanilla ts flags files as external module if they have an import or // export statement, we only check for export statements return sourceFile.statements.some(statement => - (ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export) !== 0 + (ts.getCombinedModifierFlags(statement as any as ts.Declaration) & ts.ModifierFlags.Export) !== 0 || statement.kind === ts.SyntaxKind.ExportAssignment || statement.kind === ts.SyntaxKind.ExportDeclaration); } diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 94070209e..311212c0c 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -2,7 +2,7 @@ import * as fs from "fs"; import * as path from "path"; import * as ts from "typescript"; -import { CompilerOptions } from "./CommandLineParser"; +import { CompilerOptions } from "./CompilerOptions"; import { DecoratorKind } from "./Decorator"; import { TSTLErrors } from "./Errors"; import { TSHelper as tsHelper } from "./TSHelper"; @@ -120,7 +120,7 @@ export abstract class LuaTranspiler { if (node && node.modifiers && this.isModule && this.namespace.length === 0 && - (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) + (ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export) ) { if (dummy) { result = this.indent + `exports.${this.definitionName(name)} = {}\n`; @@ -129,7 +129,7 @@ export abstract class LuaTranspiler { } } if (this.namespace.length !== 0 && - (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export)) { + (ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export)) { if (dummy) { result += this.indent + `${this.namespace[this.namespace.length - 1]}.${name} = {}\n`; } else { diff --git a/src/TranspilerFactory.ts b/src/TranspilerFactory.ts new file mode 100644 index 000000000..580438962 --- /dev/null +++ b/src/TranspilerFactory.ts @@ -0,0 +1,33 @@ +import { LuaTranspiler51 } from "./targets/Transpiler.51"; +import { LuaTranspiler52 } from "./targets/Transpiler.52"; +import { LuaTranspiler53 } from "./targets/Transpiler.53"; +import { LuaTranspilerJIT } from "./targets/Transpiler.JIT"; + +import { LuaTarget, LuaTranspiler } from "./Transpiler"; + +import { CompilerOptions } from "./CompilerOptions"; + +import * as ts from "typescript"; + +export function createTranspiler( + checker: ts.TypeChecker, options: CompilerOptions, + sourceFile: ts.SourceFile): LuaTranspiler { + let luaTargetTranspiler: LuaTranspiler; + const target = options.luaTarget ? options.luaTarget.toLowerCase() : ""; + switch (target) { + case LuaTarget.Lua51: + luaTargetTranspiler = new LuaTranspiler51(checker, options, sourceFile); + break; + case LuaTarget.Lua52: + luaTargetTranspiler = new LuaTranspiler52(checker, options, sourceFile); + break; + case LuaTarget.Lua53: + luaTargetTranspiler = new LuaTranspiler53(checker, options, sourceFile); + break; + default: + luaTargetTranspiler = new LuaTranspilerJIT(checker, options, sourceFile); + break; + } + + return luaTargetTranspiler; +} diff --git a/src/tstl.ts b/src/tstl.ts index bc74f494a..cef7e8cc0 100644 --- a/src/tstl.ts +++ b/src/tstl.ts @@ -1,12 +1,14 @@ export { - CompilerOptions, parseCommandLine } from "./CommandLineParser"; +export { + CompilerOptions +} from "./CompilerOptions"; + export { compile, compileFilesWithOptions, - createTranspiler, transpileFile, transpileString, watchWithOptions @@ -21,5 +23,9 @@ export { LuaLibFeature, LuaLibImportKind, LuaTarget, - LuaTranspiler + LuaTranspiler, } from "./Transpiler"; + +export { + createTranspiler +} from "./TranspilerFactory"; diff --git a/test/src/util.ts b/test/src/util.ts index 38e2cd2e9..71f8227ac 100644 --- a/test/src/util.ts +++ b/test/src/util.ts @@ -3,9 +3,9 @@ import * as ts from "typescript"; import { Expect } from "alsatian"; -import { CompilerOptions } from "../../src/CommandLineParser"; -import { createTranspiler, transpileString } from "../../src/Compiler"; -import { LuaLibImportKind, LuaTarget, LuaTranspiler } from "../../src/Transpiler"; +import { transpileString } from "../../src/Compiler"; +import { LuaTarget, LuaTranspiler } from "../../src/Transpiler"; +import { createTranspiler } from "../../src/TranspilerFactory"; import {lauxlib, lua, lualib, to_jsstring, to_luastring } from "fengari"; diff --git a/test/unit/cli.spec.ts b/test/unit/cli.spec.ts index f8ebcb7c2..98e842b6c 100644 --- a/test/unit/cli.spec.ts +++ b/test/unit/cli.spec.ts @@ -1,6 +1,6 @@ -import { Expect, Test, TestCase, Teardown } from "alsatian"; +import { Expect, Test, TestCase } from "alsatian"; -import { CompilerOptions, findConfigFile, parseCommandLine, ParsedCommandLine } from "../../src/CommandLineParser"; +import { findConfigFile, parseCommandLine } from "../../src/CommandLineParser"; export class CLITests { diff --git a/test/unit/compiler/configuration/mixed/index.spec.ts b/test/unit/compiler/configuration/mixed/index.spec.ts index 71c2c40ee..18e52b677 100644 --- a/test/unit/compiler/configuration/mixed/index.spec.ts +++ b/test/unit/compiler/configuration/mixed/index.spec.ts @@ -1,9 +1,10 @@ -import { Expect, Test, TestCase, Teardown } from "alsatian"; -import * as path from 'path'; -import * as fs from 'fs'; +import { Expect, Test } from "alsatian"; +import * as fs from "fs"; +import * as path from "path"; import * as ts from "typescript"; -import { CompilerOptions, findConfigFile, parseCommandLine, ParsedCommandLine, optionDeclarations } from "../../../../../src/CommandLineParser"; +import { CompilerOptions } from "../../../../../src/CompilerOptions"; +import { optionDeclarations, parseCommandLine } from "../../../../../src/CommandLineParser"; import { LuaLibImportKind } from "../../../../../src/Transpiler"; export class MixedConfigurationTests { @@ -16,17 +17,17 @@ export class MixedConfigurationTests { ts.parseConfigFileTextToJson(tsConfigPath, fs.readFileSync(tsConfigPath).toString()).config, ts.sys, path.dirname(tsConfigPath) - ); + ); const parsedArgs = parseCommandLine([ "-p", `"${tsConfigPath}"`, "--luaLibImport", LuaLibImportKind.Inline, - `${path.join(rootPath, 'test.ts')}`, + `${path.join(rootPath, "test.ts")}`, ]); - - Expect(parsedArgs.options).toEqual({ + + Expect(parsedArgs.options).toEqual({ ...expectedTsConfig.options, // Overridden by cmd args (set to "none" in project-tsconfig.json) luaLibImport: LuaLibImportKind.Inline, @@ -35,6 +36,6 @@ export class MixedConfigurationTests { // Only present in TSTL dfaults noHeader: optionDeclarations["noHeader"].default, project: tsConfigPath - }); + } as CompilerOptions); } } \ No newline at end of file From c1b36b956997288d200bd9a1c1b55122b527d8ff Mon Sep 17 00:00:00 2001 From: Lolleko Date: Mon, 15 Oct 2018 13:42:16 +0200 Subject: [PATCH 3/3] Revertet combiendmodifier cast hack for now --- src/LuaLibFeatures.ts | 0 src/TSHelper.ts | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 src/LuaLibFeatures.ts diff --git a/src/LuaLibFeatures.ts b/src/LuaLibFeatures.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/TSHelper.ts b/src/TSHelper.ts index ef8da3da8..02b5762df 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -47,8 +47,9 @@ export class TSHelper { if (sourceFile) { // Vanilla ts flags files as external module if they have an import or // export statement, we only check for export statements + // TODO will break in 3.x return sourceFile.statements.some(statement => - (ts.getCombinedModifierFlags(statement as any as ts.Declaration) & ts.ModifierFlags.Export) !== 0 + (ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export) !== 0 || statement.kind === ts.SyntaxKind.ExportAssignment || statement.kind === ts.SyntaxKind.ExportDeclaration); }