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/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 = () => 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..569198a93 --- /dev/null +++ b/src/transformation/visitors/void.ts @@ -0,0 +1,33 @@ +import * as ts from "typescript"; +import * as lua from "../../LuaAST"; +import { TransformationContext } from "../context"; +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) => { + // 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)() + return createImmediatelyInvokedFunctionExpression( + [ + lua.createVariableDeclarationStatement( + lua.createAnonymousIdentifier(), + context.transformExpression(node.expression) + ), + ], + [], + 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 { + util.testExpression`void (${value})`.expectToMatchJsResult(); +}); + +test("void applies to function declarations", () => { + util.testFunction` + let result = 0; + void function setResult() { + result = 1; + }(); + return result; + `.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(); +});