diff --git a/package.json b/package.json index 733ef7a83..737306100 100644 --- a/package.json +++ b/package.json @@ -14,16 +14,16 @@ "scripts": { "build": "tsc -p tsconfig.json && npm run build-lualib", "build-lualib": "ts-node ./build_lualib.ts", - "test": "npm run style-check && tslint -c ./tslint.json src/lualib/*.ts && npm run build-lualib && ts-node ./test/runner.ts", - "coverage": "nyc npm test && nyc report --reporter=text-lcov > coverage.lcov", - "coverage-html": "nyc npm test && nyc report --reporter=html", - "test-threaded": "style-check && npm run build && ts-node ./test/threaded_runner.ts", + "test": "npm run style-check && npm run build-lualib && tsc -p ./test/tsconfig.json && node ./test/runner.js", + "coverage": "nyc --source-map=true npm test && nyc report --reporter=text-lcov > coverage.lcov", + "coverage-html": "nyc --source-map=true npm test && nyc report --reporter=html", + "test-threaded": "npm run style-check && npm run build && node ./test/threaded_runner.js", "release-patch": "npm version patch", "release-minor": "npm version minor", "release-major": "npm version major", "preversion": "npm run build && npm test", "postversion": "git push && git push --tags", - "style-check": "tslint -p .", + "style-check": "tslint -p . && tslint -c ./tslint.json src/lualib/*.ts", "style-fix": "gts fix && tslint -p . --fix" }, "bin": { diff --git a/src/CompilerOptions.ts b/src/CompilerOptions.ts index 1f8e49676..a69cce626 100644 --- a/src/CompilerOptions.ts +++ b/src/CompilerOptions.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; export interface CompilerOptions extends ts.CompilerOptions { - addHeader?: boolean; + noHeader?: boolean; luaTarget?: string; luaLibImport?: string; } @@ -18,4 +18,4 @@ export enum LuaTarget { Lua52 = "5.2", Lua53 = "5.3", LuaJIT = "jit", -} \ No newline at end of file +} diff --git a/src/LuaAST.ts b/src/LuaAST.ts index 0145daf74..059ee3f15 100644 --- a/src/LuaAST.ts +++ b/src/LuaAST.ts @@ -189,7 +189,7 @@ export function createDoStatement(statements?: Statement[], parent?: Node, tsOri // `local test1, test2 = 12, 42` or `local test1, test2` export interface VariableDeclarationStatement extends Statement { kind: SyntaxKind.VariableDeclarationStatement; - left: IdentifierOrTableIndexExpression[]; + left: Identifier[]; right?: Expression[]; } @@ -198,7 +198,7 @@ export function isVariableDeclarationStatement(node: Node): node is VariableDecl } export function createVariableDeclarationStatement( - left: IdentifierOrTableIndexExpression | IdentifierOrTableIndexExpression[], + left: Identifier | Identifier[], right?: Expression | Expression[], parent?: Node, tsOriginal?: ts.Node): VariableDeclarationStatement { diff --git a/src/LuaPrinter.ts b/src/LuaPrinter.ts index 3a64e93df..0f509c593 100644 --- a/src/LuaPrinter.ts +++ b/src/LuaPrinter.ts @@ -48,7 +48,7 @@ export class LuaPrinter { public print(block: tstl.Block, luaLibFeatures?: Set): string { let header = ""; - if (this.options.addHeader === undefined || this.options.addHeader === true) { + if (this.options.noHeader === undefined || this.options.noHeader === false) { header += `--[[ Generated with https://github.com/Perryvw/TypescriptToLua ]]\n`; } @@ -308,7 +308,7 @@ export class LuaPrinter { paramterArr.push(this.printDotsLiteral(expression.dots)); } - let result = `function (${paramterArr.join(", ")})\n`; + let result = `function(${paramterArr.join(", ")})\n`; this.pushIndent(); result += this.printBlock(expression.body); this.popIndent(); diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index e0389b513..5007250e5 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -79,6 +79,20 @@ export class LuaTransformer { this.isModule = tsHelper.isFileModule(node); const statements = this.transformStatements(node.statements); + if (this.isModule) { + statements.unshift( + tstl.createVariableDeclarationStatement( + tstl.createIdentifier("exports"), + tstl.createBinaryExpression( + tstl.createIdentifier("exports"), + tstl.createTableExpression(), + tstl.SyntaxKind.OrOperator + ))); + statements.push( + tstl.createReturnStatement( + [tstl.createIdentifier("exports")] + )); + } return [tstl.createBlock(statements, undefined, node), this.luaLibFeatureSet]; } @@ -313,7 +327,9 @@ export class LuaTransformer { const value = this.transformExpression(f.initializer); // className["fieldName"] - const classField = tstl.createTableIndexExpression(className, fieldName); + const classField = tstl.createTableIndexExpression( + className, + fieldName); // className["fieldName"] = value; const assignClassField = tstl.createAssignmentStatement(classField, value); @@ -327,8 +343,13 @@ export class LuaTransformer { const fieldName = this.transformPropertyName(field.name); const value = this.transformExpression(field.initializer); + const classField = tstl.createTableIndexExpression( + this.addExportToIdentifier(className), + fieldName + ); + const fieldAssign = tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, fieldName), + classField, value ); @@ -340,23 +361,24 @@ export class LuaTransformer { .filter(n => ts.isConstructorDeclaration(n) && n.body)[0] as ts.ConstructorDeclaration; if (constructor) { // Add constructor plus initialization of instance fields - result.push(this.transformConstructor(constructor, className)); + result.push(this.transformConstructor(constructor, className, statement)); } else if (!isExtension && !extendsType) { // Generate a constructor if none was defined result.push(this.transformConstructor( ts.createConstructor([], [], [], ts.createBlock([], true)), - className + className, + statement )); } // Transform get accessors statement.members.filter(ts.isGetAccessor).forEach(getAccessor => { - result.push(this.transformGetAccessorDeclaration(getAccessor, className)); + result.push(this.transformGetAccessorDeclaration(getAccessor, className, statement)); }); // Transform set accessors statement.members.filter(ts.isSetAccessor).forEach(setAccessor => { - result.push(this.transformSetAccessorDeclaration(setAccessor, className)); + result.push(this.transformSetAccessorDeclaration(setAccessor, className, statement)); }); // Transform methods @@ -380,6 +402,8 @@ export class LuaTransformer { const result: tstl.Statement[] = []; + const classNameWithExport = this.addExportToIdentifier(className); + // Write class declaration if (extendsType) { const baseName = tstl.createIdentifier(extendsType.symbol.escapedName as string); @@ -392,13 +416,13 @@ export class LuaTransformer { if (!noClassOr) { // className or baseName.new() - rhs = tstl.createBinaryExpression(className, rhs, tstl.SyntaxKind.OrOperator); + rhs = tstl.createBinaryExpression(classNameWithExport, rhs, tstl.SyntaxKind.OrOperator); } // (local) className = className or baseName.new() // (local) className = baseName.new() // exports.className = baseName.new() - const classVar = this.createLocalOrGlobalDeclaration(className, rhs, undefined, statement); + const classVar = this.createLocalOrExportedOrGlobalDeclaration(className, rhs, undefined, statement); result.push(...classVar); } else { @@ -407,28 +431,28 @@ export class LuaTransformer { if (!noClassOr) { // className or {} - rhs = tstl.createBinaryExpression(className, rhs, tstl.SyntaxKind.OrOperator); + rhs = tstl.createBinaryExpression(classNameWithExport, rhs, tstl.SyntaxKind.OrOperator); } // (local) className = className or {} // (local) className = {} // exports.className = {} - const classVar = this.createLocalOrGlobalDeclaration(className, rhs, undefined, statement); + const classVar = this.createLocalOrExportedOrGlobalDeclaration(className, rhs, undefined, statement); result.push(...classVar); } // className.__index - const classIndex = tstl.createTableIndexExpression(className, tstl.createStringLiteral("__index")); + const classIndex = tstl.createTableIndexExpression(classNameWithExport, tstl.createStringLiteral("__index")); // className.__index = className - const assignClassIndex = tstl.createAssignmentStatement(classIndex, className, undefined, statement); + const assignClassIndex = tstl.createAssignmentStatement(classIndex, classNameWithExport, undefined, statement); result.push(assignClassIndex); if (extendsType) { const baseName = tstl.createIdentifier(extendsType.symbol.escapedName as string); // className.__base = baseName - const classBase = tstl.createTableIndexExpression(className, tstl.createStringLiteral("__base")); + const classBase = tstl.createTableIndexExpression(classNameWithExport, tstl.createStringLiteral("__base")); const assignClassBase = tstl.createAssignmentStatement(classBase, baseName, undefined, statement); @@ -442,7 +466,7 @@ export class LuaTransformer { this.selfIdentifier, tstl.createCallExpression( tstl.createIdentifier("setmetatable"), - [tstl.createTableExpression(), className] + [tstl.createTableExpression(), classNameWithExport] ) ); @@ -471,11 +495,11 @@ export class LuaTransformer { const ifConstructor = tstl.createIfStatement( tstl.createBinaryExpression( tstl.createIdentifier("construct"), - tstl.createTableIndexExpression(className, tstl.createStringLiteral("constructor")), + tstl.createTableIndexExpression(classNameWithExport, tstl.createStringLiteral("constructor")), tstl.SyntaxKind.AndOperator), tstl.createBlock([ tstl.createExpressionStatement(tstl.createCallExpression( - tstl.createTableIndexExpression(className, tstl.createStringLiteral("constructor")), + tstl.createTableIndexExpression(classNameWithExport, tstl.createStringLiteral("constructor")), [this.selfIdentifier, tstl.createDotsLiteral()])), ])); @@ -487,8 +511,11 @@ export class LuaTransformer { newFuncStatements.push(returnSelf); // function className.new(construct, ...) ... end + // or function export.className.new(construct, ...) ... end const newFunc = tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, tstl.createStringLiteral("new")), + tstl.createTableIndexExpression( + classNameWithExport, + tstl.createStringLiteral("new")), tstl.createFunctionExpression( tstl.createBlock(newFuncStatements), [tstl.createIdentifier("construct")], @@ -504,7 +531,8 @@ export class LuaTransformer { public transformConstructor( statement: ts.ConstructorDeclaration, - className: tstl.Identifier + className: tstl.Identifier, + classDeclaration: ts.ClassLikeDeclaration ): tstl.AssignmentStatement { // Don't transform methods without body (overload declarations) @@ -559,8 +587,11 @@ export class LuaTransformer { const body: tstl.Block = tstl.createBlock(bodyStatements); + const result = tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, tstl.createStringLiteral("constructor")), + tstl.createTableIndexExpression( + this.addExportToIdentifier(className), + tstl.createStringLiteral("constructor")), tstl.createFunctionExpression(body, params, dotsLiteral, restParamName, undefined, undefined), undefined, statement); @@ -572,7 +603,8 @@ export class LuaTransformer { public transformGetAccessorDeclaration( getAccessor: ts.GetAccessorDeclaration, - className: tstl.Identifier + className: tstl.Identifier, + classDeclaration: ts.ClassLikeDeclaration ): tstl.AssignmentStatement { const name = this.transformIdentifier(getAccessor.name as ts.Identifier); @@ -583,14 +615,17 @@ export class LuaTransformer { ); return tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, tstl.createStringLiteral("get__" + name.text)), + tstl.createTableIndexExpression( + this.addExportToIdentifier(className), + tstl.createStringLiteral("get__" + name.text)), accessorFunction ); } public transformSetAccessorDeclaration( setAccessor: ts.SetAccessorDeclaration, - className: tstl.Identifier + className: tstl.Identifier, + classDeclaration: ts.ClassLikeDeclaration ): tstl.AssignmentStatement { const name = this.transformIdentifier(setAccessor.name as ts.Identifier); @@ -605,7 +640,9 @@ export class LuaTransformer { ); return tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, tstl.createStringLiteral("set__" + name.text)), + tstl.createTableIndexExpression( + this.addExportToIdentifier(className), + tstl.createStringLiteral("set__" + name.text)), accessorFunction ); } @@ -638,8 +675,11 @@ export class LuaTransformer { restParamName ); + const parent = node.parent as ts.ClassLikeDeclaration; return tstl.createAssignmentStatement( - tstl.createTableIndexExpression(className, methodName), + tstl.createTableIndexExpression( + this.addExportToIdentifier(className), + methodName), functionExpression, undefined, node @@ -737,11 +777,11 @@ export class LuaTransformer { const namespaceDeclaration = tstl.createAssignmentStatement( tstl.createTableIndexExpression( this.transformIdentifier(this.currentNamespace.name as ts.Identifier), - this.transformIdentifier(statement.name as ts.Identifier)), + tstl.createStringLiteral(this.transformIdentifier(statement.name as ts.Identifier).text)), tstl.createBinaryExpression( tstl.createTableIndexExpression( this.transformIdentifier(this.currentNamespace.name as ts.Identifier), - this.transformIdentifier(statement.name as ts.Identifier)), + tstl.createStringLiteral(this.transformIdentifier(statement.name as ts.Identifier).text)), tstl.createTableExpression(), tstl.SyntaxKind.OrOperator)); @@ -752,20 +792,15 @@ export class LuaTransformer { this.transformIdentifier(statement.name as ts.Identifier), tstl.createTableIndexExpression( this.transformIdentifier(this.currentNamespace.name as ts.Identifier), - this.transformIdentifier(statement.name as ts.Identifier))); + tstl.createStringLiteral(this.transformIdentifier(statement.name as ts.Identifier).text))); result.push(localDeclaration); } else if (this.isModule && (ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export)) { // exports.NS = exports.NS or {} const namespaceDeclaration = tstl.createAssignmentStatement( - tstl.createTableIndexExpression( - this.transformIdentifier(ts.createIdentifier("exports")), - this.transformIdentifier(statement.name as ts.Identifier) - ), + this.createExportedIdentifier(this.transformIdentifier(statement.name as ts.Identifier)), tstl.createBinaryExpression( - tstl.createTableIndexExpression( - this.transformIdentifier(ts.createIdentifier("exports")), - this.transformIdentifier(statement.name as ts.Identifier)), + this.createExportedIdentifier(this.transformIdentifier(statement.name as ts.Identifier)), tstl.createTableExpression(), tstl.SyntaxKind.OrOperator)); @@ -774,23 +809,22 @@ export class LuaTransformer { // local NS = exports.NS const localDeclaration = tstl.createVariableDeclarationStatement( this.transformIdentifier(statement.name as ts.Identifier), - tstl.createTableIndexExpression( - this.transformIdentifier(ts.createIdentifier("exports") as ts.Identifier), - this.transformIdentifier(statement.name as ts.Identifier))); + this.createExportedIdentifier(this.transformIdentifier(statement.name as ts.Identifier))); result.push(localDeclaration); } else { // local NS = NS or {} - const localDeclaration = tstl.createVariableDeclarationStatement( + // TODO this is somewhat redundant since createLocalOrGlobalDeclaration also handles exports + const localDeclaration = this.createLocalOrExportedOrGlobalDeclaration( this.transformIdentifier(statement.name as ts.Identifier), tstl.createBinaryExpression( - tstl.createIdentifier("NS"), + this.transformIdentifier(statement.name as ts.Identifier), tstl.createTableExpression(), tstl.SyntaxKind.OrOperator ) ); - result.push(localDeclaration); + result.push(...localDeclaration); } // Set current namespace for nested NS @@ -800,7 +834,7 @@ export class LuaTransformer { // Transform moduleblock to block and visit it if (statement.body && ts.isModuleBlock(statement.body)) { - result.push(...this.transformStatements(statement.body.statements)); + result.push(tstl.createDoStatement(this.transformStatements(statement.body.statements))); } this.currentNamespace = previousNamespace; @@ -823,21 +857,21 @@ export class LuaTransformer { if (!membersOnly) { const name = this.transformIdentifier(enumDeclaration.name); const table = tstl.createTableExpression(); - result.push(...this.createLocalOrGlobalDeclaration(name, table, undefined, enumDeclaration)); + result.push(...this.createLocalOrExportedOrGlobalDeclaration(name, table, undefined, enumDeclaration)); } for (const enumMember of this.computeEnumMembers(enumDeclaration)) { const memberName = this.transformPropertyName(enumMember.name); if (membersOnly) { if (tstl.isIdentifier(memberName)) { - result.push(...this.createLocalOrGlobalDeclaration( + result.push(...this.createLocalOrExportedOrGlobalDeclaration( memberName, enumMember.value, undefined, enumDeclaration )); } else { - result.push(...this.createLocalOrGlobalDeclaration( + result.push(...this.createLocalOrExportedOrGlobalDeclaration( tstl.createIdentifier(enumMember.name.getText(), undefined, enumMember.name), enumMember.value, undefined, @@ -845,7 +879,8 @@ export class LuaTransformer { )); } } else { - const table = this.transformIdentifier(enumDeclaration.name); + const table: tstl.IdentifierOrTableIndexExpression = + this.transformIdentifierExpression(enumDeclaration.name); const property = tstl.createTableIndexExpression(table, memberName, undefined); result.push(tstl.createAssignmentStatement(property, enumMember.value, undefined, enumMember.original)); } @@ -907,7 +942,7 @@ export class LuaTransformer { ); const functionExpression = tstl.createFunctionExpression(body, params, dotsLiteral, restParamName); - return this.createLocalOrGlobalDeclaration(name, functionExpression, undefined, functionDeclaration); + return this.createLocalOrExportedOrGlobalDeclaration(name, functionExpression, undefined, functionDeclaration); } public transformTypeAliasDeclaration(statement: ts.TypeAliasDeclaration): undefined { @@ -919,7 +954,7 @@ export class LuaTransformer { } public transformVariableDeclaration(statement: ts.VariableDeclaration) - : [tstl.VariableDeclarationStatement] | [tstl.VariableDeclarationStatement, tstl.AssignmentStatement] + : tstl.Statement[] { if (statement.initializer) { // Validate assignment @@ -933,19 +968,14 @@ export class LuaTransformer { const identifierName = this.transformIdentifier(statement.name); if (statement.initializer) { const value = this.transformExpression(statement.initializer); - if (ts.isFunctionExpression(statement.initializer) || ts.isArrowFunction(statement.initializer)) { - // Separate declaration and assignment for functions to allow recursion - - // local identifierName; identifierName = value; - return [tstl.createVariableDeclarationStatement(identifierName), - tstl.createAssignmentStatement(identifierName, value)]; - } else { - // local identifierName = value; - return [tstl.createVariableDeclarationStatement(identifierName, value)]; - } + return this.createLocalOrExportedOrGlobalDeclaration(identifierName, value, undefined, statement); } else { - // local identifierName = nil; - return [tstl.createVariableDeclarationStatement(identifierName, tstl.createNilLiteral())]; + return this.createLocalOrExportedOrGlobalDeclaration( + identifierName, + tstl.createNilLiteral(), + undefined, + statement + ); } } else if (ts.isArrayBindingPattern(statement.name)) { // Destructuring type @@ -960,21 +990,27 @@ export class LuaTransformer { // Don't unpack TupleReturn decorated functions if (statement.initializer) { if (tsHelper.isTupleReturnCall(statement.initializer, this.checker)) { - // local vars = initializer; - return [tstl.createVariableDeclarationStatement( + return this.createLocalOrExportedOrGlobalDeclaration( vars, - this.transformExpression(statement.initializer) - )]; + this.transformExpression(statement.initializer), + undefined, + statement + ); } else { // local vars = this.transpileDestructingAssignmentValue(node.initializer); const initializer = this.createUnpackCall( this.transformExpression(statement.initializer), statement.initializer ); - return [tstl.createVariableDeclarationStatement(vars, initializer)]; + return this.createLocalOrExportedOrGlobalDeclaration(vars, initializer, undefined, statement); } } else { - return [tstl.createVariableDeclarationStatement(vars)]; + return this.createLocalOrExportedOrGlobalDeclaration( + vars, + tstl.createNilLiteral(), + undefined, + statement + ); } } else { throw TSTLErrors.UnsupportedKind("variable declaration", statement.name.kind, statement); @@ -1144,7 +1180,9 @@ export class LuaTransformer { if (ts.isArrayBindingPattern(initializer.declarations[0].name)) { expression = this.createUnpackCall(expression, initializer); } - return tstl.createVariableDeclarationStatement(variableDeclarations[0].left, expression); + // we can safely assume that for vars are not exported and therefore declarationstatenents + return tstl.createVariableDeclarationStatement( + (variableDeclarations[0] as tstl.VariableDeclarationStatement).left, expression); } else { // Assignment to existing variable @@ -1486,7 +1524,7 @@ export class LuaTransformer { case ts.SyntaxKind.ElementAccessExpression: return this.transformElementAccessExpression(expression as ts.ElementAccessExpression); case ts.SyntaxKind.Identifier: - return this.transformIdentifier(expression as ts.Identifier); + return this.transformIdentifierExpression(expression as ts.Identifier); case ts.SyntaxKind.StringLiteral: case ts.SyntaxKind.NoSubstitutionTemplateLiteral: return this.transformStringLiteral(expression as ts.StringLiteral); @@ -2885,21 +2923,21 @@ export class LuaTransformer { } else if (ts.isStringLiteral(propertyName)) { return this.transformStringLiteral(propertyName); } else if (ts.isNumericLiteral(propertyName)) { - const value = +propertyName.text; + const value = Number(propertyName.text); return tstl.createNumericLiteral(value, undefined, propertyName); } else { return tstl.createStringLiteral(this.transformIdentifier(propertyName).text); } } - public transformIdentifier(epxression: ts.Identifier, parent?: tstl.Node): tstl.Identifier { - if (epxression.originalKeywordKind === ts.SyntaxKind.UndefinedKeyword) { + public transformIdentifier(expression: ts.Identifier): tstl.Identifier { + if (expression.originalKeywordKind === ts.SyntaxKind.UndefinedKeyword) { return tstl.createIdentifier("nil"); // TODO this is a hack that allows use to keep Identifier // as return time as changing that would break a lot of stuff. // But this should be changed to retun tstl.createNilLiteral() // at some point. } - let escapedText = epxression.escapedText as string; + let escapedText = expression.escapedText as string; const underScoreCharCode = "_".charCodeAt(0); if (escapedText.length >= 3 && escapedText.charCodeAt(0) === underScoreCharCode && escapedText.charCodeAt(1) === underScoreCharCode && escapedText.charCodeAt(2) === underScoreCharCode) { @@ -2907,9 +2945,44 @@ export class LuaTransformer { } if (this.luaKeywords.has(escapedText)) { - throw TSTLErrors.KeywordIdentifier(epxression); + throw TSTLErrors.KeywordIdentifier(expression); + } + return tstl.createIdentifier(escapedText, undefined, expression); + } + + public transformIdentifierExpression(expression: ts.Identifier): tstl.IdentifierOrTableIndexExpression { + if (this.isIdentifierExported(expression.escapedText)) { + return this.createExportedIdentifier(this.transformIdentifier(expression)); } - return tstl.createIdentifier(escapedText, parent, epxression); + return this.transformIdentifier(expression); + } + + public isIdentifierExported(identifierName: string | ts.__String): boolean { + if (!this.isModule && !this.currentNamespace) { + return false; + } + const currentScope = this.currentNamespace ? this.currentNamespace : this.currentSourceFile; + const scopeSymbol = this.checker.getSymbolAtLocation(currentScope) + ? this.checker.getSymbolAtLocation(currentScope) + : this.checker.getTypeAtLocation(currentScope).getSymbol(); + return scopeSymbol.exports.has(identifierName as ts.__String); + } + + public addExportToIdentifier(identifier: tstl.Identifier): tstl.IdentifierOrTableIndexExpression { + if (this.isIdentifierExported(identifier.text)) { + return this.createExportedIdentifier(identifier); + } + return identifier; + } + + public createExportedIdentifier(identifier: tstl.Identifier): tstl.TableIndexExpression { + const exportTable = this.currentNamespace + ? this.transformIdentifier(this.currentNamespace.name as ts.Identifier) + : tstl.createIdentifier("exports"); + + return tstl.createTableIndexExpression( + exportTable, + tstl.createStringLiteral(identifier.text)); } public escapeString(text: string): string { @@ -3021,22 +3094,56 @@ export class LuaTransformer { return filePath.replace(new RegExp("\\\\|\/", "g"), "."); } - private createLocalOrGlobalDeclaration( + private shouldExportIdentifier(identifier: tstl.Identifier | tstl.Identifier[]): boolean { + if (!this.isModule && !this.currentNamespace) { + return false; + } + if (Array.isArray(identifier)) { + return identifier.some(i => this.isIdentifierExported(i.text)); + } else { + return this.isIdentifierExported(identifier.text); + } + } + + private createLocalOrExportedOrGlobalDeclaration( lhs: tstl.Identifier | tstl.Identifier[], rhs: tstl.Expression, parent?: tstl.Node, tsOriginal?: ts.Node ): tstl.Statement[] { - const statements: tstl.Statement[] = []; - if (this.isModule - || this.currentNamespace - || (tsOriginal && tsHelper.findFirstNodeAbove(tsOriginal, ts.isFunctionLike)) - ) { - statements.push(tstl.createVariableDeclarationStatement(lhs, undefined, parent)); - } - statements.push(tstl.createAssignmentStatement(lhs, rhs, parent, tsOriginal)); - return statements; + if (this.shouldExportIdentifier(lhs)) { + // exported + if (Array.isArray(lhs)) { + return [tstl.createAssignmentStatement(lhs.map(i => this.createExportedIdentifier(i)), rhs, parent)]; + } else { + return [tstl.createAssignmentStatement(this.createExportedIdentifier(lhs), rhs, parent)]; + } + } + + const insideFunction = this.scopeStack.some(s => s.type === ScopeType.Function); + const isLetOrConst = tsOriginal && ts.isVariableDeclaration(tsOriginal) + && (tsOriginal.parent.flags & (ts.NodeFlags.Let | ts.NodeFlags.Const)) !== 0; + if (this.isModule || this.currentNamespace || insideFunction || isLetOrConst) { + // local + const isFunction = + tsOriginal + && (ts.isFunctionDeclaration(tsOriginal) + || (ts.isVariableDeclaration(tsOriginal) && ts.isFunctionLike(tsOriginal.initializer))); + if (isFunction) { + // Separate declaration from assignment for functions to allow recursion + return [ + tstl.createVariableDeclarationStatement(lhs, undefined, parent, tsOriginal), + tstl.createAssignmentStatement(lhs, rhs, parent, tsOriginal), + ]; + } else { + return [tstl.createVariableDeclarationStatement(lhs, rhs, parent, tsOriginal)]; + } + + } else { + // global + return [tstl.createAssignmentStatement(lhs, rhs, parent, tsOriginal)]; + } } private validateFunctionAssignment(node: ts.Node, fromType: ts.Type, toType: ts.Type, toName?: string): void { diff --git a/src/TSHelper.ts b/src/TSHelper.ts index 204d6726e..2c503ec69 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -85,21 +85,6 @@ export class TSHelper { return false; } - public static isIdentifierExported( - identifier: ts.Identifier, - scope: ts.ModuleDeclaration | ts.SourceFile, - checker: ts.TypeChecker - ): boolean - { - const identifierSymbol = checker.getTypeAtLocation(scope).getSymbol(); - if (identifierSymbol.exports) -  { - return identifierSymbol.exports.has(identifier.escapedText); - } - - return false; - } - public static isInDestructingAssignment(node: ts.Node): boolean { return node.parent && ((ts.isVariableDeclaration(node.parent) && ts.isArrayBindingPattern(node.parent.name)) || (ts.isBinaryExpression(node.parent) && ts.isArrayLiteralExpression(node.parent.left))); diff --git a/test/compiler/watchmode.spec.ts b/test/compiler/watchmode.spec.ts index c943b2779..7b838316b 100644 --- a/test/compiler/watchmode.spec.ts +++ b/test/compiler/watchmode.spec.ts @@ -15,7 +15,7 @@ export class CompilerWatchModeTest { fileToChange = fileToChange; const fileToChangeOut = fileToChange.replace(".ts", ".lua"); - const child = fork(path.join(__dirname, "watcher_proccess.ts")); + const child = fork(path.join(__dirname, "watcher_proccess.js")); child.send(args); await this.waitForFileExists(fileToChangeOut, 9000) diff --git a/test/runner.ts b/test/runner.ts index dbd52cdf1..b2dfbbf2b 100644 --- a/test/runner.ts +++ b/test/runner.ts @@ -7,7 +7,7 @@ import * as path from "path"; const testSet = TestSet.create(); // add your tests -testSet.addTestsFromFiles("./test/**/*.spec.ts"); +testSet.addTestsFromFiles("./test/**/*.spec.js"); // create a test runner const testRunner = new TestRunner(); diff --git a/test/src/util.ts b/test/src/util.ts index f488341a2..a4a90f0a0 100644 --- a/test/src/util.ts +++ b/test/src/util.ts @@ -14,8 +14,8 @@ import { LuaTransformer } from "../../src/LuaTransformer"; export function transpileString(str: string, options?: CompilerOptions, ignoreDiagnostics = true): string { if (options) { - if (options.addHeader === undefined) { - options.addHeader = false; + if (options.noHeader === undefined) { + options.noHeader = true; } return compilerTranspileString(str, options, ignoreDiagnostics); } else { @@ -25,7 +25,7 @@ export function transpileString(str: string, options?: CompilerOptions, ignoreDi luaLibImport: LuaLibImportKind.Require, luaTarget: LuaTarget.Lua53, target: ts.ScriptTarget.ES2015, - addHeader: false, + noHeader: true, }, ignoreDiagnostics ); diff --git a/test/test_thread.ts b/test/test_thread.ts index 784ac3323..ffde2316f 100644 --- a/test/test_thread.ts +++ b/test/test_thread.ts @@ -1,15 +1,18 @@ import { MatchError, TestRunner, TestSet, TestOutcome } from "alsatian"; import * as JSON from "circular-json"; -module.exports = function(input, done) { +module.exports = (input, done) => { const testSet = TestSet.create(); testSet.addTestsFromFiles(input.files); const testRunner = new TestRunner(); - testRunner.onTestComplete((result) => { + let testCount = 0; + let failedTestCount = 0; + + testRunner.onTestComplete(result => { if (result.outcome === TestOutcome.Fail) { if (result.error instanceof MatchError) { - console.log(`Test ${result.testFixture.description}, ${result.test.key}(${JSON.stringify(result.testCase.caseArguments)}) Failed!`) + console.log(`Test ${result.testFixture.description}, ${result.test.key}(${JSON.stringify(result.testCase.caseArguments)}) Failed!`); console.log(" ---\n" + ' message: "' + result.error.message + @@ -23,9 +26,11 @@ module.exports = function(input, done) { result.error.expected + "\n"); } + failedTestCount++; } - }) + testCount++; + }); testRunner.run(testSet) - .then((results) => done(results, input)) + .then(() => done(testCount, failedTestCount)); }; diff --git a/test/threaded_runner.ts b/test/threaded_runner.ts index 08a304e1a..ba8f42000 100644 --- a/test/threaded_runner.ts +++ b/test/threaded_runner.ts @@ -4,6 +4,20 @@ import * as os from "os"; import * as path from "path"; import {config, Pool} from "threads"; +function fileArrToString(fileArr: string[]): string { + return fileArr.map(val => path.basename(val).replace(".spec.js", "")).join(", "); +} + +function printTestStats(testCount: number, failedTestCount: number, header: string, footer: string): void { + console.log("-----------------"); + console.log(header); + console.log(`Total: ${testCount}`); + console.log(`Passed: ${testCount - failedTestCount}`); + console.log(`Failed: ${failedTestCount}`); + console.log(footer); + console.log("-----------------"); +} + config.set({ basepath: { node: __dirname, @@ -12,45 +26,58 @@ config.set({ let cpuCount = os.cpus().length + 1; if ("TRAVIS" in process.env && "CI" in process.env) { - // fixed thread count for CI - cpuCount = 8; + // fixed thread count for CI + cpuCount = 8; } -const testFiles: string[] = glob.sync("./test/**/*.spec.ts"); +const testFiles: string[] = glob.sync("./test/**/*.spec.js"); const pool = new Pool(cpuCount); let jobCounter = 0; - -const fileArrToString = (fileArr: string[]) => - fileArr.map(val => path.basename(val).replace(".spec.ts", "")).join(", "); +const testStartTime = new Date(); +const fileCount = testFiles.length; +let exitWithError = false; +let totalTestCount = 0; +let totalFailedTestCount = 0; console.log( `Running tests: ${fileArrToString(testFiles)} with ${cpuCount} threads`); -const filesPerThread = Math.floor(testFiles.length / cpuCount); -const threadsWithMoreWork = testFiles.length % cpuCount; - -for (let i = 1; i <= cpuCount; i++) { - let files: string[] = []; - if (i <= threadsWithMoreWork) { - files = testFiles.splice(0, filesPerThread + 1); - } else { - files = testFiles.splice(0, filesPerThread); - } - console.log(`Running tests: ${fileArrToString(files)} in thread ${i}`); - - pool.run("./test_thread") - .send({files: files}) - .on("done", - (results, input) => { - jobCounter++; - console.log(`Tests ${fileArrToString(files)} ${jobCounter}/${ - cpuCount} done.`); - }) - .on("error", error => { - console.log("Exception in test:", files, error); - }); -} +testFiles.forEach(file => { + pool.run("./test_thread") + .send({files: [file]}) + .on("done", + (testCount, failedTestCount) => { + if (failedTestCount !== 0) { + exitWithError = true; + } + totalTestCount += testCount; + totalFailedTestCount += failedTestCount; + jobCounter++; + printTestStats( + testCount, + failedTestCount, + `Tests ${file} results:`, + `Thread: ${jobCounter}/${fileCount} done.`); + }) + .on("error", error => { + console.log("Fatal non test related Exception in test file:", file, error); + }); +}); pool.on("finished", () => { - console.log("Everything done, shutting down the thread pool."); - pool.killAll(); + let footer = "All tests passed!"; + if (exitWithError) { + footer = "Exiting with Error: One or more tests failed!"; + } + printTestStats(totalTestCount, totalFailedTestCount, "Final Results:", footer); + + console.log("Everything done, shutting down the thread pool."); + const timeInMs = (new Date().valueOf() - testStartTime.valueOf()); + console.log(`Tests took: ${Math.floor(timeInMs / 1000 / 60)}:${Math.floor(timeInMs / 1000) % 60}`); + + pool.killAll(); + + if (exitWithError) { + process.exit(1); + } }); + diff --git a/test/translation/lua/classExtension1.lua b/test/translation/lua/classExtension1.lua index 3aaae7b5d..ff9e5bb5d 100644 --- a/test/translation/lua/classExtension1.lua +++ b/test/translation/lua/classExtension1.lua @@ -1,2 +1,2 @@ -MyClass.myFunction = function (self) +MyClass.myFunction = function(self) end; diff --git a/test/translation/lua/classExtension2.lua b/test/translation/lua/classExtension2.lua index 826b14a59..94e8f655f 100644 --- a/test/translation/lua/classExtension2.lua +++ b/test/translation/lua/classExtension2.lua @@ -1,2 +1,2 @@ -TestClass.myFunction = function (self) +TestClass.myFunction = function(self) end; diff --git a/test/translation/lua/classExtension3.lua b/test/translation/lua/classExtension3.lua index 254b3f132..008d45956 100644 --- a/test/translation/lua/classExtension3.lua +++ b/test/translation/lua/classExtension3.lua @@ -1,4 +1,4 @@ -RenamedTestClass.myFunction = function (self) +RenamedTestClass.myFunction = function(self) end; -RenamedMyClass.myFunction = function (self) +RenamedMyClass.myFunction = function(self) end; diff --git a/test/translation/lua/classExtension4.lua b/test/translation/lua/classExtension4.lua index 46622a73d..8fcb73124 100644 --- a/test/translation/lua/classExtension4.lua +++ b/test/translation/lua/classExtension4.lua @@ -1,4 +1,4 @@ MyClass.test = "test"; MyClass.testP = "testP"; -MyClass.myFunction = function (self) +MyClass.myFunction = function(self) end; diff --git a/test/translation/lua/classPureAbstract.lua b/test/translation/lua/classPureAbstract.lua index 7fc6af804..63d61f0db 100644 --- a/test/translation/lua/classPureAbstract.lua +++ b/test/translation/lua/classPureAbstract.lua @@ -1,11 +1,11 @@ ClassB = ClassB or {}; ClassB.__index = ClassB; -ClassB.new = function (construct, ...) +ClassB.new = function(construct, ...) local self = setmetatable({}, ClassB); if construct and ClassB.constructor then ClassB.constructor(self, ...); end return self; end; -ClassB.constructor = function (self) +ClassB.constructor = function(self) end; diff --git a/test/translation/lua/functionRestArguments.lua b/test/translation/lua/functionRestArguments.lua index a1fbe94e0..25fe06c01 100644 --- a/test/translation/lua/functionRestArguments.lua +++ b/test/translation/lua/functionRestArguments.lua @@ -1,3 +1,3 @@ -varargsFunction = function (a, ...) +varargsFunction = function(a, ...) local b = ({...}); end; diff --git a/test/translation/lua/getSetAccessors.lua b/test/translation/lua/getSetAccessors.lua index 7af47a4c3..9fe62bbb6 100644 --- a/test/translation/lua/getSetAccessors.lua +++ b/test/translation/lua/getSetAccessors.lua @@ -1,18 +1,18 @@ MyClass = MyClass or {}; MyClass.__index = MyClass; -MyClass.new = function (construct, ...) +MyClass.new = function(construct, ...) local self = setmetatable({}, MyClass); if construct and MyClass.constructor then MyClass.constructor(self, ...); end return self; end; -MyClass.constructor = function (self) +MyClass.constructor = function(self) end; -MyClass.get__field = function (self) +MyClass.get__field = function(self) return self._field + 4; end; -MyClass.set__field = function (self, v) +MyClass.set__field = function(self, v) self._field = v * 2; end; local instance = MyClass.new(true); diff --git a/test/translation/lua/methodRestArguments.lua b/test/translation/lua/methodRestArguments.lua index de91da04d..236560407 100644 --- a/test/translation/lua/methodRestArguments.lua +++ b/test/translation/lua/methodRestArguments.lua @@ -1,14 +1,14 @@ MyClass = MyClass or {}; MyClass.__index = MyClass; -MyClass.new = function (construct, ...) +MyClass.new = function(construct, ...) local self = setmetatable({}, MyClass); if construct and MyClass.constructor then MyClass.constructor(self, ...); end return self; end; -MyClass.constructor = function (self) +MyClass.constructor = function(self) end; -MyClass.varargsFunction = function (self, a, ...) +MyClass.varargsFunction = function(self, a, ...) local b = ({...}); end; diff --git a/test/translation/lua/modulesChangedVariableExport.lua b/test/translation/lua/modulesChangedVariableExport.lua index 0c5c579bf..2776db6f6 100644 --- a/test/translation/lua/modulesChangedVariableExport.lua +++ b/test/translation/lua/modulesChangedVariableExport.lua @@ -1,5 +1,4 @@ -local exports = exports or {} -local test = nil; -test = 1; -exports.test = test -return exports \ No newline at end of file +local exports = exports or {}; +exports.test = nil; +exports.test = 1; +return exports; \ No newline at end of file diff --git a/test/translation/lua/modulesClassExport.lua b/test/translation/lua/modulesClassExport.lua index 9e09cb61f..a339f9482 100644 --- a/test/translation/lua/modulesClassExport.lua +++ b/test/translation/lua/modulesClassExport.lua @@ -1,12 +1,13 @@ -local exports = exports or {} -local TestClass = TestClass or {} -TestClass.__index = TestClass -function TestClass.new(construct, ...) - local self = setmetatable({}, TestClass) - if construct and TestClass.constructor then TestClass.constructor(self, ...) end - return self -end -function TestClass.constructor(self) -end -exports.TestClass = TestClass -return exports +local exports = exports or {}; +exports.TestClass = exports.TestClass or {}; +exports.TestClass.__index = exports.TestClass; +exports.TestClass.new = function(construct, ...) + local self = setmetatable({}, exports.TestClass); + if construct and exports.TestClass.constructor then + exports.TestClass.constructor(self, ...); + end + return self; +end; +exports.TestClass.constructor = function(self) +end; +return exports; diff --git a/test/translation/lua/modulesClassWithMemberExport.lua b/test/translation/lua/modulesClassWithMemberExport.lua index 4f09fd29c..655d142c8 100644 --- a/test/translation/lua/modulesClassWithMemberExport.lua +++ b/test/translation/lua/modulesClassWithMemberExport.lua @@ -1,14 +1,15 @@ -local exports = exports or {} -local TestClass = TestClass or {} -TestClass.__index = TestClass -function TestClass.new(construct, ...) - local self = setmetatable({}, TestClass) - if construct and TestClass.constructor then TestClass.constructor(self, ...) end - return self -end -function TestClass.constructor(self) -end -function TestClass.memberFunc(self) -end -exports.TestClass = TestClass -return exports +local exports = exports or {}; +exports.TestClass = exports.TestClass or {}; +exports.TestClass.__index = exports.TestClass; +exports.TestClass.new = function(construct, ...) + local self = setmetatable({}, exports.TestClass); + if construct and exports.TestClass.constructor then + exports.TestClass.constructor(self, ...); + end + return self; +end; +exports.TestClass.constructor = function(self) +end; +exports.TestClass.memberFunc = function(self) +end; +return exports; diff --git a/test/translation/lua/modulesFunctionExport.lua b/test/translation/lua/modulesFunctionExport.lua index 5b447e5b2..12e69553c 100644 --- a/test/translation/lua/modulesFunctionExport.lua +++ b/test/translation/lua/modulesFunctionExport.lua @@ -1,5 +1,4 @@ -local exports = exports or {} -local function publicFunc() -end -exports.publicFunc = publicFunc -return exports +local exports = exports or {}; +exports.publicFunc = function() +end; +return exports; diff --git a/test/translation/lua/modulesFunctionNoExport.lua b/test/translation/lua/modulesFunctionNoExport.lua index 490b4a36f..37ea15ea9 100644 --- a/test/translation/lua/modulesFunctionNoExport.lua +++ b/test/translation/lua/modulesFunctionNoExport.lua @@ -1,2 +1,2 @@ -publicFunc = function () +publicFunc = function() end; diff --git a/test/translation/lua/modulesNamespaceExport.lua b/test/translation/lua/modulesNamespaceExport.lua index 1572312b2..122f64cf0 100644 --- a/test/translation/lua/modulesNamespaceExport.lua +++ b/test/translation/lua/modulesNamespaceExport.lua @@ -1,6 +1,6 @@ -local exports = exports or {} -local TestSpace = exports.TestSpace or TestSpace or {} +local exports = exports or {}; +exports.TestSpace = exports.TestSpace or {}; +local TestSpace = exports.TestSpace; do end -exports.TestSpace = TestSpace -return exports +return exports; diff --git a/test/translation/lua/modulesNamespaceExportEnum.lua b/test/translation/lua/modulesNamespaceExportEnum.lua index 002807a03..938fdd56b 100644 --- a/test/translation/lua/modulesNamespaceExportEnum.lua +++ b/test/translation/lua/modulesNamespaceExportEnum.lua @@ -1,10 +1,9 @@ -local exports = exports or {} -local test = exports.test or test or {} +local exports = exports or {}; +exports.test = exports.test or {}; +local test = exports.test; do - local TestEnum={} - TestEnum.foo="foo" - TestEnum.bar="bar" - test.TestEnum = TestEnum + test.TestEnum = {}; + test.TestEnum.foo = "foo"; + test.TestEnum.bar = "bar"; end -exports.test = test -return exports +return exports; diff --git a/test/translation/lua/modulesNamespaceNestedWithMemberExport.lua b/test/translation/lua/modulesNamespaceNestedWithMemberExport.lua index 326a00294..44509f50d 100644 --- a/test/translation/lua/modulesNamespaceNestedWithMemberExport.lua +++ b/test/translation/lua/modulesNamespaceNestedWithMemberExport.lua @@ -1,13 +1,12 @@ -local exports = exports or {} -local TestSpace = exports.TestSpace or TestSpace or {} +local exports = exports or {}; +exports.TestSpace = exports.TestSpace or {}; +local TestSpace = exports.TestSpace; do - local TestNestedSpace = TestNestedSpace or {} + TestSpace.TestNestedSpace = TestSpace.TestNestedSpace or {}; + local TestNestedSpace = TestSpace.TestNestedSpace; do - local function innerFunc() - end - TestNestedSpace.innerFunc = innerFunc + TestNestedSpace.innerFunc = function() + end; end - TestSpace.TestNestedSpace = TestNestedSpace end -exports.TestSpace = TestSpace -return exports +return exports; diff --git a/test/translation/lua/modulesNamespaceNoExport.lua b/test/translation/lua/modulesNamespaceNoExport.lua index 5c9ff3a1f..9f4892365 100644 --- a/test/translation/lua/modulesNamespaceNoExport.lua +++ b/test/translation/lua/modulesNamespaceNoExport.lua @@ -1,3 +1,3 @@ -TestSpace = TestSpace or {} +TestSpace = TestSpace or {}; do end diff --git a/test/translation/lua/modulesNamespaceWithMemberExport.lua b/test/translation/lua/modulesNamespaceWithMemberExport.lua index 7e9204160..020bcf4d5 100644 --- a/test/translation/lua/modulesNamespaceWithMemberExport.lua +++ b/test/translation/lua/modulesNamespaceWithMemberExport.lua @@ -1,9 +1,8 @@ -local exports = exports or {} -local TestSpace = exports.TestSpace or TestSpace or {} +local exports = exports or {}; +exports.TestSpace = exports.TestSpace or {}; +local TestSpace = exports.TestSpace; do - local function innerFunc() - end - TestSpace.innerFunc = innerFunc + TestSpace.innerFunc = function() + end; end -exports.TestSpace = TestSpace -return exports +return exports; diff --git a/test/translation/lua/modulesNamespaceWithMemberNoExport.lua b/test/translation/lua/modulesNamespaceWithMemberNoExport.lua index a2afe84fe..b0abeb433 100644 --- a/test/translation/lua/modulesNamespaceWithMemberNoExport.lua +++ b/test/translation/lua/modulesNamespaceWithMemberNoExport.lua @@ -1,8 +1,9 @@ -local exports = exports or {} -local TestSpace = exports.TestSpace or TestSpace or {} +local exports = exports or {}; +exports.TestSpace = exports.TestSpace or {}; +local TestSpace = exports.TestSpace; do - local function innerFunc() - end + local innerFunc; + innerFunc = function() + end; end -exports.TestSpace = TestSpace -return exports +return exports; diff --git a/test/translation/lua/modulesVariableExport.lua b/test/translation/lua/modulesVariableExport.lua index 3ecfdc4c3..76c98810f 100644 --- a/test/translation/lua/modulesVariableExport.lua +++ b/test/translation/lua/modulesVariableExport.lua @@ -1,4 +1,3 @@ -local exports = exports or {} -local test = "test"; -exports.test = test -return exports +local exports = exports or {}; +exports.test = "test"; +return exports; diff --git a/test/translation/lua/namespace.lua b/test/translation/lua/namespace.lua index c5a266c7f..bdf6664fd 100644 --- a/test/translation/lua/namespace.lua +++ b/test/translation/lua/namespace.lua @@ -1,5 +1,6 @@ -myNamespace = myNamespace or {} +myNamespace = myNamespace or {}; do - local function nsMember() - end + local nsMember; + nsMember = function() + end; end diff --git a/test/translation/lua/namespaceMerge.lua b/test/translation/lua/namespaceMerge.lua index 58e982078..e585c3c83 100644 --- a/test/translation/lua/namespaceMerge.lua +++ b/test/translation/lua/namespaceMerge.lua @@ -1,30 +1,31 @@ -MergedClass = MergedClass or {} -MergedClass.__index = MergedClass -function MergedClass.new(construct, ...) - local self = setmetatable({}, MergedClass) +MergedClass = MergedClass or {}; +MergedClass.__index = MergedClass; +MergedClass.new = function(construct, ...) + local self = setmetatable({}, MergedClass); self.propertyFunc = function(____) -end - if construct and MergedClass.constructor then MergedClass.constructor(self, ...) end - return self -end -function MergedClass.constructor(self) -end -function MergedClass.staticMethodA(self) -end -function MergedClass.staticMethodB(self) + end; + if construct and MergedClass.constructor then + MergedClass.constructor(self, ...); + end + return self; +end; +MergedClass.constructor = function(self) +end; +MergedClass.staticMethodA = function(self) +end; +MergedClass.staticMethodB = function(self) self:staticMethodA(); -end -function MergedClass.methodA(self) -end -function MergedClass.methodB(self) +end; +MergedClass.methodA = function(self) +end; +MergedClass.methodB = function(self) self:methodA(); self:propertyFunc(); -end -MergedClass = MergedClass or {} +end; +MergedClass = MergedClass or {}; do - local function namespaceFunc() - end - MergedClass.namespaceFunc = namespaceFunc + MergedClass.namespaceFunc = function() + end; end local mergedClass = MergedClass.new(true); mergedClass:methodB(); diff --git a/test/translation/lua/namespaceNested.lua b/test/translation/lua/namespaceNested.lua index bff87b32e..dd1006ee9 100644 --- a/test/translation/lua/namespaceNested.lua +++ b/test/translation/lua/namespaceNested.lua @@ -1,8 +1,10 @@ -myNamespace = myNamespace or {} +myNamespace = myNamespace or {}; do - local myNestedNamespace = myNestedNamespace or {} + myNamespace.myNestedNamespace = myNamespace.myNestedNamespace or {}; + local myNestedNamespace = myNamespace.myNestedNamespace; do - local function nsMember() - end + local nsMember; + nsMember = function() + end; end end diff --git a/test/translation/lua/namespacePhantom.lua b/test/translation/lua/namespacePhantom.lua index 86727cc4c..3844b51be 100644 --- a/test/translation/lua/namespacePhantom.lua +++ b/test/translation/lua/namespacePhantom.lua @@ -1,2 +1,2 @@ -nsMember = function () +nsMember = function() end; diff --git a/test/translation/lua/returnDefault.lua b/test/translation/lua/returnDefault.lua index df97fc8ea..a0e35c570 100644 --- a/test/translation/lua/returnDefault.lua +++ b/test/translation/lua/returnDefault.lua @@ -1,3 +1,3 @@ -myFunc = function () +myFunc = function() return; end; diff --git a/test/translation/lua/shorthandPropertyAssignment.lua b/test/translation/lua/shorthandPropertyAssignment.lua index 3be2aad3b..0c5898188 100644 --- a/test/translation/lua/shorthandPropertyAssignment.lua +++ b/test/translation/lua/shorthandPropertyAssignment.lua @@ -1,4 +1,4 @@ local f; -f = function (x) +f = function(x) return ({x = x}); end; diff --git a/test/translation/lua/tryCatch.lua b/test/translation/lua/tryCatch.lua index 46dfea6c0..f3194765e 100644 --- a/test/translation/lua/tryCatch.lua +++ b/test/translation/lua/tryCatch.lua @@ -1,5 +1,5 @@ do - local ____TS_try, er = pcall(function () + local ____TS_try, er = pcall(function() local a = 42; end); if not ____TS_try then diff --git a/test/translation/lua/tryCatchFinally.lua b/test/translation/lua/tryCatchFinally.lua index 64b54da9e..4b5caf9a6 100644 --- a/test/translation/lua/tryCatchFinally.lua +++ b/test/translation/lua/tryCatchFinally.lua @@ -1,5 +1,5 @@ do - local ____TS_try, er = pcall(function () + local ____TS_try, er = pcall(function() local a = 42; end); if not ____TS_try then diff --git a/test/translation/lua/tryFinally.lua b/test/translation/lua/tryFinally.lua index 91b09f1a2..a117b8bb2 100644 --- a/test/translation/lua/tryFinally.lua +++ b/test/translation/lua/tryFinally.lua @@ -1,5 +1,5 @@ do - pcall(function () + pcall(function() local a = 42; end); do diff --git a/test/translation/lua/tupleReturn.lua b/test/translation/lua/tupleReturn.lua index 85815cad7..a75c85272 100644 --- a/test/translation/lua/tupleReturn.lua +++ b/test/translation/lua/tupleReturn.lua @@ -1,4 +1,4 @@ -tupleReturn = function () +tupleReturn = function() return 0, "foobar"; end; tupleReturn(); @@ -13,16 +13,16 @@ e = ({tupleReturn()}); f = noTupleReturn(); foo(({tupleReturn()})); foo(noTupleReturn()); -tupleReturnFromVar = function () +tupleReturnFromVar = function() local r = {1, "baz"}; return table.unpack(r); end; -tupleReturnForward = function () +tupleReturnForward = function() return tupleReturn(); end; -tupleNoForward = function () +tupleNoForward = function() return ({tupleReturn()}); end; -tupleReturnUnpack = function () +tupleReturnUnpack = function() return table.unpack(tupleNoForward()); end; diff --git a/test/translation/ts/getSetAccessors.ts b/test/translation/ts/getSetAccessors.ts index 714be88a8..b721f0f0b 100644 --- a/test/translation/ts/getSetAccessors.ts +++ b/test/translation/ts/getSetAccessors.ts @@ -8,7 +8,7 @@ class MyClass { } } -var instance = new MyClass(); +let instance = new MyClass(); instance.field = 4; const b = instance.field; -const c = (4 + instance.field)*3; \ No newline at end of file +const c = (4 + instance.field)*3; diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index 814069201..badd03262 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -41,7 +41,7 @@ export class AssignmentTests { @TestCase("true", "true") @TestCase("false", "false") @TestCase(`{a:3,b:"4"}`, `{a = 3, b = "4"}`) - @Test("Const assignment") + @Test("Let assignment") public letAssignment(inp: string, out: string): void { const lua = util.transpileString(`let myvar = ${inp};`); Expect(lua).toBe(`local myvar = ${out};`); @@ -53,10 +53,10 @@ export class AssignmentTests { @TestCase("true", "true") @TestCase("false", "false") @TestCase(`{a:3,b:"4"}`, `{a = 3, b = "4"}`) - @Test("Const assignment") + @Test("Var assignment") public varAssignment(inp: string, out: string): void { const lua = util.transpileString(`var myvar = ${inp};`); - Expect(lua).toBe(`local myvar = ${out};`); + Expect(lua).toBe(`myvar = ${out};`); } @TestCase("var myvar;") diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 17580493d..8f5f8e716 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -13,9 +13,9 @@ export class ExpressionTests { @TestCase("--i", "i = i - 1;") @TestCase("!a", "not a;") @TestCase("-a", "-a;") - @TestCase("let a = delete tbl['test']", "local a = (function ()\n tbl.test = nil;\n return true;\nend)();") + @TestCase("let a = delete tbl['test']", "local a = (function()\n tbl.test = nil;\n return true;\nend)();") @TestCase("delete tbl['test']", "tbl.test = nil;") - @TestCase("let a = delete tbl.test", "local a = (function ()\n tbl.test = nil;\n return true;\nend)();") + @TestCase("let a = delete tbl.test", "local a = (function()\n tbl.test = nil;\n return true;\nend)();") @TestCase("delete tbl.test", "tbl.test = nil;") @Test("Unary expressions basic") public unaryBasic(input: string, lua: string): void { @@ -204,14 +204,6 @@ export class ExpressionTests { @TestCase("true ? undefined : true", undefined, { luaTarget: LuaTarget.LuaJIT }) @Test("Ternary operator") public ternaryOperator(input: string, expected: any, options?: ts.CompilerOptions): void { - console.log(util.transpileString( - `const literalValue = 'literal'; - let variableValue:string; - let maybeBooleanValue:string|boolean = false; - let maybeUndefinedValue:string|undefined; - return ${input};`, options - - )); const result = util.transpileAndExecute( `const literalValue = 'literal'; let variableValue:string;