From 0724d18933d2589f664ed5d08555ffaa41ca0623 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Thu, 9 Jan 2020 22:13:23 +0100 Subject: [PATCH 01/10] Fixed inconsistent scoping of top-level variable declarations --- src/transformation/utils/lua-ast.ts | 3 +- .../__snapshots__/transformation.spec.ts.snap | 36 +++++++++------ .../transformation/topLevelVariables.ts | 6 +++ test/unit/assignments.spec.ts | 18 ++++++-- test/unit/objectLiteral.spec.ts | 46 ++++++++----------- 5 files changed, 64 insertions(+), 45 deletions(-) create mode 100644 test/translation/transformation/topLevelVariables.ts diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index a04c69035..8cc29b7d7 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -122,7 +122,6 @@ export function createLocalOrExportedOrGlobalDeclaration( let declaration: lua.VariableDeclarationStatement | undefined; let assignment: lua.AssignmentStatement | undefined; - const isVariableDeclaration = tsOriginal !== undefined && ts.isVariableDeclaration(tsOriginal); const isFunctionDeclaration = tsOriginal !== undefined && ts.isFunctionDeclaration(tsOriginal); const identifiers = Array.isArray(lhs) ? lhs : [lhs]; @@ -145,7 +144,7 @@ export function createLocalOrExportedOrGlobalDeclaration( } else { const insideFunction = findScope(context, ScopeType.Function) !== undefined; - if (context.isModule || getCurrentNamespace(context) || insideFunction || isVariableDeclaration) { + if (context.isModule || getCurrentNamespace(context) || insideFunction) { const scope = peekScope(context); const isPossibleWrappedFunction = diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index 6d64751eb..67d5443e4 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -1,18 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Transformation (characterEscapeSequence) 1`] = ` -"local quoteInDoubleQuotes = \\"' ' '\\" -local quoteInTemplateString = \\"' ' '\\" -local doubleQuoteInQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" -local doubleQuoteInDoubleQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" -local doubleQuoteInTemplateString = \\"\\\\\\" \\\\\\" \\\\\\"\\" -local backQuoteInQuotes = \\"\` \` \`\\" -local backQuoteInDoubleQuotes = \\"\` \` \`\\" -local backQuoteInTemplateString = \\"\` \` \`\\" -local escapedCharsInQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" -local escapedCharsInDoubleQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" -local escapedCharsInTemplateString = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" -local nonEmptyTemplateString = \\"Level 0: \\\\n\\\\t \\" .. \\"Level 1: \\\\n\\\\t\\\\t \\" .. \\"Level 3: \\\\n\\\\t\\\\t\\\\t \\" .. \\"Last level \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\"" +"quoteInDoubleQuotes = \\"' ' '\\" +quoteInTemplateString = \\"' ' '\\" +doubleQuoteInQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" +doubleQuoteInDoubleQuotes = \\"\\\\\\" \\\\\\" \\\\\\"\\" +doubleQuoteInTemplateString = \\"\\\\\\" \\\\\\" \\\\\\"\\" +backQuoteInQuotes = \\"\` \` \`\\" +backQuoteInDoubleQuotes = \\"\` \` \`\\" +backQuoteInTemplateString = \\"\` \` \`\\" +escapedCharsInQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" +escapedCharsInDoubleQuotes = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" +escapedCharsInTemplateString = \\"\\\\\\\\ \\\\0 \\\\b \\\\t \\\\n \\\\v \\\\f \\\\\\" ' \`\\" +nonEmptyTemplateString = \\"Level 0: \\\\n\\\\t \\" .. \\"Level 1: \\\\n\\\\t\\\\t \\" .. \\"Level 3: \\\\n\\\\t\\\\t\\\\t \\" .. \\"Last level \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\" .. \\" \\\\n --\\"" `; exports[`Transformation (classExtension1) 1`] = ` @@ -244,7 +244,7 @@ ____exports.foo = \\"bar\\" return ____exports" `; -exports[`Transformation (modulesVariableNoExport) 1`] = `"local foo = \\"bar\\""`; +exports[`Transformation (modulesVariableNoExport) 1`] = `"foo = \\"bar\\""`; exports[`Transformation (namespacePhantom) 1`] = ` "function nsMember(self) @@ -257,6 +257,16 @@ exports[`Transformation (returnDefault) 1`] = ` end" `; +exports[`Transformation (topLevelVariables) 1`] = ` +"obj = {value1 = 1, value2 = 2} +value1 = obj.value1 +value2 = obj.value2 +function fun1(self) +end +fun2 = function() +end" +`; + exports[`Transformation (unusedDefaultWithNamespaceImport) 1`] = ` "local ____exports = {} local x = require(\\"module\\") diff --git a/test/translation/transformation/topLevelVariables.ts b/test/translation/transformation/topLevelVariables.ts new file mode 100644 index 000000000..6007ad21b --- /dev/null +++ b/test/translation/transformation/topLevelVariables.ts @@ -0,0 +1,6 @@ +const obj = { value1: 1, value2: 2 }; +const value1 = obj.value1; +const { value2 } = obj; + +function fun1(): void {} +const fun2 = () => {}; \ No newline at end of file diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index c559690d0..19c248edb 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -1,13 +1,23 @@ import * as util from "../util"; test("const declaration", () => { - const lua = util.transpileString(`const foo = true;`); - expect(lua).toBe(`local foo = true`); + const lua = util.testFunction`const foo = true;`.getMainLuaCodeChunk(); + expect(lua).toContain(`local foo = true`); }); test("let declaration", () => { - const lua = util.transpileString(`let foo = true;`); - expect(lua).toBe(`local foo = true`); + const lua = util.testFunction`let foo = true;`.getMainLuaCodeChunk(); + expect(lua).toContain(`local foo = true`); +}); + +test("const declaration top-level is global", () => { + const lua = util.testModule`const foo = true;`.getMainLuaCodeChunk(); + expect(lua).toBe(`foo = true`); +}); + +test("let declaration top-level is global", () => { + const lua = util.testModule`let foo = true;`.getMainLuaCodeChunk(); + expect(lua).toBe(`foo = true`); }); test("var declaration is disallowed", () => { diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index b4bcb3d4e..a36ef0d26 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -8,59 +8,53 @@ test.each([ { inp: `{[myFunc()]:3,b:"4"}`, out: '{\n [myFunc(_G)] = 3,\n b = "4"\n}' }, { inp: `{x}`, out: `{x = x}` }, ])("Object Literal (%p)", ({ inp, out }) => { - const lua = util.transpileString(`const myvar = ${inp};`); - expect(lua).toBe(`local myvar = ${out}`); + const lua = util.testModule`const myvar = ${inp};`.getMainLuaCodeChunk(); + expect(lua).toBe(`myvar = ${out}`); }); describe("property shorthand", () => { test("should support property shorthand", () => { - const result = util.transpileAndExecute(` + util.testFunction` const x = 1; const o = { x }; return o.x; - `); - - expect(result).toBe(1); + `.expectToMatchJsResult(); }); test.each([NaN, Infinity])("should support %p shorthand", identifier => { - const result = util.transpileAndExecute(`return ({ ${identifier} }).${identifier}`); - - expect(result).toBe(identifier); + util.testFunction`return ({ ${identifier} }).${identifier}`.expectToMatchJsResult(); }); test("should support _G shorthand", () => { - const result = util.transpileAndExecute( - `return ({ _G })._G.foobar;`, - undefined, - `foobar = "foobar"`, - "declare const _G: any;" - ); - - expect(result).toBe("foobar"); + const luaResult = util.testFunction` + return ({ _G })._G.foobar; + ` + .setTsHeader(`declare const _G: any;`) + .setLuaHeader(`foobar = "foobar"`) + .getLuaExecutionResult(); + + expect(luaResult).toEqual("foobar"); }); test("should support export property shorthand", () => { - const code = ` + util.testModule` export const x = 1; const o = { x }; export const y = o.x; - `; - expect(util.transpileExecuteAndReturnExport(code, "y")).toBe(1); + `.expectToMatchJsResult(); }); }); test("undefined as object key", () => { - const code = `const foo = {undefined: "foo"}; - return foo.undefined;`; - expect(util.transpileAndExecute(code)).toBe("foo"); + util.testFunction` + const foo = {undefined: "foo"}; + return foo.undefined; + `.expectToMatchJsResult(); }); test.each([`({x: "foobar"}.x)`, `({x: "foobar"}["x"])`, `({x: () => "foobar"}.x())`, `({x: () => "foobar"}["x"]())`])( "object literal property access (%p)", expression => { - const code = `return ${expression}`; - const expectResult = eval(expression); - expect(util.transpileAndExecute(code)).toBe(expectResult); + util.testFunction`return ${expression}`.expectToMatchJsResult(); } ); From 8df49ddd35480a54cbd2a9b025efde9e29860c1f Mon Sep 17 00:00:00 2001 From: Perryvw Date: Thu, 9 Jan 2020 22:22:15 +0100 Subject: [PATCH 02/10] Added let variables in transformation test --- test/translation/__snapshots__/transformation.spec.ts.snap | 3 +++ test/translation/transformation/topLevelVariables.ts | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index 67d5443e4..22439ed14 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -261,6 +261,9 @@ exports[`Transformation (topLevelVariables) 1`] = ` "obj = {value1 = 1, value2 = 2} value1 = obj.value1 value2 = obj.value2 +obj2 = {value3 = 1, value4 = 2} +value3 = obj2.value3 +value4 = obj2.value4 function fun1(self) end fun2 = function() diff --git a/test/translation/transformation/topLevelVariables.ts b/test/translation/transformation/topLevelVariables.ts index 6007ad21b..c37d57978 100644 --- a/test/translation/transformation/topLevelVariables.ts +++ b/test/translation/transformation/topLevelVariables.ts @@ -2,5 +2,9 @@ const obj = { value1: 1, value2: 2 }; const value1 = obj.value1; const { value2 } = obj; +let obj2 = { value3: 1, value4: 2 }; +let value3 = obj2.value3; +let { value4 } = obj2; + function fun1(): void {} -const fun2 = () => {}; \ No newline at end of file +const fun2 = () => {}; From 22a871d04789f2561e3afda0714a2ccd6d7312c1 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Thu, 9 Jan 2020 22:39:46 +0100 Subject: [PATCH 03/10] Added handling for variables in block scope, addressed some PR feedback --- src/transformation/utils/lua-ast.ts | 3 ++- .../__snapshots__/transformation.spec.ts.snap | 9 +++++++++ .../transformation/blockScopeVariables.ts | 5 +++++ test/unit/assignments.spec.ts | 14 ++++++-------- test/unit/objectLiteral.spec.ts | 12 ++++-------- 5 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 test/translation/transformation/blockScopeVariables.ts diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index 8cc29b7d7..fcb8a863b 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -143,8 +143,9 @@ export function createLocalOrExportedOrGlobalDeclaration( } } else { const insideFunction = findScope(context, ScopeType.Function) !== undefined; + const insideBlock = findScope(context, ScopeType.Block) !== undefined; - if (context.isModule || getCurrentNamespace(context) || insideFunction) { + if (context.isModule || getCurrentNamespace(context) || insideFunction || insideBlock) { const scope = peekScope(context); const isPossibleWrappedFunction = diff --git a/test/translation/__snapshots__/transformation.spec.ts.snap b/test/translation/__snapshots__/transformation.spec.ts.snap index 22439ed14..f4e2ce661 100644 --- a/test/translation/__snapshots__/transformation.spec.ts.snap +++ b/test/translation/__snapshots__/transformation.spec.ts.snap @@ -1,5 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Transformation (blockScopeVariables) 1`] = ` +"do + local a = 1 + local b = 1 + local ____ = {c = 1} + local c = ____.c +end" +`; + exports[`Transformation (characterEscapeSequence) 1`] = ` "quoteInDoubleQuotes = \\"' ' '\\" quoteInTemplateString = \\"' ' '\\" diff --git a/test/translation/transformation/blockScopeVariables.ts b/test/translation/transformation/blockScopeVariables.ts new file mode 100644 index 000000000..7623f0efa --- /dev/null +++ b/test/translation/transformation/blockScopeVariables.ts @@ -0,0 +1,5 @@ +{ + const a = 1; + const [b] = [1]; + const { c } = { c: 1 }; +} diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index 19c248edb..97d3e8e9d 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -10,14 +10,12 @@ test("let declaration", () => { expect(lua).toContain(`local foo = true`); }); -test("const declaration top-level is global", () => { - const lua = util.testModule`const foo = true;`.getMainLuaCodeChunk(); - expect(lua).toBe(`foo = true`); -}); - -test("let declaration top-level is global", () => { - const lua = util.testModule`let foo = true;`.getMainLuaCodeChunk(); - expect(lua).toBe(`foo = true`); +test.each(["const", "let"])("%s declaration top-level is global", declarationKind => { + util.testModule` + ${declarationKind} foo = true; + // @ts-ignore + return (globalThis as any).foo; + `.expectToEqual(true); }); test("var declaration is disallowed", () => { diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index a36ef0d26..d45378e93 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -22,18 +22,14 @@ describe("property shorthand", () => { }); test.each([NaN, Infinity])("should support %p shorthand", identifier => { - util.testFunction`return ({ ${identifier} }).${identifier}`.expectToMatchJsResult(); + util.testExpression`({ ${identifier} }).${identifier}`.expectToMatchJsResult(); }); test("should support _G shorthand", () => { - const luaResult = util.testFunction` - return ({ _G })._G.foobar; - ` + util.testExpression`({ _G })._G.foobar` .setTsHeader(`declare const _G: any;`) .setLuaHeader(`foobar = "foobar"`) - .getLuaExecutionResult(); - - expect(luaResult).toEqual("foobar"); + .expectToEqual("foobar"); }); test("should support export property shorthand", () => { @@ -55,6 +51,6 @@ test("undefined as object key", () => { test.each([`({x: "foobar"}.x)`, `({x: "foobar"}["x"])`, `({x: () => "foobar"}.x())`, `({x: () => "foobar"}["x"]())`])( "object literal property access (%p)", expression => { - util.testFunction`return ${expression}`.expectToMatchJsResult(); + util.testExpression(expression).expectToMatchJsResult(); } ); From 3eac0758628e8cbc706e0ad6151569a5afe6e82c Mon Sep 17 00:00:00 2001 From: Perryvw Date: Fri, 10 Jan 2020 21:51:39 +0100 Subject: [PATCH 04/10] simplified ast declaration logic --- src/transformation/utils/lua-ast.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index fcb8a863b..0176e02ed 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -1,11 +1,10 @@ -import * as ts from "typescript"; import * as assert from "assert"; +import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { getCurrentNamespace } from "../visitors/namespace"; import { createExportedIdentifier, getIdentifierExportScope } from "./export"; -import { findScope, peekScope, ScopeType } from "./scope"; +import { peekScope, ScopeType } from "./scope"; import { isFunctionType } from "./typescript"; export type OneToManyVisitorResult = T | T[] | undefined; @@ -142,10 +141,12 @@ export function createLocalOrExportedOrGlobalDeclaration( ); } } else { - const insideFunction = findScope(context, ScopeType.Function) !== undefined; - const insideBlock = findScope(context, ScopeType.Block) !== undefined; + const isTopLevelVariable = peekScope(context).type === ScopeType.File; - if (context.isModule || getCurrentNamespace(context) || insideFunction || insideBlock) { + if (rhs && isTopLevelVariable && !context.isModule) { + // top-level declarations in non-module files are considered global + assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal); + } else { const scope = peekScope(context); const isPossibleWrappedFunction = @@ -175,11 +176,6 @@ export function createLocalOrExportedOrGlobalDeclaration( declaration = undefined; } } - } else if (rhs) { - // global - assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal); - } else { - return []; } } From 93bddac8202cdd59fa19782ee2735de745189005 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 11 Jan 2020 15:18:37 +0100 Subject: [PATCH 05/10] reverted if statement refactor, some changes to tests --- src/transformation/utils/lua-ast.ts | 16 +++++++++------- .../transformation/topLevelVariables.ts | 1 + test/unit/objectLiteral.spec.ts | 4 +++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index 0176e02ed..ef65c2beb 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -3,6 +3,7 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; +import { getCurrentNamespace } from "../visitors/namespace"; import { createExportedIdentifier, getIdentifierExportScope } from "./export"; import { peekScope, ScopeType } from "./scope"; import { isFunctionType } from "./typescript"; @@ -141,14 +142,10 @@ export function createLocalOrExportedOrGlobalDeclaration( ); } } else { - const isTopLevelVariable = peekScope(context).type === ScopeType.File; - - if (rhs && isTopLevelVariable && !context.isModule) { - // top-level declarations in non-module files are considered global - assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal); - } else { - const scope = peekScope(context); + const scope = peekScope(context); + const isTopLevelVariable = scope.type === ScopeType.File; + if (context.isModule || getCurrentNamespace(context) || !isTopLevelVariable) { const isPossibleWrappedFunction = !isFunctionDeclaration && tsOriginal && @@ -176,6 +173,11 @@ export function createLocalOrExportedOrGlobalDeclaration( declaration = undefined; } } + } else if (rhs) { + // global + assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal); + } else { + return []; } } diff --git a/test/translation/transformation/topLevelVariables.ts b/test/translation/transformation/topLevelVariables.ts index c37d57978..5782c4cf4 100644 --- a/test/translation/transformation/topLevelVariables.ts +++ b/test/translation/transformation/topLevelVariables.ts @@ -2,6 +2,7 @@ const obj = { value1: 1, value2: 2 }; const value1 = obj.value1; const { value2 } = obj; +let noValueLet; let obj2 = { value3: 1, value4: 2 }; let value3 = obj2.value3; let { value4 } = obj2; diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index d45378e93..a8cd2b0ad 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -8,7 +8,9 @@ test.each([ { inp: `{[myFunc()]:3,b:"4"}`, out: '{\n [myFunc(_G)] = 3,\n b = "4"\n}' }, { inp: `{x}`, out: `{x = x}` }, ])("Object Literal (%p)", ({ inp, out }) => { - const lua = util.testModule`const myvar = ${inp};`.getMainLuaCodeChunk(); + const lua = util.testModule` + const myvar = ${inp}; + `.getMainLuaCodeChunk(); expect(lua).toBe(`myvar = ${out}`); }); From 0a7e10e0bc35849433e8160f7bb959df1c60d359 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 11 Jan 2020 15:33:44 +0100 Subject: [PATCH 06/10] Added functional test to check local variables are not in scope --- test/unit/assignments.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index 97d3e8e9d..e66eea117 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -10,6 +10,16 @@ test("let declaration", () => { expect(lua).toContain(`local foo = true`); }); +test.each(["const", "let"])("%s declaration not top-level is not global", declarationKind => { + util.testModule` + { + ${declarationKind} foo = true; + } + // @ts-ignore + return (globalThis as any).foo; + `.expectToEqual(undefined); +}); + test.each(["const", "let"])("%s declaration top-level is global", declarationKind => { util.testModule` ${declarationKind} foo = true; From d893fe84451b41162ff9589c09454357e6a36bd2 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 12 Jan 2020 23:41:21 +0100 Subject: [PATCH 07/10] Made object literal tests functional --- test/unit/objectLiteral.spec.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index a8cd2b0ad..fec87e9e8 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -1,17 +1,21 @@ import * as util from "../util"; -test.each([ - { inp: `{a:3,b:"4"}`, out: '{a = 3, b = "4"}' }, - { inp: `{"a":3,b:"4"}`, out: '{a = 3, b = "4"}' }, - { inp: `{["a"]:3,b:"4"}`, out: '{a = 3, b = "4"}' }, - { inp: `{["a"+123]:3,b:"4"}`, out: '{["a" .. 123] = 3, b = "4"}' }, - { inp: `{[myFunc()]:3,b:"4"}`, out: '{\n [myFunc(_G)] = 3,\n b = "4"\n}' }, - { inp: `{x}`, out: `{x = x}` }, -])("Object Literal (%p)", ({ inp, out }) => { - const lua = util.testModule` - const myvar = ${inp}; - `.getMainLuaCodeChunk(); - expect(lua).toBe(`myvar = ${out}`); +test.each([`{a:3,b:"4"}`, `{"a":3,b:"4"}`, `{["a"]:3,b:"4"}`, `{["a"+123]:3,b:"4"}`])("Object Literal (%p)", inp => { + util.testExpression(inp).expectToMatchJsResult(); +}); + +test("object literal with function call to get key", () => { + util.testFunction` + const myFunc = () => "a"; + return {[myFunc() + "b"]: 3}; + `.expectToMatchJsResult(); +}); + +test("object literal with shorthand property", () => { + util.testFunction` + const x = 5; + return {x}; + `.expectToMatchJsResult(); }); describe("property shorthand", () => { From fa4a78c1bb62fae23460da1fda137dbde01009b1 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 13 Jan 2020 21:21:27 +0100 Subject: [PATCH 08/10] PR comments --- src/transformation/utils/lua-ast.ts | 3 +-- test/unit/objectLiteral.spec.ts | 13 ++++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index ef65c2beb..effc18814 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -3,7 +3,6 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { getCurrentNamespace } from "../visitors/namespace"; import { createExportedIdentifier, getIdentifierExportScope } from "./export"; import { peekScope, ScopeType } from "./scope"; import { isFunctionType } from "./typescript"; @@ -145,7 +144,7 @@ export function createLocalOrExportedOrGlobalDeclaration( const scope = peekScope(context); const isTopLevelVariable = scope.type === ScopeType.File; - if (context.isModule || getCurrentNamespace(context) || !isTopLevelVariable) { + if (context.isModule || !isTopLevelVariable) { const isPossibleWrappedFunction = !isFunctionDeclaration && tsOriginal && diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index fec87e9e8..203b05780 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -1,20 +1,23 @@ import * as util from "../util"; -test.each([`{a:3,b:"4"}`, `{"a":3,b:"4"}`, `{["a"]:3,b:"4"}`, `{["a"+123]:3,b:"4"}`])("Object Literal (%p)", inp => { - util.testExpression(inp).expectToMatchJsResult(); -}); +test.each([`{ a: 3, b: "4" }`, `{ "a": 3, b: "4" }`, `{ ["a"]: 3, b: "4" }`, `{ ["a" + 123]: 3, b: "4" }`])( + "Object Literal (%p)", + inp => { + util.testExpression(inp).expectToMatchJsResult(); + } +); test("object literal with function call to get key", () => { util.testFunction` const myFunc = () => "a"; - return {[myFunc() + "b"]: 3}; + return { [myFunc() + "b"]: 3 }; `.expectToMatchJsResult(); }); test("object literal with shorthand property", () => { util.testFunction` const x = 5; - return {x}; + return { x }; `.expectToMatchJsResult(); }); From 68d811eeb70e9f97c3fac340522dc0e4de7e0ade Mon Sep 17 00:00:00 2001 From: Perryvw Date: Wed, 15 Jan 2020 21:29:58 +0100 Subject: [PATCH 09/10] Removed no longer needed getCurrentNamespace --- src/transformation/visitors/namespace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transformation/visitors/namespace.ts b/src/transformation/visitors/namespace.ts index 5835f9112..fc269f5e7 100644 --- a/src/transformation/visitors/namespace.ts +++ b/src/transformation/visitors/namespace.ts @@ -46,8 +46,8 @@ function moduleHasEmittedBody( return false; } +// Static context -> namespace dictionary keeping the current namespace for each transformation context const currentNamespaces = new WeakMap(); -export const getCurrentNamespace = (context: TransformationContext) => currentNamespaces.get(context); export const transformModuleDeclaration: FunctionVisitor = (node, context) => { const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(node)); From 03a63eff0545ce83460e90890cd4ed30d0729414 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Thu, 16 Jan 2020 21:22:52 +0100 Subject: [PATCH 10/10] Removed obsolete tests --- test/unit/assignments.spec.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index e66eea117..ce7abd622 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -1,15 +1,5 @@ import * as util from "../util"; -test("const declaration", () => { - const lua = util.testFunction`const foo = true;`.getMainLuaCodeChunk(); - expect(lua).toContain(`local foo = true`); -}); - -test("let declaration", () => { - const lua = util.testFunction`let foo = true;`.getMainLuaCodeChunk(); - expect(lua).toContain(`local foo = true`); -}); - test.each(["const", "let"])("%s declaration not top-level is not global", declarationKind => { util.testModule` {