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
1,993 changes: 821 additions & 1,172 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,24 @@
"node": ">=8.5.0"
},
"dependencies": {
"resolve": "^1.11.0",
"resolve": "^1.13.1",
"source-map": "^0.7.3",
"typescript": "^3.6.2"
"typescript": "^3.7.3"
},
"devDependencies": {
"@types/fs-extra": "^8.0.1",
"@types/glob": "^7.1.1",
"@types/jest": "^24.0.15",
"@types/node": "^11.13.14",
"@types/jest": "^24.0.23",
"@types/node": "^12.12.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",
"prettier": "^1.18.2",
"ts-jest": "^24.0.2",
"ts-node": "^7.0.1",
"tslint": "^5.17.0"
"javascript-stringify": "^2.0.1",
"jest": "^24.9.0",
"jest-circus": "^24.9.0",
"prettier": "^1.19.1",
"ts-jest": "^24.2.0",
"ts-node": "^8.5.4",
"tslint": "^5.20.1"
}
}
4 changes: 2 additions & 2 deletions src/Emit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function emitTranspiledFiles(
let { outDir, luaLibImport, luaBundle } = options;

const rootDir = program.getCommonSourceDirectory();
outDir = outDir || rootDir;
outDir = outDir ?? rootDir;

const files: OutputFile[] = [];
for (const { fileName, lua, sourceMap, declaration, declarationMap } of transpiledFiles) {
Expand Down Expand Up @@ -54,7 +54,7 @@ export function emitTranspiledFiles(
luaLibImport === LuaLibImportKind.Require ||
luaLibImport === LuaLibImportKind.Always)
) {
const lualibRequired = files.some(f => f.text && f.text.includes(`require("lualib_bundle")`));
const lualibRequired = files.some(f => f.text?.includes(`require("lualib_bundle")`));
if (lualibRequired) {
if (lualibContent === undefined) {
const lualibBundle = emitHost.readFile(path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"));
Expand Down
12 changes: 3 additions & 9 deletions src/LuaAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export function setParent(node: Node | Node[] | undefined, parent: Node): void {
}

function getSourcePosition(sourceNode: ts.Node): TextRange | undefined {
if (sourceNode !== undefined && sourceNode.getSourceFile() !== undefined && sourceNode.pos >= 0) {
if (sourceNode.getSourceFile() !== undefined && sourceNode.pos >= 0) {
const { line, character } = ts.getLineAndCharacterOfPosition(
sourceNode.getSourceFile(),
sourceNode.pos + sourceNode.getLeadingTriviaWidth()
Expand Down Expand Up @@ -901,12 +901,7 @@ export type FunctionDefinition = (VariableDeclarationStatement | AssignmentState
export function isFunctionDefinition(
statement: VariableDeclarationStatement | AssignmentStatement
): statement is FunctionDefinition {
return (
statement.left.length === 1 &&
statement.right !== undefined &&
statement.right.length === 1 &&
isFunctionExpression(statement.right[0])
);
return statement.left.length === 1 && statement.right?.length === 1 && isFunctionExpression(statement.right[0]);
}

export type InlineFunctionExpression = FunctionExpression & {
Expand All @@ -915,8 +910,7 @@ export type InlineFunctionExpression = FunctionExpression & {

export function isInlineFunctionExpression(expression: FunctionExpression): expression is InlineFunctionExpression {
return (
expression.body.statements !== undefined &&
expression.body.statements.length === 1 &&
expression.body.statements?.length === 1 &&
isReturnStatement(expression.body.statements[0]) &&
(expression.body.statements[0] as ReturnStatement).expressions !== undefined &&
(expression.flags & FunctionExpressionFlags.Inline) !== 0
Expand Down
62 changes: 50 additions & 12 deletions src/LuaPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ const escapeStringMap: Record<string, string> = {
"\0": "\\0",
};

export const escapeString = (value: string) =>
`"${value.replace(escapeStringRegExp, char => escapeStringMap[char] || char)}"`;
export const escapeString = (value: string) => `"${value.replace(escapeStringRegExp, char => escapeStringMap[char])}"`;

/**
* Checks that a name is valid for use in lua function declaration syntax:
Expand Down Expand Up @@ -198,7 +197,7 @@ export class LuaPrinter {
header += `--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]\n`;
}

const luaLibImport = this.options.luaLibImport || LuaLibImportKind.Require;
const luaLibImport = this.options.luaLibImport ?? LuaLibImportKind.Require;
if (
luaLibImport === LuaLibImportKind.Always ||
(luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0)
Expand Down Expand Up @@ -341,11 +340,21 @@ export class LuaPrinter {
// Print all local functions as `local function foo()` instead of `local foo = function` to allow recursion
chunks.push(this.printFunctionDefinition(statement));
} else {
chunks.push(...this.joinChunks(", ", statement.left.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
statement.left.map(e => this.printExpression(e))
)
);

if (statement.right) {
chunks.push(" = ");
chunks.push(...this.joinChunks(", ", statement.right.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
statement.right.map(e => this.printExpression(e))
)
);
}
}

Expand All @@ -369,9 +378,19 @@ export class LuaPrinter {
}
}

chunks.push(...this.joinChunks(", ", statement.left.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
statement.left.map(e => this.printExpression(e))
)
);
chunks.push(" = ");
chunks.push(...this.joinChunks(", ", statement.right.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
statement.right.map(e => this.printExpression(e))
)
);

return this.createSourceNode(statement, chunks);
}
Expand Down Expand Up @@ -458,8 +477,14 @@ export class LuaPrinter {
}

public printForInStatement(statement: lua.ForInStatement): SourceNode {
const names = this.joinChunks(", ", statement.names.map(i => this.printIdentifier(i)));
const expressions = this.joinChunks(", ", statement.expressions.map(e => this.printExpression(e)));
const names = this.joinChunks(
", ",
statement.names.map(i => this.printIdentifier(i))
);
const expressions = this.joinChunks(
", ",
statement.expressions.map(e => this.printExpression(e))
);

const chunks: SourceChunk[] = [];

Expand Down Expand Up @@ -488,7 +513,12 @@ export class LuaPrinter {

const chunks: SourceChunk[] = [];

chunks.push(...this.joinChunks(", ", statement.expressions.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
statement.expressions.map(e => this.printExpression(e))
)
);

return this.createSourceNode(statement, [this.indent(), "return ", ...chunks]);
}
Expand Down Expand Up @@ -588,7 +618,10 @@ export class LuaPrinter {
chunks.push(" ");
const returnNode: SourceChunk[] = [
"return ",
...this.joinChunks(", ", returnStatement.expressions.map(e => this.printExpression(e))),
...this.joinChunks(
", ",
returnStatement.expressions.map(e => this.printExpression(e))
),
];
chunks.push(this.createSourceNode(returnStatement, returnNode));
chunks.push(this.createSourceNode(expression, " end"));
Expand Down Expand Up @@ -780,7 +813,12 @@ export class LuaPrinter {
const chunks: SourceChunk[] = [];

if (expressions.every(isSimpleExpression)) {
chunks.push(...this.joinChunks(", ", expressions.map(e => this.printExpression(e))));
chunks.push(
...this.joinChunks(
", ",
expressions.map(e => this.printExpression(e))
)
);
} else {
chunks.push("\n");
this.pushIndent();
Expand Down
14 changes: 7 additions & 7 deletions src/TSTransformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export function getCustomTransformers(
const transformersFromOptions = loadTransformersFromOptions(program, diagnostics);

const afterDeclarations = [
...(transformersFromOptions.afterDeclarations || []),
...(customTransformers.afterDeclarations || []),
...(transformersFromOptions.afterDeclarations ?? []),
...(customTransformers.afterDeclarations ?? []),
];

const options = program.getCompilerOptions() as CompilerOptions;
Expand All @@ -32,11 +32,11 @@ export function getCustomTransformers(
return {
afterDeclarations,
before: [
...(customTransformers.before || []),
...(transformersFromOptions.before || []),
...(customTransformers.before ?? []),
...(transformersFromOptions.before ?? []),

...(transformersFromOptions.after || []),
...(customTransformers.after || []),
...(transformersFromOptions.after ?? []),
...(customTransformers.after ?? []),
luaTransformer,
],
};
Expand Down Expand Up @@ -197,7 +197,7 @@ function loadTransformer(
} else {
const isValidGroupTransformer =
typeof transformer === "object" &&
(transformer.before || transformer.after || transformer.afterDeclarations);
(transformer.before ?? transformer.after ?? transformer.afterDeclarations) !== undefined;

if (!isValidGroupTransformer) {
return { error: diagnosticFactories.transformerShouldBeATsTransformerFactory(transform) };
Expand Down
2 changes: 1 addition & 1 deletion src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function bundleTranspiledFiles(
);

// If any of the modules contains a require for lualib_bundle, add it to the module table.
const lualibRequired = transpiledFiles.some(f => f.lua && f.lua.includes(`require("lualib_bundle")`));
const lualibRequired = transpiledFiles.some(f => f.lua?.includes(`require("lualib_bundle")`));
if (lualibRequired) {
const lualibBundle = emitHost.readFile(path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"));
moduleTableEntries.push(`["lualib_bundle"] = function() ${lualibBundle} end,\n`);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/information.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function getHelpString(): string {

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

const valuesHint = option.type === "enum" ? option.choices.join("|") : option.type;
Expand Down
26 changes: 13 additions & 13 deletions src/transformation/builtins/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ts from "typescript";
import * as lua from "../../LuaAST";
import { assume } from "../../utils";
import { TransformationContext } from "../context";
import { importLuaLibFeature, LuaLibFeature } from "../utils/lualib";
import { getIdentifierSymbolId } from "../utils/symbols";
Expand Down Expand Up @@ -60,8 +61,7 @@ export function transformBuiltinCallExpression(
return;
}

// TODO(TypeScript 3.7): assume
const propertyCall = node as PropertyCallExpression;
assume<PropertyCallExpression>(node);

// If the function being called is of type owner.func, get the type of owner
const ownerType = context.checker.getTypeAtLocation(node.expression.expression);
Expand All @@ -71,40 +71,40 @@ export function transformBuiltinCallExpression(
const symbolName = symbol && symbol.name;
switch (symbolName) {
case "Console":
return transformConsoleCall(context, propertyCall);
return transformConsoleCall(context, node);
case "Math":
return transformMathCall(context, propertyCall);
return transformMathCall(context, node);
case "StringConstructor":
return transformStringConstructorCall(context, propertyCall);
return transformStringConstructorCall(context, node);
case "ObjectConstructor":
return transformObjectConstructorCall(context, propertyCall);
return transformObjectConstructorCall(context, node);
case "SymbolConstructor":
return transformSymbolConstructorCall(context, propertyCall);
return transformSymbolConstructorCall(context, node);
case "NumberConstructor":
return transformNumberConstructorCall(context, propertyCall);
return transformNumberConstructorCall(context, node);
}
}

if (isStringType(context, ownerType)) {
return transformStringPrototypeCall(context, propertyCall);
return transformStringPrototypeCall(context, node);
}

if (isNumberType(context, ownerType)) {
return transformNumberPrototypeCall(context, propertyCall);
return transformNumberPrototypeCall(context, node);
}

if (isArrayType(context, ownerType)) {
const result = transformArrayPrototypeCall(context, propertyCall);
const result = transformArrayPrototypeCall(context, node);
if (result) {
return result;
}
}

if (isFunctionType(context, ownerType)) {
return transformFunctionPrototypeCall(context, propertyCall);
return transformFunctionPrototypeCall(context, node);
}

const objectResult = transformObjectPrototypeCall(context, propertyCall);
const objectResult = transformObjectPrototypeCall(context, node);
if (objectResult) {
return objectResult;
}
Expand Down
9 changes: 4 additions & 5 deletions src/transformation/context/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,24 @@ export class TransformationContext {
public readonly resolver: EmitResolver;

public readonly options: CompilerOptions = this.program.getCompilerOptions();
public readonly luaTarget = this.options.luaTarget || LuaTarget.LuaJIT;
public readonly luaTarget = this.options.luaTarget ?? LuaTarget.LuaJIT;
public readonly isModule = isFileModule(this.sourceFile);
public readonly isStrict =
this.options.alwaysStrict !== undefined ||
(this.options.strict !== undefined && this.options.alwaysStrict !== false) ||
(this.options.alwaysStrict ?? this.options.strict) ||
(this.isModule && this.options.target !== undefined && this.options.target >= ts.ScriptTarget.ES2015);

public constructor(public program: ts.Program, public sourceFile: ts.SourceFile, private visitorMap: VisitorMap) {
// Use `getParseTreeNode` to get original SourceFile node, before it was substituted by custom transformers.
// It's required because otherwise `getEmitResolver` won't use cached diagnostics, produced in `emitWorker`
// and would try to re-analyze the file, which would fail because of replaced nodes.
const originalSourceFile = ts.getParseTreeNode(sourceFile, ts.isSourceFile) || sourceFile;
const originalSourceFile = ts.getParseTreeNode(sourceFile, ts.isSourceFile) ?? sourceFile;
this.resolver = this.checker.getEmitResolver(originalSourceFile);
}

private currentNodeVisitors: Array<ObjectVisitor<ts.Node>> = [];
public transformNode(node: ts.Node): lua.Node[] {
// TODO: Move to visitors?
if (node.modifiers && node.modifiers.some(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword)) {
if (node.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword)) {
return [];
}

Expand Down
2 changes: 1 addition & 1 deletion src/transformation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function createVisitorMap(customVisitors: Visitors[]): VisitorMap {
}

for (const nodeVisitors of visitorMap.values()) {
nodeVisitors.sort((a, b) => (a.priority || 0) - (b.priority || 0));
nodeVisitors.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
}

return visitorMap;
Expand Down
2 changes: 1 addition & 1 deletion src/transformation/utils/annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function getFileAnnotations(sourceFile: ts.SourceFile): AnnotationsMap {
// Manually collect jsDoc because `getJSDocTags` includes tags only from closest comment
const jsDoc = sourceFile.statements[0].jsDoc;
if (jsDoc) {
for (const tag of flatMap(jsDoc, x => x.tags || [])) {
for (const tag of flatMap(jsDoc, x => x.tags ?? [])) {
const tagName = tag.tagName.text;
const annotation = createAnnotation(tagName, tag.comment ? tag.comment.split(" ") : []);
if (annotation) {
Expand Down
4 changes: 2 additions & 2 deletions src/transformation/utils/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { createExportsIdentifier } from "./lua-ast";
import { getSymbolInfo } from "./symbols";
import { findFirstNodeAbove, isFileModule } from "./typescript";

export function hasDefaultExportModifier({ modifiers }: ts.Node): boolean {
return modifiers !== undefined && modifiers.some(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword);
export function hasDefaultExportModifier(node: ts.Node): boolean {
return (node.modifiers ?? []).some(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword);
}

export const createDefaultExportIdentifier = (original: ts.Node): lua.Identifier =>
Expand Down
2 changes: 1 addition & 1 deletion src/transformation/utils/function-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function getSignatureDeclarations(

export function getFunctionContextType(context: TransformationContext, type: ts.Type): ContextType {
if (type.isTypeParameter()) {
type = type.getConstraint() || type;
type = type.getConstraint() ?? type;
}

if (type.isUnion()) {
Expand Down
Loading