Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@
"typescript": "^3.6.2"
},
"devDependencies": {
"@types/fs-extra": "^8.0.1",
"@types/glob": "^7.1.1",
"@types/jest": "^24.0.15",
"@types/node": "^11.13.14",
"@types/resolve": "0.0.8",
"fengari": "^0.1.4",
"fs-extra": "^8.1.0",
"javascript-stringify": "^2.0.0",
"jest": "^24.8.0",
"jest-circus": "^24.8.0",
Expand Down
4 changes: 2 additions & 2 deletions src/Emit.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as path from "path";
import * as ts from "typescript";
import { CompilerOptions, LuaLibImportKind } from "./CompilerOptions";
import { TranspiledFile, EmitHost } from "./Transpile";
import { EmitHost, TranspiledFile } from "./Transpile";
import { normalizeSlashes } from "./utils";

const trimExt = (filePath: string) => filePath.slice(0, -path.extname(filePath).length);
const normalizeSlashes = (filePath: string) => filePath.replace(/\\/g, "/");

export interface OutputFile {
name: string;
Expand Down
9 changes: 5 additions & 4 deletions src/TSTransformers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from "path";
import * as resolve from "resolve";
import * as ts from "typescript";
import * as cliDiagnostics from "./cli/diagnostics";
import { CompilerOptions, TransformerImport } from "./CompilerOptions";
import * as diagnosticFactories from "./diagnostics";
import { noImplicitSelfTransformer } from "./NoImplicitSelfTransformer";
Expand Down Expand Up @@ -111,7 +112,7 @@ function resolveTransformerFactory(
): { error?: ts.Diagnostic; factory?: TransformerFactory } {
if (typeof transform !== "string") {
const optionName = `${transformerOptionPath}.transform`;
return { error: diagnosticFactories.compilerOptionRequiresAValueOfType(optionName, "string") };
return { error: cliDiagnostics.compilerOptionRequiresAValueOfType(optionName, "string") };
}

let resolved: string;
Expand Down Expand Up @@ -167,18 +168,18 @@ function loadTransformer(
break;
default: {
const optionName = `--${transformerOptionPath}.type`;
return { error: diagnosticFactories.argumentForOptionMustBe(optionName, "program") };
return { error: cliDiagnostics.argumentForOptionMustBe(optionName, "program") };
}
}

if (typeof after !== "boolean") {
const optionName = `${transformerOptionPath}.after`;
return { error: diagnosticFactories.compilerOptionRequiresAValueOfType(optionName, "boolean") };
return { error: cliDiagnostics.compilerOptionRequiresAValueOfType(optionName, "boolean") };
}

if (typeof afterDeclarations !== "boolean") {
const optionName = `${transformerOptionPath}.afterDeclarations`;
return { error: diagnosticFactories.compilerOptionRequiresAValueOfType(optionName, "boolean") };
return { error: cliDiagnostics.compilerOptionRequiresAValueOfType(optionName, "boolean") };
}

if (typeof transformer === "function") {
Expand Down
81 changes: 81 additions & 0 deletions src/cli/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as ts from "typescript";

export const tstlOptionsAreMovingToTheTstlObject = (tstl: Record<string, any>): ts.Diagnostic => ({
file: undefined,
start: undefined,
length: undefined,
category: ts.DiagnosticCategory.Warning,
code: 0,
source: "typescript-to-lua",
messageText:
'TSTL options are moving to the "tstl" object. Adjust your tsconfig to look like\n' +
`"tstl": ${JSON.stringify(tstl, undefined, 4)}`,
});

export const watchErrorSummary = (errorCount: number): ts.Diagnostic => ({
file: undefined,
start: undefined,
length: undefined,
category: ts.DiagnosticCategory.Message,
code: errorCount === 1 ? 6193 : 6194,
messageText:
errorCount === 1
? "Found 1 error. Watching for file changes."
: `Found ${errorCount} errors. Watching for file changes.`,
});

const createCommandLineError = <Args extends any[]>(code: number, getMessage: (...args: Args) => string) => (
...args: Args
): ts.Diagnostic => ({
file: undefined,
start: undefined,
length: undefined,
category: ts.DiagnosticCategory.Error,
code,
messageText: getMessage(...args),
});

export const unknownCompilerOption = createCommandLineError(
5023,
(name: string) => `Unknown compiler option '${name}'.`
);

export const compilerOptionRequiresAValueOfType = createCommandLineError(
5024,
(name: string, type: string) => `Compiler option '${name}' requires a value of type ${type}.`
);

export const optionProjectCannotBeMixedWithSourceFilesOnACommandLine = createCommandLineError(
5042,
() => "Option 'project' cannot be mixed with source files on a command line."
);

export const cannotFindATsconfigJsonAtTheSpecifiedDirectory = createCommandLineError(
5057,
(dir: string) => `Cannot find a tsconfig.json file at the specified directory: '${dir}'.`
);

export const theSpecifiedPathDoesNotExist = createCommandLineError(
5058,
(dir: string) => `The specified path does not exist: '${dir}'.`
);

export const compilerOptionExpectsAnArgument = createCommandLineError(
6044,
(name: string) => `Compiler option '${name}' expects an argument.`
);

export const argumentForOptionMustBe = createCommandLineError(
6046,
(name: string, values: string) => `Argument for '${name}' option must be: ${values}.`
);

export const optionCanOnlyBeSpecifiedInTsconfigJsonFile = createCommandLineError(
6064,
(name: string) => `Option '${name}' can only be specified in 'tsconfig.json' file.`
);

export const optionBuildMustBeFirstCommandLineArgument = createCommandLineError(
6369,
() => "Option '--build' must be the first command line argument."
);
32 changes: 32 additions & 0 deletions src/cli/information.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { optionDeclarations } from "./parse";

export const { version } = require("../../package.json");
export const versionString = `Version ${version}`;

const helpString = `
Syntax: tstl [options] [files...]

Examples: tstl path/to/file.ts [...]
tstl -p path/to/tsconfig.json

In addition to the options listed below you can also pass options
for the typescript compiler (For a list of options use tsc -h).
Some tsc options might have no effect.
`.trim();

export function getHelpString(): string {
let result = helpString + "\n\n";

result += "Options:\n";
for (const option of optionDeclarations) {
const aliasStrings = (option.aliases || []).map(a => "-" + a);
const optionString = aliasStrings.concat(["--" + option.name]).join("|");

const valuesHint = option.type === "enum" ? option.choices.join("|") : option.type;
const spacing = " ".repeat(Math.max(1, 45 - optionString.length - valuesHint.length));

result += `\n ${optionString} <${valuesHint}>${spacing}${option.description}\n`;
}

return result;
}
78 changes: 9 additions & 69 deletions src/CommandLineParser.ts → src/cli/parse.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as path from "path";
import * as ts from "typescript";
import { CompilerOptions, LuaLibImportKind, LuaTarget } from "./CompilerOptions";
import * as diagnosticFactories from "./diagnostics";
import { CompilerOptions, LuaLibImportKind, LuaTarget } from "../CompilerOptions";
import * as cliDiagnostics from "./diagnostics";

export interface ParsedCommandLine extends ts.ParsedCommandLine {
options: CompilerOptions;
Expand All @@ -24,7 +23,7 @@ interface CommandLineOptionOfBoolean extends CommandLineOptionBase {

type CommandLineOption = CommandLineOptionOfEnum | CommandLineOptionOfBoolean;

const optionDeclarations: CommandLineOption[] = [
export const optionDeclarations: CommandLineOption[] = [
{
name: "luaLibImport",
description: "Specifies how js standard features missing in lua are imported.",
Expand Down Expand Up @@ -60,36 +59,6 @@ const optionDeclarations: CommandLineOption[] = [
},
];

export const version = `Version ${require("../package.json").version}`;

const helpString = `
Syntax: tstl [options] [files...]

Examples: tstl path/to/file.ts [...]
tstl -p path/to/tsconfig.json

In addition to the options listed below you can also pass options
for the typescript compiler (For a list of options use tsc -h).
Some tsc options might have no effect.
`.trim();

export function getHelpString(): string {
let result = helpString + "\n\n";

result += "Options:\n";
for (const option of optionDeclarations) {
const aliasStrings = (option.aliases || []).map(a => "-" + a);
const optionString = aliasStrings.concat(["--" + option.name]).join("|");

const valuesHint = option.type === "enum" ? option.choices.join("|") : option.type;
const spacing = " ".repeat(Math.max(1, 45 - optionString.length - valuesHint.length));

result += `\n ${optionString} <${valuesHint}>${spacing}${option.description}\n`;
}

return result;
}

export function updateParsedConfigFile(parsedConfigFile: ts.ParsedCommandLine): ParsedCommandLine {
let hasRootLevelOptions = false;
for (const key in parsedConfigFile.raw) {
Expand All @@ -103,15 +72,13 @@ export function updateParsedConfigFile(parsedConfigFile: ts.ParsedCommandLine):

if (parsedConfigFile.raw.tstl) {
if (hasRootLevelOptions) {
parsedConfigFile.errors.push(
diagnosticFactories.tstlOptionsAreMovingToTheTstlObject(parsedConfigFile.raw.tstl)
);
parsedConfigFile.errors.push(cliDiagnostics.tstlOptionsAreMovingToTheTstlObject(parsedConfigFile.raw.tstl));
}

for (const key in parsedConfigFile.raw.tstl) {
const option = optionDeclarations.find(option => option.name === key);
if (!option) {
parsedConfigFile.errors.push(diagnosticFactories.unknownCompilerOption(key));
parsedConfigFile.errors.push(cliDiagnostics.unknownCompilerOption(key));
continue;
}

Expand Down Expand Up @@ -179,7 +146,7 @@ function readCommandLineArgument(option: CommandLineOption, value: any): Command

if (value === undefined) {
return {
error: diagnosticFactories.compilerOptionExpectsAnArgument(option.name),
error: cliDiagnostics.compilerOptionExpectsAnArgument(option.name),
value: undefined,
increment: 0,
};
Expand All @@ -201,7 +168,7 @@ function readValue(option: CommandLineOption, value: unknown): ReadValueResult {
if (typeof value !== "boolean") {
return {
value: undefined,
error: diagnosticFactories.compilerOptionRequiresAValueOfType(option.name, "boolean"),
error: cliDiagnostics.compilerOptionRequiresAValueOfType(option.name, "boolean"),
};
}

Expand All @@ -212,7 +179,7 @@ function readValue(option: CommandLineOption, value: unknown): ReadValueResult {
if (typeof value !== "string") {
return {
value: undefined,
error: diagnosticFactories.compilerOptionRequiresAValueOfType(option.name, "string"),
error: cliDiagnostics.compilerOptionRequiresAValueOfType(option.name, "string"),
};
}

Expand All @@ -221,38 +188,11 @@ function readValue(option: CommandLineOption, value: unknown): ReadValueResult {
const optionChoices = option.choices.join(", ");
return {
value: undefined,
error: diagnosticFactories.argumentForOptionMustBe(`--${option.name}`, optionChoices),
error: cliDiagnostics.argumentForOptionMustBe(`--${option.name}`, optionChoices),
};
}

return { value: enumValue };
}
}
}

export function parseConfigFileWithSystem(
configFileName: string,
commandLineOptions?: CompilerOptions,
system = ts.sys
): ParsedCommandLine {
const parsedConfigFile = ts.parseJsonSourceFileConfigFileContent(
ts.readJsonConfigFile(configFileName, system.readFile),
system,
path.dirname(configFileName),
commandLineOptions,
configFileName
);

return updateParsedConfigFile(parsedConfigFile);
}

export function createDiagnosticReporter(pretty: boolean, system = ts.sys): ts.DiagnosticReporter {
const reporter: ts.DiagnosticReporter = (ts as any).createDiagnosticReporter(system, pretty);
return diagnostic => {
if (diagnostic.source === "typescript-to-lua") {
diagnostic = { ...diagnostic, code: ("TL" + diagnostic.code) as any };
}

reporter(diagnostic);
};
}
Loading