From 118a3f290757177976458a29166311fa703c5eac Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 23 Oct 2021 21:56:15 +0200 Subject: [PATCH 1/2] Implement support for void expression --- src/transformation/utils/diagnostics.ts | 6 +++--- src/transformation/visitors/index.ts | 2 ++ src/transformation/visitors/void.ts | 18 ++++++++++++++++++ test/unit/void.spec.ts | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/transformation/visitors/void.ts create mode 100644 test/unit/void.spec.ts diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index a7a63a717..d6d151de9 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -10,9 +10,9 @@ const createDiagnosticFactory = ( message: MessageProvider ) => createSerialDiagnosticFactory((node: ts.Node, ...args: TArgs) => ({ - file: node.getSourceFile(), - start: node.getStart(), - length: node.getWidth(), + file: ts.getOriginalNode(node).getSourceFile(), + start: ts.getOriginalNode(node).getStart(), + length: ts.getOriginalNode(node).getWidth(), messageText: typeof message === "string" ? message : message(...args), category, })); diff --git a/src/transformation/visitors/index.ts b/src/transformation/visitors/index.ts index f6bb8b697..466f5ed35 100644 --- a/src/transformation/visitors/index.ts +++ b/src/transformation/visitors/index.ts @@ -41,6 +41,7 @@ import { typescriptVisitors } from "./typescript"; import { transformPostfixUnaryExpression, transformPrefixUnaryExpression } from "./unary-expression"; import { transformVariableStatement } from "./variable-declaration"; import { transformAwaitExpression } from "./async-await"; +import { transformVoidExpression } from "./void"; const transformEmptyStatement: FunctionVisitor = () => undefined; const transformParenthesizedExpression: FunctionVisitor = (node, context) => @@ -98,4 +99,5 @@ export const standardVisitors: Visitors = { [ts.SyntaxKind.VariableStatement]: transformVariableStatement, [ts.SyntaxKind.WhileStatement]: transformWhileStatement, [ts.SyntaxKind.YieldExpression]: transformYieldExpression, + [ts.SyntaxKind.VoidExpression]: transformVoidExpression, }; diff --git a/src/transformation/visitors/void.ts b/src/transformation/visitors/void.ts new file mode 100644 index 000000000..d8dd826b2 --- /dev/null +++ b/src/transformation/visitors/void.ts @@ -0,0 +1,18 @@ +import * as ts from "typescript"; +import * as lua from "../../LuaAST"; +import { FunctionVisitor } from "../context/visitors"; +import { createImmediatelyInvokedFunctionExpression } from "../utils/lua-ast"; + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void +export const transformVoidExpression: FunctionVisitor = (node, context) => + // (function() local ____ = end)() + createImmediatelyInvokedFunctionExpression( + [ + lua.createVariableDeclarationStatement( + lua.createAnonymousIdentifier(), + context.transformExpression(node.expression) + ), + ], + [], + node + ); diff --git a/test/unit/void.spec.ts b/test/unit/void.spec.ts new file mode 100644 index 000000000..8222f8291 --- /dev/null +++ b/test/unit/void.spec.ts @@ -0,0 +1,20 @@ +import * as util from "../util"; + +test.each(["0", "1", '"a"'])("void evaluates to undefined (%p)", value => { + util.testExpression`void (${value})`.expectToMatchJsResult(); +}); + +test("void applies to function declarations", () => { + util.testFunction` + let result = 0; + void function setResult() { + result = 1; + }(); + return result; + `.expectToMatchJsResult(); +}); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1102 +test("void works with lambdas", () => { + util.testExpression`void (() => {})()`.expectToMatchJsResult(); +}); From 380ca9a438c8cb50fa480f816feb5ff86ff1f372 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 25 Oct 2021 22:35:48 +0200 Subject: [PATCH 2/2] PR feedback --- .../visitors/expression-statement.ts | 5 +++++ src/transformation/visitors/void.ts | 19 +++++++++++++++++-- src/transpilation/transformers.ts | 2 ++ test/unit/void.spec.ts | 14 ++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/transformation/visitors/expression-statement.ts b/src/transformation/visitors/expression-statement.ts index 228307f25..2f64ec9d8 100644 --- a/src/transformation/visitors/expression-statement.ts +++ b/src/transformation/visitors/expression-statement.ts @@ -9,6 +9,7 @@ import { transformTableSetExpression, } from "./language-extensions/table"; import { transformUnaryExpressionStatement } from "./unary-expression"; +import { transformVoidExpressionStatement } from "./void"; export const transformExpressionStatement: FunctionVisitor = (node, context) => { const expression = node.expression; @@ -21,6 +22,10 @@ export const transformExpressionStatement: FunctionVisitor = (node, context) => +export const transformVoidExpression: FunctionVisitor = (node, context) => { + // If content is a literal it is safe to replace the entire expression with nil + if (ts.isLiteralExpression(node.expression)) { + return lua.createNilLiteral(node); + } + // (function() local ____ = end)() - createImmediatelyInvokedFunctionExpression( + return createImmediatelyInvokedFunctionExpression( [ lua.createVariableDeclarationStatement( lua.createAnonymousIdentifier(), @@ -16,3 +22,12 @@ export const transformVoidExpression: FunctionVisitor = (node [], node ); +}; + +export const transformVoidExpressionStatement = (node: ts.VoidExpression, context: TransformationContext) => + // In case of a void expression statement we can omit the IIFE + lua.createVariableDeclarationStatement( + lua.createAnonymousIdentifier(), + context.transformExpression(node.expression), + node + ); diff --git a/src/transpilation/transformers.ts b/src/transpilation/transformers.ts index 386d7f475..ac81f6d68 100644 --- a/src/transpilation/transformers.ts +++ b/src/transpilation/transformers.ts @@ -71,6 +71,8 @@ export const stripParenthesisExpressionsTransformer: ts.TransformerFactory { `.expectToMatchJsResult(); }); +test("void used to ignore function return values", () => { + util.testFunction` + let result = 0; + function setResult() { + result = 1; + return 3 + }; + + void(setResult()); + + return result; + `.expectToMatchJsResult(); +}); + // https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1102 test("void works with lambdas", () => { util.testExpression`void (() => {})()`.expectToMatchJsResult();