diff --git a/.prettierignore b/.prettierignore index fef924d04..cbfe6aa04 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,3 @@ /dist /coverage /test/translation/transformation/characterEscapeSequence.ts - -/src -*.md diff --git a/.prettierrc.js b/.prettierrc.js index 1e032a0bf..87974397e 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -2,10 +2,9 @@ const isCI = require("is-ci"); /** @type {import("prettier").Options} */ module.exports = { - printWidth: 100, + printWidth: 120, tabWidth: 4, - trailingComma: "all", - proseWrap: "always", + trailingComma: "es5", endOfLine: isCI ? "lf" : "auto", overrides: [{ files: ["**/*.md", "**/*.yml", "**/.*.yml"], options: { tabWidth: 2 } }], }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 72034d078..e7eab90af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## 0.20.0 + - Added support for `string.repeat`, `string.padStart` and `string.padEnd`. - Added automatic variable renaming for invalid Lua identifiers. - Fixed `/** @tupleReturn */` not working for function types (i.e `myFunc: () => [number, number]`) @@ -8,8 +9,9 @@ - Various small code tweaks and improvements. ## 0.19.0 + - **BREAKING CHANGE:** All tstl-specific options should now be inside the "tstl" section in tsconfig.json (see README.md). **Root-level options are no longer supported**. -- Added a compiler API to programmatically invoke TypeScriptToLua, and to modify or extend the default transpiler. More info on the [Compiler API wiki page](). +- Added a compiler API to programmatically invoke TypeScriptToLua, and to modify or extend the default transpiler. More info on the [Compiler API wiki page](https://github.com/TypeScriptToLua/TypeScriptToLua/wiki/TypeScriptToLua-API). - Added support for [class decorators](https://www.typescriptlang.org/docs/handbook/decorators.html#class-decorators). - Added support for the [@luaTable directive](https://github.com/TypeScriptToLua/TypeScriptToLua/wiki/Compiler-Directives#luatable) which will force a class to be transpiled as vanilla lua table. - Added support for NaN, Infinity and related number functions. @@ -21,57 +23,60 @@ - Fixed an issue with parameters that had `false` as default value. ## 0.18.0 -* Added support for setting array length. Doing `array.length = x` will set the length of the array to `x` (or shorter, if the starting array was shorter!). -* Added the `.name` property to all transpiled classes, so `class.name` will contain the classname as string. -* Changed `class = class or {}` syntax to just be `class = {}`. -* Cleaned up printer output so it produces more human-readable code. -* Fixed bug with expression statements. -* Fixed incorrect inline sourcemap format. -* Fixed bug when merging an interface and module. -* Fixed a bug with inherited constructor super call ordering. +- Added support for setting array length. Doing `array.length = x` will set the length of the array to `x` (or shorter, if the starting array was shorter!). +- Added the `.name` property to all transpiled classes, so `class.name` will contain the classname as string. +- Changed `class = class or {}` syntax to just be `class = {}`. +- Cleaned up printer output so it produces more human-readable code. + +- Fixed bug with expression statements. +- Fixed incorrect inline sourcemap format. +- Fixed bug when merging an interface and module. +- Fixed a bug with inherited constructor super call ordering. -* Enabled strict tsconfig. +- Enabled strict tsconfig. ## 0.17.0 -* We now support source maps in the [standard JS v3 format](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1). You can generate source maps with the `--sourceMap` CLI argument, or by adding `sourceMap: true` to your tsconfig. Inline source maps are also supported with `--inlineSourceMap` CLI/tsconfig parameter. -* Also added [tstl option](https://github.com/TypeScriptToLua/TypeScriptToLua/wiki#tstl-specific-options) `--sourceMapTraceback`, which will add an override to Lua's `debug.traceback()` to each file, so source maps will automatically be applied to Lua stacktraces (i.e. in errors). -* Made watch mode incremental. +- We now support source maps in the [standard JS v3 format](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1). You can generate source maps with the `--sourceMap` CLI argument, or by adding `sourceMap: true` to your tsconfig. Inline source maps are also supported with `--inlineSourceMap` CLI/tsconfig parameter. +- Also added [tstl option](https://github.com/TypeScriptToLua/TypeScriptToLua/wiki#tstl-specific-options) `--sourceMapTraceback`, which will add an override to Lua's `debug.traceback()` to each file, so source maps will automatically be applied to Lua stacktraces (i.e. in errors). -* Added support for `Object.fromEntries`, `array.flat` and `array.flatMap`. +- Made watch mode incremental. -* **BREAKING CHANGE:** Directive `@tupleReturn` should now be specified **per overload**. +- Added support for `Object.fromEntries`, `array.flat` and `array.flatMap`. -* Fixed a bug where rest parameters would not transpile correctly. -* Fixed an issue with escaped backticks. -* Various small fixes function inference and array detection. +- **BREAKING CHANGE:** Directive `@tupleReturn` should now be specified **per overload**. -* Changed testing framework to [jest](https://github.com/facebook/jest). +- Fixed a bug where rest parameters would not transpile correctly. +- Fixed an issue with escaped backticks. +- Various small fixes function inference and array detection. +- Changed testing framework to [jest](https://github.com/facebook/jest). ## 0.16.0 -* **BREAKING CHANGE:** All functions now take a `self` parameter. This means that without further action calls to declaration functions might be given an extra argument. - * To remove the self parameter from a single function add `this: void` to its declaration: - ```declare function foo(this: void, ...)``` - * To remove the self parameter from all methods or functions in a class/interface/namespace add `/** @noSelf */`: - ```/** @noSelf */ interface Foo {``` - * To remove the self parameter from all functions in a file, add `/** @noSelfInFile */` at the top. + +- **BREAKING CHANGE:** All functions now take a `self` parameter. This means that without further action calls to declaration functions might be given an extra argument. + - To remove the self parameter from a single function add `this: void` to its declaration: + `declare function foo(this: void, ...)` + - To remove the self parameter from all methods or functions in a class/interface/namespace add `/** @noSelf */`: + `/** @noSelf */ interface Foo {` + - To remove the self parameter from all functions in a file, add `/** @noSelfInFile */` at the top. --- -* **BREAKING CHANGE:** Directive `/** @luaIterator */` should now be put on types instead of on the functions returning them. +- **BREAKING CHANGE:** Directive `/** @luaIterator */` should now be put on types instead of on the functions returning them. --- -* Fixed a bug breaking named class expressions. -* Fixed inconsistency between the meaning of `>>` and `>>>` in JS vs. Lua. -* Added `/** @noResolution */` directive to prevent path resolution on declared modules. -* It is now possible to put `/** @luaIterator */` on types extending `Array`. -* Fixed issue with the moment static fields were initialized. -* Fixed issue where `undefined` as property name was not transpiled correctly. -* Various improvements to function/method self parameter inference. -* Tstl options can now be defined in their own `tstl` block in tsconfig.json. For example: +- Fixed a bug breaking named class expressions. +- Fixed inconsistency between the meaning of `>>` and `>>>` in JS vs. Lua. +- Added `/** @noResolution */` directive to prevent path resolution on declared modules. +- It is now possible to put `/** @luaIterator */` on types extending `Array`. +- Fixed issue with the moment static fields were initialized. +- Fixed issue where `undefined` as property name was not transpiled correctly. +- Various improvements to function/method self parameter inference. +- Tstl options can now be defined in their own `tstl` block in tsconfig.json. For example: + ``` { "compilerOptions" : {} @@ -80,152 +85,167 @@ } } ``` -* Fixed issue when redeclaring TypeScript libraries/globals. -* Fixed exception resolving function signatures. -* Added support for automatically transpiling several `console` calls to their Lua equivalent: - * `console.log(...)` -> `print(...)` - * `console.assert(...)` -> `assert(...)` - * `console.trace(...)` -> `print(debug.traceback(...))` -* Added support for `array.findIndex()`. -* Fixed `array.sort()` not working with a compare function. -* Added support for several common `Math.` functions and constants. -* Added support for several common string instance functions such as `upper()`. + +- Fixed issue when redeclaring TypeScript libraries/globals. +- Fixed exception resolving function signatures. +- Added support for automatically transpiling several `console` calls to their Lua equivalent: + - `console.log(...)` -> `print(...)` + - `console.assert(...)` -> `assert(...)` + - `console.trace(...)` -> `print(debug.traceback(...))` +- Added support for `array.findIndex()`. +- Fixed `array.sort()` not working with a compare function. +- Added support for several common `Math.` functions and constants. +- Added support for several common string instance functions such as `upper()`. ## 0.15.2 -* Several improvements to module path resolution. -* Removed header comment appearing in lualib. -* Several package config improvements. -* Static get/set accessors. + +- Several improvements to module path resolution. +- Removed header comment appearing in lualib. +- Several package config improvements. +- Static get/set accessors. ## 0.15.1 -* Fixed array detection for unit and intersection types. -* Support for import without `from`. -* Added support for `WeakMap` and `WeakSet`. -* Added support for `Object.keys` and `Object.assign`. -* Added support for importing JSON files. -* Fixed bug with where loop variables were not properly scoped. -* Added support for ExportDeclarations + +- Fixed array detection for unit and intersection types. +- Support for import without `from`. +- Added support for `WeakMap` and `WeakSet`. +- Added support for `Object.keys` and `Object.assign`. +- Added support for importing JSON files. +- Fixed bug with where loop variables were not properly scoped. +- Added support for ExportDeclarations ## 0.15.0 -* Now written for TypeScript 3.3.x! -* Removed external CLI parser dependency and wrote our own `CommandLineParser.ts` to read CLI and tsconfig input. -* Added support for hoisting, can be disabled with the `noHoisting` option in CLI or tsconfig. -* Added support for generator functions. -* Reworked classes into a system more similar to JavaScript with prototype tables. -* Improved support for ObjectBindingPatterns. -* Added support for enums with identifier values. -* Added support for the binary comma operator. -* Added support for `string.concat`, `string.slice` and `string.charCodeAt`. -* Refactored LuaTranspiler.emitLuaLib to its own method so it can be called from external code. -* Improved function type inference. -* Fixed some bugs in for loops with expressions. -* Fixed a bug forwarding luaIterator functions. + +- Now written for TypeScript 3.3.x! +- Removed external CLI parser dependency and wrote our own `CommandLineParser.ts` to read CLI and tsconfig input. +- Added support for hoisting, can be disabled with the `noHoisting` option in CLI or tsconfig. +- Added support for generator functions. +- Reworked classes into a system more similar to JavaScript with prototype tables. +- Improved support for ObjectBindingPatterns. +- Added support for enums with identifier values. +- Added support for the binary comma operator. +- Added support for `string.concat`, `string.slice` and `string.charCodeAt`. +- Refactored LuaTranspiler.emitLuaLib to its own method so it can be called from external code. +- Improved function type inference. +- Fixed some bugs in for loops with expressions. +- Fixed a bug forwarding luaIterator functions. ## 0.14.0 -* Reworked internal transpiler structure to be more suited for future extension. -* Reworked module and exports system. -* Added support for custom iterators. -* Improved formatting consistency. -* Errors are now reported with location `(line, column)` instead of `line: line, column: column`. -* Added back default lua header: `--[[ Generated with https://github.com/Perryvw/TypescriptToLua ]]`. -* Fixed some bugs with switches and breaks. -* Fixed several bugs with functions and context parameters. + +- Reworked internal transpiler structure to be more suited for future extension. +- Reworked module and exports system. +- Added support for custom iterators. +- Improved formatting consistency. +- Errors are now reported with location `(line, column)` instead of `line: line, column: column`. +- Added back default lua header: `--[[ Generated with https://github.com/Perryvw/TypescriptToLua ]]`. +- Fixed some bugs with switches and breaks. +- Fixed several bugs with functions and context parameters. ## 0.13.0 -* Reworked how functions are transpiled, see https://github.com/TypeScriptToLua/TypescriptToLua/wiki/Differences-Between-Functions-and-Methods -* Improved handling of types extending Array. -* Fixed several bugs with classes. -* Fixed issues with inherited accessors. + +- Reworked how functions are transpiled, see https://github.com/TypeScriptToLua/TypescriptToLua/wiki/Differences-Between-Functions-and-Methods +- Improved handling of types extending Array. +- Fixed several bugs with classes. +- Fixed issues with inherited accessors. ## 0.12.0 -* Added detection of types extending Array. -* Added new JSDoc-style compiler directives, deprecated the old `!` decorators, see https://github.com/TypeScriptToLua/TypescriptToLua/wiki/Compiler-Directives -* Fixed bug with constructor default values. -* The Lualib is no longer included when not used. -* Fixed bug with unpack in LuaJIT. + +- Added detection of types extending Array. +- Added new JSDoc-style compiler directives, deprecated the old `!` decorators, see https://github.com/TypeScriptToLua/TypescriptToLua/wiki/Compiler-Directives +- Fixed bug with constructor default values. +- The Lualib is no longer included when not used. +- Fixed bug with unpack in LuaJIT. ## 0.11.0 -* Fixed bug when throwing anything that was not a string. (@tomblind) -* Added support for object literal method declarations. (@tomblind) -* Fixed several issues with assignment operators (@tomblind) -* `else if` statements are now transpiled to Lua `elseif` instead of nested ifs statements. (@tomblind) -* Occurrences of const enum values are now directly replaced with their value in the Lua output. (@DoctorGester) -* Rethrowing is now possible from try/catch blocks (@tomblind) -* Destructing statements in LuaJit now use `unpack` instead of `table.unpack` -* Removed support for switch statements for versions <= 5.1. -* Refactored `for ... of` translation, it now uses numeric `for ` loops instead of `ipairs` for performance reasons. + +- Fixed bug when throwing anything that was not a string. (@tomblind) +- Added support for object literal method declarations. (@tomblind) +- Fixed several issues with assignment operators (@tomblind) +- `else if` statements are now transpiled to Lua `elseif` instead of nested ifs statements. (@tomblind) +- Occurrences of const enum values are now directly replaced with their value in the Lua output. (@DoctorGester) +- Rethrowing is now possible from try/catch blocks (@tomblind) +- Destructing statements in LuaJit now use `unpack` instead of `table.unpack` +- Removed support for switch statements for versions <= 5.1. +- Refactored `for ... of` translation, it now uses numeric `for` loops instead of `ipairs` for performance reasons. ## 0.10.0 -* Added support for NonNullExpression (`abc!` transforming the type from `abc | undefined` to `abc`) -* Added expression position to replacement binary expression to improve error messages. -* Fixed various issues with !TupleReturn (@tomblind) -* Added support for `array.reverse`, `array.shift`, `array.unshift`, `array.sort`. (@andreiradu) -* Added translation for `Object.hasOwnProperty()`. (@andreiradu) -* Added support for class expressions (@andreiradu) -* Fixed bug in detecting array types (@tomblind) -* Added public API functions and better webpack functionality. + +- Added support for NonNullExpression (`abc!` transforming the type from `abc | undefined` to `abc`) +- Added expression position to replacement binary expression to improve error messages. +- Fixed various issues with !TupleReturn (@tomblind) +- Added support for `array.reverse`, `array.shift`, `array.unshift`, `array.sort`. (@andreiradu) +- Added translation for `Object.hasOwnProperty()`. (@andreiradu) +- Added support for class expressions (@andreiradu) +- Fixed bug in detecting array types (@tomblind) +- Added public API functions and better webpack functionality. ## 0.9.0 -* Fixed an issue where default parameter values were ignored in function declarations. -* Fixed a bug where `self` was undefined in function properties. -* Fixed a bug where addition of +1 to indices sometimes caused issues with operation order (thanks @brianhang) -* Fixed super calls having issues with their `self` instance. (thanks @hazzard993) -* Methods now also accept custom decorators (thanks @hazzard993) -* Improved support for `toString` calls (thanks @andreiradu) -* Added support for block expressions (thanks @andreiradu) + +- Fixed an issue where default parameter values were ignored in function declarations. +- Fixed a bug where `self` was undefined in function properties. +- Fixed a bug where addition of +1 to indices sometimes caused issues with operation order (thanks @brianhang) +- Fixed super calls having issues with their `self` instance. (thanks @hazzard993) +- Methods now also accept custom decorators (thanks @hazzard993) +- Improved support for `toString` calls (thanks @andreiradu) +- Added support for block expressions (thanks @andreiradu) Thanks @tomblind for the following changes: -* Fixed a bug where recursive use of a function expression caused a nil error. -* Fixed syntax error when compiling variable declaration lists. -* Fixed an issue with assignment order in exported namespaces. -* Various fixes to `!TupleReturn` functions. -* Fixed an issue with declaration merging. + +- Fixed a bug where recursive use of a function expression caused a nil error. +- Fixed syntax error when compiling variable declaration lists. +- Fixed an issue with assignment order in exported namespaces. +- Various fixes to `!TupleReturn` functions. +- Fixed an issue with declaration merging. ## 0.8.0 -* Added experimental watch mode, use it with `tstl --watch` -* Refactored decorators -* Added `...` spread operator -* Added error when a lua keyword is used as variable name -* Added support for shorthand object literals (thanks @gakada) -* Added array.pop (thanks @andreiradu) -* Added `;` after lines to avoid ambiguous syntax (thanks @andreiradu) -* Fixed issue with tsconfig being overriden (thanks @Janne252) + +- Added experimental watch mode, use it with `tstl --watch` +- Refactored decorators +- Added `...` spread operator +- Added error when a lua keyword is used as variable name +- Added support for shorthand object literals (thanks @gakada) +- Added array.pop (thanks @andreiradu) +- Added `;` after lines to avoid ambiguous syntax (thanks @andreiradu) +- Fixed issue with tsconfig being overriden (thanks @Janne252) ## 0.7.0 -* Lualib runtime library is now compiled from TypeScript using the transpiler when building! - * Split up runtime library definition into individual files. - * Added multiple inclusion modes using the tsconfig option `lubLibImport`, options are: - * `require` : Requires the entire library if lualib features are used. - * `always` : Always require the runtime library. - * `inline` : Inline the library code for used features in the file. - * `none` : Do not include the runtime library -* Added support for assigning expressions (`+=`, `&=`, `++`, etc) in other expressions (i.e. `lastIndex = i++` or `return a += b`) by transpiling them as immediately called anonymous functions. -* Unreachable code (after returns) is no longer transpiled, preventing a Lua syntax error. -* Fixed issue with destructing statements in Lua 5.1 -* Fixed issue with escaped characters in strings. -* Fixed bug regarding changing an exported variable after its export. +- Lualib runtime library is now compiled from TypeScript using the transpiler when building! + - Split up runtime library definition into individual files. + - Added multiple inclusion modes using the tsconfig option `lubLibImport`, options are: + - `require` : Requires the entire library if lualib features are used. + - `always` : Always require the runtime library. + - `inline` : Inline the library code for used features in the file. + - `none` : Do not include the runtime library +- Added support for assigning expressions (`+=`, `&=`, `++`, etc) in other expressions (i.e. `lastIndex = i++` or `return a += b`) by transpiling them as immediately called anonymous functions. +- Unreachable code (after returns) is no longer transpiled, preventing a Lua syntax error. +- Fixed issue with destructing statements in Lua 5.1 +- Fixed issue with escaped characters in strings. +- Fixed bug regarding changing an exported variable after its export. ## 0.6.0 -* Reworked part of the class system to solve some issues. -* Reworked class tests from translation to functional. -* Fixed issue with Lua splice implementation. -* Added threaded test runner to use for faster testing (use with `npm run test-threaded`). -* Added support for string-valued enums. -* Added tsconfig values to target Lua 5.1 and 5.2. + +- Reworked part of the class system to solve some issues. +- Reworked class tests from translation to functional. +- Fixed issue with Lua splice implementation. +- Added threaded test runner to use for faster testing (use with `npm run test-threaded`). +- Added support for string-valued enums. +- Added tsconfig values to target Lua 5.1 and 5.2. ## 0.5.0 -* Added support for `**` operator. -* Added support for `~` operator. -* Improved handling of assignment binary operators (`+=`,`*=`,`&=`, etc). -* Rewrote `Map` and `Set` to implement the ES6 specification for [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). -* Added support for `baseUrl` in [tsconfig](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). -* Added `bit32` bit operations for Lua 5.2. -* Fixed various little bugs. -* Added tslint rule to enforce use of `/** @override */` decorator. -* Improved tests. + +- Added support for `**` operator. +- Added support for `~` operator. +- Improved handling of assignment binary operators (`+=`,`*=`,`&=`, etc). +- Rewrote `Map` and `Set` to implement the ES6 specification for [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). +- Added support for `baseUrl` in [tsconfig](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). +- Added `bit32` bit operations for Lua 5.2. +- Fixed various little bugs. +- Added tslint rule to enforce use of `/** @override */` decorator. +- Improved tests. ## 0.4.0 -* Added support for `typeof` -* Added support for `instanceof` -* Added support for [TypeScript overloads](https://www.typescriptlang.org/docs/handbook/functions.html#overloads) + +- Added support for `typeof` +- Added support for `instanceof` +- Added support for [TypeScript overloads](https://www.typescriptlang.org/docs/handbook/functions.html#overloads) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d298d2374..f44bb3522 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,30 +1,33 @@ # Contributing to TypeScriptToLua -1) [Project Overview](#project-overview) -2) [Running Tests](#running-tests) -3) [Testing Guidelines](#testing-guidelines) -4) [Coding Conventions](#coding-conventions) +1. [Project Overview](#project-overview) +2. [Running Tests](#running-tests) +3. [Testing Guidelines](#testing-guidelines) +4. [Coding Conventions](#coding-conventions) ## Project Overview + To get familiar with the project structure, here is a short overview of each directory and their function. + - `src/` - * Source code for the project, has the transpiler core files in its root. - * `src/lualib/` + - Source code for the project, has the transpiler core files in its root. + - `src/lualib/` - Contains the TypeScript source for the lualib. This consists of implementations of standard TypeScript functions that are not present in Lua. These files are compiled to Lua using the transpiler. They are included in the Lua result when transpiling. - * `src/targets/` + - `src/targets/` - Version-specific transpiler overrides for the different Lua targets. The main transpiler transpiles Lua 5.0, each target-specific transpiler extends the transpiler of the version before it, so the 5.3 inherits 5.2 which inherits 5.1 which inherits 5.0. LuaJIT is based on 5.2 so inherits from the 5.2 transpiler. - * *Compiler.ts* - Main entry point of the transpiler, this is what interfaces with the TypeScript compiler API. - * *LuaTransformer.ts* - Main transpiler code, transforms a TypeScript AST to a Lua AST. - * *LuaPrinter.ts* - Transforms a Lua AST to a string. - * *TSHelper.ts* - Helper methods used during the transpilation process. + - _Compiler.ts_ - Main entry point of the transpiler, this is what interfaces with the TypeScript compiler API. + - _LuaTransformer.ts_ - Main transpiler code, transforms a TypeScript AST to a Lua AST. + - _LuaPrinter.ts_ - Transforms a Lua AST to a string. + - _TSHelper.ts_ - Helper methods used during the transpilation process. - `test/` - * This directory contains all testing code for the transpiler. - * `test/unit/` + - This directory contains all testing code for the transpiler. + - `test/unit/` - Unit/Functional tests for the transpiler. Tests in here are grouped by functionality they are testing. Generally each of these tests uses the transpiler to transpile some TypeScript to Lua, then executes it using the Fengari Lua VM. Assertion is done on the result of the lua code. - * `test/translation/` + - `test/translation/` - **[Obsolete]** Contains tests that only check the transpiled Lua String. We prefer adding unit/functional tests over translation tests. This directory will probably be removed at some point. ## Running Tests + The tests for this project can be executed using the standard `npm test`. This runs all tests. Due to the time required to run all tests, it is impractical to run every test while developing part of the transpiler. To speed up the test run you can: @@ -46,14 +49,17 @@ Due to the time required to run all tests, it is impractical to run every test w ``` ## Testing Guidelines + When submitting a pull request with new functionality, we require some functional (transpile and execute Lua) to be added, to ensure the new functionality works as expected, and will continue to work that way. Translation tests are discouraged as in most cases as we do not really care about the exact Lua output, as long as executing it results in the correct result (which is tested by functional tests). ## Coding Conventions + Most coding conventions are enforced by the TSLint and Prettier. You can check your code locally by running `npm run lint`. The CI build will fail if your code does not pass the linter. For better experience, you can install extensions for your code editor for [TSLint](https://palantir.github.io/tslint/usage/third-party-tools/) and [Prettier](https://prettier.io/docs/en/editors.html). Some extra conventions worth mentioning: -* Do not abbreviate variable names. The exception here are inline lambda arguments, if it is obvious what the argument is you can abbreviate to the first letter, e.g: `statements.filter(s => ts.VariableStatement(s))` -* Readability of code is more important than the amount of space it takes. If extra line breaks make your code more readable, add them. -* Functional style is encouraged! + +- Do not abbreviate variable names. The exception here are inline lambda arguments, if it is obvious what the argument is you can abbreviate to the first letter, e.g: `statements.filter(s => ts.VariableStatement(s))` +- Readability of code is more important than the amount of space it takes. If extra line breaks make your code more readable, add them. +- Functional style is encouraged! diff --git a/README.md b/README.md index 21b013de7..024e3ca3e 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ A generic TypeScript to Lua transpiler. Write your code in TypeScript and publis Large projects written in lua can become hard to maintain and make it easy to make mistakes. Writing code in TypeScript instead improves maintainability, readability and robustness, with the added bonus of good IDE support. This project is useful in any environment where Lua code is accepted, with the powerful option of simply declaring any existing API using TypeScript declaration files. ## Documentation + More detailed documentation and info on writing declarations can be found [on the wiki](https://github.com/TypeScriptToLua/TypescriptToLua/wiki). Changelog can be found in [CHANGELOG.md](https://github.com/TypeScriptToLua/TypescriptToLua/blob/master/CHANGELOG.md) @@ -38,24 +39,28 @@ Changelog can be found in [CHANGELOG.md](https://github.com/TypeScriptToLua/Type `tstl -p path/to/tsconfig.json --watch` **Example tsconfig.json** + ```json { - "compilerOptions": { - "target": "esnext", - "lib": ["esnext"], - "strict": true - }, - "tstl": { - "luaTarget": "JIT" - } + "compilerOptions": { + "target": "esnext", + "lib": ["esnext"], + "strict": true + }, + "tstl": { + "luaTarget": "JIT" + } } ``` ## Contributing + All contributions are welcome, but please read our [contribution guidelines](https://github.com/TypeScriptToLua/TypescriptToLua/blob/master/CONTRIBUTING.md)! ## Declarations + The real power of this transpiler is usage together with good declarations for the Lua API provided. Some examples of Lua interface declarations can be found here: + - [Dota 2 Modding](https://github.com/ModDota/API/tree/master/declarations/server) - [Defold Game Engine Scripting](https://github.com/dasannikov/DefoldTypeScript/blob/master/defold.d.ts) - [LÖVE 2D Game Development](https://github.com/hazzard993/love-typescript-definitions) @@ -71,12 +76,14 @@ The real power of this transpiler is usage together with good declarations for t `npm run coverage` or `npm run coverage-html` to generate a coverage report. ## Sublime Text integration + This compiler works great in combination with the [Sublime Text Typescript plugin](https://github.com/Microsoft/TypeScript-Sublime-Plugin) (available through the package manager as `TypeScript`). You can simply open your typescript project assuming a valid tsconfig.json file is present. The default TypeScript plugin will provide all functionality of a regular TypeScript project. ### Setting up a custom build system -To add the option to build with the Lua transpiler instead of the regular typescript compiler, go to `Tools > Build System > New Build System...`. In the new sublime-build file that opens, enter the following (adjust path to tstl if not installed globally): + +To add the option to build with the Lua transpiler instead of the regular typescript compiler, go to `Tools > Build System > New Build System...`. In the new sublime-build file that opens, enter the following (adjust path to tstl if not installed globally): ``` { @@ -84,4 +91,5 @@ To add the option to build with the Lua transpiler instead of the regular typesc "shell": true } ``` + Save this in your Sublime settings as a `TypeScriptToLua.sublime-build`. You can now select the TypeScriptToLua build system in `Tools > Build System` to build using the normal hotkey (`ctrl+B`), or if you have multiple TypeScript projects open, you can choose your compiler before building by pressing `ctrl+shift+B`. diff --git a/package.json b/package.json index 8bceba6b6..aaa0e27b8 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "pretest": "npm run lint && ts-node --transpile-only ./build_lualib.ts", "test": "jest", "lint": "npm run lint:tslint && npm run lint:prettier", - "lint:prettier": "prettier --check **/*.{js,ts,yml,json} || (echo 'Run `npm run fix:prettier` to fix it.' && exit 1)", + "lint:prettier": "prettier --check **/*.{js,ts,yml,json,md} || (echo 'Run `npm run fix:prettier` to fix it.' && exit 1)", "lint:tslint": "tslint -p . && tslint -p test && tslint -p src/lualib", - "fix:prettier": "prettier --check --write **/*.{js,ts,yml,json}", + "fix:prettier": "prettier --check --write **/*.{js,ts,yml,json,md}", "release-major": "npm version major", "release-minor": "npm version minor", "release-patch": "npm version patch", diff --git a/src/CommandLineParser.ts b/src/CommandLineParser.ts index a63f936d3..c2fb5b975 100644 --- a/src/CommandLineParser.ts +++ b/src/CommandLineParser.ts @@ -97,9 +97,7 @@ export function updateParsedConfigFile(parsedConfigFile: ts.ParsedCommandLine): if (parsedConfigFile.raw.tstl) { if (hasRootLevelOptions) { - parsedConfigFile.errors.push( - diagnostics.tstlOptionsAreMovingToTheTstlObject(parsedConfigFile.raw.tstl) - ); + parsedConfigFile.errors.push(diagnostics.tstlOptionsAreMovingToTheTstlObject(parsedConfigFile.raw.tstl)); } for (const key in parsedConfigFile.raw.tstl) { @@ -122,10 +120,7 @@ export function parseCommandLine(args: string[]): ParsedCommandLine { return updateParsedCommandLine(ts.parseCommandLine(args), args); } -function updateParsedCommandLine( - parsedCommandLine: ts.ParsedCommandLine, - args: string[] -): ParsedCommandLine { +function updateParsedCommandLine(parsedCommandLine: ts.ParsedCommandLine, args: string[]): ParsedCommandLine { for (let i = 0; i < args.length; i++) { if (!args[i].startsWith("-")) continue; @@ -143,10 +138,10 @@ function updateParsedCommandLine( if (option) { // Ignore errors caused by tstl specific compiler options const tsInvalidCompilerOptionErrorCode = 5023; - parsedCommandLine.errors = parsedCommandLine.errors.filter(err => { + parsedCommandLine.errors = parsedCommandLine.errors.filter(error => { return !( - err.code === tsInvalidCompilerOptionErrorCode && - String(err.messageText).endsWith(`'${args[i]}'.`) + error.code === tsInvalidCompilerOptionErrorCode && + String(error.messageText).endsWith(`'${args[i]}'.`) ); }); diff --git a/src/Emit.ts b/src/Emit.ts index 74b6f3eb3..e2004b0f9 100644 --- a/src/Emit.ts +++ b/src/Emit.ts @@ -12,10 +12,7 @@ export interface OutputFile { } let lualibContent: string; -export function emitTranspiledFiles( - options: CompilerOptions, - transpiledFiles: TranspiledFile[] -): OutputFile[] { +export function emitTranspiledFiles(options: CompilerOptions, transpiledFiles: TranspiledFile[]): OutputFile[] { let { rootDir, outDir, outFile, luaLibImport } = options; const configFileName = options.configFilePath as string | undefined; @@ -60,10 +57,7 @@ export function emitTranspiledFiles( if (luaLibImport === LuaLibImportKind.Require || luaLibImport === LuaLibImportKind.Always) { if (lualibContent === undefined) { - lualibContent = fs.readFileSync( - path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"), - "utf8" - ); + lualibContent = fs.readFileSync(path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"), "utf8"); } let outPath = path.resolve(rootDir, "lualib_bundle.lua"); diff --git a/src/LuaAST.ts b/src/LuaAST.ts index edce002e1..7616177e4 100644 --- a/src/LuaAST.ts +++ b/src/LuaAST.ts @@ -8,6 +8,7 @@ import * as ts from "typescript"; export enum SyntaxKind { Block, + // Statements DoStatement, VariableDeclarationStatement, @@ -22,6 +23,7 @@ export enum SyntaxKind { ReturnStatement, BreakStatement, ExpressionStatement, + // Expression StringLiteral, NumericLiteral, @@ -39,60 +41,83 @@ export enum SyntaxKind { MethodCallExpression, Identifier, TableIndexExpression, + // Operators + // Arithmetic - AdditionOperator, // Maybe use abbreviations for those add, sub, mul ... + AdditionOperator, // Maybe use abbreviations for those add, sub, mul ... SubtractionOperator, MultiplicationOperator, DivisionOperator, FloorDivisionOperator, ModuloOperator, PowerOperator, - NegationOperator, // Unary minus + NegationOperator, // Unary minus + // Concat ConcatOperator, + // Length - LengthOperator, // Unary + LengthOperator, // Unary + // Relational Ops EqualityOperator, InequalityOperator, LessThanOperator, LessEqualOperator, - GreaterThanOperator, // Syntax Sugar `x > y` <=> `not (y <= x)` - // but we should probably use them to make the output code more readable - GreaterEqualOperator, // Syntax Sugar `x >= y` <=> `not (y < x)` + // Syntax Sugar `x > y` <=> `not (y <= x)` + // but we should probably use them to make the output code more readable + GreaterThanOperator, + GreaterEqualOperator, // Syntax Sugar `x >= y` <=> `not (y < x)` + // Logical AndOperator, OrOperator, - NotOperator, // Unary + NotOperator, // Unary + // Bitwise BitwiseAndOperator, BitwiseOrOperator, BitwiseExclusiveOrOperator, BitwiseRightShiftOperator, BitwiseLeftShiftOperator, - BitwiseNotOperator, // Unary + BitwiseNotOperator, // Unary } // TODO maybe name this PrefixUnary? not sure it makes sense to do so, because all unary ops in Lua are prefix export type UnaryBitwiseOperator = SyntaxKind.BitwiseNotOperator; -export type UnaryOperator = SyntaxKind.NegationOperator +export type UnaryOperator = + | SyntaxKind.NegationOperator | SyntaxKind.LengthOperator | SyntaxKind.NotOperator | UnaryBitwiseOperator; -export type BinaryBitwiseOperator = SyntaxKind.BitwiseAndOperator | SyntaxKind.BitwiseOrOperator - | SyntaxKind.BitwiseExclusiveOrOperator | SyntaxKind.BitwiseRightShiftOperator +export type BinaryBitwiseOperator = + | SyntaxKind.BitwiseAndOperator + | SyntaxKind.BitwiseOrOperator + | SyntaxKind.BitwiseExclusiveOrOperator + | SyntaxKind.BitwiseRightShiftOperator | SyntaxKind.BitwiseLeftShiftOperator; export type BinaryOperator = - SyntaxKind.AdditionOperator | SyntaxKind.SubtractionOperator | SyntaxKind.MultiplicationOperator - | SyntaxKind.DivisionOperator | SyntaxKind.FloorDivisionOperator | SyntaxKind.ModuloOperator - | SyntaxKind.PowerOperator | SyntaxKind.ConcatOperator | SyntaxKind.EqualityOperator - | SyntaxKind.InequalityOperator | SyntaxKind.LessThanOperator | SyntaxKind.LessEqualOperator - | SyntaxKind.GreaterThanOperator | SyntaxKind.GreaterEqualOperator | SyntaxKind.AndOperator - | SyntaxKind.OrOperator | BinaryBitwiseOperator; + | SyntaxKind.AdditionOperator + | SyntaxKind.SubtractionOperator + | SyntaxKind.MultiplicationOperator + | SyntaxKind.DivisionOperator + | SyntaxKind.FloorDivisionOperator + | SyntaxKind.ModuloOperator + | SyntaxKind.PowerOperator + | SyntaxKind.ConcatOperator + | SyntaxKind.EqualityOperator + | SyntaxKind.InequalityOperator + | SyntaxKind.LessThanOperator + | SyntaxKind.LessEqualOperator + | SyntaxKind.GreaterThanOperator + | SyntaxKind.GreaterEqualOperator + | SyntaxKind.AndOperator + | SyntaxKind.OrOperator + | BinaryBitwiseOperator; export type Operator = UnaryOperator | BinaryOperator; @@ -110,14 +135,14 @@ export interface Node extends TextRange { export function createNode(kind: SyntaxKind, tsOriginal?: ts.Node, parent?: Node): Node { if (tsOriginal === undefined) { - return {kind, parent}; + return { kind, parent }; } const sourcePosition = getSourcePosition(tsOriginal); if (sourcePosition) { - return {kind, parent, line: sourcePosition.line, column: sourcePosition.column}; + return { kind, parent, line: sourcePosition.line, column: sourcePosition.column }; } else { - return {kind, parent}; + return { kind, parent }; } } @@ -147,7 +172,7 @@ export function setNodeOriginal(node: T | undefined, tsOriginal: return node; } -export function setParent(node: Node | Node[] | undefined, parent: Node): void { +export function setParent(node: Node | Node[] | undefined, parent: Node): void { if (!node) { return; } @@ -162,7 +187,6 @@ 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) { - const { line, character } = ts.getLineAndCharacterOfPosition( sourceNode.getSourceFile(), sourceNode.pos + sourceNode.getLeadingTriviaWidth() @@ -228,8 +252,7 @@ export function createVariableDeclarationStatement( right?: Expression | Expression[], tsOriginal?: ts.Node, parent?: Node -): VariableDeclarationStatement -{ +): VariableDeclarationStatement { const statement = createNode( SyntaxKind.VariableDeclarationStatement, tsOriginal, @@ -263,11 +286,10 @@ export function isAssignmentStatement(node: Node): node is AssignmentStatement { export function createAssignmentStatement( left: AssignmentLeftHandSideExpression | AssignmentLeftHandSideExpression[], - right?: Expression | Expression[], + right?: Expression | Expression[], tsOriginal?: ts.Node, parent?: Node -): AssignmentStatement -{ +): AssignmentStatement { const statement = createNode(SyntaxKind.AssignmentStatement, tsOriginal, parent) as AssignmentStatement; setParent(left, statement); if (Array.isArray(left)) { @@ -301,8 +323,7 @@ export function createIfStatement( elseBlock?: Block | IfStatement, tsOriginal?: ts.Node, parent?: Node -): IfStatement -{ +): IfStatement { const statement = createNode(SyntaxKind.IfStatement, tsOriginal, parent) as IfStatement; setParent(condition, statement); statement.condition = condition; @@ -318,8 +339,12 @@ export interface IterationStatement extends Statement { } export function isIterationStatement(node: Node): node is IterationStatement { - return node.kind === SyntaxKind.WhileStatement || node.kind === SyntaxKind.RepeatStatement - || node.kind === SyntaxKind.ForStatement || node.kind === SyntaxKind.ForInStatement; + return ( + node.kind === SyntaxKind.WhileStatement || + node.kind === SyntaxKind.RepeatStatement || + node.kind === SyntaxKind.ForStatement || + node.kind === SyntaxKind.ForInStatement + ); } export interface WhileStatement extends IterationStatement { @@ -336,8 +361,7 @@ export function createWhileStatement( condition: Expression, tsOriginal?: ts.Node, parent?: Node -): WhileStatement -{ +): WhileStatement { const statement = createNode(SyntaxKind.WhileStatement, tsOriginal, parent) as WhileStatement; setParent(body, statement); statement.body = body; @@ -360,8 +384,7 @@ export function createRepeatStatement( condition: Expression, tsOriginal?: ts.Node, parent?: Node -): RepeatStatement -{ +): RepeatStatement { const statement = createNode(SyntaxKind.RepeatStatement, tsOriginal, parent) as RepeatStatement; setParent(body, statement); statement.body = body; @@ -391,8 +414,7 @@ export function createForStatement( stepExpression?: Expression, tsOriginal?: ts.Node, parent?: Node -): ForStatement -{ +): ForStatement { const statement = createNode(SyntaxKind.ForStatement, tsOriginal, parent) as ForStatement; setParent(body, statement); statement.body = body; @@ -423,8 +445,7 @@ export function createForInStatement( expressions: Expression[], tsOriginal?: ts.Node, parent?: Node -): ForInStatement -{ +): ForInStatement { const statement = createNode(SyntaxKind.ForInStatement, tsOriginal, parent) as ForInStatement; setParent(body, statement); statement.body = body; @@ -437,7 +458,7 @@ export function createForInStatement( export interface GotoStatement extends Statement { kind: SyntaxKind.GotoStatement; - label: string; // or identifier ? + label: string; // or identifier ? } export function isGotoStatement(node: Node): node is GotoStatement { @@ -452,7 +473,7 @@ export function createGotoStatement(label: string, tsOriginal?: ts.Node, parent? export interface LabelStatement extends Statement { kind: SyntaxKind.LabelStatement; - name: string; // or identifier ? + name: string; // or identifier ? } export function isLabelStatement(node: Node): node is LabelStatement { @@ -478,8 +499,7 @@ export function createReturnStatement( expressions?: Expression[], tsOriginal?: ts.Node, parent?: Node -): ReturnStatement -{ +): ReturnStatement { const statement = createNode(SyntaxKind.ReturnStatement, tsOriginal, parent) as ReturnStatement; setParent(expressions, statement); statement.expressions = expressions; @@ -511,8 +531,7 @@ export function createExpressionStatement( expressions: Expression, tsOriginal?: ts.Node, parent?: Node -): ExpressionStatement -{ +): ExpressionStatement { const statement = createNode(SyntaxKind.ExpressionStatement, tsOriginal, parent) as ExpressionStatement; setParent(expressions, statement); statement.expression = expressions; @@ -628,8 +647,7 @@ export function createFunctionExpression( flags = FunctionExpressionFlags.None, tsOriginal?: ts.Node, parent?: Node -): FunctionExpression -{ +): FunctionExpression { const expression = createNode(SyntaxKind.FunctionExpression, tsOriginal, parent) as FunctionExpression; setParent(body, expression); expression.body = body; @@ -658,8 +676,7 @@ export function createTableFieldExpression( key?: Expression, tsOriginal?: ts.Node, parent?: Node -): TableFieldExpression -{ +): TableFieldExpression { const expression = createNode(SyntaxKind.TableExpression, tsOriginal, parent) as TableFieldExpression; setParent(value, expression); expression.value = value; @@ -681,8 +698,7 @@ export function createTableExpression( fields?: TableFieldExpression[], tsOriginal?: ts.Node, parent?: Node -): TableExpression -{ +): TableExpression { const expression = createNode(SyntaxKind.TableExpression, tsOriginal, parent) as TableExpression; setParent(fields, expression); expression.fields = fields; @@ -704,8 +720,7 @@ export function createUnaryExpression( operator: UnaryOperator, tsOriginal?: ts.Node, parent?: Node -): UnaryExpression -{ +): UnaryExpression { const expression = createNode(SyntaxKind.UnaryExpression, tsOriginal, parent) as UnaryExpression; setParent(operand, expression); expression.operand = operand; @@ -730,8 +745,7 @@ export function createBinaryExpression( operator: BinaryOperator, tsOriginal?: ts.Node, parent?: Node -): BinaryExpression -{ +): BinaryExpression { const expression = createNode(SyntaxKind.BinaryExpression, tsOriginal, parent) as BinaryExpression; setParent(left, expression); expression.left = left; @@ -754,8 +768,7 @@ export function createParenthesizedExpression( innerExpression: Expression, tsOriginal?: ts.Node, parent?: Node -): ParenthesizedExpression -{ +): ParenthesizedExpression { const expression = createNode(SyntaxKind.ParenthesizedExpression, tsOriginal, parent) as ParenthesizedExpression; setParent(innerExpression, expression); expression.innerExpression = innerExpression; @@ -777,8 +790,7 @@ export function createCallExpression( params?: Expression[], tsOriginal?: ts.Node, parent?: Node -): CallExpression -{ +): CallExpression { const callExpression = createNode(SyntaxKind.CallExpression, tsOriginal, parent) as CallExpression; setParent(expression, callExpression); callExpression.expression = expression; @@ -804,8 +816,7 @@ export function createMethodCallExpression( params?: Expression[], tsOriginal?: ts.Node, parent?: Node -): MethodCallExpression -{ +): MethodCallExpression { const callExpression = createNode(SyntaxKind.MethodCallExpression, tsOriginal, parent) as MethodCallExpression; setParent(prefixExpression, callExpression); callExpression.prefixExpression = prefixExpression; @@ -831,8 +842,7 @@ export function createIdentifier( tsOriginal?: ts.Node, symbolId?: SymbolId, parent?: Node -): Identifier -{ +): Identifier { const expression = createNode(SyntaxKind.Identifier, tsOriginal, parent) as Identifier; expression.text = text as string; expression.symbolId = symbolId; @@ -864,8 +874,7 @@ export function createTableIndexExpression( index: Expression, tsOriginal?: ts.Node, parent?: Node -): TableIndexExpression -{ +): TableIndexExpression { const expression = createNode(SyntaxKind.TableIndexExpression, tsOriginal, parent) as TableIndexExpression; setParent(table, expression); expression.table = table; @@ -880,23 +889,27 @@ export type FunctionDefinition = (VariableDeclarationStatement | AssignmentState right: [FunctionExpression]; }; -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]); +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]) + ); } export type InlineFunctionExpression = FunctionExpression & { - body: { statements: [ReturnStatement & { expressions: Expression[] }]; }; + body: { statements: [ReturnStatement & { expressions: Expression[] }] }; }; -export function isInlineFunctionExpression(expression: FunctionExpression) : expression is InlineFunctionExpression { - return expression.body.statements !== undefined - && expression.body.statements.length === 1 - && isReturnStatement(expression.body.statements[0]) - && (expression.body.statements[0] as ReturnStatement).expressions !== undefined - && (expression.flags & FunctionExpressionFlags.Inline) !== 0; +export function isInlineFunctionExpression(expression: FunctionExpression): expression is InlineFunctionExpression { + return ( + expression.body.statements !== undefined && + expression.body.statements.length === 1 && + isReturnStatement(expression.body.statements[0]) && + (expression.body.statements[0] as ReturnStatement).expressions !== undefined && + (expression.flags & FunctionExpressionFlags.Inline) !== 0 + ); } diff --git a/src/LuaKeywords.ts b/src/LuaKeywords.ts index 6f3bff133..55aa120f9 100644 --- a/src/LuaKeywords.ts +++ b/src/LuaKeywords.ts @@ -1,9 +1,46 @@ export const luaKeywords: Set = new Set([ - "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "goto", "if", "in", "local", "nil", - "not", "or", "repeat", "return", "then", "until", "while", + "and", + "break", + "do", + "else", + "elseif", + "end", + "false", + "for", + "function", + "goto", + "if", + "in", + "local", + "nil", + "not", + "or", + "repeat", + "return", + "then", + "until", + "while", ]); export const luaBuiltins: Set = new Set([ - "_G", "assert", "coroutine", "debug", "error", "ipairs", "math", "pairs", "pcall", "print", "rawget", "rawset", - "repeat", "require", "self", "string", "table", "tostring", "type", "unpack", + "_G", + "assert", + "coroutine", + "debug", + "error", + "ipairs", + "math", + "pairs", + "pcall", + "print", + "rawget", + "rawset", + "repeat", + "require", + "self", + "string", + "table", + "tostring", + "type", + "unpack", ]); diff --git a/src/LuaLib.ts b/src/LuaLib.ts index d339fc945..70799e090 100644 --- a/src/LuaLib.ts +++ b/src/LuaLib.ts @@ -56,7 +56,7 @@ export enum LuaLibFeature { SymbolRegistry = "SymbolRegistry", } -const luaLibDependencies: {[lib in LuaLibFeature]?: LuaLibFeature[]} = { +const luaLibDependencies: { [lib in LuaLibFeature]?: LuaLibFeature[] } = { ArrayFlat: [LuaLibFeature.ArrayConcat], ArrayFlatMap: [LuaLibFeature.ArrayConcat], InstanceOf: [LuaLibFeature.Symbol], diff --git a/src/LuaPrinter.ts b/src/LuaPrinter.ts index ba5da24f6..0792cb7bc 100644 --- a/src/LuaPrinter.ts +++ b/src/LuaPrinter.ts @@ -11,7 +11,7 @@ import { luaKeywords } from "./LuaKeywords"; type SourceChunk = string | SourceNode; export class LuaPrinter { - private static operatorMap: {[key in tstl.Operator]: string} = { + private static operatorMap: { [key in tstl.Operator]: string } = { [tstl.SyntaxKind.AdditionOperator]: "+", [tstl.SyntaxKind.SubtractionOperator]: "-", [tstl.SyntaxKind.MultiplicationOperator]: "*", @@ -60,8 +60,9 @@ export class LuaPrinter { const rootSourceNode = this.printImplementation(block, luaLibFeatures, sourceFile); - const sourceRoot = this.options.sourceRoot - || (this.options.outDir ? path.relative(this.options.outDir, this.options.rootDir || process.cwd()) : "."); + const sourceRoot = + this.options.sourceRoot || + (this.options.outDir ? path.relative(this.options.outDir, this.options.rootDir || process.cwd()) : "."); const sourceMap = this.buildSourceMap(sourceFile, sourceRoot, rootSourceNode); @@ -81,14 +82,14 @@ export class LuaPrinter { private printInlineSourceMap(sourceMap: SourceMapGenerator): string { const map = sourceMap.toString(); - const base64Map = Buffer.from(map).toString('base64'); + const base64Map = Buffer.from(map).toString("base64"); return `--# sourceMappingURL=data:application/json;base64,${base64Map}\n`; } private printStackTraceOverride(rootNode: SourceNode): string { let line = 1; - const map: {[line: number]: number} = {}; + const map: { [line: number]: number } = {}; rootNode.walk((chunk, mappedPosition) => { if (mappedPosition.line !== undefined && mappedPosition.line > 0) { if (map[line] === undefined) { @@ -110,11 +111,7 @@ export class LuaPrinter { return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString});`; } - private printImplementation( - block: tstl.Block, - luaLibFeatures?: Set, - sourceFile = ""): SourceNode { - + private printImplementation(block: tstl.Block, luaLibFeatures?: Set, sourceFile = ""): SourceNode { let header = ""; if (!this.options.noHeader) { @@ -124,9 +121,10 @@ export class LuaPrinter { if (luaLibFeatures) { const luaLibImport = this.options.luaLibImport || LuaLibImportKind.Inline; // Require lualib bundle - if ((luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) - || luaLibImport === LuaLibImportKind.Always) - { + if ( + (luaLibImport === LuaLibImportKind.Require && luaLibFeatures.size > 0) || + luaLibImport === LuaLibImportKind.Always + ) { header += `require("lualib_bundle");\n`; } // Inline lualib features @@ -164,8 +162,7 @@ export class LuaPrinter { return originalPos !== undefined && originalPos.line !== undefined && originalPos.column !== undefined ? new SourceNode(originalPos.line + 1, originalPos.column, this.sourceFile, chunks) - // tslint:disable-next-line:no-null-keyword - : new SourceNode(null, null, this.sourceFile, chunks); + : new SourceNode(null, null, this.sourceFile, chunks); // tslint:disable-line:no-null-keyword } protected concatNodes(...chunks: SourceChunk[]): SourceNode { @@ -179,9 +176,11 @@ export class LuaPrinter { private statementMayRequireSemiColon(statement: tstl.Statement): boolean { // Types of statements that could create ambiguous syntax if followed by parenthesis - return tstl.isVariableDeclarationStatement(statement) - || tstl.isAssignmentStatement(statement) - || tstl.isExpressionStatement(statement); + return ( + tstl.isVariableDeclarationStatement(statement) || + tstl.isAssignmentStatement(statement) || + tstl.isExpressionStatement(statement) + ); } private nodeStartsWithParenthesis(sourceNode: SourceNode): boolean { @@ -201,20 +200,15 @@ export class LuaPrinter { protected printStatementArray(statements: tstl.Statement[]): SourceChunk[] { const statementNodes: SourceNode[] = []; statements = this.removeDeadAndEmptyStatements(statements); - statements.forEach( - (s, i) => { - const node = this.printStatement(s); - - if (i > 0 - && this.statementMayRequireSemiColon(statements[i - 1]) - && this.nodeStartsWithParenthesis(node)) - { - statementNodes[i - 1].add(";"); - } + statements.forEach((s, i) => { + const node = this.printStatement(s); - statementNodes.push(node); + if (i > 0 && this.statementMayRequireSemiColon(statements[i - 1]) && this.nodeStartsWithParenthesis(node)) { + statementNodes[i - 1].add(";"); } - ); + + statementNodes.push(node); + }); return statementNodes.length > 0 ? [...this.joinChunks("\n", statementNodes), "\n"] : []; } @@ -271,7 +265,6 @@ export class LuaPrinter { if (tstl.isFunctionDefinition(statement)) { // 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)))); @@ -289,9 +282,10 @@ export class LuaPrinter { chunks.push(this.indent()); - if (tstl.isFunctionDefinition(statement) - && (statement.right[0].flags & tstl.FunctionExpressionFlags.Declaration) !== 0) - { + if ( + tstl.isFunctionDefinition(statement) && + (statement.right[0].flags & tstl.FunctionExpressionFlags.Declaration) !== 0 + ) { // Use `function foo()` instead of `foo = function()` const name = this.printExpression(statement.left[0]); if (tsHelper.isValidLuaFunctionDeclarationName(name.toString())) { @@ -310,8 +304,7 @@ export class LuaPrinter { public printIfStatement(statement: tstl.IfStatement): SourceNode { const chunks: SourceChunk[] = []; - const isElseIf = statement.parent !== undefined - && tstl.isIfStatement(statement.parent); + const isElseIf = statement.parent !== undefined && tstl.isIfStatement(statement.parent); const prefix = isElseIf ? "elseif" : "if"; @@ -524,7 +517,6 @@ export class LuaPrinter { ]; chunks.push(this.createSourceNode(returnStatement, returnNode)); chunks.push(" end"); - } else { chunks.push("\n"); this.pushIndent(); @@ -560,10 +552,11 @@ export class LuaPrinter { const value = this.printExpression(expression.value); if (expression.key) { - if (tstl.isStringLiteral(expression.key) - && tsHelper.isValidLuaIdentifier(expression.key.value) - && !luaKeywords.has(expression.key.value)) - { + if ( + tstl.isStringLiteral(expression.key) && + tsHelper.isValidLuaIdentifier(expression.key.value) && + !luaKeywords.has(expression.key.value) + ) { chunks.push(expression.key.value, " = ", value); } else { chunks.push("[", this.printExpression(expression.key), "] = ", value); @@ -584,7 +577,6 @@ export class LuaPrinter { if (expression.fields.length === 1) { // Inline tables with only one entry chunks.push(this.printTableFieldExpression(expression.fields[0])); - } else { chunks.push("\n"); this.pushIndent(); @@ -625,9 +617,8 @@ export class LuaPrinter { public printCallExpression(expression: tstl.CallExpression): SourceNode { const chunks = []; - const parameterChunks = expression.params !== undefined - ? expression.params.map(e => this.printExpression(e)) - : []; + const parameterChunks = + expression.params !== undefined ? expression.params.map(e => this.printExpression(e)) : []; chunks.push(this.printExpression(expression.expression), "(", ...this.joinChunks(", ", parameterChunks), ")"); @@ -637,16 +628,19 @@ export class LuaPrinter { public printMethodCallExpression(expression: tstl.MethodCallExpression): SourceNode { const prefix = this.printExpression(expression.prefixExpression); - const parameterChunks = expression.params !== undefined - ? expression.params.map(e => this.printExpression(e)) - : []; + const parameterChunks = + expression.params !== undefined ? expression.params.map(e => this.printExpression(e)) : []; const name = this.printIdentifier(expression.name); - return this.createSourceNode( - expression, - [prefix, ":", name, "(", ...this.joinChunks(", ", parameterChunks), ")"] - ); + return this.createSourceNode(expression, [ + prefix, + ":", + name, + "(", + ...this.joinChunks(", ", parameterChunks), + ")", + ]); } public printIdentifier(expression: tstl.Identifier): SourceNode { @@ -657,10 +651,11 @@ export class LuaPrinter { const chunks: SourceChunk[] = []; chunks.push(this.printExpression(expression.table)); - if (tstl.isStringLiteral(expression.index) - && tsHelper.isValidLuaIdentifier(expression.index.value) - && !luaKeywords.has(expression.index.value)) - { + if ( + tstl.isStringLiteral(expression.index) && + tsHelper.isValidLuaIdentifier(expression.index.value) && + !luaKeywords.has(expression.index.value) + ) { chunks.push(".", this.createSourceNode(expression.index, expression.index.value)); } else { chunks.push("[", this.printExpression(expression.index), "]"); @@ -720,13 +715,15 @@ export class LuaPrinter { if (currentMapping === undefined) { return true; } - if (currentMapping.generated.line === generatedLine - && currentMapping.generated.column === generatedColumn) - { + if ( + currentMapping.generated.line === generatedLine && + currentMapping.generated.column === generatedColumn + ) { return false; } - return (currentMapping.original.line !== sourceNode.line - || currentMapping.original.column !== sourceNode.column); + return ( + currentMapping.original.line !== sourceNode.line || currentMapping.original.column !== sourceNode.column + ); }; const build = (sourceNode: SourceNode) => { @@ -748,7 +745,6 @@ export class LuaPrinter { currentMapping = undefined; // Mappings end at newlines } generatedColumn += lines[lines.length - 1].length; - } else { build(chunk); } diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index d7e0b4eeb..2cd7db45c 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -80,11 +80,10 @@ export class LuaTransformer { public constructor(protected program: ts.Program) { this.checker = (program as any).getDiagnosticsProducingTypeChecker(); this.options = program.getCompilerOptions(); - this.isStrict = this.options.alwaysStrict !== undefined - || (this.options.strict !== undefined && this.options.alwaysStrict !== false) - || (this.isModule - && this.options.target !== undefined - && this.options.target >= ts.ScriptTarget.ES2015); + this.isStrict = + this.options.alwaysStrict !== undefined || + (this.options.strict !== undefined && this.options.alwaysStrict !== false) || + (this.isModule && this.options.target !== undefined && this.options.target >= ts.ScriptTarget.ES2015); this.luaTarget = this.options.luaTarget || LuaTarget.LuaJIT; @@ -119,9 +118,7 @@ export class LuaTransformer { throw TSTLErrors.InvalidJsonFileContent(node); } - statements.push( - tstl.createReturnStatement([this.transformExpression(statement.expression)]) - ); + statements.push(tstl.createReturnStatement([this.transformExpression(statement.expression)])); } else { this.pushScope(ScopeType.File); @@ -140,11 +137,7 @@ export class LuaTransformer { ); // return exports - statements.push( - tstl.createReturnStatement( - [this.createExportsIdentifier()] - ) - ); + statements.push(tstl.createReturnStatement([this.createExportsIdentifier()])); } } @@ -241,10 +234,13 @@ export class LuaTransformer { public transformExportDeclaration(statement: ts.ExportDeclaration): StatementVisitResult { if (statement.exportClause) { - if (statement.exportClause.elements.some(e => - (e.name !== undefined && e.name.originalKeywordKind === ts.SyntaxKind.DefaultKeyword) - || (e.propertyName !== undefined - && e.propertyName.originalKeywordKind === ts.SyntaxKind.DefaultKeyword)) + if ( + statement.exportClause.elements.some( + e => + (e.name !== undefined && e.name.originalKeywordKind === ts.SyntaxKind.DefaultKeyword) || + (e.propertyName !== undefined && + e.propertyName.originalKeywordKind === ts.SyntaxKind.DefaultKeyword) + ) ) { throw TSTLErrors.UnsupportedDefaultExport(statement); } @@ -262,7 +258,7 @@ export class LuaTransformer { let exportedIdentifier: tstl.Expression | undefined; if (specifier.propertyName !== undefined) { exportedIdentifier = this.transformIdentifier(specifier.propertyName); - } else { + } else { const exportedSymbol = this.checker.getExportSpecifierLocalTargetSymbol(specifier); exportedIdentifier = this.createShorthandIdentifier(exportedSymbol, specifier.name); } @@ -277,9 +273,7 @@ export class LuaTransformer { // First transpile as import clause const importClause = ts.createImportClause( undefined, - ts.createNamedImports( - exportSpecifiers.map(s => ts.createImportSpecifier(s.propertyName, s.name)) - ) + ts.createNamedImports(exportSpecifiers.map(s => ts.createImportSpecifier(s.propertyName, s.name))) ); const importDeclaration = ts.createImportDeclaration( @@ -322,15 +316,12 @@ export class LuaTransformer { const forKey = tstl.createIdentifier("____exportKey"); const forValue = tstl.createIdentifier("____exportValue"); - const body = tstl.createBlock( - [tstl.createAssignmentStatement( - tstl.createTableIndexExpression( - this.createExportsIdentifier(), - forKey - ), + const body = tstl.createBlock([ + tstl.createAssignmentStatement( + tstl.createTableIndexExpression(this.createExportsIdentifier(), forKey), forValue - )] - ); + ), + ]); const pairsIdentifier = tstl.createIdentifier("pairs"); const forIn = tstl.createForInStatement( @@ -360,7 +351,7 @@ export class LuaTransformer { } const moduleSpecifier = statement.moduleSpecifier as ts.StringLiteral; - const importPath = moduleSpecifier.text.replace(new RegExp("\"", "g"), ""); + const importPath = moduleSpecifier.text.replace(new RegExp('"', "g"), ""); if (!statement.importClause) { const requireCall = this.createModuleRequire(statement.moduleSpecifier as ts.StringLiteral); @@ -386,9 +377,9 @@ export class LuaTransformer { const filteredElements = imports.elements.filter(e => { const decorators = tsHelper.getCustomDecorators(this.checker.getTypeAtLocation(e), this.checker); return ( - this.resolver.isReferencedAliasDeclaration(e) - && !decorators.has(DecoratorKind.Extension) - && !decorators.has(DecoratorKind.MetaExtension) + this.resolver.isReferencedAliasDeclaration(e) && + !decorators.has(DecoratorKind.Extension) && + !decorators.has(DecoratorKind.MetaExtension) ); }); @@ -398,9 +389,9 @@ export class LuaTransformer { } const tstlIdentifier = (name: string) => "__TSTL_" + tsHelper.fixInvalidLuaIdentifier(name); - const importUniqueName = tstl.createIdentifier(tstlIdentifier(path.basename((importPath)))); + const importUniqueName = tstl.createIdentifier(tstlIdentifier(path.basename(importPath))); const requireStatement = tstl.createVariableDeclarationStatement( - tstl.createIdentifier(tstlIdentifier(path.basename((importPath)))), + tstl.createIdentifier(tstlIdentifier(path.basename(importPath))), requireCall, statement ); @@ -412,7 +403,8 @@ export class LuaTransformer { const renamedImport = tstl.createVariableDeclarationStatement( this.transformIdentifier(importSpecifier.name), tstl.createTableIndexExpression(importUniqueName, propertyName), - importSpecifier); + importSpecifier + ); result.push(renamedImport); } else { const name = tstl.createStringLiteral(importSpecifier.name.text); @@ -430,7 +422,6 @@ export class LuaTransformer { } else { return result; } - } else if (ts.isNamespaceImport(imports)) { if (!this.resolver.isReferencedAliasDeclaration(imports)) { return undefined; @@ -453,7 +444,7 @@ export class LuaTransformer { private createModuleRequire(moduleSpecifier: ts.StringLiteral, resolveModule = true): tstl.CallExpression { const modulePathString = resolveModule - ? this.getImportPath(moduleSpecifier.text.replace(new RegExp("\"", "g"), ""), moduleSpecifier) + ? this.getImportPath(moduleSpecifier.text.replace(new RegExp('"', "g"), ""), moduleSpecifier) : moduleSpecifier.text; const modulePath = tstl.createStringLiteral(modulePathString); return tstl.createCallExpression(tstl.createIdentifier("require"), [modulePath], moduleSpecifier); @@ -470,8 +461,7 @@ export class LuaTransformer { public transformClassDeclaration( statement: ts.ClassLikeDeclaration, nameOverride?: tstl.Identifier - ): StatementVisitResult - { + ): StatementVisitResult { this.classStack.push(statement); if (statement.name === undefined && nameOverride === undefined) { @@ -560,8 +550,10 @@ export class LuaTransformer { ), [] ), - extendsName), - statement); + extendsName + ), + statement + ); result.push(assignDebugCallIndex); } @@ -577,11 +569,7 @@ export class LuaTransformer { let localClassName: tstl.Identifier; if (this.isUnsafeName(className.text)) { - localClassName = tstl.createIdentifier( - this.createSafeName(className.text), - undefined, - className.symbolId - ); + localClassName = tstl.createIdentifier(this.createSafeName(className.text), undefined, className.symbolId); tstl.setNodePosition(localClassName, className); } else { localClassName = className; @@ -600,14 +588,10 @@ export class LuaTransformer { for (const f of instanceFields) { const fieldName = this.transformPropertyName(f.name); - const value = f.initializer !== undefined - ? this.transformExpression(f.initializer) - : undefined; + const value = f.initializer !== undefined ? this.transformExpression(f.initializer) : undefined; // className["fieldName"] - const classField = tstl.createTableIndexExpression( - tstl.cloneIdentifier(className), - fieldName); + const classField = tstl.createTableIndexExpression(tstl.cloneIdentifier(className), fieldName); // className["fieldName"] = value; const assignClassField = tstl.createAssignmentStatement(classField, value); @@ -618,8 +602,9 @@ export class LuaTransformer { // Find first constructor with body if (!isExtension && !isMetaExtension) { - const constructor = statement.members - .filter(n => ts.isConstructorDeclaration(n) && n.body)[0] as ts.ConstructorDeclaration; + const constructor = statement.members.filter( + n => ts.isConstructorDeclaration(n) && n.body + )[0] as ts.ConstructorDeclaration; if (constructor) { // Add constructor plus initialization of instance fields const constructorResult = this.transformConstructorDeclaration( @@ -638,9 +623,10 @@ export class LuaTransformer { statement ); result.push(...this.statementVisitResultToArray(constructorResult)); - } else if (instanceFields.length > 0 - || statement.members.some(m => tsHelper.isGetAccessorOverride(m, statement, this.checker))) - { + } else if ( + instanceFields.length > 0 || + statement.members.some(m => tsHelper.isGetAccessorOverride(m, statement, this.checker)) + ) { // Generate a constructor if none was defined in a class with instance fields that need initialization // localClassName.prototype.____constructor = function(self, ...) // baseClassName.prototype.____constructor(self, ...) @@ -663,11 +649,13 @@ export class LuaTransformer { undefined, tstl.FunctionExpressionFlags.Declaration ); - result.push(tstl.createAssignmentStatement( - this.createConstructorName(localClassName), - constructorFunction, - statement - )); + result.push( + tstl.createAssignmentStatement( + this.createConstructorName(localClassName), + constructorFunction, + statement + ) + ); } } @@ -700,15 +688,9 @@ export class LuaTransformer { const fieldName = this.transformPropertyName(field.name); const value = field.initializer ? this.transformExpression(field.initializer) : undefined; - const classField = tstl.createTableIndexExpression( - tstl.cloneIdentifier(localClassName), - fieldName - ); + const classField = tstl.createTableIndexExpression(tstl.cloneIdentifier(localClassName), fieldName); - const fieldAssign = tstl.createAssignmentStatement( - classField, - value - ); + const fieldAssign = tstl.createAssignmentStatement(classField, value); result.push(fieldAssign); } @@ -729,8 +711,7 @@ export class LuaTransformer { localClassName: tstl.Identifier, classNameText: string, extendsType?: ts.Type - ): tstl.Statement[] - { + ): tstl.Statement[] { const result: tstl.Statement[] = []; // [____exports.]className = {} @@ -803,10 +784,11 @@ export class LuaTransformer { } // localClassName.prototype = {} - const createClassPrototype = () => tstl.createTableIndexExpression( - tstl.cloneIdentifier(localClassName), - tstl.createStringLiteral("prototype") - ); + const createClassPrototype = () => + tstl.createTableIndexExpression( + tstl.cloneIdentifier(localClassName), + tstl.createStringLiteral("prototype") + ); const classPrototypeTable = tstl.createTableExpression(); const assignClassPrototype = tstl.createAssignmentStatement( createClassPrototype(), @@ -841,7 +823,6 @@ export class LuaTransformer { statement ); result.push(assignClassPrototypeIndex); - } else { // localClassName.prototype.__index = localClassName.prototype const assignClassPrototypeIndex = tstl.createAssignmentStatement( @@ -902,10 +883,11 @@ export class LuaTransformer { } // localClassName.____super = extendsExpression - const createClassBase = () => tstl.createTableIndexExpression( - tstl.cloneIdentifier(localClassName), - tstl.createStringLiteral("____super") - ); + const createClassBase = () => + tstl.createTableIndexExpression( + tstl.cloneIdentifier(localClassName), + tstl.createStringLiteral("____super") + ); const assignClassBase = tstl.createAssignmentStatement( createClassBase(), this.transformExpression(extendedTypeNode.expression), @@ -954,7 +936,6 @@ export class LuaTransformer { ) ); result.push(setClassMetatable); - } else { // setmetatable(localClassName, localClassName.____super) const setClassMetatable = tstl.createExpressionStatement( @@ -973,14 +954,13 @@ export class LuaTransformer { tstl.createStringLiteral("prototype") ); const setClassPrototypeMetatable = tstl.createExpressionStatement( - tstl.createCallExpression( - tstl.createIdentifier("setmetatable"), - [createClassPrototype(), basePrototype] - ), + tstl.createCallExpression(tstl.createIdentifier("setmetatable"), [ + createClassPrototype(), + basePrototype, + ]), extendedTypeNode.expression ); result.push(setClassPrototypeMetatable); - } else if (hasStaticGetters || hasStaticSetters) { const metatableFields: tstl.TableFieldExpression[] = []; if (hasStaticGetters) { @@ -1006,10 +986,10 @@ export class LuaTransformer { } const setClassMetatable = tstl.createExpressionStatement( - tstl.createCallExpression( - tstl.createIdentifier("setmetatable"), - [tstl.cloneIdentifier(localClassName), tstl.createTableExpression(metatableFields)] - ), + tstl.createCallExpression(tstl.createIdentifier("setmetatable"), [ + tstl.cloneIdentifier(localClassName), + tstl.createTableExpression(metatableFields), + ]), statement ); result.push(setClassMetatable); @@ -1020,20 +1000,18 @@ export class LuaTransformer { // local self = setmetatable({}, localClassName.prototype) const assignSelf = tstl.createVariableDeclarationStatement( this.createSelfIdentifier(), - tstl.createCallExpression( - tstl.createIdentifier("setmetatable"), - [tstl.createTableExpression(), createClassPrototype()] - ) + tstl.createCallExpression(tstl.createIdentifier("setmetatable"), [ + tstl.createTableExpression(), + createClassPrototype(), + ]) ); newFuncStatements.push(assignSelf); // self:____constructor(...) const callConstructor = tstl.createExpressionStatement( - tstl.createMethodCallExpression( - this.createSelfIdentifier(), - tstl.createIdentifier("____constructor"), - [tstl.createDotsLiteral()] - ) + tstl.createMethodCallExpression(this.createSelfIdentifier(), tstl.createIdentifier("____constructor"), [ + tstl.createDotsLiteral(), + ]) ); newFuncStatements.push(callConstructor); @@ -1044,9 +1022,7 @@ export class LuaTransformer { // function localClassName.new(construct, ...) ... end // or function export.localClassName.new(construct, ...) ... end const newFunc = tstl.createAssignmentStatement( - tstl.createTableIndexExpression( - tstl.cloneIdentifier(localClassName), - tstl.createStringLiteral("new")), + tstl.createTableIndexExpression(tstl.cloneIdentifier(localClassName), tstl.createStringLiteral("new")), tstl.createFunctionExpression( tstl.createBlock(newFuncStatements), undefined, @@ -1063,8 +1039,7 @@ export class LuaTransformer { private transformClassInstanceFields( classDeclaration: ts.ClassLikeDeclaration, instanceFields: ts.PropertyDeclaration[] - ): tstl.Statement[] - { + ): tstl.Statement[] { const statements: tstl.Statement[] = []; for (const f of instanceFields) { @@ -1092,10 +1067,11 @@ export class LuaTransformer { const getterName = this.transformPropertyName(getter.name); const resetGetter = tstl.createExpressionStatement( - tstl.createCallExpression( - tstl.createIdentifier("rawset"), - [this.createSelfIdentifier(), getterName, tstl.createNilLiteral()] - ) + tstl.createCallExpression(tstl.createIdentifier("rawset"), [ + this.createSelfIdentifier(), + getterName, + tstl.createNilLiteral(), + ]) ); statements.push(resetGetter); } @@ -1105,10 +1081,7 @@ export class LuaTransformer { private createConstructorName(className: tstl.Identifier): tstl.TableIndexExpression { return tstl.createTableIndexExpression( - tstl.createTableIndexExpression( - tstl.cloneIdentifier(className), - tstl.createStringLiteral("prototype") - ), + tstl.createTableIndexExpression(tstl.cloneIdentifier(className), tstl.createStringLiteral("prototype")), tstl.createStringLiteral("____constructor") ); } @@ -1118,8 +1091,7 @@ export class LuaTransformer { className: tstl.Identifier, instanceFields: ts.PropertyDeclaration[], classDeclaration: ts.ClassLikeDeclaration - ): StatementVisitResult - { + ): StatementVisitResult { // Don't transform methods without body (overload declarations) if (!statement.body) { return undefined; @@ -1140,7 +1112,8 @@ export class LuaTransformer { // self.declarationName = declarationName or initializer const assignment = tstl.createAssignmentStatement( tstl.createTableIndexExpression( - this.createSelfIdentifier(), tstl.createStringLiteral(declarationName.text) + this.createSelfIdentifier(), + tstl.createStringLiteral(declarationName.text) ), tstl.createBinaryExpression( declarationName, @@ -1174,10 +1147,11 @@ export class LuaTransformer { // If there are field initializers and the first statement is a super call, hoist the super call to the top if (bodyWithFieldInitializers.length > 0 && statement.body && statement.body.statements.length > 0) { const firstStatement = statement.body.statements[0]; - if (ts.isExpressionStatement(firstStatement) - && ts.isCallExpression(firstStatement.expression) - && firstStatement.expression.expression.kind === ts.SyntaxKind.SuperKeyword) - { + if ( + ts.isExpressionStatement(firstStatement) && + ts.isCallExpression(firstStatement.expression) && + firstStatement.expression.expression.kind === ts.SyntaxKind.SuperKeyword + ) { const superCall = body.shift(); if (superCall) { bodyWithFieldInitializers.unshift(superCall); @@ -1207,8 +1181,7 @@ export class LuaTransformer { public transformGetAccessorDeclaration( getAccessor: ts.GetAccessorDeclaration, className: tstl.Identifier - ): StatementVisitResult - { + ): StatementVisitResult { if (getAccessor.body === undefined) { return undefined; } @@ -1230,14 +1203,8 @@ export class LuaTransformer { ? tstl.cloneIdentifier(className) : tstl.createTableIndexExpression(tstl.cloneIdentifier(className), tstl.createStringLiteral("prototype")); - const classGetters = tstl.createTableIndexExpression( - methodTable, - tstl.createStringLiteral("____getters") - ); - const getter = tstl.createTableIndexExpression( - classGetters, - tstl.createStringLiteral(name.text) - ); + const classGetters = tstl.createTableIndexExpression(methodTable, tstl.createStringLiteral("____getters")); + const getter = tstl.createTableIndexExpression(classGetters, tstl.createStringLiteral(name.text)); const assignGetter = tstl.createAssignmentStatement(getter, accessorFunction, getAccessor); return assignGetter; } @@ -1245,8 +1212,7 @@ export class LuaTransformer { public transformSetAccessorDeclaration( setAccessor: ts.SetAccessorDeclaration, className: tstl.Identifier - ): StatementVisitResult - { + ): StatementVisitResult { if (setAccessor.body === undefined) { return undefined; } @@ -1270,14 +1236,8 @@ export class LuaTransformer { ? tstl.cloneIdentifier(className) : tstl.createTableIndexExpression(tstl.cloneIdentifier(className), tstl.createStringLiteral("prototype")); - const classSetters = tstl.createTableIndexExpression( - methodTable, - tstl.createStringLiteral("____setters") - ); - const setter = tstl.createTableIndexExpression( - classSetters, - tstl.createStringLiteral(name.text) - ); + const classSetters = tstl.createTableIndexExpression(methodTable, tstl.createStringLiteral("____setters")); + const setter = tstl.createTableIndexExpression(classSetters, tstl.createStringLiteral(name.text)); const assignSetter = tstl.createAssignmentStatement(setter, accessorFunction, setAccessor); return assignSetter; } @@ -1286,8 +1246,7 @@ export class LuaTransformer { node: ts.MethodDeclaration, className: tstl.Identifier, noPrototype: boolean - ): StatementVisitResult - { + ): StatementVisitResult { // Don't transform methods without body (overload declarations) if (!node.body) { return undefined; @@ -1301,9 +1260,10 @@ export class LuaTransformer { } const type = this.checker.getTypeAtLocation(node); - const context = tsHelper.getFunctionContextType(type, this.checker) !== ContextType.Void - ? this.createSelfIdentifier() - : undefined; + const context = + tsHelper.getFunctionContextType(type, this.checker) !== ContextType.Void + ? this.createSelfIdentifier() + : undefined; const [paramNames, dots, restParamName] = this.transformParameters(node.parameters, context); const [body] = this.transformFunctionBody(node.parameters, node.body, restParamName); @@ -1316,21 +1276,25 @@ export class LuaTransformer { node.body ); - const methodTable = tsHelper.isStatic(node) || noPrototype - ? tstl.cloneIdentifier(className) - : tstl.createTableIndexExpression(tstl.cloneIdentifier(className), tstl.createStringLiteral("prototype")); + const methodTable = + tsHelper.isStatic(node) || noPrototype + ? tstl.cloneIdentifier(className) + : tstl.createTableIndexExpression( + tstl.cloneIdentifier(className), + tstl.createStringLiteral("prototype") + ); return tstl.createAssignmentStatement( - tstl.createTableIndexExpression( - methodTable, - methodName), + tstl.createTableIndexExpression(methodTable, methodName), functionExpression, node ); } - private transformParameters(parameters: ts.NodeArray, context?: tstl.Identifier): - [tstl.Identifier[], tstl.DotsLiteral | undefined, tstl.Identifier | undefined] { + private transformParameters( + parameters: ts.NodeArray, + context?: tstl.Identifier + ): [tstl.Identifier[], tstl.DotsLiteral | undefined, tstl.Identifier | undefined] { // Build parameter string const paramNames: tstl.Identifier[] = []; if (context) { @@ -1349,9 +1313,10 @@ export class LuaTransformer { // Binding patterns become ____TS_bindingPattern0, ____TS_bindingPattern1, etc as function parameters // See transformFunctionBody for how these values are destructured - const paramName = ts.isObjectBindingPattern(param.name) || ts.isArrayBindingPattern(param.name) - ? tstl.createIdentifier(`____TS_bindingPattern${identifierIndex++}`) - : this.transformIdentifier(param.name as ts.Identifier); + const paramName = + ts.isObjectBindingPattern(param.name) || ts.isArrayBindingPattern(param.name) + ? tstl.createIdentifier(`____TS_bindingPattern${identifierIndex++}`) + : this.transformIdentifier(param.name as ts.Identifier); // This parameter is a spread parameter (...param) if (!param.dotDotDotToken) { @@ -1370,8 +1335,7 @@ export class LuaTransformer { parameters: ts.NodeArray, body: ts.Block, spreadIdentifier?: tstl.Identifier - ): [tstl.Statement[], Scope] - { + ): [tstl.Statement[], Scope] { this.pushScope(ScopeType.Function); const headerStatements = []; @@ -1390,10 +1354,9 @@ export class LuaTransformer { } // Binding pattern - bindingPatternDeclarations.push(...this.statementVisitResultToArray( - this.transformBindingPattern(declaration.name, identifier) - )); - + bindingPatternDeclarations.push( + ...this.statementVisitResultToArray(this.transformBindingPattern(declaration.name, identifier)) + ); } else if (declaration.initializer !== undefined) { // Default parameter headerStatements.push( @@ -1425,8 +1388,7 @@ export class LuaTransformer { parameterName: tstl.Identifier, value?: ts.Expression, tsOriginal?: ts.Node - ): tstl.Statement - { + ): tstl.Statement { const parameterValue = value ? this.transformExpression(value) : undefined; const assignment = tstl.createAssignmentStatement(parameterName, parameterValue); @@ -1445,8 +1407,7 @@ export class LuaTransformer { pattern: ts.BindingPattern, table: tstl.Identifier, propertyAccessStack: ts.PropertyName[] = [] - ): StatementVisitResult - { + ): StatementVisitResult { const result: tstl.Statement[] = []; const isObjectBindingPattern = ts.isObjectBindingPattern(pattern); for (let index = 0; index < pattern.elements.length; index++) { @@ -1460,9 +1421,11 @@ export class LuaTransformer { if (propertyName !== undefined) { propertyAccessStack.push(propertyName); } - result.push(...this.statementVisitResultToArray( - this.transformBindingPattern(element.name, table, propertyAccessStack) - )); + result.push( + ...this.statementVisitResultToArray( + this.transformBindingPattern(element.name, table, propertyAccessStack) + ) + ); } else { // Disallow ellipsis destructure if (element.dotDotDotToken) { @@ -1474,10 +1437,7 @@ export class LuaTransformer { const propertyName = ts.isPropertyName(property) ? this.transformPropertyName(property) : this.transformNumericLiteral(property); - tableExpression = tstl.createTableIndexExpression( - tableExpression, - propertyName - ); + tableExpression = tstl.createTableIndexExpression(tableExpression, propertyName); }); // The identifier of the new variable const variableName = this.transformIdentifier(element.name as ts.Identifier); @@ -1491,21 +1451,21 @@ export class LuaTransformer { const identifier = this.shouldExportIdentifier(variableName) ? this.createExportedIdentifier(variableName) : variableName; - result.push(tstl.createIfStatement( - tstl.createBinaryExpression( - identifier, - tstl.createNilLiteral(), - tstl.SyntaxKind.EqualityOperator - ), - tstl.createBlock( - [ + result.push( + tstl.createIfStatement( + tstl.createBinaryExpression( + identifier, + tstl.createNilLiteral(), + tstl.SyntaxKind.EqualityOperator + ), + tstl.createBlock([ tstl.createAssignmentStatement( identifier, this.transformExpression(element.initializer) ), - ] + ]) ) - )); + ); } } } @@ -1542,9 +1502,9 @@ export class LuaTransformer { // - declared as a module before this (ignore interfaces with same name) // - declared as a class or function at all (TS requires these to be before module, unless module is empty) const isFirstDeclaration = - symbol === undefined - || (symbol.declarations.findIndex(d => ts.isClassLike(d) || ts.isFunctionDeclaration(d)) === -1 - && statement === symbol.declarations.find(ts.isModuleDeclaration)); + symbol === undefined || + (symbol.declarations.findIndex(d => ts.isClassLike(d) || ts.isFunctionDeclaration(d)) === -1 && + statement === symbol.declarations.find(ts.isModuleDeclaration)); const nameIdentifier = this.transformIdentifier(statement.name as ts.Identifier); @@ -1574,7 +1534,6 @@ export class LuaTransformer { result.push(localDeclaration); } - } else if (isExported && !this.currentNamespace && this.isModule) { // exports.NS = {} const namespaceDeclaration = tstl.createAssignmentStatement( @@ -1593,7 +1552,6 @@ export class LuaTransformer { result.push(localDeclaration); } - } else { // local NS = {} const localDeclaration = this.createLocalOrExportedOrGlobalDeclaration( @@ -1648,17 +1606,17 @@ export class LuaTransformer { const memberName = this.transformPropertyName(enumMember.name); if (membersOnly) { if (tstl.isIdentifier(memberName)) { - result.push(...this.createLocalOrExportedOrGlobalDeclaration( - memberName, - enumMember.value, - enumDeclaration - )); + result.push( + ...this.createLocalOrExportedOrGlobalDeclaration(memberName, enumMember.value, enumDeclaration) + ); } else { - result.push(...this.createLocalOrExportedOrGlobalDeclaration( - tstl.createIdentifier(enumMember.name.getText(), enumMember.name), - enumMember.value, - enumDeclaration - )); + result.push( + ...this.createLocalOrExportedOrGlobalDeclaration( + tstl.createIdentifier(enumMember.name.getText(), enumMember.name), + enumMember.value, + enumDeclaration + ) + ); } } else { const enumTable = this.transformIdentifierExpression(enumDeclaration.name); @@ -1673,8 +1631,9 @@ export class LuaTransformer { return result; } - protected computeEnumMembers(node: ts.EnumDeclaration): - Array<{name: ts.PropertyName, value: tstl.Expression, original: ts.Node}> { + protected computeEnumMembers( + node: ts.EnumDeclaration + ): Array<{ name: ts.PropertyName; value: tstl.Expression; original: ts.Node }> { let numericValue = 0; let hasStringInitializers = false; @@ -1683,19 +1642,14 @@ export class LuaTransformer { return node.members.map(member => { let valueExpression: ExpressionVisitResult; if (member.initializer) { - if (ts.isNumericLiteral(member.initializer)) - { + if (ts.isNumericLiteral(member.initializer)) { numericValue = Number(member.initializer.text); valueExpression = this.transformNumericLiteral(member.initializer); numericValue++; - } - else if (ts.isStringLiteral(member.initializer)) - { + } else if (ts.isStringLiteral(member.initializer)) { hasStringInitializers = true; valueExpression = this.transformStringLiteral(member.initializer); - } - else - { + } else { if (ts.isIdentifier(member.initializer)) { const [isEnumMember, originalName] = tsHelper.isEnumMember(node, member.initializer); if (isEnumMember === true && originalName !== undefined) { @@ -1711,13 +1665,9 @@ export class LuaTransformer { valueExpression = this.transformExpression(member.initializer); } } - } - else if (hasStringInitializers) - { + } else if (hasStringInitializers) { throw TSTLErrors.HeterogeneousEnum(node); - } - else - { + } else { valueExpression = tstl.createNumericLiteral(numericValue); numericValue++; } @@ -1738,58 +1688,40 @@ export class LuaTransformer { parameters: ts.NodeArray, body: ts.Block, spreadIdentifier?: tstl.Identifier - ): [tstl.Statement[], Scope] - { + ): [tstl.Statement[], Scope] { this.importLuaLibFeature(LuaLibFeature.Symbol); - const [functionBody, functionScope] = this.transformFunctionBody( - parameters, - body - ); + const [functionBody, functionScope] = this.transformFunctionBody(parameters, body); const coroutineIdentifier = tstl.createIdentifier("____co"); - const valueIdentifier = tstl.createIdentifier("____value"); - const errIdentifier = tstl.createIdentifier("____err"); + const valueIdentifier = tstl.createIdentifier("____value"); + const errIdentifier = tstl.createIdentifier("____err"); const itIdentifier = tstl.createIdentifier("____it"); //local ____co = coroutine.create(originalFunction) - const coroutine = - tstl.createVariableDeclarationStatement(coroutineIdentifier, - tstl.createCallExpression( - tstl.createTableIndexExpression(tstl.createIdentifier("coroutine"), - tstl.createStringLiteral("create") - ), - [tstl.createFunctionExpression(tstl.createBlock(functionBody))] - ) - ); + const coroutine = tstl.createVariableDeclarationStatement( + coroutineIdentifier, + tstl.createCallExpression( + tstl.createTableIndexExpression(tstl.createIdentifier("coroutine"), tstl.createStringLiteral("create")), + [tstl.createFunctionExpression(tstl.createBlock(functionBody))] + ) + ); const nextBody = []; // coroutine.resume(__co, ...) const resumeCall = tstl.createCallExpression( - tstl.createTableIndexExpression( - tstl.createIdentifier("coroutine"), - tstl.createStringLiteral("resume") - ), + tstl.createTableIndexExpression(tstl.createIdentifier("coroutine"), tstl.createStringLiteral("resume")), [coroutineIdentifier, tstl.createDotsLiteral()] ); // ____err, ____value = coroutine.resume(____co, ...) - nextBody.push(tstl.createVariableDeclarationStatement( - [errIdentifier, valueIdentifier], - resumeCall) - ); + nextBody.push(tstl.createVariableDeclarationStatement([errIdentifier, valueIdentifier], resumeCall)); //if(not ____err){error(____value)} const errorCheck = tstl.createIfStatement( - tstl.createUnaryExpression( - errIdentifier, - tstl.SyntaxKind.NotOperator - ), + tstl.createUnaryExpression(errIdentifier, tstl.SyntaxKind.NotOperator), tstl.createBlock([ tstl.createExpressionStatement( - tstl.createCallExpression( - tstl.createIdentifier("error"), - [valueIdentifier] - ) + tstl.createCallExpression(tstl.createIdentifier("error"), [valueIdentifier]) ), ]) ); @@ -1797,10 +1729,7 @@ export class LuaTransformer { //coroutine.status(____co) == "dead"; const coStatus = tstl.createCallExpression( - tstl.createTableIndexExpression( - tstl.createIdentifier("coroutine"), - tstl.createStringLiteral("status") - ), + tstl.createTableIndexExpression(tstl.createIdentifier("coroutine"), tstl.createStringLiteral("status")), [coroutineIdentifier] ); const status = tstl.createBinaryExpression( @@ -1811,14 +1740,8 @@ export class LuaTransformer { //{done = coroutine.status(____co) == "dead"; value = ____value} const iteratorResult = tstl.createTableExpression([ - tstl.createTableFieldExpression( - status, - tstl.createStringLiteral("done") - ), - tstl.createTableFieldExpression( - valueIdentifier, - tstl.createStringLiteral("value") - ), + tstl.createTableFieldExpression(status, tstl.createStringLiteral("done")), + tstl.createTableFieldExpression(valueIdentifier, tstl.createStringLiteral("value")), ]); nextBody.push(tstl.createReturnStatement([iteratorResult])); @@ -1826,16 +1749,14 @@ export class LuaTransformer { const nextFunctionDeclaration = tstl.createFunctionExpression( tstl.createBlock(nextBody), [tstl.createAnonymousIdentifier()], - tstl.createDotsLiteral()); + tstl.createDotsLiteral() + ); //____it = {next = function(____, ...)} const iterator = tstl.createVariableDeclarationStatement( itIdentifier, tstl.createTableExpression([ - tstl.createTableFieldExpression( - nextFunctionDeclaration, - tstl.createStringLiteral("next") - ), + tstl.createTableFieldExpression(nextFunctionDeclaration, tstl.createStringLiteral("next")), ]) ); @@ -1849,15 +1770,8 @@ export class LuaTransformer { iterator, //____it[Symbol.iterator] = {return ____it} tstl.createAssignmentStatement( - tstl.createTableIndexExpression( - itIdentifier, - symbolIterator - ), - tstl.createFunctionExpression( - tstl.createBlock( - [tstl.createReturnStatement([itIdentifier])] - ) - ) + tstl.createTableIndexExpression(itIdentifier, symbolIterator), + tstl.createFunctionExpression(tstl.createBlock([tstl.createReturnStatement([itIdentifier])])) ), //return ____it tstl.createReturnStatement([itIdentifier]), @@ -1878,9 +1792,10 @@ export class LuaTransformer { } const type = this.checker.getTypeAtLocation(functionDeclaration); - const context = tsHelper.getFunctionContextType(type, this.checker) !== ContextType.Void - ? this.createSelfIdentifier() - : undefined; + const context = + tsHelper.getFunctionContextType(type, this.checker) !== ContextType.Void + ? this.createSelfIdentifier() + : undefined; const [params, dotsLiteral, restParamName] = this.transformParameters(functionDeclaration.parameters, context); if (functionDeclaration.name === undefined) { @@ -1889,16 +1804,8 @@ export class LuaTransformer { const name = this.transformIdentifier(functionDeclaration.name); const [body, functionScope] = functionDeclaration.asteriskToken - ? this.transformGeneratorFunction( - functionDeclaration.parameters, - functionDeclaration.body, - restParamName - ) - : this.transformFunctionBody( - functionDeclaration.parameters, - functionDeclaration.body, - restParamName - ); + ? this.transformGeneratorFunction(functionDeclaration.parameters, functionDeclaration.body, restParamName) + : this.transformFunctionBody(functionDeclaration.parameters, functionDeclaration.body, restParamName); const block = tstl.createBlock(body); const functionExpression = tstl.createFunctionExpression( block, @@ -1913,8 +1820,10 @@ export class LuaTransformer { if (scope === undefined) { throw TSTLErrors.UndefinedScope(); } - if (!scope.functionDefinitions) { scope.functionDefinitions = new Map(); } - const functionInfo = {referencedSymbols: functionScope.referencedSymbols || new Set()}; + if (!scope.functionDefinitions) { + scope.functionDefinitions = new Map(); + } + const functionInfo = { referencedSymbols: functionScope.referencedSymbols || new Set() }; scope.functionDefinitions.set(name.symbolId, functionInfo); } return this.createLocalOrExportedOrGlobalDeclaration(name, functionExpression, functionDeclaration); @@ -1928,8 +1837,7 @@ export class LuaTransformer { return undefined; } - public transformVariableDeclaration(statement: ts.VariableDeclaration): StatementVisitResult - { + public transformVariableDeclaration(statement: ts.VariableDeclaration): StatementVisitResult { if (statement.initializer && statement.type) { // Validate assignment const initializerType = this.checker.getTypeAtLocation(statement.initializer); @@ -1944,11 +1852,7 @@ export class LuaTransformer { const value = this.transformExpression(statement.initializer); return this.createLocalOrExportedOrGlobalDeclaration(identifierName, value, statement); } else { - return this.createLocalOrExportedOrGlobalDeclaration( - identifierName, - undefined, - statement - ); + return this.createLocalOrExportedOrGlobalDeclaration(identifierName, undefined, statement); } } else if (ts.isArrayBindingPattern(statement.name) || ts.isObjectBindingPattern(statement.name)) { // Destructuring types @@ -1956,8 +1860,10 @@ export class LuaTransformer { const statements: tstl.Statement[] = []; // For nested bindings and object bindings, fall back to transformBindingPattern - if (ts.isObjectBindingPattern(statement.name) - || statement.name.elements.some(elem => !ts.isBindingElement(elem) || !ts.isIdentifier(elem.name))) { + if ( + ts.isObjectBindingPattern(statement.name) || + statement.name.elements.some(elem => !ts.isBindingElement(elem) || !ts.isIdentifier(elem.name)) + ) { const statements = []; let table: tstl.Identifier; if (statement.initializer !== undefined && ts.isIdentifier(statement.initializer)) { @@ -1966,13 +1872,17 @@ export class LuaTransformer { // Contain the expression in a temporary variable table = tstl.createAnonymousIdentifier(); if (statement.initializer) { - statements.push(tstl.createVariableDeclarationStatement( - table, this.transformExpression(statement.initializer))); + statements.push( + tstl.createVariableDeclarationStatement( + table, + this.transformExpression(statement.initializer) + ) + ); } } - statements.push(...this.statementVisitResultToArray( - this.transformBindingPattern(statement.name, table) - )); + statements.push( + ...this.statementVisitResultToArray(this.transformBindingPattern(statement.name, table)) + ); return statements; } @@ -1981,11 +1891,13 @@ export class LuaTransformer { throw TSTLErrors.ForbiddenEllipsisDestruction(statement); } - const vars = statement.name.elements.length > 0 - ? this.filterUndefinedAndCast( - statement.name.elements.map(e => this.transformArrayBindingElement(e)), - tstl.isIdentifier) - : tstl.createAnonymousIdentifier(statement.name); + const vars = + statement.name.elements.length > 0 + ? this.filterUndefinedAndCast( + statement.name.elements.map(e => this.transformArrayBindingElement(e)), + tstl.isIdentifier + ) + : tstl.createAnonymousIdentifier(statement.name); if (statement.initializer) { if (tsHelper.isTupleReturnCall(statement.initializer, this.checker)) { @@ -1999,16 +1911,11 @@ export class LuaTransformer { ); } else if (ts.isArrayLiteralExpression(statement.initializer)) { // Don't unpack array literals - const values = statement.initializer.elements.length > 0 - ? statement.initializer.elements.map(e => this.transformExpression(e)) - : tstl.createNilLiteral(); - statements.push( - ...this.createLocalOrExportedOrGlobalDeclaration( - vars, - values, - statement - ) - ); + const values = + statement.initializer.elements.length > 0 + ? statement.initializer.elements.map(e => this.transformExpression(e)) + : tstl.createNilLiteral(); + statements.push(...this.createLocalOrExportedOrGlobalDeclaration(vars, values, statement)); } else { // local vars = this.transpileDestructingAssignmentValue(node.initializer); const initializer = this.createUnpackCall( @@ -2019,11 +1926,7 @@ export class LuaTransformer { } } else { statements.push( - ...this.createLocalOrExportedOrGlobalDeclaration( - vars, - tstl.createNilLiteral(), - statement - ) + ...this.createLocalOrExportedOrGlobalDeclaration(vars, tstl.createNilLiteral(), statement) ); } @@ -2040,14 +1943,12 @@ export class LuaTransformer { tstl.createNilLiteral(), tstl.SyntaxKind.EqualityOperator ), - tstl.createBlock( - [ - tstl.createAssignmentStatement( - identifier, - this.transformExpression(element.initializer) - ), - ] - ) + tstl.createBlock([ + tstl.createAssignmentStatement( + identifier, + this.transformExpression(element.initializer) + ), + ]) ) ); } @@ -2078,25 +1979,24 @@ export class LuaTransformer { expression.right, replacementOperator ); - } else if (expression.operatorToken.kind === ts.SyntaxKind.EqualsToken) { // = assignment return this.transformAssignmentStatement(expression); - } else if (expression.operatorToken.kind === ts.SyntaxKind.CommaToken) { const lhs = this.statementVisitResultToArray(this.transformExpressionStatement(expression.left)); const rhs = this.statementVisitResultToArray(this.transformExpressionStatement(expression.right)); return tstl.createDoStatement([...lhs, ...rhs], expression); } - } else if ( ts.isPrefixUnaryExpression(expression) && - (expression.operator === ts.SyntaxKind.PlusPlusToken - || expression.operator === ts.SyntaxKind.MinusMinusToken)) { + (expression.operator === ts.SyntaxKind.PlusPlusToken || + expression.operator === ts.SyntaxKind.MinusMinusToken) + ) { // ++i, --i - const replacementOperator = expression.operator === ts.SyntaxKind.PlusPlusToken - ? ts.SyntaxKind.PlusToken - : ts.SyntaxKind.MinusToken; + const replacementOperator = + expression.operator === ts.SyntaxKind.PlusPlusToken + ? ts.SyntaxKind.PlusToken + : ts.SyntaxKind.MinusToken; return this.transformCompoundAssignmentStatement( expression, @@ -2104,13 +2004,12 @@ export class LuaTransformer { ts.createLiteral(1), replacementOperator ); - } - - else if (ts.isPostfixUnaryExpression(expression)) { + } else if (ts.isPostfixUnaryExpression(expression)) { // i++, i-- - const replacementOperator = expression.operator === ts.SyntaxKind.PlusPlusToken - ? ts.SyntaxKind.PlusToken - : ts.SyntaxKind.MinusToken; + const replacementOperator = + expression.operator === ts.SyntaxKind.PlusPlusToken + ? ts.SyntaxKind.PlusToken + : ts.SyntaxKind.MinusToken; return this.transformCompoundAssignmentStatement( expression, @@ -2118,9 +2017,7 @@ export class LuaTransformer { ts.createLiteral(1), replacementOperator ); - } - - else if (ts.isDeleteExpression(expression)) { + } else if (ts.isDeleteExpression(expression)) { return tstl.createAssignmentStatement( this.transformExpression(expression.expression) as tstl.AssignmentLeftHandSideExpression, tstl.createNilLiteral(), @@ -2144,11 +2041,9 @@ export class LuaTransformer { expression as ts.CallExpression & { expression: ts.PropertyAccessExpression }, true ); - return this.transformLuaTableExpressionStatement( - statement as ts.ExpressionStatement - & { expression: ts.CallExpression } - & { expression: { expression: ts.PropertyAccessExpression } } - ); + return this.transformLuaTableExpressionStatement(statement as ts.ExpressionStatement & { + expression: ts.CallExpression; + } & { expression: { expression: ts.PropertyAccessExpression } }); } } @@ -2157,14 +2052,10 @@ export class LuaTransformer { public transformYieldExpression(expression: ts.YieldExpression): ExpressionVisitResult { return tstl.createCallExpression( - tstl.createTableIndexExpression( - tstl.createIdentifier("coroutine"), - tstl.createStringLiteral("yield")), - expression.expression - ? [this.transformExpression(expression.expression)] - : [], - expression - ); + tstl.createTableIndexExpression(tstl.createIdentifier("coroutine"), tstl.createStringLiteral("yield")), + expression.expression ? [this.transformExpression(expression.expression)] : [], + expression + ); } public transformReturnStatement(statement: ts.ReturnStatement): StatementVisitResult { @@ -2184,9 +2075,10 @@ export class LuaTransformer { } const expressionType = this.checker.getTypeAtLocation(statement.expression); - if (!tsHelper.isTupleReturnCall(statement.expression, this.checker) - && tsHelper.isArrayType(expressionType, this.checker, this.program)) - { + if ( + !tsHelper.isTupleReturnCall(statement.expression, this.checker) && + tsHelper.isArrayType(expressionType, this.checker, this.program) + ) { // If return expression is an array-type and not another TupleReturn call, unpack it const expression = this.createUnpackCall( this.transformExpression(statement.expression), @@ -2236,9 +2128,7 @@ export class LuaTransformer { return tstl.createRepeatStatement( tstl.createBlock(this.transformLoopBody(statement)), tstl.createUnaryExpression( - tstl.createParenthesizedExpression( - this.transformExpression(statement.expression) - ), + tstl.createParenthesizedExpression(this.transformExpression(statement.expression)), tstl.SyntaxKind.NotOperator ), statement @@ -2285,7 +2175,6 @@ export class LuaTransformer { const variableDeclarations = this.transformVariableDeclaration(initializer.declarations[0]); if (ts.isArrayBindingPattern(initializer.declarations[0].name)) { expression = this.createUnpackCall(expression, initializer); - } else if (ts.isObjectBindingPattern(initializer.declarations[0].name)) { throw TSTLErrors.UnsupportedObjectDestructuringInForOf(initializer); } @@ -2294,22 +2183,22 @@ export class LuaTransformer { if (variableStatements[0]) { // we can safely assume that for vars are not exported and therefore declarationstatenents return tstl.createVariableDeclarationStatement( - (variableStatements[0] as tstl.VariableDeclarationStatement).left, expression); + (variableStatements[0] as tstl.VariableDeclarationStatement).left, + expression + ); } else { throw TSTLErrors.MissingForOfVariables(initializer); } - } else { // Assignment to existing variable let variables: tstl.AssignmentLeftHandSideExpression | tstl.AssignmentLeftHandSideExpression[]; if (ts.isArrayLiteralExpression(initializer)) { expression = this.createUnpackCall(expression, initializer); - variables = initializer.elements - .map(e => this.transformExpression(e)) as tstl.AssignmentLeftHandSideExpression[]; - + variables = initializer.elements.map(e => + this.transformExpression(e) + ) as tstl.AssignmentLeftHandSideExpression[]; } else if (ts.isObjectLiteralExpression(initializer)) { throw TSTLErrors.UnsupportedObjectDestructuringInForOf(initializer); - } else { variables = this.transformExpression(initializer) as tstl.AssignmentLeftHandSideExpression; } @@ -2319,8 +2208,7 @@ export class LuaTransformer { protected transformLoopBody( loop: ts.WhileStatement | ts.DoStatement | ts.ForStatement | ts.ForOfStatement | ts.ForInOrOfStatement - ): tstl.Statement[] - { + ): tstl.Statement[] { this.pushScope(ScopeType.Loop); const body = this.performHoisting(this.transformBlockOrStatement(loop.statement)); const scope = this.popScope(); @@ -2351,21 +2239,18 @@ export class LuaTransformer { if (ts.isArrayBindingPattern(variables) || ts.isObjectBindingPattern(variables)) { valueVariable = tstl.createIdentifier("____TS_values"); block.statements.unshift(this.transformForOfInitializer(statement.initializer, valueVariable)); - } else { valueVariable = this.transformIdentifier(variables); } - } else { // Assignment to existing variable valueVariable = tstl.createIdentifier("____TS_value"); block.statements.unshift(this.transformForOfInitializer(statement.initializer, valueVariable)); } - const ipairsCall = tstl.createCallExpression( - tstl.createIdentifier("ipairs"), - [this.transformExpression(statement.expression)] - ); + const ipairsCall = tstl.createCallExpression(tstl.createIdentifier("ipairs"), [ + this.transformExpression(statement.expression), + ]); return tstl.createForInStatement( block, @@ -2390,41 +2275,41 @@ export class LuaTransformer { block, this.filterUndefinedAndCast( initializerVariable.elements.map(e => this.transformArrayBindingElement(e)), - tstl.isIdentifier), + tstl.isIdentifier + ), [luaIterator] ); - } else { // Single variable is not allowed throw TSTLErrors.UnsupportedNonDestructuringLuaIterator(statement.initializer); } - } else { // Variables NOT declared in for loop - catch iterator values in temps and assign // for ____TS_value0 in ${iterable} do // ${initializer} = ____TS_value0 if (ts.isArrayLiteralExpression(statement.initializer)) { - const tmps = statement.initializer.elements - .map((_, i) => tstl.createIdentifier(`____TS_value${i}`)); + const tmps = statement.initializer.elements.map((_, i) => + tstl.createIdentifier(`____TS_value${i}`) + ); const assign = tstl.createAssignmentStatement( - statement.initializer.elements.map(e => - this.transformExpression(e) as tstl.AssignmentLeftHandSideExpression + statement.initializer.elements.map( + e => this.transformExpression(e) as tstl.AssignmentLeftHandSideExpression ), tmps ); block.statements.splice(0, 0, assign); return tstl.createForInStatement(block, tmps, [luaIterator]); - } else { // Single variable is not allowed throw TSTLErrors.UnsupportedNonDestructuringLuaIterator(statement.initializer); } } - } else { // LuaIterator (no TupleReturn) - if (ts.isVariableDeclarationList(statement.initializer) - && ts.isIdentifier(statement.initializer.declarations[0].name)) { + if ( + ts.isVariableDeclarationList(statement.initializer) && + ts.isIdentifier(statement.initializer.declarations[0].name) + ) { // Single variable declared in for loop // for ${initializer} in ${iterator} do return tstl.createForInStatement( @@ -2432,7 +2317,6 @@ export class LuaTransformer { [this.transformIdentifier(statement.initializer.declarations[0].name as ts.Identifier)], [luaIterator] ); - } else { // Destructuring or variable NOT declared in for loop // for ____TS_value in ${iterator} do @@ -2440,19 +2324,17 @@ export class LuaTransformer { const valueVariable = tstl.createIdentifier("____TS_value"); const initializer = this.transformForOfInitializer(statement.initializer, valueVariable); block.statements.splice(0, 0, initializer); - return tstl.createForInStatement( - block, - [valueVariable], - [luaIterator] - ); + return tstl.createForInStatement(block, [valueVariable], [luaIterator]); } } } private transformForOfIteratorStatement(statement: ts.ForOfStatement, block: tstl.Block): StatementVisitResult { const iterable = this.transformExpression(statement.expression); - if (ts.isVariableDeclarationList(statement.initializer) - && ts.isIdentifier(statement.initializer.declarations[0].name)) { + if ( + ts.isVariableDeclarationList(statement.initializer) && + ts.isIdentifier(statement.initializer.declarations[0].name) + ) { // Single variable declared in for loop // for ${initializer} in __TS__iterator(${iterator}) do return tstl.createForInStatement( @@ -2460,7 +2342,6 @@ export class LuaTransformer { [this.transformIdentifier(statement.initializer.declarations[0].name as ts.Identifier)], [this.transformLuaLibFunction(LuaLibFeature.Iterator, statement.expression, iterable)] ); - } else { // Destructuring or variable NOT declared in for loop // for ____TS_value in __TS__iterator(${iterator}) do @@ -2483,15 +2364,11 @@ export class LuaTransformer { if (tsHelper.isLuaIteratorType(statement.expression, this.checker)) { // LuaIterators return this.transformForOfLuaIteratorStatement(statement, body); - - } else if (tsHelper.isArrayType( - this.checker.getTypeAtLocation(statement.expression), - this.checker, - this.program) + } else if ( + tsHelper.isArrayType(this.checker.getTypeAtLocation(statement.expression), this.checker, this.program) ) { // Arrays return this.transformForOfArrayStatement(statement, body); - } else { // TS Iterables return this.transformForOfIteratorStatement(statement, body); @@ -2514,12 +2391,7 @@ export class LuaTransformer { const body = tstl.createBlock(this.transformLoopBody(statement)); - return tstl.createForInStatement( - body, - [this.transformIdentifier(identifier)], - [pairsCall], - statement - ); + return tstl.createForInStatement(body, [this.transformIdentifier(identifier)], [pairsCall], statement); } public transformSwitchStatement(statement: ts.SwitchStatement): StatementVisitResult { @@ -2606,9 +2478,13 @@ export class LuaTransformer { if (statement.catchClause) { const tryResult = tstl.createIdentifier("____TS_try"); - const returnVariables = statement.catchClause && statement.catchClause.variableDeclaration - ? [tryResult, this.transformIdentifier(statement.catchClause.variableDeclaration.name as ts.Identifier)] - : [tryResult]; + const returnVariables = + statement.catchClause && statement.catchClause.variableDeclaration + ? [ + tryResult, + this.transformIdentifier(statement.catchClause.variableDeclaration.name as ts.Identifier), + ] + : [tryResult]; const catchAssignment = tstl.createVariableDeclarationStatement(returnVariables, tryCall); @@ -2619,7 +2495,6 @@ export class LuaTransformer { tstl.SyntaxKind.NotOperator ); result.push(tstl.createIfStatement(notTryResult, this.transformBlock(statement.catchClause.block))); - } else { result.push(tstl.createExpressionStatement(tryCall)); } @@ -2628,10 +2503,7 @@ export class LuaTransformer { result.push(tstl.createDoStatement(this.transformBlock(statement.finallyBlock).statements)); } - return tstl.createDoStatement( - result, - statement - ); + return tstl.createDoStatement(result, statement); } public transformThrowStatement(statement: ts.ThrowStatement): StatementVisitResult { @@ -2662,10 +2534,7 @@ export class LuaTransformer { } scope.loopContinued = true; - return tstl.createGotoStatement( - `__continue${scope.id}`, - statement - ); + return tstl.createGotoStatement(`__continue${scope.id}`, statement); } public transformEmptyStatement(_statement: ts.EmptyStatement): StatementVisitResult { @@ -2747,8 +2616,7 @@ export class LuaTransformer { right: tstl.Expression, operator: ts.BinaryOperator, tsOriginal: ts.Node - ): ExpressionVisitResult - { + ): ExpressionVisitResult { switch (operator) { case ts.SyntaxKind.AmpersandToken: case ts.SyntaxKind.BarToken: @@ -2881,9 +2749,10 @@ export class LuaTransformer { if (ts.isArrayLiteralExpression(expression.left)) { // Destructuring assignment - const left = expression.left.elements.length > 0 - ? expression.left.elements.map(e => this.transformExpression(e)) - : [tstl.createAnonymousIdentifier(expression.left)]; + const left = + expression.left.elements.length > 0 + ? expression.left.elements.map(e => this.transformExpression(e)) + : [tstl.createAnonymousIdentifier(expression.left)]; let right: tstl.Expression[]; if (ts.isArrayLiteralExpression(expression.right)) { if (expression.right.elements.length > 0) { @@ -2897,20 +2766,16 @@ export class LuaTransformer { } else { right = [this.createUnpackCall(this.transformExpression(expression.right), expression.right)]; } - return tstl.createAssignmentStatement( - left as tstl.AssignmentLeftHandSideExpression[], - right, - expression - ); + return tstl.createAssignmentStatement(left as tstl.AssignmentLeftHandSideExpression[], right, expression); } else { // Simple assignment return this.transformAssignment(expression.left, this.transformExpression(expression.right)); } } - private transformAssignmentExpression(expression: ts.BinaryExpression) - : tstl.CallExpression | tstl.MethodCallExpression - { + private transformAssignmentExpression( + expression: ts.BinaryExpression + ): tstl.CallExpression | tstl.MethodCallExpression { // Validate assignment const rightType = this.checker.getTypeAtLocation(expression.right); const leftType = this.checker.getTypeAtLocation(expression.left); @@ -2929,14 +2794,16 @@ export class LuaTransformer { if (ts.isArrayLiteralExpression(expression.left)) { // Destructuring assignment // (function() local ${tmps} = ${right}; ${left} = ${tmps}; return {${tmps}} end)() - const left = expression.left.elements.length > 0 - ? expression.left.elements.map(e => this.transformExpression(e)) - : [tstl.createAnonymousIdentifier(expression.left)]; + const left = + expression.left.elements.length > 0 + ? expression.left.elements.map(e => this.transformExpression(e)) + : [tstl.createAnonymousIdentifier(expression.left)]; let right: tstl.Expression[]; if (ts.isArrayLiteralExpression(expression.right)) { - right = expression.right.elements.length > 0 - ? expression.right.elements.map(e => this.transformExpression(e)) - : [tstl.createNilLiteral()]; + right = + expression.right.elements.length > 0 + ? expression.right.elements.map(e => this.transformExpression(e)) + : [tstl.createNilLiteral()]; } else if (tsHelper.isTupleReturnCall(expression.right, this.checker)) { right = [this.transformExpression(expression.right)]; } else { @@ -2965,10 +2832,11 @@ export class LuaTransformer { tstl.createAssignmentStatement(indexStatement, valueParameter), tstl.createReturnStatement([valueParameter]), ]; - const iife = tstl.createFunctionExpression( - tstl.createBlock(statements), - [objParameter, indexParameter, valueParameter] - ); + const iife = tstl.createFunctionExpression(tstl.createBlock(statements), [ + objParameter, + indexParameter, + valueParameter, + ]); const objExpression = this.transformExpression(expression.left.expression); let indexExpression: tstl.Expression; if (ts.isPropertyAccessExpression(expression.left)) { @@ -3005,8 +2873,7 @@ export class LuaTransformer { rhs: ts.Expression, replacementOperator: ts.BinaryOperator, isPostfix: boolean - ): tstl.CallExpression - { + ): tstl.CallExpression { const left = this.transformExpression(lhs) as tstl.AssignmentLeftHandSideExpression; let right = this.transformExpression(rhs); @@ -3054,7 +2921,6 @@ export class LuaTransformer { tmp, expression ); - } else if (isPostfix) { // Postfix expressions need to cache original value in temp // local ____TS_tmp = ${left}; @@ -3074,7 +2940,6 @@ export class LuaTransformer { tmpIdentifier, expression ); - } else if (ts.isPropertyAccessExpression(lhs) || ts.isElementAccessExpression(lhs)) { // Simple property/element access expressions need to cache in temp to avoid double-evaluation // local ____TS_tmp = ${left} ${replacementOperator} ${right}; @@ -3089,7 +2954,6 @@ export class LuaTransformer { tmpIdentifier, expression ); - } else { // Simple expressions // ${left} = ${right}; return ${right} @@ -3159,11 +3023,12 @@ export class LuaTransformer { } public transformClassExpression(expression: ts.ClassExpression): ExpressionVisitResult { - const className = expression.name !== undefined - ? this.transformIdentifier(expression.name) - : tstl.createAnonymousIdentifier(); + const className = + expression.name !== undefined + ? this.transformIdentifier(expression.name) + : tstl.createAnonymousIdentifier(); - const classDeclaration = this.transformClassDeclaration(expression, className); + const classDeclaration = this.transformClassDeclaration(expression, className); return this.createImmediatelyInvokedFunctionExpression( this.statementVisitResultToArray(classDeclaration), className, @@ -3176,8 +3041,7 @@ export class LuaTransformer { lhs: ts.Expression, rhs: ts.Expression, replacementOperator: ts.BinaryOperator - ): tstl.Statement - { + ): tstl.Statement { const left = this.transformExpression(lhs) as tstl.AssignmentLeftHandSideExpression; const right = this.transformExpression(rhs); @@ -3205,7 +3069,6 @@ export class LuaTransformer { ); const assignStatement = tstl.createAssignmentStatement(accessExpression, operatorExpression); return tstl.createDoStatement([objAndIndexDeclaration, assignStatement]); - } else { // Simple statements // ${left} = ${left} ${replacementOperator} ${right} @@ -3219,8 +3082,7 @@ export class LuaTransformer { expression: tstl.Expression, operator: tstl.UnaryBitwiseOperator, lib: string - ): ExpressionVisitResult - { + ): ExpressionVisitResult { let bitFunction: string; switch (operator) { case tstl.SyntaxKind.BitwiseNotOperator: @@ -3240,8 +3102,7 @@ export class LuaTransformer { node: ts.Node, expression: tstl.Expression, operator: tstl.UnaryBitwiseOperator - ): ExpressionVisitResult - { + ): ExpressionVisitResult { switch (this.luaTarget) { case LuaTarget.Lua51: throw TSTLErrors.UnsupportedForTarget("Bitwise operations", this.luaTarget, node); @@ -3263,8 +3124,7 @@ export class LuaTransformer { right: tstl.Expression, operator: ts.BinaryOperator, lib: string - ): ExpressionVisitResult - { + ): ExpressionVisitResult { let bitFunction: string; switch (operator) { case ts.SyntaxKind.AmpersandToken: @@ -3300,8 +3160,7 @@ export class LuaTransformer { left: tstl.Expression, right: tstl.Expression, operator: ts.BinaryOperator - ): ExpressionVisitResult - { + ): ExpressionVisitResult { switch (this.luaTarget) { case LuaTarget.Lua51: throw TSTLErrors.UnsupportedForTarget("Bitwise operations", this.luaTarget, node); @@ -3343,12 +3202,7 @@ export class LuaTransformer { // condition and v1 or v2 const conditionAnd = tstl.createBinaryExpression(condition, val1, tstl.SyntaxKind.AndOperator); - return tstl.createBinaryExpression( - conditionAnd, - val2, - tstl.SyntaxKind.OrOperator, - expression - ); + return tstl.createBinaryExpression(conditionAnd, val2, tstl.SyntaxKind.OrOperator, expression); } public transformPostfixUnaryExpression(expression: ts.PostfixUnaryExpression): ExpressionVisitResult { @@ -3424,8 +3278,8 @@ export class LuaTransformer { } public transformArrayLiteral(expression: ts.ArrayLiteralExpression): ExpressionVisitResult { - const values = expression.elements.map( - e => tstl.createTableFieldExpression(this.transformExpression(e), undefined, e) + const values = expression.elements.map(e => + tstl.createTableFieldExpression(this.transformExpression(e), undefined, e) ); return tstl.createTableExpression(values, expression); @@ -3439,7 +3293,6 @@ export class LuaTransformer { if (ts.isPropertyAssignment(element)) { const expression = this.transformExpression(element.initializer); properties.push(tstl.createTableFieldExpression(expression, name, element)); - } else if (ts.isShorthandPropertyAssignment(element)) { const valueSymbol = this.checker.getShorthandAssignmentValueSymbol(element); let identifier = this.createShorthandIdentifier(valueSymbol, element.name); @@ -3447,11 +3300,9 @@ export class LuaTransformer { identifier = this.createExportedIdentifier(identifier); } properties.push(tstl.createTableFieldExpression(identifier, name, element)); - } else if (ts.isMethodDeclaration(element)) { const expression = this.transformFunctionExpression(element); properties.push(tstl.createTableFieldExpression(expression, name, element)); - } else { throw TSTLErrors.UnsupportedKind("object literal element", element.kind, expression); } @@ -3462,11 +3313,7 @@ export class LuaTransformer { public transformDeleteExpression(expression: ts.DeleteExpression): ExpressionVisitResult { const lhs = this.transformExpression(expression.expression) as tstl.AssignmentLeftHandSideExpression; - const assignment = tstl.createAssignmentStatement( - lhs, - tstl.createNilLiteral(), - expression - ); + const assignment = tstl.createAssignmentStatement(lhs, tstl.createNilLiteral(), expression); return this.createImmediatelyInvokedFunctionExpression( [assignment], @@ -3578,10 +3425,7 @@ export class LuaTransformer { return this.transformExpression(expression.expression); } - return tstl.createParenthesizedExpression( - this.transformExpression(expression.expression), - expression - ); + return tstl.createParenthesizedExpression(this.transformExpression(expression.expression), expression); } public transformSuperKeyword(expression: ts.SuperExpression): ExpressionVisitResult { @@ -3616,14 +3460,15 @@ export class LuaTransformer { let parameters: tstl.Expression[] = []; const isTupleReturn = tsHelper.isTupleReturnCall(expression, this.checker); - const isTupleReturnForward = expression.parent - && ts.isReturnStatement(expression.parent) - && tsHelper.isInTupleReturnFunction(expression, this.checker); + const isTupleReturnForward = + expression.parent && + ts.isReturnStatement(expression.parent) && + tsHelper.isInTupleReturnFunction(expression, this.checker); const isInDestructingAssignment = tsHelper.isInDestructingAssignment(expression); const isInSpread = expression.parent && ts.isSpreadElement(expression.parent); const returnValueIsUsed = expression.parent && !ts.isExpressionStatement(expression.parent); - const wrapResult = isTupleReturn && !isTupleReturnForward && !isInDestructingAssignment - && !isInSpread && returnValueIsUsed; + const wrapResult = + isTupleReturn && !isTupleReturnForward && !isInDestructingAssignment && !isInSpread && returnValueIsUsed; if (ts.isPropertyAccessExpression(expression.expression)) { const result = this.transformPropertyCall(expression); @@ -3660,9 +3505,10 @@ export class LuaTransformer { const callPath = this.transformExpression(expression.expression); const signatureDeclaration = signature && signature.getDeclaration(); - if (signatureDeclaration - && tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) === ContextType.Void) - { + if ( + signatureDeclaration && + tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) === ContextType.Void + ) { parameters = this.transformArguments(expression.arguments, signature); } else { const context = this.isStrict ? ts.createNull() : ts.createIdentifier("_G"); @@ -3742,13 +3588,10 @@ export class LuaTransformer { const classDecorators = tsHelper.getCustomDecorators(ownerType, this.checker); if (classDecorators.has(DecoratorKind.LuaTable)) { - this.validateLuaTableCall( - node as ts.CallExpression & { expression: ts.PropertyAccessExpression }, - false - ); - return this.transformLuaTableCallExpression( - node as ts.CallExpression & { expression: ts.PropertyAccessExpression } - ); + this.validateLuaTableCall(node as ts.CallExpression & { expression: ts.PropertyAccessExpression }, false); + return this.transformLuaTableCallExpression(node as ts.CallExpression & { + expression: ts.PropertyAccessExpression; + }); } switch (ownerType.flags) { @@ -3763,8 +3606,10 @@ export class LuaTransformer { } // if ownerType inherits from an array, use array calls where appropriate - if (tsHelper.isArrayType(ownerType, this.checker, this.program) && - tsHelper.isDefaultArrayCallMethodName(node.expression.name.escapedText as string)) { + if ( + tsHelper.isArrayType(ownerType, this.checker, this.program) && + tsHelper.isDefaultArrayCallMethodName(node.expression.name.escapedText as string) + ) { return this.transformArrayCallExpression(node); } @@ -3776,10 +3621,7 @@ export class LuaTransformer { if (node.expression.expression.kind === ts.SyntaxKind.SuperKeyword) { // Super calls take the format of super.call(self,...) parameters = this.transformArguments(node.arguments, signature, ts.createThis()); - return tstl.createCallExpression( - this.transformExpression(node.expression), - parameters - ); + return tstl.createCallExpression(this.transformExpression(node.expression), parameters); } else { // Replace last . with : here const name = node.expression.name.escapedText; @@ -3797,20 +3639,25 @@ export class LuaTransformer { const rawGetCall = tstl.createCallExpression(rawGetIdentifier, [expr, ...parameters]); return tstl.createParenthesizedExpression( tstl.createBinaryExpression( - rawGetCall, tstl.createNilLiteral(), tstl.SyntaxKind.InequalityOperator, node) - ); + rawGetCall, + tstl.createNilLiteral(), + tstl.SyntaxKind.InequalityOperator, + node + ) + ); } else { const parameters = this.transformArguments(node.arguments, signature); const table = this.transformExpression(node.expression.expression); const signatureDeclaration = signature && signature.getDeclaration(); - if (!signatureDeclaration - || tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) !== ContextType.Void) - { - if (luaKeywords.has(node.expression.name.text) - || !tsHelper.isValidLuaIdentifier(node.expression.name.text)) - { + if ( + !signatureDeclaration || + tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) !== ContextType.Void + ) { + if ( + luaKeywords.has(node.expression.name.text) || + !tsHelper.isValidLuaIdentifier(node.expression.name.text) + ) { return this.transformElementCall(node); - } else { // table:name() return tstl.createMethodCallExpression( @@ -3842,8 +3689,10 @@ export class LuaTransformer { let parameters = this.transformArguments(node.arguments, signature); const signatureDeclaration = signature && signature.getDeclaration(); - if (!signatureDeclaration - || tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) !== ContextType.Void) { + if ( + !signatureDeclaration || + tsHelper.getDeclarationContextType(signatureDeclaration, this.checker) !== ContextType.Void + ) { // Pass left-side as context const context = this.transformExpression(node.expression.expression); @@ -3881,8 +3730,7 @@ export class LuaTransformer { params: ts.NodeArray | ts.Expression[], sig?: ts.Signature, context?: T - ): tstl.Expression[] - { + ): tstl.Expression[] { const parameters: tstl.Expression[] = []; // Add context as first param if present @@ -3913,14 +3761,12 @@ export class LuaTransformer { const type = this.checker.getTypeAtLocation(expression.expression); if (tsHelper.isStringType(type)) { return this.transformStringProperty(expression); - } else if (tsHelper.isArrayType(type, this.checker, this.program)) { const arrayPropertyAccess = this.transformArrayProperty(expression); if (arrayPropertyAccess) { return arrayPropertyAccess; } - - } else if (type.symbol && (type.symbol.flags & ts.SymbolFlags.ConstEnum)) { + } else if (type.symbol && type.symbol.flags & ts.SymbolFlags.ConstEnum) { return this.transformConstEnumValue(type, property, expression); } @@ -3983,8 +3829,7 @@ export class LuaTransformer { const expressionName = expression.name.escapedText as string; switch (expressionName) { // math.tan(x / y) - case "atan2": - { + case "atan2": { const math = tstl.createIdentifier("math"); const atan = tstl.createStringLiteral("atan"); const div = tstl.createBinaryExpression(params[0], params[1], tstl.SyntaxKind.DivisionOperator); @@ -3993,22 +3838,20 @@ export class LuaTransformer { // (math.log(x) / Math.LNe) case "log10": - case "log2": - { + case "log2": { const math = tstl.createIdentifier("math"); const log1 = tstl.createTableIndexExpression(math, tstl.createStringLiteral("log")); const logCall1 = tstl.createCallExpression(log1, params); const e = tstl.createNumericLiteral(expressionName === "log10" ? Math.LN10 : Math.LN2); const div = tstl.createBinaryExpression(logCall1, e, tstl.SyntaxKind.DivisionOperator); return ts.isExpressionStatement(node.parent) - // if used as a stand-alone statement, needs to be a call expression to be valid lua - ? this.createImmediatelyInvokedFunctionExpression([], div, node) + ? // if used as a stand-alone statement, needs to be a call expression to be valid lua + this.createImmediatelyInvokedFunctionExpression([], div, node) : tstl.createParenthesizedExpression(div, node); } // math.log(1 + x) - case "log1p": - { + case "log1p": { const math = tstl.createIdentifier("math"); const log = tstl.createStringLiteral("log"); const one = tstl.createNumericLiteral(1); @@ -4017,8 +3860,7 @@ export class LuaTransformer { } // math.floor(x + 0.5) - case "round": - { + case "round": { const math = tstl.createIdentifier("math"); const floor = tstl.createStringLiteral("floor"); const half = tstl.createNumericLiteral(0.5); @@ -4041,8 +3883,7 @@ export class LuaTransformer { case "random": case "sin": case "sqrt": - case "tan": - { + case "tan": { const math = tstl.createIdentifier("math"); const method = tstl.createStringLiteral(expressionName); return tstl.createCallExpression(tstl.createTableIndexExpression(math, method), params, node); @@ -4091,9 +3932,11 @@ export class LuaTransformer { const type = this.checker.getTypeAtLocation(expression.expression); - if (type.symbol && (type.symbol.flags & ts.SymbolFlags.ConstEnum) - && ts.isStringLiteral(expression.argumentExpression)) - { + if ( + type.symbol && + type.symbol.flags & ts.SymbolFlags.ConstEnum && + ts.isStringLiteral(expression.argumentExpression) + ) { return this.transformConstEnumValue(type, expression.argumentExpression.text, expression); } @@ -4117,8 +3960,7 @@ export class LuaTransformer { ): ExpressionVisitResult { // Assumption: the enum only has one declaration const enumDeclaration = enumType.symbol.declarations.find(d => ts.isEnumDeclaration(d)) as ts.EnumDeclaration; - const enumMember = enumDeclaration.members - .find(m => ts.isIdentifier(m.name) && m.name.text === memberName); + const enumMember = enumDeclaration.members.find(m => ts.isIdentifier(m.name) && m.name.text === memberName); if (enumMember) { if (enumMember.initializer) { @@ -4170,10 +4012,13 @@ export class LuaTransformer { node.arguments.length === 1 ? this.createStringCall("find", node, caller, params[0]) : this.createStringCall( - "find", node, caller, params[0], - this.expressionPlusOne(params[1]), - tstl.createBooleanLiteral(true) - ); + "find", + node, + caller, + params[0], + this.expressionPlusOne(params[1]), + tstl.createBooleanLiteral(true) + ); return tstl.createParenthesizedExpression( tstl.createBinaryExpression( @@ -4216,8 +4061,7 @@ export class LuaTransformer { case "slice": if (node.arguments.length === 0) { return caller; - } - else if (node.arguments.length === 1) { + } else if (node.arguments.length === 1) { const arg1 = this.expressionPlusOne(params[0]); return this.createStringCall("sub", node, caller, arg1); } else { @@ -4234,8 +4078,7 @@ export class LuaTransformer { case "charAt": const firstParamPlusOne = this.expressionPlusOne(params[0]); return this.createStringCall("sub", node, caller, firstParamPlusOne, firstParamPlusOne); - case "charCodeAt": - { + case "charCodeAt": { const firstParamPlusOne = this.expressionPlusOne(params[0]); return this.createStringCall("byte", node, caller, firstParamPlusOne); } @@ -4290,8 +4133,7 @@ export class LuaTransformer { methodName: string, tsOriginal: ts.Node, ...params: tstl.Expression[] - ): tstl.CallExpression - { + ): tstl.CallExpression { const stringIdentifier = tstl.createIdentifier("string"); return tstl.createCallExpression( tstl.createTableIndexExpression(stringIdentifier, tstl.createStringLiteral(methodName)), @@ -4337,11 +4179,7 @@ export class LuaTransformer { case "values": return this.transformLuaLibFunction(LuaLibFeature.ObjectValues, expression, ...parameters); default: - throw TSTLErrors.UnsupportedForTarget( - `object property ${methodName}`, - this.luaTarget, - expression - ); + throw TSTLErrors.UnsupportedForTarget(`object property ${methodName}`, this.luaTarget, expression); } } @@ -4352,19 +4190,16 @@ export class LuaTransformer { switch (methodName) { case "log": - if (expression.arguments.length > 0 - && this.isStringFormatTemplate(expression.arguments[0])) { + if (expression.arguments.length > 0 && this.isStringFormatTemplate(expression.arguments[0])) { // print(string.format([arguments])) const stringFormatCall = tstl.createCallExpression( tstl.createTableIndexExpression( tstl.createIdentifier("string"), - tstl.createStringLiteral("format")), + tstl.createStringLiteral("format") + ), this.transformArguments(expression.arguments, signature) ); - return tstl.createCallExpression( - tstl.createIdentifier("print"), - [stringFormatCall] - ); + return tstl.createCallExpression(tstl.createIdentifier("print"), [stringFormatCall]); } // print([arguments]) return tstl.createCallExpression( @@ -4373,63 +4208,49 @@ export class LuaTransformer { ); case "assert": const args = this.transformArguments(expression.arguments, signature); - if (expression.arguments.length > 1 - && this.isStringFormatTemplate(expression.arguments[1])) { + if (expression.arguments.length > 1 && this.isStringFormatTemplate(expression.arguments[1])) { // assert([condition], string.format([arguments])) const stringFormatCall = tstl.createCallExpression( tstl.createTableIndexExpression( tstl.createIdentifier("string"), - tstl.createStringLiteral("format")), + tstl.createStringLiteral("format") + ), args.slice(1) ); - return tstl.createCallExpression( - tstl.createIdentifier("assert"), - [args[0], stringFormatCall] - ); + return tstl.createCallExpression(tstl.createIdentifier("assert"), [args[0], stringFormatCall]); } // assert() - return tstl.createCallExpression( - tstl.createIdentifier("assert"), - args - ); + return tstl.createCallExpression(tstl.createIdentifier("assert"), args); case "trace": - if (expression.arguments.length > 0 - && this.isStringFormatTemplate(expression.arguments[0])) { + if (expression.arguments.length > 0 && this.isStringFormatTemplate(expression.arguments[0])) { // print(debug.traceback(string.format([arguments]))) const stringFormatCall = tstl.createCallExpression( tstl.createTableIndexExpression( tstl.createIdentifier("string"), - tstl.createStringLiteral("format")), + tstl.createStringLiteral("format") + ), this.transformArguments(expression.arguments, signature) ); const debugTracebackCall = tstl.createCallExpression( tstl.createTableIndexExpression( tstl.createIdentifier("debug"), - tstl.createStringLiteral("traceback")), + tstl.createStringLiteral("traceback") + ), [stringFormatCall] ); - return tstl.createCallExpression( - tstl.createIdentifier("print"), - [debugTracebackCall] - ); + return tstl.createCallExpression(tstl.createIdentifier("print"), [debugTracebackCall]); } // print(debug.traceback([arguments]))) const debugTracebackCall = tstl.createCallExpression( tstl.createTableIndexExpression( tstl.createIdentifier("debug"), - tstl.createStringLiteral("traceback")), + tstl.createStringLiteral("traceback") + ), this.transformArguments(expression.arguments, signature) ); - return tstl.createCallExpression( - tstl.createIdentifier("print"), - [debugTracebackCall] - ); + return tstl.createCallExpression(tstl.createIdentifier("print"), [debugTracebackCall]); default: - throw TSTLErrors.UnsupportedForTarget( - `console property ${methodName}`, - this.luaTarget, - expression - ); + throw TSTLErrors.UnsupportedForTarget(`console property ${methodName}`, this.luaTarget, expression); } } @@ -4452,11 +4273,7 @@ export class LuaTransformer { const functionIdentifier = tstl.createIdentifier(`__TS__SymbolRegistry${upperMethodName}`); return tstl.createCallExpression(functionIdentifier, parameters, expression); default: - throw TSTLErrors.UnsupportedForTarget( - `symbol property ${methodName}`, - this.luaTarget, - expression - ); + throw TSTLErrors.UnsupportedForTarget(`symbol property ${methodName}`, this.luaTarget, expression); } } @@ -4472,11 +4289,7 @@ export class LuaTransformer { case "isFinite": return this.transformLuaLibFunction(LuaLibFeature.NumberIsFinite, expression, ...parameters); default: - throw TSTLErrors.UnsupportedForTarget( - `number property ${methodName}`, - this.luaTarget, - expression - ); + throw TSTLErrors.UnsupportedForTarget(`number property ${methodName}`, this.luaTarget, expression); } } @@ -4492,10 +4305,7 @@ export class LuaTransformer { switch (methodName) { case "get": if (expression.arguments.length !== 1) { - throw TSTLErrors.ForbiddenLuaTableUseException( - "One parameter is required for get().", - expression - ); + throw TSTLErrors.ForbiddenLuaTableUseException("One parameter is required for get().", expression); } break; case "set": @@ -4513,9 +4323,9 @@ export class LuaTransformer { } private transformLuaTableExpressionStatement( - node: ts.ExpressionStatement - & { expression: ts.CallExpression } - & { expression: { expression: ts.PropertyAccessExpression }} + node: ts.ExpressionStatement & { expression: ts.CallExpression } & { + expression: { expression: ts.PropertyAccessExpression }; + } ): tstl.VariableDeclarationStatement | tstl.AssignmentStatement { const methodName = node.expression.expression.name.escapedText; const signature = this.checker.getResolvedSignature(node.expression); @@ -4537,10 +4347,7 @@ export class LuaTransformer { node.expression ); default: - throw TSTLErrors.ForbiddenLuaTableUseException( - "Unsupported method.", - node.expression - ); + throw TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", node.expression); } } @@ -4558,10 +4365,7 @@ export class LuaTransformer { case "get": return tstl.createTableIndexExpression(luaTable, params[0], expression); default: - throw TSTLErrors.ForbiddenLuaTableUseException( - "Unsupported method.", - expression - ); + throw TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", expression); } } @@ -4609,9 +4413,8 @@ export class LuaTransformer { case "splice": return this.transformLuaLibFunction(LuaLibFeature.ArraySplice, node, caller, ...params); case "join": - const parameters = node.arguments.length === 0 - ? [caller, tstl.createStringLiteral(",")] - : [caller].concat(params); + const parameters = + node.arguments.length === 0 ? [caller, tstl.createStringLiteral(",")] : [caller].concat(params); return tstl.createCallExpression( tstl.createTableIndexExpression(tstl.createIdentifier("table"), tstl.createStringLiteral("concat")), @@ -4680,12 +4483,7 @@ export class LuaTransformer { const andClause = tstl.createBinaryExpression(condition, objectString, tstl.SyntaxKind.AndOperator); return tstl.createParenthesizedExpression( - tstl.createBinaryExpression( - andClause, - tstl.cloneNode(typeCall), - tstl.SyntaxKind.OrOperator, - expression - ) + tstl.createBinaryExpression(andClause, tstl.cloneNode(typeCall), tstl.SyntaxKind.OrOperator, expression) ); } @@ -4747,10 +4545,8 @@ export class LuaTransformer { } }); - return parts.reduce((prev, current) => tstl.createBinaryExpression( - prev, - current, - tstl.SyntaxKind.ConcatOperator) + return parts.reduce((prev, current) => + tstl.createBinaryExpression(prev, current, tstl.SyntaxKind.ConcatOperator) ); } @@ -4773,10 +4569,11 @@ export class LuaTransformer { public transformIdentifier(identifier: ts.Identifier): tstl.Identifier { if (identifier.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 return tstl.createNilLiteral() - // at some point. + // 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 return tstl.createNilLiteral() + // at some point. + return tstl.createIdentifier("nil"); } const text = this.hasUnsafeIdentifierName(identifier) @@ -4868,22 +4665,18 @@ export class LuaTransformer { } else { exportTable = this.transformIdentifier(this.currentNamespace.name as ts.Identifier); } - } else { exportTable = this.createExportsIdentifier(); } - return tstl.createTableIndexExpression( - exportTable, - tstl.createStringLiteral(identifier.text)); + return tstl.createTableIndexExpression(exportTable, tstl.createStringLiteral(identifier.text)); } protected transformLuaLibFunction( func: LuaLibFeature, tsParent?: ts.Expression, ...params: tstl.Expression[] - ): tstl.CallExpression - { + ): tstl.CallExpression { this.importLuaLibFeature(func); const functionIdentifier = tstl.createIdentifier(`__TS__${func}`); return tstl.createCallExpression(functionIdentifier, params, tsParent); @@ -4916,8 +4709,7 @@ export class LuaTransformer { statements: tstl.Statement[], result: tstl.Expression | tstl.Expression[], tsOriginal: ts.Node - ): tstl.CallExpression - { + ): tstl.CallExpression { const body = statements ? statements.slice(0) : []; body.push(tstl.createReturnStatement(Array.isArray(result) ? result : [result])); const flags = statements.length === 0 ? tstl.FunctionExpressionFlags.Inline : tstl.FunctionExpressionFlags.None; @@ -4962,12 +4754,13 @@ export class LuaTransformer { const absoluteImportPath = path.format(path.parse(this.getAbsoluteImportPath(relativePath))); const absoluteRootDirPath = path.format(path.parse(rootDir)); if (absoluteImportPath.includes(absoluteRootDirPath)) { - return this.formatPathToLuaPath( - absoluteImportPath.replace(absoluteRootDirPath, "").slice(1)); + return this.formatPathToLuaPath(absoluteImportPath.replace(absoluteRootDirPath, "").slice(1)); } else { - throw TSTLErrors.UnresolvableRequirePath(node, + throw TSTLErrors.UnresolvableRequirePath( + node, `Cannot create require path. Module does not exist within --rootDir`, - relativePath); + relativePath + ); } } @@ -4975,13 +4768,9 @@ export class LuaTransformer { filePath = filePath.replace(/\.json$/, ""); if (process.platform === "win32") { // Windows can use backslashes - filePath = filePath - .replace(/\.\\/g, "") - .replace(/\\/g, "."); + filePath = filePath.replace(/\.\\/g, "").replace(/\\/g, "."); } - return filePath - .replace(/\.\//g, "") - .replace(/\//g, "."); + return filePath.replace(/\.\//g, "").replace(/\//g, "."); } protected shouldExportIdentifier(identifier: tstl.Identifier | tstl.Identifier[]): boolean { @@ -5008,8 +4797,7 @@ export class LuaTransformer { rhs?: tstl.Expression | tstl.Expression[], tsOriginal?: ts.Node, parent?: tstl.Node - ): tstl.Statement[] - { + ): tstl.Statement[] { let declaration: tstl.VariableDeclarationStatement | undefined; let assignment: tstl.AssignmentStatement | undefined; @@ -5026,7 +4814,6 @@ export class LuaTransformer { tsOriginal, parent ); - } else { assignment = tstl.createAssignmentStatement( this.createExportedIdentifier(lhs), @@ -5035,7 +4822,6 @@ export class LuaTransformer { parent ); } - } else { const insideFunction = this.findScope(ScopeType.Function) !== undefined; let isLetOrConst = false; @@ -5046,38 +4832,39 @@ export class LuaTransformer { } if ((this.isModule || this.currentNamespace || insideFunction || isLetOrConst) && isFirstDeclaration) { // local - const isPossibleWrappedFunction = !functionDeclaration - && tsOriginal - && ts.isVariableDeclaration(tsOriginal) - && tsOriginal.initializer - && tsHelper.isFunctionTypeAtLocation(tsOriginal.initializer, this.checker); + const isPossibleWrappedFunction = + !functionDeclaration && + tsOriginal && + ts.isVariableDeclaration(tsOriginal) && + tsOriginal.initializer && + tsHelper.isFunctionTypeAtLocation(tsOriginal.initializer, this.checker); if (isPossibleWrappedFunction) { // Split declaration and assignment for wrapped function types to allow recursion declaration = tstl.createVariableDeclarationStatement(lhs, undefined, tsOriginal, parent); assignment = tstl.createAssignmentStatement(lhs, rhs, tsOriginal, parent); - } else { declaration = tstl.createVariableDeclarationStatement(lhs, rhs, tsOriginal, parent); } if (!this.options.noHoisting) { // Remember local variable declarations for hoisting later - const scope = isLetOrConst || functionDeclaration - ? this.peekScope() - : this.findScope(ScopeType.Function | ScopeType.File); + const scope = + isLetOrConst || functionDeclaration + ? this.peekScope() + : this.findScope(ScopeType.Function | ScopeType.File); if (scope === undefined) { throw TSTLErrors.UndefinedScope(); } - if (!scope.variableDeclarations) { scope.variableDeclarations = []; } + if (!scope.variableDeclarations) { + scope.variableDeclarations = []; + } scope.variableDeclarations.push(declaration); } - } else if (rhs) { // global assignment = tstl.createAssignmentStatement(lhs, rhs, tsOriginal, parent); - } else { return []; } @@ -5151,8 +4938,10 @@ export class LuaTransformer { return; } - if ((ts.isArrayTypeNode(toTypeNode) || ts.isTupleTypeNode(toTypeNode)) - && (ts.isArrayTypeNode(fromTypeNode) || ts.isTupleTypeNode(fromTypeNode))) { + if ( + (ts.isArrayTypeNode(toTypeNode) || ts.isTupleTypeNode(toTypeNode)) && + (ts.isArrayTypeNode(fromTypeNode) || ts.isTupleTypeNode(fromTypeNode)) + ) { // Recurse into arrays/tuples const fromTypeArguments = (fromType as ts.TypeReference).typeArguments; const toTypeArguments = (toType as ts.TypeReference).typeArguments; @@ -5163,19 +4952,18 @@ export class LuaTransformer { const count = Math.min(fromTypeArguments.length, toTypeArguments.length); for (let i = 0; i < count; ++i) { - this.validateFunctionAssignment( - node, - fromTypeArguments[i], - toTypeArguments[i], - toName - ); + this.validateFunctionAssignment(node, fromTypeArguments[i], toTypeArguments[i], toName); } } - if ((toType.flags & ts.TypeFlags.Object) !== 0 - && ((toType as ts.ObjectType).objectFlags & ts.ObjectFlags.ClassOrInterface) !== 0 - && toType.symbol && toType.symbol.members && fromType.symbol && fromType.symbol.members) - { + if ( + (toType.flags & ts.TypeFlags.Object) !== 0 && + ((toType as ts.ObjectType).objectFlags & ts.ObjectFlags.ClassOrInterface) !== 0 && + toType.symbol && + toType.symbol.members && + fromType.symbol && + fromType.symbol.members + ) { // Recurse into interfaces toType.symbol.members.forEach((toMember, memberName) => { if (fromType.symbol.members) { @@ -5184,10 +4972,10 @@ export class LuaTransformer { const toMemberType = this.checker.getTypeOfSymbolAtLocation(toMember, node); const fromMemberType = this.checker.getTypeOfSymbolAtLocation(fromMember, node); this.validateFunctionAssignment( - node, fromMemberType, toMemberType, - toName - ? `${toName}.${memberName}` - : memberName.toString() + node, + fromMemberType, + toMemberType, + toName ? `${toName}.${memberName}` : memberName.toString() ); } } @@ -5228,10 +5016,11 @@ export class LuaTransformer { } protected wrapInToStringForConcat(expression: tstl.Expression): tstl.Expression { - if (tstl.isStringLiteral(expression) - || tstl.isNumericLiteral(expression) - || (tstl.isBinaryExpression(expression) && expression.operator === tstl.SyntaxKind.ConcatOperator)) - { + if ( + tstl.isStringLiteral(expression) || + tstl.isNumericLiteral(expression) || + (tstl.isBinaryExpression(expression) && expression.operator === tstl.SyntaxKind.ConcatOperator) + ) { return expression; } return tstl.createCallExpression(tstl.createIdentifier("tostring"), [expression]); @@ -5262,23 +5051,19 @@ export class LuaTransformer { protected createShorthandIdentifier( valueSymbol: ts.Symbol | undefined, propertyIdentifier: ts.Identifier - ): tstl.Expression - { + ): tstl.Expression { let name: string; if (valueSymbol !== undefined) { name = this.hasUnsafeSymbolName(valueSymbol, propertyIdentifier) ? this.createSafeName(valueSymbol.name) : valueSymbol.name; - } else { const propertyName = this.getIdentifierText(propertyIdentifier); if (luaKeywords.has(propertyName) || !tsHelper.isValidLuaIdentifier(propertyName)) { // Catch ambient declarations of identifiers with bad names throw TSTLErrors.InvalidAmbientIdentifierName(propertyIdentifier); } - name = this.hasUnsafeIdentifierName(propertyIdentifier) - ? this.createSafeName(propertyName) - : propertyName; + name = this.hasUnsafeIdentifierName(propertyIdentifier) ? this.createSafeName(propertyName) : propertyName; } const identifier = this.transformIdentifierExpression(ts.createIdentifier(name)); @@ -5331,10 +5116,9 @@ export class LuaTransformer { if (!this.symbolIds.has(symbol)) { symbolId = this.genSymbolIdCounter++; - const symbolInfo: SymbolInfo = {symbol, firstSeenAtPos: identifier.pos}; + const symbolInfo: SymbolInfo = { symbol, firstSeenAtPos: identifier.pos }; this.symbolIds.set(symbol, symbolId); this.symbolInfo.set(symbolId, symbolInfo); - } else { symbolId = this.symbolIds.get(symbol); } @@ -5345,7 +5129,6 @@ export class LuaTransformer { if (declaration && identifier.pos < declaration.pos) { throw TSTLErrors.ReferencedBeforeDeclaration(identifier); } - } else if (symbolId !== undefined) { //Mark symbol as seen in all current scopes for (const scope of this.scopeStack) { @@ -5360,7 +5143,10 @@ export class LuaTransformer { } protected findScope(scopeTypes: ScopeType): Scope | undefined { - return this.scopeStack.slice().reverse().find(s => (scopeTypes & s.type) !== 0); + return this.scopeStack + .slice() + .reverse() + .find(s => (scopeTypes & s.type) !== 0); } protected peekScope(): Scope | undefined { @@ -5403,11 +5189,12 @@ export class LuaTransformer { const { line, column } = tstl.getOriginalPos(functionDefinition.definition); if (line !== undefined && column !== undefined) { const definitionPos = ts.getPositionOfLineAndCharacter(this.currentSourceFile, line, column); - if (functionSymbolId !== symbolId // Don't recurse into self - && declaration.pos < definitionPos // Ignore functions before symbol declaration - && functionDefinition.referencedSymbols.has(symbolId) - && this.shouldHoist(functionSymbolId, scope)) - { + if ( + functionSymbolId !== symbolId && // Don't recurse into self + declaration.pos < definitionPos && // Ignore functions before symbol declaration + functionDefinition.referencedSymbols.has(symbolId) && + this.shouldHoist(functionSymbolId, scope) + ) { return true; } } @@ -5534,15 +5321,16 @@ export class LuaTransformer { initializer?: tstl.Expression, tsOriginal?: ts.Node, parent?: tstl.Node - ): tstl.AssignmentStatement | tstl.VariableDeclarationStatement - { + ): tstl.AssignmentStatement | tstl.VariableDeclarationStatement { const declaration = tstl.createVariableDeclarationStatement(identifier, initializer, tsOriginal, parent); if (!this.options.noHoisting && identifier.symbolId) { const scope = this.peekScope(); if (scope === undefined) { throw TSTLErrors.UndefinedScope(); } - if (!scope.variableDeclarations) { scope.variableDeclarations = []; } + if (!scope.variableDeclarations) { + scope.variableDeclarations = []; + } scope.variableDeclarations.push(declaration); } return declaration; @@ -5564,7 +5352,8 @@ export class LuaTransformer { } protected filterUndefinedAndCast( - items: Array, cast: (item: TOriginal) => item is TCast + items: Array, + cast: (item: TOriginal) => item is TCast ): TCast[] { const filteredItems = items.filter(i => i !== undefined) as TOriginal[]; if (filteredItems.every(i => cast(i))) { @@ -5577,18 +5366,23 @@ export class LuaTransformer { private createConstructorDecorationStatement( declaration: ts.ClassLikeDeclaration ): tstl.AssignmentStatement | undefined { - const className = declaration.name !== undefined - ? this.addExportToIdentifier(this.transformIdentifier(declaration.name)) - : tstl.createAnonymousIdentifier(); + const className = + declaration.name !== undefined + ? this.addExportToIdentifier(this.transformIdentifier(declaration.name)) + : tstl.createAnonymousIdentifier(); const decorators = declaration.decorators; - if (!decorators) { return undefined; } + if (!decorators) { + return undefined; + } const decoratorExpressions = decorators.map(decorator => { const expression = decorator.expression; const type = this.checker.getTypeAtLocation(expression); const context = tsHelper.getFunctionContextType(type, this.checker); - if (context === ContextType.Void) { throw TSTLErrors.InvalidDecoratorContext(decorator); } + if (context === ContextType.Void) { + throw TSTLErrors.InvalidDecoratorContext(decorator); + } return this.transformExpression(expression); }); @@ -5607,4 +5401,3 @@ export class LuaTransformer { ); } } - diff --git a/src/TSHelper.ts b/src/TSHelper.ts index 8764f500f..ad63e2e19 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -30,8 +30,10 @@ const defaultArrayCallMethodNames = new Set([ ]); export class TSHelper { - public static getExtendedTypeNode(node: ts.ClassLikeDeclarationBase, checker: ts.TypeChecker): - ts.ExpressionWithTypeArguments | undefined { + public static getExtendedTypeNode( + node: ts.ClassLikeDeclarationBase, + checker: ts.TypeChecker + ): ts.ExpressionWithTypeArguments | undefined { if (node && node.heritageClauses) { for (const clause of node.heritageClauses) { if (clause.token === ts.SyntaxKind.ExtendsKeyword) { @@ -61,22 +63,37 @@ export class TSHelper { } if (ts.isVariableStatement(statement)) { return statement.declarationList.declarations.some( - declaration => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0); + declaration => (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) !== 0 + ); } - return TSHelper.isDeclaration(statement) - && ((ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export) !== 0); + return ( + TSHelper.isDeclaration(statement) && + (ts.getCombinedModifierFlags(statement) & ts.ModifierFlags.Export) !== 0 + ); } public static isDeclaration(node: ts.Node): node is ts.Declaration { - return ts.isEnumDeclaration(node) || ts.isClassDeclaration(node) || ts.isExportDeclaration(node) - || ts.isImportDeclaration(node) || ts.isMethodDeclaration(node) || ts.isModuleDeclaration(node) - || ts.isFunctionDeclaration(node) || ts.isVariableDeclaration(node) || ts.isInterfaceDeclaration(node) - || ts.isTypeAliasDeclaration(node) || ts.isNamespaceExportDeclaration(node); + return ( + ts.isEnumDeclaration(node) || + ts.isClassDeclaration(node) || + ts.isExportDeclaration(node) || + ts.isImportDeclaration(node) || + ts.isMethodDeclaration(node) || + ts.isModuleDeclaration(node) || + ts.isFunctionDeclaration(node) || + ts.isVariableDeclaration(node) || + ts.isInterfaceDeclaration(node) || + ts.isTypeAliasDeclaration(node) || + ts.isNamespaceExportDeclaration(node) + ); } 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))); + return ( + node.parent && + ((ts.isVariableDeclaration(node.parent) && ts.isArrayBindingPattern(node.parent.name)) || + (ts.isBinaryExpression(node.parent) && ts.isArrayLiteralExpression(node.parent.left))) + ); } // iterate over a type and its bases until the callback returns true. @@ -84,8 +101,7 @@ export class TSHelper { type: ts.Type, checker: ts.TypeChecker, predicate: (type: ts.Type) => boolean - ): boolean - { + ): boolean { if (predicate(type)) { return true; } @@ -112,13 +128,19 @@ export class TSHelper { } public static isStringType(type: ts.Type): boolean { - return (type.flags & ts.TypeFlags.String) !== 0 || (type.flags & ts.TypeFlags.StringLike) !== 0 || - (type.flags & ts.TypeFlags.StringLiteral) !== 0; + return ( + (type.flags & ts.TypeFlags.String) !== 0 || + (type.flags & ts.TypeFlags.StringLike) !== 0 || + (type.flags & ts.TypeFlags.StringLiteral) !== 0 + ); } public static isNumberType(type: ts.Type): boolean { - return (type.flags & ts.TypeFlags.Number) !== 0 || (type.flags & ts.TypeFlags.NumberLike) !== 0 || - (type.flags & ts.TypeFlags.NumberLiteral) !== 0; + return ( + (type.flags & ts.TypeFlags.Number) !== 0 || + (type.flags & ts.TypeFlags.NumberLike) !== 0 || + (type.flags & ts.TypeFlags.NumberLiteral) !== 0 + ); } public static isExplicitArrayType(type: ts.Type, checker: ts.TypeChecker, program: ts.Program): boolean { @@ -164,9 +186,11 @@ export class TSHelper { // Only check function type for directive if it is declared as an interface or type alias const declaration = signature.getDeclaration(); - const isInterfaceOrAlias = declaration && declaration.parent - && ((ts.isInterfaceDeclaration(declaration.parent) && ts.isCallSignatureDeclaration(declaration)) - || ts.isTypeAliasDeclaration(declaration.parent)); + const isInterfaceOrAlias = + declaration && + declaration.parent && + ((ts.isInterfaceDeclaration(declaration.parent) && ts.isCallSignatureDeclaration(declaration)) || + ts.isTypeAliasDeclaration(declaration.parent)); if (!isInterfaceOrAlias) { return false; } @@ -174,7 +198,6 @@ export class TSHelper { const type = checker.getTypeAtLocation(node.expression); return TSHelper.getCustomDecorators(type, checker).has(DecoratorKind.TupleReturn); - } else { return false; } @@ -200,15 +223,15 @@ export class TSHelper { // Check all overloads for directive const signatures = functionType.getCallSignatures(); - if (signatures && signatures.some( - s => TSHelper.getCustomSignatureDirectives(s, checker).has(DecoratorKind.TupleReturn))) - { + if ( + signatures && + signatures.some(s => TSHelper.getCustomSignatureDirectives(s, checker).has(DecoratorKind.TupleReturn)) + ) { return true; } const decorators = TSHelper.getCustomDecorators(functionType, checker); return decorators.has(DecoratorKind.TupleReturn); - } else { return false; } @@ -227,14 +250,14 @@ export class TSHelper { source: ts.Symbol | ts.Signature, checker: ts.TypeChecker, decMap: Map - ): void - { + ): void { const comments = source.getDocumentationComment(checker); - const decorators = comments.filter(comment => comment.kind === "text") - .map(comment => comment.text.split("\n")) - .reduce((a, b) => a.concat(b), []) - .map(line => line.trim()) - .filter(comment => comment[0] === "!"); + const decorators = comments + .filter(comment => comment.kind === "text") + .map(comment => comment.text.split("\n")) + .reduce((a, b) => a.concat(b), []) + .map(line => line.trim()) + .filter(comment => comment[0] === "!"); decorators.forEach(decStr => { const [decoratorName, ...decoratorArguments] = decStr.split(" "); @@ -242,8 +265,8 @@ export class TSHelper { const dec = new Decorator(decoratorName.substr(1), decoratorArguments); decMap.set(dec.kind, dec); console.warn( - `[Deprecated] Decorators with ! are being deprecated, ` + - `use @${decStr.substr(1)} instead`); + `[Deprecated] Decorators with ! are being deprecated, ` + `use @${decStr.substr(1)} instead` + ); } else { console.warn(`Encountered unknown decorator ${decStr}.`); } @@ -282,9 +305,10 @@ export class TSHelper { return decMap; } - public static getCustomSignatureDirectives(signature: ts.Signature, checker: ts.TypeChecker) - : Map - { + public static getCustomSignatureDirectives( + signature: ts.Signature, + checker: ts.TypeChecker + ): Map { const directivesMap = new Map(); TSHelper.collectCustomDecorators(signature, checker, directivesMap); @@ -302,7 +326,8 @@ export class TSHelper { // Search up until finding a node satisfying the callback public static findFirstNodeAbove( - node: ts.Node, callback: (n: ts.Node) => n is T + node: ts.Node, + callback: (n: ts.Node) => n is T ): T | undefined { let current = node; while (current.parent) { @@ -357,11 +382,12 @@ export class TSHelper { node: ts.Expression, checker: ts.TypeChecker, program: ts.Program - ): [true, ts.Expression, ts.Expression] | [false, undefined, undefined] - { - if (ts.isElementAccessExpression(node) && - (TSHelper.isExpressionWithEvaluationEffect(node.expression) - || TSHelper.isExpressionWithEvaluationEffect(node.argumentExpression))) { + ): [true, ts.Expression, ts.Expression] | [false, undefined, undefined] { + if ( + ts.isElementAccessExpression(node) && + (TSHelper.isExpressionWithEvaluationEffect(node.expression) || + TSHelper.isExpressionWithEvaluationEffect(node.argumentExpression)) + ) { const type = checker.getTypeAtLocation(node.expression); if (TSHelper.isArrayType(type, checker, program)) { // Offset arrays by one @@ -386,15 +412,15 @@ export class TSHelper { signatureDeclaration: ts.SignatureDeclaration ): ts.ParameterDeclaration | undefined { return signatureDeclaration.parameters.find( - param => ts.isIdentifier(param.name) && param.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword); + param => ts.isIdentifier(param.name) && param.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword + ); } public static findInClassOrAncestor( classDeclaration: ts.ClassLikeDeclarationBase, callback: (classDeclaration: ts.ClassLikeDeclarationBase) => boolean, checker: ts.TypeChecker - ): ts.ClassLikeDeclarationBase | undefined - { + ): ts.ClassLikeDeclarationBase | undefined { if (callback(classDeclaration)) { return classDeclaration; } @@ -426,26 +452,28 @@ export class TSHelper { classDeclaration: ts.ClassLikeDeclarationBase, isStatic: boolean, checker: ts.TypeChecker - ): boolean - { - return TSHelper.findInClassOrAncestor( - classDeclaration, - c => c.members.some(m => ts.isSetAccessor(m) && TSHelper.isStatic(m) === isStatic), - checker - ) !== undefined; + ): boolean { + return ( + TSHelper.findInClassOrAncestor( + classDeclaration, + c => c.members.some(m => ts.isSetAccessor(m) && TSHelper.isStatic(m) === isStatic), + checker + ) !== undefined + ); } public static hasGetAccessorInClassOrAncestor( classDeclaration: ts.ClassLikeDeclarationBase, isStatic: boolean, checker: ts.TypeChecker - ): boolean - { - return TSHelper.findInClassOrAncestor( - classDeclaration, - c => c.members.some(m => ts.isGetAccessor(m) && TSHelper.isStatic(m) === isStatic), - checker - ) !== undefined; + ): boolean { + return ( + TSHelper.findInClassOrAncestor( + classDeclaration, + c => c.members.some(m => ts.isGetAccessor(m) && TSHelper.isStatic(m) === isStatic), + checker + ) !== undefined + ); } public static getPropertyName(propertyName: ts.PropertyName): string | number | undefined { @@ -466,22 +494,20 @@ export class TSHelper { element: ts.ClassElement, classDeclaration: ts.ClassLikeDeclarationBase, checker: ts.TypeChecker - ): element is ts.GetAccessorDeclaration - { + ): element is ts.GetAccessorDeclaration { if (!ts.isGetAccessor(element) || TSHelper.isStatic(element)) { return false; } const hasInitializedField = (e: ts.ClassElement) => - ts.isPropertyDeclaration(e) - && e.initializer !== undefined - && TSHelper.isSamePropertyName(e.name, element.name); + ts.isPropertyDeclaration(e) && + e.initializer !== undefined && + TSHelper.isSamePropertyName(e.name, element.name); - return TSHelper.findInClassOrAncestor( - classDeclaration, - c => c.members.some(hasInitializedField), - checker - ) !== undefined; + return ( + TSHelper.findInClassOrAncestor(classDeclaration, c => c.members.some(hasInitializedField), checker) !== + undefined + ); } public static inferAssignedType(expression: ts.Expression, checker: ts.TypeChecker): ts.Type { @@ -498,14 +524,14 @@ export class TSHelper { public static getSignatureDeclarations( signatures: readonly ts.Signature[], checker: ts.TypeChecker - ): ts.SignatureDeclaration[] - { + ): ts.SignatureDeclaration[] { const signatureDeclarations: ts.SignatureDeclaration[] = []; for (const signature of signatures) { const signatureDeclaration = signature.getDeclaration(); - if ((ts.isFunctionExpression(signatureDeclaration) || ts.isArrowFunction(signatureDeclaration)) - && !TSHelper.getExplicitThisParameter(signatureDeclaration)) - { + if ( + (ts.isFunctionExpression(signatureDeclaration) || ts.isArrowFunction(signatureDeclaration)) && + !TSHelper.getExplicitThisParameter(signatureDeclaration) + ) { // Infer type of function expressions/arrow functions const inferredType = TSHelper.inferAssignedType(signatureDeclaration, checker); if (inferredType) { @@ -542,8 +568,7 @@ export class TSHelper { public static getDeclarationContextType( signatureDeclaration: ts.SignatureDeclaration, checker: ts.TypeChecker - ): ContextType - { + ): ContextType { const thisParameter = TSHelper.getExplicitThisParameter(signatureDeclaration); if (thisParameter) { // Explicit 'this' @@ -552,20 +577,19 @@ export class TSHelper { : ContextType.NonVoid; } - if (ts.isMethodSignature(signatureDeclaration) - || ts.isMethodDeclaration(signatureDeclaration) - || ts.isConstructSignatureDeclaration(signatureDeclaration) - || ts.isConstructorDeclaration(signatureDeclaration) - || (signatureDeclaration.parent && ts.isPropertyDeclaration(signatureDeclaration.parent)) - || (signatureDeclaration.parent && ts.isPropertySignature(signatureDeclaration.parent))) - { + if ( + ts.isMethodSignature(signatureDeclaration) || + ts.isMethodDeclaration(signatureDeclaration) || + ts.isConstructSignatureDeclaration(signatureDeclaration) || + ts.isConstructorDeclaration(signatureDeclaration) || + (signatureDeclaration.parent && ts.isPropertyDeclaration(signatureDeclaration.parent)) || + (signatureDeclaration.parent && ts.isPropertySignature(signatureDeclaration.parent)) + ) { // Class/interface methods only respect @noSelf on their parent const scopeDeclaration = TSHelper.findFirstNodeAbove( signatureDeclaration, (n): n is ts.ClassLikeDeclaration | ts.InterfaceDeclaration => - ts.isClassDeclaration(n) - || ts.isClassExpression(n) - || ts.isInterfaceDeclaration(n) + ts.isClassDeclaration(n) || ts.isClassExpression(n) || ts.isInterfaceDeclaration(n) ); if (scopeDeclaration === undefined) { @@ -608,9 +632,7 @@ export class TSHelper { } if (type.isUnion()) { - return TSHelper.reduceContextTypes( - type.types.map(t => TSHelper.getFunctionContextType(t, checker)) - ); + return TSHelper.reduceContextTypes(type.types.map(t => TSHelper.getFunctionContextType(t, checker))); } const signatures = checker.getSignaturesOfType(type, ts.SignatureKind.Call); @@ -619,15 +641,16 @@ export class TSHelper { } const signatureDeclarations = TSHelper.getSignatureDeclarations(signatures, checker); return TSHelper.reduceContextTypes( - signatureDeclarations.map(s => TSHelper.getDeclarationContextType(s, checker))); + signatureDeclarations.map(s => TSHelper.getDeclarationContextType(s, checker)) + ); } public static escapeString(text: string): string { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String const escapeSequences: Array<[RegExp, string]> = [ [/[\\]/g, "\\\\"], - [/[\']/g, "\\\'"], - [/[\"]/g, "\\\""], + [/[\']/g, "\\'"], + [/[\"]/g, '\\"'], [/[\n]/g, "\\n"], [/[\r]/g, "\\r"], [/[\v]/g, "\\v"], @@ -651,7 +674,14 @@ export class TSHelper { } public static fixInvalidLuaIdentifier(name: string): string { - return name.replace(/[^a-zA-Z0-9_]/g, c => `_${c.charCodeAt(0).toString(16).toUpperCase()}`); + return name.replace( + /[^a-zA-Z0-9_]/g, + c => + `_${c + .charCodeAt(0) + .toString(16) + .toUpperCase()}` + ); } // Checks that a name is valid for use in lua function declaration syntax: @@ -663,13 +693,14 @@ export class TSHelper { } public static isFalsible(type: ts.Type, strictNullChecks: boolean): boolean { - const falsibleFlags = ts.TypeFlags.Boolean - | ts.TypeFlags.BooleanLiteral - | ts.TypeFlags.Undefined - | ts.TypeFlags.Null - | ts.TypeFlags.Never - | ts.TypeFlags.Void - | ts.TypeFlags.Any; + const falsibleFlags = + ts.TypeFlags.Boolean | + ts.TypeFlags.BooleanLiteral | + ts.TypeFlags.Undefined | + ts.TypeFlags.Null | + ts.TypeFlags.Never | + ts.TypeFlags.Void | + ts.TypeFlags.Any; if (type.flags & falsibleFlags) { return true; @@ -694,9 +725,7 @@ export class TSHelper { if (sourceFile) { declarations = declarations.filter(d => this.findFirstNodeAbove(d, ts.isSourceFile) === sourceFile); } - return declarations.length > 0 - ? declarations.reduce((p, c) => p.pos < c.pos ? p : c) - : undefined; + return declarations.length > 0 ? declarations.reduce((p, c) => (p.pos < c.pos ? p : c)) : undefined; } public static isFirstDeclaration(node: ts.VariableDeclaration, checker: ts.TypeChecker): boolean { @@ -710,18 +739,22 @@ export class TSHelper { public static isStandardLibraryDeclaration(declaration: ts.Declaration, program: ts.Program): boolean { const source = declaration.getSourceFile(); - if (!source) { return false; } + if (!source) { + return false; + } return program.isSourceFileDefaultLibrary(source); } public static isStandardLibraryType(type: ts.Type, name: string | undefined, program: ts.Program): boolean { const symbol = type.getSymbol(); - if (!symbol || (name ? symbol.escapedName !== name : symbol.escapedName === '__type')) { + if (!symbol || (name ? symbol.escapedName !== name : symbol.escapedName === "__type")) { return false; } const declaration = symbol.valueDeclaration; - if(!declaration) { return true; } // assume to be lib function if no valueDeclaration exists + if (!declaration) { + return true; + } // assume to be lib function if no valueDeclaration exists return this.isStandardLibraryDeclaration(declaration, program); } @@ -745,15 +778,17 @@ export class TSHelper { } } - public static moduleHasEmittedBody(statement: ts.ModuleDeclaration) - : statement is ts.ModuleDeclaration & {body: ts.ModuleBlock | ts.ModuleDeclaration} - { + public static moduleHasEmittedBody( + statement: ts.ModuleDeclaration + ): statement is ts.ModuleDeclaration & { body: ts.ModuleBlock | ts.ModuleDeclaration } { if (statement.body) { if (ts.isModuleBlock(statement.body)) { // Ignore if body has no emitted statements - return statement.body.statements.findIndex( - s => !ts.isInterfaceDeclaration(s) && !ts.isTypeAliasDeclaration(s) - ) !== -1; + return ( + statement.body.statements.findIndex( + s => !ts.isInterfaceDeclaration(s) && !ts.isTypeAliasDeclaration(s) + ) !== -1 + ); } else if (ts.isModuleDeclaration(statement.body)) { return true; } @@ -765,8 +800,7 @@ export class TSHelper { expression: ts.BinaryExpression, checker: ts.TypeChecker, program: ts.Program - ): expression is ts.BinaryExpression & { left: ts.PropertyAccessExpression | ts.ElementAccessExpression; } - { + ): expression is ts.BinaryExpression & { left: ts.PropertyAccessExpression | ts.ElementAccessExpression } { if (expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken) { return false; } @@ -781,7 +815,7 @@ export class TSHelper { } const name = ts.isPropertyAccessExpression(expression.left) - ? expression.left.name.escapedText as string + ? (expression.left.name.escapedText as string) : ts.isStringLiteral(expression.left.argumentExpression) && expression.left.argumentExpression.text; return name === "length"; diff --git a/src/TSTLErrors.ts b/src/TSTLErrors.ts index 4f2b6e565..26d08d1ca 100644 --- a/src/TSTLErrors.ts +++ b/src/TSTLErrors.ts @@ -2,8 +2,7 @@ import * as ts from "typescript"; import { TranspileError } from "./TranspileError"; import { LuaTarget } from "./CompilerOptions"; -const getLuaTargetName = (version: LuaTarget) => - version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`; +const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); export class TSTLErrors { public static CouldNotCast = (castName: string) => @@ -21,9 +20,11 @@ export class TSTLErrors { public static ForbiddenForIn = (node: ts.Node) => new TranspileError(`Iterating over arrays with 'for ... in' is not allowed.`, node); - public static ForbiddenLuaTableSetExpression = (node: ts.Node) => new TranspileError( - `A '@luaTable' object's 'set()' method can only be used as a Statement, not an Expression.`, - node); + public static ForbiddenLuaTableSetExpression = (node: ts.Node) => + new TranspileError( + `A '@luaTable' object's 'set()' method can only be used as a Statement, not an Expression.`, + node + ); public static ForbiddenLuaTableNonDeclaration = (node: ts.Node) => new TranspileError(`Classes with the '@luaTable' decorator must be declared.`, node); @@ -37,10 +38,12 @@ export class TSTLErrors { public static ForbiddenLuaTableUseException = (description: string, node: ts.Node) => new TranspileError(`Invalid @luaTable usage: ${description}`, node); - public static HeterogeneousEnum = (node: ts.Node) => new TranspileError( - `Invalid heterogeneous enum. Enums should either specify no member values, ` + - `or specify values (of the same type) for all members.`, - node); + public static HeterogeneousEnum = (node: ts.Node) => + new TranspileError( + `Invalid heterogeneous enum. Enums should either specify no member values, ` + + `or specify values (of the same type) for all members.`, + node + ); public static InvalidDecoratorArgumentNumber = (name: string, got: number, expected: number, node: ts.Node) => new TranspileError(`${name} expects ${expected} argument(s) but got ${got}.`, node); @@ -66,8 +69,7 @@ export class TSTLErrors { public static InvalidInstanceOfExtension = (node: ts.Node) => new TranspileError(`Cannot use instanceof on classes with decorator '@extension' or '@metaExtension'.`, node); - public static InvalidJsonFileContent = (node: ts.Node) => - new TranspileError("Invalid JSON file content", node); + public static InvalidJsonFileContent = (node: ts.Node) => new TranspileError("Invalid JSON file content", node); public static InvalidPropertyCall = (node: ts.Node) => new TranspileError(`Tried to transpile a non-property call as property call.`, node); @@ -93,14 +95,12 @@ export class TSTLErrors { public static MissingMetaExtension = (node: ts.Node) => new TranspileError(`@metaExtension requires the extension of the metatable class.`, node); - public static MissingSourceFile = () => - new Error("Expected transformer.sourceFile to be set, but it isn't."); + public static MissingSourceFile = () => new Error("Expected transformer.sourceFile to be set, but it isn't."); public static UndefinedFunctionDefinition = (functionSymbolId: number) => new Error(`Function definition for function symbol ${functionSymbolId} is undefined.`); - public static UndefinedScope = () => - new Error("Expected to pop a scope, but found undefined."); + public static UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); public static UndefinedTypeNode = (node: ts.Node) => new TranspileError("Failed to resolve required type node.", node); @@ -111,8 +111,7 @@ export class TSTLErrors { public static UnsupportedDefaultExport = (node: ts.Node) => new TranspileError(`Default exports are not supported.`, node); - public static UnsupportedImportType = (node: ts.Node) => - new TranspileError(`Unsupported import type.`, node); + public static UnsupportedImportType = (node: ts.Node) => new TranspileError(`Unsupported import type.`, node); public static UnsupportedKind = (description: string, kind: ts.SyntaxKind, node: ts.Node) => new TranspileError(`Unsupported ${description} kind: ${ts.SyntaxKind[kind]}`, node); @@ -130,13 +129,15 @@ export class TSTLErrors { if (name) { return new TranspileError( `Unable to convert function with a 'this' parameter to function "${name}" with no 'this'. ` + - `To fix, wrap in an arrow function, or declare with 'this: void'.`, - node); + `To fix, wrap in an arrow function, or declare with 'this: void'.`, + node + ); } else { return new TranspileError( `Unable to convert function with a 'this' parameter to function with no 'this'. ` + - `To fix, wrap in an arrow function, or declare with 'this: void'.`, - node); + `To fix, wrap in an arrow function, or declare with 'this: void'.`, + node + ); } }; @@ -144,13 +145,15 @@ export class TSTLErrors { if (name) { return new TranspileError( `Unable to convert function with no 'this' parameter to function "${name}" with 'this'. ` + - `To fix, wrap in an arrow function or declare with 'this: any'.`, - node); + `To fix, wrap in an arrow function or declare with 'this: any'.`, + node + ); } else { return new TranspileError( `Unable to convert function with no 'this' parameter to function with 'this'. ` + - `To fix, wrap in an arrow function or declare with 'this: any'.`, - node); + `To fix, wrap in an arrow function or declare with 'this: any'.`, + node + ); } }; @@ -158,13 +161,15 @@ export class TSTLErrors { if (name) { return new TranspileError( `Unsupported assignment of function with different overloaded types for 'this' to "${name}". ` + - `Overloads should all have the same type for 'this'.`, - node); + `Overloads should all have the same type for 'this'.`, + node + ); } else { return new TranspileError( `Unsupported assignment of function with different overloaded types for 'this'. ` + - `Overloads should all have the same type for 'this'.`, - node); + `Overloads should all have the same type for 'this'.`, + node + ); } }; @@ -173,20 +178,18 @@ export class TSTLErrors { "Unsupported use of lua iterator with TupleReturn decorator in for...of statement. " + "You must use a destructuring statement to catch results from a lua iterator with " + "the TupleReturn decorator.", - node); + node + ); }; public static UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => { - return new TranspileError( - `${reason}. ` + - `TypeScript path: ${path}.`, - node); + return new TranspileError(`${reason}. ` + `TypeScript path: ${path}.`, node); }; public static ReferencedBeforeDeclaration = (node: ts.Identifier) => { return new TranspileError( `Identifier "${node.text}" was referenced before it was declared. The declaration ` + - "must be moved before the identifier's use, or hoisting must be enabled.", + "must be moved before the identifier's use, or hoisting must be enabled.", node ); }; diff --git a/src/Transpile.ts b/src/Transpile.ts index a8df4c38e..cefebf463 100644 --- a/src/Transpile.ts +++ b/src/Transpile.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import { CompilerOptions } from "./CompilerOptions"; import { transpileError } from "./diagnostics"; -import { Block } from './LuaAST'; +import { Block } from "./LuaAST"; import { LuaPrinter } from "./LuaPrinter"; import { LuaTransformer } from "./LuaTransformer"; import { TranspileError } from "./TranspileError"; @@ -12,10 +12,7 @@ function getCustomTransformers( onSourceFile: (sourceFile: ts.SourceFile) => void ): ts.CustomTransformers { // TODO: https://github.com/Microsoft/TypeScript/issues/28310 - const forEachSourceFile = ( - node: ts.SourceFile, - callback: (sourceFile: ts.SourceFile) => ts.SourceFile - ) => + const forEachSourceFile = (node: ts.SourceFile, callback: (sourceFile: ts.SourceFile) => ts.SourceFile) => ts.isBundle(node) ? ((ts.updateBundle(node, node.sourceFiles.map(callback)) as unknown) as ts.SourceFile) : callback(node); @@ -28,11 +25,7 @@ function getCustomTransformers( return { afterDeclarations: customTransformers.afterDeclarations, - before: [ - ...(customTransformers.before || []), - ...(customTransformers.after || []), - luaTransformer, - ], + before: [...(customTransformers.before || []), ...(customTransformers.after || []), luaTransformer], }; } @@ -82,10 +75,7 @@ export function transpile({ }; if (options.noEmitOnError) { - const preEmitDiagnostics = [ - ...program.getOptionsDiagnostics(), - ...program.getGlobalDiagnostics(), - ]; + const preEmitDiagnostics = [...program.getOptionsDiagnostics(), ...program.getGlobalDiagnostics()]; if (targetSourceFiles) { for (const sourceFile of targetSourceFiles) { @@ -110,11 +100,7 @@ export function transpile({ try { const [luaAst, lualibFeatureSet] = transformer.transformSourceFile(sourceFile); if (!options.noEmit && !options.emitDeclarationOnly) { - const [lua, sourceMap] = printer.print( - luaAst, - lualibFeatureSet, - sourceFile.fileName - ); + const [lua, sourceMap] = printer.print(luaAst, lualibFeatureSet, sourceFile.fileName); updateTranspiledFile(sourceFile.fileName, { luaAst, lua, sourceMap }); } } catch (err) { @@ -157,15 +143,11 @@ export function transpile({ if (isEmittableJsonFile(file)) { processSourceFile(file); } else { - diagnostics.push( - ...program.emit(file, writeFile, undefined, false, transformers).diagnostics - ); + diagnostics.push(...program.emit(file, writeFile, undefined, false, transformers).diagnostics); } } } else { - diagnostics.push( - ...program.emit(undefined, writeFile, undefined, false, transformers).diagnostics - ); + diagnostics.push(...program.emit(undefined, writeFile, undefined, false, transformers).diagnostics); // JSON files don't get through transformers and aren't written when outDir is the same as rootDir program diff --git a/src/TranspileError.ts b/src/TranspileError.ts index dc64f3da6..baeded940 100644 --- a/src/TranspileError.ts +++ b/src/TranspileError.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; export class TranspileError extends Error { - public name = 'TranspileError'; + public name = "TranspileError"; constructor(message: string, public node: ts.Node) { super(message); } diff --git a/src/diagnostics.ts b/src/diagnostics.ts index ddc8611c4..eb96ecb79 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -35,10 +35,9 @@ export const watchErrorSummary = (errorCount: number): ts.Diagnostic => ({ : `Found ${errorCount} errors. Watching for file changes.`, }); -const createCommandLineError = ( - code: number, - getMessage: (...args: Args) => string -) => (...args: Args): ts.Diagnostic => ({ +const createCommandLineError = (code: number, getMessage: (...args: Args) => string) => ( + ...args: Args +): ts.Diagnostic => ({ file: undefined, start: undefined, length: undefined, diff --git a/src/index.ts b/src/index.ts index 76cacd36a..4da0e6639 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,10 +26,7 @@ export interface TranspileFilesResult { emitResult: OutputFile[]; } -export function transpileFiles( - rootNames: string[], - options: CompilerOptions = {} -): TranspileFilesResult { +export function transpileFiles(rootNames: string[], options: CompilerOptions = {}): TranspileFilesResult { const program = ts.createProgram(rootNames, options); const { transpiledFiles, diagnostics: transpileDiagnostics } = transpile({ program }); const emitResult = emitTranspiledFiles(program.getCompilerOptions(), transpiledFiles); @@ -42,10 +39,7 @@ export function transpileFiles( return { diagnostics: [...diagnostics], emitResult }; } -export function transpileProject( - configFileName: string, - optionsToExtend?: CompilerOptions -): TranspileFilesResult { +export function transpileProject(configFileName: string, optionsToExtend?: CompilerOptions): TranspileFilesResult { const parseResult = parseConfigFileWithSystem(configFileName, optionsToExtend); if (parseResult.errors.length > 0) { return { diagnostics: parseResult.errors, emitResult: [] }; @@ -57,10 +51,7 @@ export function transpileProject( const libCache: { [key: string]: ts.SourceFile } = {}; /** @internal */ -export function createVirtualProgram( - input: Record, - options: CompilerOptions = {} -): ts.Program { +export function createVirtualProgram(input: Record, options: CompilerOptions = {}): ts.Program { const compilerHost: ts.CompilerHost = { fileExists: () => true, getCanonicalFileName: fileName => fileName, @@ -73,12 +64,7 @@ export function createVirtualProgram( getSourceFile: filename => { if (filename in input) { - return ts.createSourceFile( - filename, - input[filename], - ts.ScriptTarget.Latest, - false - ); + return ts.createSourceFile(filename, input[filename], ts.ScriptTarget.Latest, false); } if (filename.startsWith("lib.")) { @@ -87,12 +73,7 @@ export function createVirtualProgram( const filePath = path.join(typeScriptDir, filename); const content = fs.readFileSync(filePath, "utf8"); - libCache[filename] = ts.createSourceFile( - filename, - content, - ts.ScriptTarget.Latest, - false - ); + libCache[filename] = ts.createSourceFile(filename, content, ts.ScriptTarget.Latest, false); return libCache[filename]; } @@ -102,16 +83,10 @@ export function createVirtualProgram( return ts.createProgram(Object.keys(input), options, compilerHost); } -export function transpileVirtualProject( - files: Record, - options: CompilerOptions = {} -): TranspileResult { +export function transpileVirtualProject(files: Record, options: CompilerOptions = {}): TranspileResult { const program = createVirtualProgram(files, options); const result = transpile({ program }); - const diagnostics = ts.sortAndDeduplicateDiagnostics([ - ...ts.getPreEmitDiagnostics(program), - ...result.diagnostics, - ]); + const diagnostics = ts.sortAndDeduplicateDiagnostics([...ts.getPreEmitDiagnostics(program), ...result.diagnostics]); return { ...result, diagnostics: [...diagnostics] }; } @@ -121,10 +96,7 @@ export interface TranspileStringResult { file?: TranspiledFile; } -export function transpileString( - main: string, - options: CompilerOptions = {} -): TranspileStringResult { +export function transpileString(main: string, options: CompilerOptions = {}): TranspileStringResult { const { diagnostics, transpiledFiles } = transpileVirtualProject({ "main.ts": main }, options); return { diagnostics, file: transpiledFiles.find(({ fileName }) => fileName === "main.ts") }; } diff --git a/src/lualib/ArrayConcat.ts b/src/lualib/ArrayConcat.ts index ee34e427b..a133bb97a 100644 --- a/src/lualib/ArrayConcat.ts +++ b/src/lualib/ArrayConcat.ts @@ -1,19 +1,19 @@ function __TS__ArrayConcat(this: void, arr1: any[], ...args: any[]): any[] { - const out: any[] = []; - for (const val of arr1) { - out[out.length] = val; - } - for (const arg of args) { - // Hack because we don't have an isArray function - if (pcall(() => (arg as any[]).length) && type(arg) !== "string") { - const argAsArray = (arg as any[]); - for (const val of argAsArray) { - out[out.length] = val; + const out: any[] = []; + for (const val of arr1) { + out[out.length] = val; + } + for (const arg of args) { + // Hack because we don't have an isArray function + if (pcall(() => (arg as any[]).length) && type(arg) !== "string") { + const argAsArray = arg as any[]; + for (const val of argAsArray) { + out[out.length] = val; + } + } else { + out[out.length] = arg; } - } else { - out[out.length] = arg; } - } - return out; + return out; } diff --git a/src/lualib/ArrayEvery.ts b/src/lualib/ArrayEvery.ts index cc08c2fab..011dd9abe 100644 --- a/src/lualib/ArrayEvery.ts +++ b/src/lualib/ArrayEvery.ts @@ -1,6 +1,8 @@ -function __TS__ArrayEvery(this: void, arr: T[], callbackfn: (value: T, index?: number, array?: any[]) => boolean) - : boolean -{ +function __TS__ArrayEvery( + this: void, + arr: T[], + callbackfn: (value: T, index?: number, array?: any[]) => boolean +): boolean { for (let i = 0; i < arr.length; i++) { if (!callbackfn(arr[i], i, arr)) { return false; diff --git a/src/lualib/ArrayFilter.ts b/src/lualib/ArrayFilter.ts index 2a64a7389..3d88ddffa 100644 --- a/src/lualib/ArrayFilter.ts +++ b/src/lualib/ArrayFilter.ts @@ -1,6 +1,8 @@ -function __TS__ArrayFilter(this: void, arr: T[], callbackfn: (value: T, index?: number, array?: any[]) => boolean) - : T[] -{ +function __TS__ArrayFilter( + this: void, + arr: T[], + callbackfn: (value: T, index?: number, array?: any[]) => boolean +): T[] { const result: T[] = []; for (let i = 0; i < arr.length; i++) { if (callbackfn(arr[i], i, arr)) { diff --git a/src/lualib/ArrayForEach.ts b/src/lualib/ArrayForEach.ts index 6f6c931f7..96ac4a806 100644 --- a/src/lualib/ArrayForEach.ts +++ b/src/lualib/ArrayForEach.ts @@ -1,6 +1,8 @@ -function __TS__ArrayForEach(this: void, arr: T[], callbackFn: (value: T, index?: number, array?: any[]) => any) - : void -{ +function __TS__ArrayForEach( + this: void, + arr: T[], + callbackFn: (value: T, index?: number, array?: any[]) => any +): void { for (let i = 0; i < arr.length; i++) { callbackFn(arr[i], i, arr); } diff --git a/src/lualib/ArraySetLength.ts b/src/lualib/ArraySetLength.ts index 2d6b0b87f..10132ff3e 100644 --- a/src/lualib/ArraySetLength.ts +++ b/src/lualib/ArraySetLength.ts @@ -1,9 +1,11 @@ function __TS__ArraySetLength(this: void, arr: T[], length: number): number { - if (length < 0 - || length !== length // NaN - || length === Infinity // Infinity - || Math.floor(length) !== length) // non-integer - { + if ( + length < 0 || + length !== length || // NaN + length === Infinity || // Infinity + Math.floor(length) !== length + ) { + // non-integer // tslint:disable-next-line:no-string-throw throw `invalid array length: ${length}`; } diff --git a/src/lualib/ArraySome.ts b/src/lualib/ArraySome.ts index 293e60c60..9122b1bbc 100644 --- a/src/lualib/ArraySome.ts +++ b/src/lualib/ArraySome.ts @@ -1,6 +1,8 @@ -function __TS__ArraySome(this: void, arr: T[], callbackfn: (value: T, index?: number, array?: any[]) => boolean) - : boolean -{ +function __TS__ArraySome( + this: void, + arr: T[], + callbackfn: (value: T, index?: number, array?: any[]) => boolean +): boolean { for (let i = 0; i < arr.length; i++) { if (callbackfn(arr[i], i, arr)) { return true; diff --git a/src/lualib/ArraySplice.ts b/src/lualib/ArraySplice.ts index a1e4e29c4..5e92837b1 100644 --- a/src/lualib/ArraySplice.ts +++ b/src/lualib/ArraySplice.ts @@ -1,10 +1,9 @@ function __TS__ArraySplice(this: void, list: T[], start: number, deleteCount: number, ...items: T[]): T[] { - const len = list.length; let actualStart; - if (start < 0) { + if (start < 0) { actualStart = Math.max(len + start, 0); } else { actualStart = Math.min(start, len); @@ -18,7 +17,7 @@ function __TS__ArraySplice(this: void, list: T[], start: number, deleteCount: actualDeleteCount = 0; } else if (!deleteCount) { actualDeleteCount = len - actualStart; - } else { + } else { actualDeleteCount = Math.min(Math.max(deleteCount, 0), len - actualStart); } @@ -47,7 +46,6 @@ function __TS__ArraySplice(this: void, list: T[], start: number, deleteCount: list[k - 1] = undefined; } } else if (itemCount > actualDeleteCount) { - for (let k = len - actualDeleteCount; k > actualStart; k--) { const from = k + actualDeleteCount - 1; const to = k + itemCount - 1; diff --git a/src/lualib/ArrayUnshift.ts b/src/lualib/ArrayUnshift.ts index f12d6e913..95dc15b8f 100644 --- a/src/lualib/ArrayUnshift.ts +++ b/src/lualib/ArrayUnshift.ts @@ -1,4 +1,4 @@ -function __TS__ArrayUnshift(this: void, arr: T[], ...items: T[]): number { +function __TS__ArrayUnshift(this: void, arr: T[], ...items: T[]): number { for (let i = items.length - 1; i >= 0; --i) { table.insert(arr, 1, items[i]); } diff --git a/src/lualib/ClassNewIndex.ts b/src/lualib/ClassNewIndex.ts index 6447f9b8f..99205093c 100644 --- a/src/lualib/ClassNewIndex.ts +++ b/src/lualib/ClassNewIndex.ts @@ -11,8 +11,7 @@ function __TS__ClassNewIndex(this: void, classTable: LuaClass, key: any, val: an } tbl = rawget(tbl, "____super"); - } - while (tbl); + } while (tbl); rawset(classTable, key, val); } diff --git a/src/lualib/FunctionApply.ts b/src/lualib/FunctionApply.ts index 896e75978..294efdda9 100644 --- a/src/lualib/FunctionApply.ts +++ b/src/lualib/FunctionApply.ts @@ -1,9 +1,4 @@ -function __TS__FunctionApply( - this: void, - fn: (this: void, ...args: any[]) => any, - thisArg: any, - args?: any[] -): any { +function __TS__FunctionApply(this: void, fn: (this: void, ...args: any[]) => any, thisArg: any, args?: any[]): any { if (args) { return fn(thisArg, (unpack || table.unpack)(args)); } else { diff --git a/src/lualib/FunctionCall.ts b/src/lualib/FunctionCall.ts index 525086b58..e9b50fbbe 100644 --- a/src/lualib/FunctionCall.ts +++ b/src/lualib/FunctionCall.ts @@ -1,8 +1,3 @@ -function __TS__FunctionCall( - this: void, - fn: (this: void, ...args: any[]) => any, - thisArg: any, - ...args: any[] -): any { +function __TS__FunctionCall(this: void, fn: (this: void, ...args: any[]) => any, thisArg: any, ...args: any[]): any { return fn(thisArg, (unpack || table.unpack)(args)); } diff --git a/src/lualib/NewIndex.ts b/src/lualib/NewIndex.ts index 1c912fa6f..da0d4d12a 100644 --- a/src/lualib/NewIndex.ts +++ b/src/lualib/NewIndex.ts @@ -1,6 +1,4 @@ -function __TS__NewIndex(this: void, classProto: LuaObject) - : (this: void, tbl: LuaObject, key: any, val: any) => void -{ +function __TS__NewIndex(this: void, classProto: LuaObject): (this: void, tbl: LuaObject, key: any, val: any) => void { return (tbl, key, val) => { let proto = classProto; while (true) { diff --git a/src/lualib/Number.ts b/src/lualib/Number.ts index c333c1ed1..0b19a1600 100644 --- a/src/lualib/Number.ts +++ b/src/lualib/Number.ts @@ -8,7 +8,7 @@ function __TS__Number(this: void, value: unknown): number { if (value === "Infinity") return Infinity; if (value === "-Infinity") return -Infinity; - const [stringWithoutSpaces] = string.gsub(value as string, '%s', ''); + const [stringWithoutSpaces] = string.gsub(value as string, "%s", ""); if (stringWithoutSpaces === "") return 0; return NaN; diff --git a/src/lualib/NumberIsFinite.ts b/src/lualib/NumberIsFinite.ts index 9338f2e34..98df30790 100644 --- a/src/lualib/NumberIsFinite.ts +++ b/src/lualib/NumberIsFinite.ts @@ -1,5 +1,3 @@ function __TS__NumberIsFinite(this: void, value: unknown): boolean { - return ( - typeof value === "number" && value === value && value !== Infinity && value !== -Infinity - ); + return typeof value === "number" && value === value && value !== Infinity && value !== -Infinity; } diff --git a/src/lualib/SourceMapTraceBack.ts b/src/lualib/SourceMapTraceBack.ts index 827ce7874..4aed661cc 100644 --- a/src/lualib/SourceMapTraceBack.ts +++ b/src/lualib/SourceMapTraceBack.ts @@ -1,6 +1,6 @@ // TODO: In the future, change this to __TS__RegisterFileInfo and provide tstl interface to // get some metadata about transpilation. -function __TS__SourceMapTraceBack(this: void, fileName: string, sourceMap: {[line: number]: number}): void { +function __TS__SourceMapTraceBack(this: void, fileName: string, sourceMap: { [line: number]: number }): void { _G["__TS__sourcemap"] = _G["__TS__sourcemap"] || {}; _G["__TS__sourcemap"][fileName] = sourceMap; @@ -8,16 +8,12 @@ function __TS__SourceMapTraceBack(this: void, fileName: string, sourceMap: {[lin _G.__TS__originalTraceback = debug.traceback; debug.traceback = (thread, message, level) => { const trace = _G["__TS__originalTraceback"](thread, message, level); - const [result] = string.gsub( - trace, - "(%S+).lua:(%d+)", - (file, line) => { - if (_G["__TS__sourcemap"][file + ".lua"] && _G["__TS__sourcemap"][file + ".lua"][line]) { - return `${file}.ts:${_G["__TS__sourcemap"][file + ".lua"][line]}`; - } - return `${file}.lua:${line}`; + const [result] = string.gsub(trace, "(%S+).lua:(%d+)", (file, line) => { + if (_G["__TS__sourcemap"][file + ".lua"] && _G["__TS__sourcemap"][file + ".lua"][line]) { + return `${file}.ts:${_G["__TS__sourcemap"][file + ".lua"][line]}`; } - ); + return `${file}.lua:${line}`; + }); return result; }; diff --git a/src/lualib/StringConcat.ts b/src/lualib/StringConcat.ts index ce3f6dd6e..e18a2e890 100644 --- a/src/lualib/StringConcat.ts +++ b/src/lualib/StringConcat.ts @@ -1,7 +1,7 @@ function __TS__StringConcat(this: void, str1: string, ...args: string[]): string { - let out = str1; - for (const arg of args) { - out = out + arg; - } - return out; + let out = str1; + for (const arg of args) { + out = out + arg; + } + return out; } diff --git a/src/lualib/SymbolRegistry.ts b/src/lualib/SymbolRegistry.ts index c1fa21df5..93b19e9b7 100644 --- a/src/lualib/SymbolRegistry.ts +++ b/src/lualib/SymbolRegistry.ts @@ -2,7 +2,7 @@ const ____symbolRegistry: Record = {}; function __TS__SymbolRegistryFor(this: void, key: string): symbol { - if (!____symbolRegistry[key]) { + if (!____symbolRegistry[key]) { ____symbolRegistry[key] = __TS__Symbol(key); } diff --git a/src/lualib/WeakMap.ts b/src/lualib/WeakMap.ts index e3b08543d..cf93e3421 100644 --- a/src/lualib/WeakMap.ts +++ b/src/lualib/WeakMap.ts @@ -2,7 +2,7 @@ WeakMap = class WeakMap { public static [Symbol.species] = WeakMap; public [Symbol.toStringTag] = "WeakMap"; - // Type of key is actually K + // Type of key is actually K private items: { [key: string]: V } = {}; constructor(entries?: Iterable | Array) { diff --git a/src/tstl.ts b/src/tstl.ts index 7a21449aa..4f3b974f5 100644 --- a/src/tstl.ts +++ b/src/tstl.ts @@ -46,9 +46,7 @@ function locateConfigFile(commandLine: tstl.ParsedCommandLine): string | undefin if (ts.sys.fileExists(configFileName)) { return configFileName; } else { - reportDiagnostic( - cliDiagnostics.cannotFindATsconfigJsonAtTheSpecifiedDirectory(project) - ); + reportDiagnostic(cliDiagnostics.cannotFindATsconfigJsonAtTheSpecifiedDirectory(project)); ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } } else { @@ -97,10 +95,7 @@ function executeCommandLine(args: string[]): void { const configFileName = locateConfigFile(commandLine); const commandLineOptions = commandLine.options; if (configFileName) { - const configParseResult = CommandLineParser.parseConfigFileWithSystem( - configFileName, - commandLineOptions - ); + const configParseResult = CommandLineParser.parseConfigFileWithSystem(configFileName, commandLineOptions); updateReportDiagnostic(configParseResult.options); if (configParseResult.options.watch) { @@ -118,11 +113,7 @@ function executeCommandLine(args: string[]): void { if (commandLineOptions.watch) { createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions); } else { - performCompilation( - commandLine.fileNames, - commandLine.projectReferences, - commandLineOptions - ); + performCompilation(commandLine.fileNames, commandLine.projectReferences, commandLineOptions); } } } @@ -166,10 +157,7 @@ function performCompilation( return ts.sys.exit(exitCode); } -function createWatchOfConfigFile( - configFileName: string, - optionsToExtend: tstl.CompilerOptions -): void { +function createWatchOfConfigFile(configFileName: string, optionsToExtend: tstl.CompilerOptions): void { const watchCompilerHost = ts.createWatchCompilerHost( configFileName, optionsToExtend, @@ -183,10 +171,7 @@ function createWatchOfConfigFile( ts.createWatchProgram(watchCompilerHost); } -function createWatchOfFilesAndCompilerOptions( - rootFiles: string[], - options: tstl.CompilerOptions -): void { +function createWatchOfFilesAndCompilerOptions(rootFiles: string[], options: tstl.CompilerOptions): void { const watchCompilerHost = ts.createWatchCompilerHost( rootFiles, options, @@ -249,10 +234,7 @@ function updateWatchCompilationHost( } } - const { diagnostics: emitDiagnostics, transpiledFiles } = tstl.transpile({ - program, - sourceFiles, - }); + const { diagnostics: emitDiagnostics, transpiledFiles } = tstl.transpile({ program, sourceFiles }); const emitResult = tstl.emitTranspiledFiles(options, transpiledFiles); emitResult.forEach(({ name, text }) => ts.sys.writeFile(name, text)); @@ -272,11 +254,7 @@ function updateWatchCompilationHost( // do a full recompile after an error fullRecompile = errors.length > 0; - host.onWatchStatusChange!( - cliDiagnostics.watchErrorSummary(errors.length), - host.getNewLine(), - options - ); + host.onWatchStatusChange!(cliDiagnostics.watchErrorSummary(errors.length), host.getNewLine(), options); }; } diff --git a/test/setup.ts b/test/setup.ts index e1c041d8c..dff900cb9 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -47,9 +47,7 @@ expect.extend({ return ( matcherHint + "\n\n" + - (this.isNot - ? diagnosticMessages - : `Received: ${this.utils.printReceived(diagnostics)}\n`) + (this.isNot ? diagnosticMessages : `Received: ${this.utils.printReceived(diagnostics)}\n`) ); }, }; diff --git a/test/transpile/directories.spec.ts b/test/transpile/directories.spec.ts index 877e58f50..458c14fec 100644 --- a/test/transpile/directories.spec.ts +++ b/test/transpile/directories.spec.ts @@ -24,7 +24,7 @@ test.each([ }; const { fileNames, options } = tstl.updateParsedConfigFile( - ts.parseJsonConfigFileContent(config, ts.sys, projectPath), + ts.parseJsonConfigFileContent(config, ts.sys, projectPath) ); const { diagnostics, emittedFiles } = buildVirtualProject(fileNames, options); diff --git a/test/transpile/run.ts b/test/transpile/run.ts index 57bbc8f6b..72afa7ca2 100644 --- a/test/transpile/run.ts +++ b/test/transpile/run.ts @@ -8,17 +8,12 @@ interface BuildVirtualProjectResult { emittedFiles: string[]; } -export function buildVirtualProject( - rootNames: string[], - options: tstl.CompilerOptions, -): BuildVirtualProjectResult { +export function buildVirtualProject(rootNames: string[], options: tstl.CompilerOptions): BuildVirtualProjectResult { options.skipLibCheck = true; options.types = []; const { diagnostics, emitResult } = tstl.transpileFiles(rootNames, options); - const emittedFiles = emitResult - .map(result => path.relative(__dirname, result.name).replace(/\\/g, "/")) - .sort(); + const emittedFiles = emitResult.map(result => path.relative(__dirname, result.name).replace(/\\/g, "/")).sort(); return { diagnostics, emitResult, emittedFiles }; } diff --git a/test/tsconfig.json b/test/tsconfig.json index 34b2ee7a4..b22f71bc9 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -12,11 +12,5 @@ "noEmit": true, "module": "commonjs" }, - "exclude": [ - "translation/transformation", - "cli/errors", - "cli/watch", - "transpile/directories", - "transpile/outFile" - ] + "exclude": ["translation/transformation", "cli/errors", "cli/watch", "transpile/directories", "transpile/outFile"] } diff --git a/test/tslint.json b/test/tslint.json deleted file mode 100644 index 2796d7894..000000000 --- a/test/tslint.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "rules": { - "array-type": [true, "array-simple"], - "arrow-return-shorthand": true, - "ban": [ - true, - { "name": "parseInt", "message": "tsstyle#type-coercion" }, - { "name": "parseFloat", "message": "tsstyle#type-coercion" }, - { "name": "Array", "message": "tsstyle#array-constructor" } - ], - "ban-types": [ - true, - ["Object", "Use {} instead."], - ["String", "Use 'string' instead."], - ["Number", "Use 'number' instead."], - ["Boolean", "Use 'boolean' instead."] - ], - "class-name": true, - "curly": [true, "ignore-same-line"], - "deprecation": true, - "forin": false, - "interface-name": [true, "never-prefix"], - "jsdoc-format": true, - "label-position": true, - "max-classes-per-file": [true, 1], - "member-access": true, - "no-angle-bracket-type-assertion": true, - "no-any": false, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-switch-case": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "no-namespace": [true, "allow-declarations"], - "no-null-keyword": true, - "no-reference": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [true, "allow-declarations", "allow-named-functions"], - "prefer-const": [true, { "destructuring": "all" }], - "radix": true, - "switch-default": false, - "triple-equals": [true, "allow-null-check"], - "typedef": [true, "call-signature", "property-declaration"], - "use-isnan": true, - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-pascal-case" - ] - } -} diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 85dde6455..44d3cb3d6 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -3,7 +3,7 @@ import * as util from "../util"; test("Array access", () => { const result = util.transpileAndExecute( `const arr: Array = [3,5,1]; - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -11,7 +11,7 @@ test("Array access", () => { test("ReadonlyArray access", () => { const result = util.transpileAndExecute( `const arr: ReadonlyArray = [3,5,1]; - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -19,7 +19,7 @@ test("ReadonlyArray access", () => { test("Array literal access", () => { const result = util.transpileAndExecute( `const arr: number[] = [3,5,1]; - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -27,7 +27,7 @@ test("Array literal access", () => { test("Readonly array literal access", () => { const result = util.transpileAndExecute( `const arr: readonly number[] = [3,5,1]; - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -36,7 +36,7 @@ test("Array union access", () => { const result = util.transpileAndExecute( `function makeArray(): number[] | string[] { return [3,5,1]; } const arr = makeArray(); - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -45,7 +45,7 @@ test("Array union access with empty tuple", () => { const result = util.transpileAndExecute( `function makeArray(): number[] | [] { return [3,5,1]; } const arr = makeArray(); - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -54,7 +54,7 @@ test("Array union length", () => { const result = util.transpileAndExecute( `function makeArray(): number[] | string[] { return [3,5,1]; } const arr = makeArray(); - return arr.length;`, + return arr.length;` ); expect(result).toBe(3); }); @@ -68,7 +68,7 @@ test("Array intersection access", () => { return (t as I); } const arr = makeArray(); - return arr[1];`, + return arr[1];` ); expect(result).toBe(5); }); @@ -82,7 +82,7 @@ test("Array intersection length", () => { return (t as I); } const arr = makeArray(); - return arr.length;`, + return arr.length;` ); expect(result).toBe(3); }); @@ -107,7 +107,7 @@ test.each([ return arr.${member};`, undefined, luaHeader, - typeScriptHeader, + typeScriptHeader ); expect(result).toBe(expected); @@ -117,7 +117,7 @@ test("Array delete", () => { const result = util.transpileAndExecute( `const myarray = [1,2,3,4]; delete myarray[2]; - return \`\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;`, + return \`\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;` ); expect(result).toBe("1,2,nil,4"); @@ -127,7 +127,7 @@ test("Array delete return true", () => { const result = util.transpileAndExecute( `const myarray = [1,2,3,4]; const exists = delete myarray[2]; - return \`\${exists}:\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;`, + return \`\${exists}:\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;` ); expect(result).toBe("true:1,2,nil,4"); @@ -137,7 +137,7 @@ test("Array delete return false", () => { const result = util.transpileAndExecute( `const myarray = [1,2,3,4]; const exists = delete myarray[4]; - return \`\${exists}:\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;`, + return \`\${exists}:\${myarray[0]},\${myarray[1]},\${myarray[2]},\${myarray[3]}\`;` ); expect(result).toBe("true:1,2,3,4"); @@ -162,21 +162,20 @@ test.each([{ length: 0, result: 0 }, { length: 1, result: 1 }, { length: 7, resu return arr.length; `; expect(util.transpileAndExecute(code)).toBe(result); - }, + } ); -test.each([ - { length: 0, result: "0/0" }, - { length: 1, result: "1/1" }, - { length: 7, result: "7/3" }, -])("Array length set as expression", ({ length, result }) => { - const code = ` +test.each([{ length: 0, result: "0/0" }, { length: 1, result: "1/1" }, { length: 7, result: "7/3" }])( + "Array length set as expression", + ({ length, result }) => { + const code = ` const arr = [1, 2, 3]; const l = arr.length = ${length}; return \`\${l}/\${arr.length}\`; `; - expect(util.transpileAndExecute(code)).toBe(result); -}); + expect(util.transpileAndExecute(code)).toBe(result); + } +); test.each([ { length: -1, result: -1 }, diff --git a/test/unit/assignments/assignments.spec.ts b/test/unit/assignments/assignments.spec.ts index b6fd9350d..7eb8e5ecd 100644 --- a/test/unit/assignments/assignments.spec.ts +++ b/test/unit/assignments/assignments.spec.ts @@ -42,7 +42,7 @@ test.each(["var myvar;", "let myvar;", "const myvar = null;", "const myvar = und declaration => { const result = util.transpileAndExecute(declaration + " return myvar;"); expect(result).toBe(undefined); - }, + } ); test.each([ @@ -61,7 +61,7 @@ test.each([ test("Ellipsis binding pattern", () => { expect(() => util.transpileString("let [a,b,...c] = [1,2,3];")).toThrowExactError( - TSTLErrors.ForbiddenEllipsisDestruction(util.nodeStub), + TSTLErrors.ForbiddenEllipsisDestruction(util.nodeStub) ); }); diff --git a/test/unit/assignments/functionExpressionTypeInference.spec.ts b/test/unit/assignments/functionExpressionTypeInference.spec.ts index aa47a8c18..aefc24427 100644 --- a/test/unit/assignments/functionExpressionTypeInference.spec.ts +++ b/test/unit/assignments/functionExpressionTypeInference.spec.ts @@ -16,19 +16,18 @@ test.each(["noSelf", "noSelfInFile"])("noSelf function method argument (%p)", no expect(util.transpileAndExecute(code, undefined, undefined, header)).toBe("foo"); }); -test.each([ - "(this: void, s: string) => string", - "(this: any, s: string) => string", - "(s: string) => string", -])("Function expression type inference in binary operator (%p)", funcType => { - const header = `declare const undefinedFunc: ${funcType};`; - const code = ` +test.each(["(this: void, s: string) => string", "(this: any, s: string) => string", "(s: string) => string"])( + "Function expression type inference in binary operator (%p)", + funcType => { + const header = `declare const undefinedFunc: ${funcType};`; + const code = ` let func: ${funcType} = s => s; func = undefinedFunc || (s => s); return func("foo"); `; - expect(util.transpileAndExecute(code, undefined, undefined, header)).toBe("foo"); -}); + expect(util.transpileAndExecute(code, undefined, undefined, header)).toBe("foo"); + } +); test.each(["s => s", "(s => s)", "function(s) { return s; }", "(function(s) { return s; })"])( "Function expression type inference in class (%p)", @@ -44,7 +43,7 @@ test.each(["s => s", "(s => s)", "function(s) { return s; }", "(function(s) { re return foo.func("a") + foo.method("b") + Foo.staticFunc("c") + Foo.staticMethod("d"); `; expect(util.transpileAndExecute(code)).toBe("abcd"); - }, + } ); test.each([ @@ -85,19 +84,16 @@ test.each([ { assignTo: "let foo: Foo; foo", funcExp: "(s => s)" }, { assignTo: "let foo: Foo; foo", funcExp: "function(s) { return s; }" }, { assignTo: "let foo: Foo; foo", funcExp: "(function(s) { return s; })" }, -])( - "Function expression type inference in object literal (generic key) (%p)", - ({ assignTo, funcExp }) => { - const code = ` +])("Function expression type inference in object literal (generic key) (%p)", ({ assignTo, funcExp }) => { + const code = ` interface Foo { [f: string]: (this: void, s: string) => string; } ${assignTo} = {func: ${funcExp}}; return foo.func("foo"); `; - expect(util.transpileAndExecute(code)).toBe("foo"); - }, -); + expect(util.transpileAndExecute(code)).toBe("foo"); +}); test.each([ { @@ -218,23 +214,11 @@ test.each([ { assignTo: "const meths: Method[]", method: "meths[0]", funcExp: "s => s" }, { assignTo: "const meths: Method[]", method: "meths[0]", funcExp: "(s => s)" }, { assignTo: "const meths: Method[]", method: "meths[0]", funcExp: "function(s) { return s; }" }, - { - assignTo: "const meths: Method[]", - method: "meths[0]", - funcExp: "(function(s) { return s; })", - }, + { assignTo: "const meths: Method[]", method: "meths[0]", funcExp: "(function(s) { return s; })" }, { assignTo: "let meths: Method[]; meths", method: "meths[0]", funcExp: "s => s" }, { assignTo: "let meths: Method[]; meths", method: "meths[0]", funcExp: "(s => s)" }, - { - assignTo: "let meths: Method[]; meths", - method: "meths[0]", - funcExp: "function(s) { return s; }", - }, - { - assignTo: "let meths: Method[]; meths", - method: "meths[0]", - funcExp: "(function(s) { return s; })", - }, + { assignTo: "let meths: Method[]; meths", method: "meths[0]", funcExp: "function(s) { return s; }" }, + { assignTo: "let meths: Method[]; meths", method: "meths[0]", funcExp: "(function(s) { return s; })" }, { assignTo: "const [meth]: Method[]", method: "meth", funcExp: "s => s" }, { assignTo: "const [meth]: Method[]", method: "meth", funcExp: "(s => s)" }, { assignTo: "const [meth]: Method[]", method: "meth", funcExp: "function(s) { return s; }" }, @@ -242,11 +226,7 @@ test.each([ { assignTo: "let meth: Method; [meth]", method: "meth", funcExp: "s => s" }, { assignTo: "let meth: Method; [meth]", method: "meth", funcExp: "(s => s)" }, { assignTo: "let meth: Method; [meth]", method: "meth", funcExp: "function(s) { return s; }" }, - { - assignTo: "let meth: Method; [meth]", - method: "meth", - funcExp: "(function(s) { return s; })", - }, + { assignTo: "let meth: Method; [meth]", method: "meth", funcExp: "(function(s) { return s; })" }, ])("Function expression type inference in array (%p)", ({ assignTo, method, funcExp }) => { const code = ` interface Foo { diff --git a/test/unit/assignments/functionPermutations.ts b/test/unit/assignments/functionPermutations.ts index 45fbd52f1..cbbef188e 100644 --- a/test/unit/assignments/functionPermutations.ts +++ b/test/unit/assignments/functionPermutations.ts @@ -328,46 +328,18 @@ export const validTestFunctionCasts: TestFunctionCast[] = [ [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${selfTestFunctionType})`], [noSelfTestFunctions[0], `<${noSelfTestFunctionType}>(${noSelfTestFunctions[0].value})`], [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${noSelfTestFunctionType})`], - [ - noSelfInFileTestFunctions[0], - `<${anonTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, - ], - [ - noSelfInFileTestFunctions[0], - `(${noSelfInFileTestFunctions[0].value}) as (${anonTestFunctionType})`, - ], - [ - noSelfInFileTestFunctions[0], - `<${noSelfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, - ], - [ - noSelfInFileTestFunctions[0], - `(${noSelfInFileTestFunctions[0].value}) as (${noSelfTestFunctionType})`, - ], + [noSelfInFileTestFunctions[0], `<${anonTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`], + [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${anonTestFunctionType})`], + [noSelfInFileTestFunctions[0], `<${noSelfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`], + [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${noSelfTestFunctionType})`], ]; export const invalidTestFunctionCasts: TestFunctionCast[] = [ [noSelfTestFunctions[0], `<${anonTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], - [ - noSelfTestFunctions[0], - `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`, - false, - ], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`, false], [noSelfTestFunctions[0], `<${selfTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], - [ - noSelfTestFunctions[0], - `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`, - false, - ], - [ - noSelfInFileTestFunctions[0], - `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, - false, - ], - [ - noSelfInFileTestFunctions[0], - `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`, - false, - ], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`, false], + [noSelfInFileTestFunctions[0], `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, false], + [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`, false], [selfTestFunctions[0], `<${noSelfTestFunctionType}>(${selfTestFunctions[0].value})`, true], [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${noSelfTestFunctionType})`, true], ]; @@ -388,24 +360,14 @@ export const validTestFunctionAssignments: TestFunctionAssignment[] = [ ...anonTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), - ...noSelfTestFunctionExpressions.map( - (f): TestFunctionAssignment => [f, noSelfTestFunctionType], - ), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ]; export const invalidTestFunctionAssignments: TestFunctionAssignment[] = [ ...selfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), - ...noSelfInFileTestFunctions.map( - (f): TestFunctionAssignment => [f, selfTestFunctionType, true], - ), - ...selfTestFunctionExpressions.map( - (f): TestFunctionAssignment => [f, noSelfTestFunctionType, false], - ), - ...noSelfTestFunctionExpressions.map( - (f): TestFunctionAssignment => [f, anonTestFunctionType, true], - ), - ...noSelfTestFunctionExpressions.map( - (f): TestFunctionAssignment => [f, selfTestFunctionType, true], - ), + ...noSelfInFileTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), + ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), ]; diff --git a/test/unit/assignments/invalidFunctionAssignments.spec.ts b/test/unit/assignments/invalidFunctionAssignments.spec.ts index 3c8108c18..ea3de0d88 100644 --- a/test/unit/assignments/invalidFunctionAssignments.spec.ts +++ b/test/unit/assignments/invalidFunctionAssignments.spec.ts @@ -13,7 +13,7 @@ test.each(invalidTestFunctionAssignments)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionAssignments)( @@ -28,7 +28,7 @@ test.each(invalidTestFunctionAssignments)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionCasts)( @@ -43,7 +43,7 @@ test.each(invalidTestFunctionCasts)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionAssignments)( @@ -58,7 +58,7 @@ test.each(invalidTestFunctionAssignments)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub, "fn") : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test("Invalid lua lib function argument", () => { @@ -83,7 +83,7 @@ test.each(invalidTestFunctionCasts)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub, "fn") : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionAssignments)( @@ -98,7 +98,7 @@ test.each(invalidTestFunctionAssignments)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub, "fn") : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionAssignments)( @@ -114,7 +114,7 @@ test.each(invalidTestFunctionAssignments)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test.each(invalidTestFunctionCasts)( @@ -130,7 +130,7 @@ test.each(invalidTestFunctionCasts)( ? TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) : TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub); expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - }, + } ); test("Interface method assignment", () => { @@ -158,7 +158,7 @@ test("Invalid function tuple assignment", () => { let [i, f]: [number, Func] = getTuple(); `; expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub), + TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub) ); }); @@ -170,7 +170,7 @@ test("Invalid method tuple assignment", () => { let [i, f]: [number, Meth] = getTuple(); `; expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub), + TSTLErrors.UnsupportedSelfFunctionConversion(util.nodeStub) ); }); @@ -182,7 +182,7 @@ test("Invalid interface method assignment", () => { const b: B = a; `; expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"), + TSTLErrors.UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn") ); }); @@ -200,7 +200,5 @@ test.each([ declare const o: O; let f: ${assignType} = o; `; - expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.UnsupportedOverloadAssignment(util.nodeStub), - ); + expect(() => util.transpileString(code)).toThrowExactError(TSTLErrors.UnsupportedOverloadAssignment(util.nodeStub)); }); diff --git a/test/unit/assignments/validFunctionAssignments.spec.ts b/test/unit/assignments/validFunctionAssignments.spec.ts index 86b4ce230..be553b956 100644 --- a/test/unit/assignments/validFunctionAssignments.spec.ts +++ b/test/unit/assignments/validFunctionAssignments.spec.ts @@ -14,57 +14,37 @@ import { TestFunction, } from "./functionPermutations"; -test.each(validTestFunctionAssignments)( - "Valid function variable declaration (%p)", - (testFunction, functionType) => { - const code = `const fn: ${functionType} = ${testFunction.value}; +test.each(validTestFunctionAssignments)("Valid function variable declaration (%p)", (testFunction, functionType) => { + const code = `const fn: ${functionType} = ${testFunction.value}; return fn("foobar");`; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); -test.each(validTestFunctionAssignments)( - "Valid function assignment (%p)", - (testFunction, functionType) => { - const code = `let fn: ${functionType}; +test.each(validTestFunctionAssignments)("Valid function assignment (%p)", (testFunction, functionType) => { + const code = `let fn: ${functionType}; fn = ${testFunction.value}; return fn("foobar");`; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); -test.each(validTestFunctionCasts)( - "Valid function assignment with cast (%p)", - (testFunction, castedFunction) => { - const code = ` +test.each(validTestFunctionCasts)("Valid function assignment with cast (%p)", (testFunction, castedFunction) => { + const code = ` let fn: typeof ${testFunction.value}; fn = ${castedFunction}; return fn("foobar"); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); -test.each(validTestFunctionAssignments)( - "Valid function argument (%p)", - (testFunction, functionType) => { - const code = ` +test.each(validTestFunctionAssignments)("Valid function argument (%p)", (testFunction, functionType) => { + const code = ` function takesFunction(fn: ${functionType}) { return fn("foobar"); } return takesFunction(${testFunction.value}); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); test("Valid lua lib function argument", () => { const code = `let result = ""; @@ -75,20 +55,15 @@ test("Valid lua lib function argument", () => { expect(util.transpileAndExecute(code)).toBe("foobar"); }); -test.each(validTestFunctionCasts)( - "Valid function argument with cast (%p)", - (testFunction, castedFunction) => { - const code = ` +test.each(validTestFunctionCasts)("Valid function argument with cast (%p)", (testFunction, castedFunction) => { + const code = ` function takesFunction(fn: typeof ${testFunction.value}) { return fn("foobar"); } return takesFunction(${castedFunction}); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); test.each([ // TODO: Fix function expression inference with generic types. The following should work, but doesn't: @@ -100,9 +75,7 @@ test.each([ ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), - ...noSelfTestFunctionExpressions.map( - (f): TestFunctionAssignment => [f, noSelfTestFunctionType], - ), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ])("Valid function generic argument (%p)", (testFunction, functionType) => { const code = ` function takesFunction(fn: T) { @@ -110,9 +83,7 @@ test.each([ } return takesFunction(${testFunction.value}); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); }); test.each([ @@ -126,40 +97,28 @@ test.each([ } return takesFunction(${testFunction.value}, ${args.join(", ")}); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); }); -test.each(validTestFunctionAssignments)( - "Valid function return (%p)", - (testFunction, functionType) => { - const code = ` +test.each(validTestFunctionAssignments)("Valid function return (%p)", (testFunction, functionType) => { + const code = ` function returnsFunction(): ${functionType} { return ${testFunction.value}; } const fn = returnsFunction(); return fn("foobar"); `; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); -test.each(validTestFunctionCasts)( - "Valid function return with cast (%p)", - (testFunction, castedFunction) => { - const code = `function returnsFunction(): typeof ${testFunction.value} { +test.each(validTestFunctionCasts)("Valid function return with cast (%p)", (testFunction, castedFunction) => { + const code = `function returnsFunction(): typeof ${testFunction.value} { return ${castedFunction}; } const fn = returnsFunction(); return fn("foobar");`; - expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe( - "foobar", - ); - }, -); + expect(util.transpileAndExecute(code, undefined, undefined, testFunction.definition)).toBe("foobar"); +}); test("Interface method assignment", () => { const code = `class Foo { @@ -210,16 +169,8 @@ test("Valid interface method assignment", () => { test.each([ { assignType: "(this: any, s: string) => string", args: ["foo"], expectResult: "foobar" }, { assignType: "{(this: any, s: string): string}", args: ["foo"], expectResult: "foobar" }, - { - assignType: "(this: any, s1: string, s2: string) => string", - args: ["foo", "baz"], - expectResult: "foobaz", - }, - { - assignType: "{(this: any, s1: string, s2: string): string}", - args: ["foo", "baz"], - expectResult: "foobaz", - }, + { assignType: "(this: any, s1: string, s2: string) => string", args: ["foo", "baz"], expectResult: "foobaz" }, + { assignType: "{(this: any, s1: string, s2: string): string}", args: ["foo", "baz"], expectResult: "foobaz" }, ])("Valid function overload assignment (%p)", ({ assignType, args, expectResult }) => { const code = `interface O { (s1: string, s2: string): string; diff --git a/test/unit/bindingpatterns.spec.ts b/test/unit/bindingpatterns.spec.ts index b7ed32de5..aad38661b 100644 --- a/test/unit/bindingpatterns.spec.ts +++ b/test/unit/bindingpatterns.spec.ts @@ -9,26 +9,10 @@ const testCases = [ { bindingString: "[[y, z]]", objectString: "[[false, true]]", returnVariable: "z" }, { bindingString: "{x, y}", objectString: "{x: false, y: true}", returnVariable: "y" }, { bindingString: "{x: foo, y}", objectString: "{x: true, y: false}", returnVariable: "foo" }, - { - bindingString: "{x: foo, y: bar}", - objectString: "{x: false, y: true}", - returnVariable: "bar", - }, - { - bindingString: "{x: {x, y}, z}", - objectString: "{x: {x: true, y: false}, z: false}", - returnVariable: "x", - }, - { - bindingString: "{x: {x, y}, z}", - objectString: "{x: {x: false, y: true}, z: false}", - returnVariable: "y", - }, - { - bindingString: "{x: {x, y}, z}", - objectString: "{x: {x: false, y: false}, z: true}", - returnVariable: "z", - }, + { bindingString: "{x: foo, y: bar}", objectString: "{x: false, y: true}", returnVariable: "bar" }, + { bindingString: "{x: {x, y}, z}", objectString: "{x: {x: true, y: false}, z: false}", returnVariable: "x" }, + { bindingString: "{x: {x, y}, z}", objectString: "{x: {x: false, y: true}, z: false}", returnVariable: "y" }, + { bindingString: "{x: {x, y}, z}", objectString: "{x: {x: false, y: false}, z: true}", returnVariable: "z" }, ]; const testCasesDefault = [ @@ -38,11 +22,7 @@ const testCasesDefault = [ test.each([ { bindingString: "{x, y}, z", objectString: "{x: false, y: false}, true", returnVariable: "z" }, - { - bindingString: "{x, y}, {z}", - objectString: "{x: false, y: false}, {z: true}", - returnVariable: "z", - }, + { bindingString: "{x, y}, {z}", objectString: "{x: false, y: false}, {z: true}", returnVariable: "z" }, ...testCases, ...testCasesDefault, ])("Object bindings in functions (%p)", ({ bindingString, objectString, returnVariable }) => { @@ -63,7 +43,7 @@ test.each([...testCases, ...testCasesDefault])( return ${returnVariable}; `); expect(result).toBe(true); - }, + } ); test.each([...testCases, ...testCasesDefault])( @@ -71,10 +51,10 @@ test.each([...testCases, ...testCasesDefault])( ({ bindingString, objectString, returnVariable }) => { const result = util.transpileExecuteAndReturnExport( `export const ${bindingString} = ${objectString};`, - returnVariable, + returnVariable ); expect(result).toBe(true); - }, + } ); test.each(testCases)( @@ -88,24 +68,17 @@ test.each(testCases)( return ${returnVariable}; `); expect(result).toBe(true); - }, + } ); test.each([ { bindingString: "{x, y = true}", objectString: "{x: false, y: false}", returnVariable: "y" }, - { - bindingString: "{x, y: [z = true]}", - objectString: "{x: false, y: [false]}", - returnVariable: "z", - }, + { bindingString: "{x, y: [z = true]}", objectString: "{x: false, y: [false]}", returnVariable: "z" }, { bindingString: "[x = true]", objectString: "[false]", returnVariable: "x" }, -])( - "Binding patterns handle false correctly (%p)", - ({ bindingString, objectString, returnVariable }) => { - const result = util.transpileExecuteAndReturnExport( - `export const ${bindingString} = ${objectString};`, - returnVariable, - ); - expect(result).toBe(false); - }, -); +])("Binding patterns handle false correctly (%p)", ({ bindingString, objectString, returnVariable }) => { + const result = util.transpileExecuteAndReturnExport( + `export const ${bindingString} = ${objectString};`, + returnVariable + ); + expect(result).toBe(false); +}); diff --git a/test/unit/class.spec.ts b/test/unit/class.spec.ts index 42b575064..c4d2943bb 100644 --- a/test/unit/class.spec.ts +++ b/test/unit/class.spec.ts @@ -7,7 +7,7 @@ test("ClassFieldInitializer", () => { `class a { field: number = 4; } - return new a().field;`, + return new a().field;` ); expect(result).toBe(4); @@ -18,7 +18,7 @@ test("ClassNumericLiteralFieldInitializer", () => { `class a { 1: number = 4; } - return new a()[1];`, + return new a()[1];` ); expect(result).toBe(4); @@ -29,7 +29,7 @@ test("ClassStringLiteralFieldInitializer", () => { `class a { "field": number = 4; } - return new a()["field"];`, + return new a()["field"];` ); expect(result).toBe(4); @@ -41,7 +41,7 @@ test("ClassComputedFieldInitializer", () => { class a { [field]: number = 4; } - return new a()[field];`, + return new a()[field];` ); expect(result).toBe(4); @@ -55,7 +55,7 @@ test("ClassConstructor", () => { this.field = n * 2; } } - return new a(4).field;`, + return new a(4).field;` ); expect(result).toBe(8); @@ -64,7 +64,7 @@ test("ClassConstructor", () => { test("ClassConstructorAssignment", () => { const result = util.transpileAndExecute( `class a { constructor(public field: number) {} } - return new a(4).field;`, + return new a(4).field;` ); expect(result).toBe(4); @@ -73,7 +73,7 @@ test("ClassConstructorAssignment", () => { test("ClassConstructorDefaultParameter", () => { const result = util.transpileAndExecute( `class a { public field: number; constructor(f: number = 3) { this.field = f; } } - return new a().field;`, + return new a().field;` ); expect(result).toBe(3); @@ -82,7 +82,7 @@ test("ClassConstructorDefaultParameter", () => { test("ClassConstructorAssignmentDefault", () => { const result = util.transpileAndExecute( `class a { constructor(public field: number = 3) { } } - return new a().field;`, + return new a().field;` ); expect(result).toBe(3); @@ -95,7 +95,7 @@ test("ClassNewNoBrackets", () => { constructor() {} } let inst = new a; - return inst.field;`, + return inst.field;` ); expect(result).toBe(4); @@ -104,7 +104,7 @@ test("ClassNewNoBrackets", () => { test("ClassStaticFields", () => { const result = util.transpileAndExecute( `class a { static field: number = 4; } - return a.field;`, + return a.field;` ); expect(result).toBe(4); @@ -113,7 +113,7 @@ test("ClassStaticFields", () => { test("ClassStaticNumericLiteralFields", () => { const result = util.transpileAndExecute( `class a { static 1: number = 4; } - return a[1];`, + return a[1];` ); expect(result).toBe(4); @@ -122,7 +122,7 @@ test("ClassStaticNumericLiteralFields", () => { test("ClassStaticStringLiteralFields", () => { const result = util.transpileAndExecute( `class a { static "field": number = 4; } - return a["field"];`, + return a["field"];` ); expect(result).toBe(4); @@ -132,7 +132,7 @@ test("ClassStaticComputedFields", () => { const result = util.transpileAndExecute( `const field: "field" = "field"; class a { static [field]: number = 4; } - return a[field];`, + return a[field];` ); expect(result).toBe(4); @@ -142,7 +142,7 @@ test("classExtends", () => { const result = util.transpileAndExecute( `class a { field: number = 4; } class b extends a {} - return new b().field;`, + return new b().field;` ); expect(result).toBe(4); @@ -157,7 +157,7 @@ test("SubclassDefaultConstructor", () => { } } class b extends a {} - return new b(10).field;`, + return new b(10).field;` ); expect(result).toBe(10); @@ -173,7 +173,7 @@ test("SubsubclassDefaultConstructor", () => { } class b extends a {} class c extends b {} - return new c(10).field;`, + return new c(10).field;` ); expect(result).toBe(10); @@ -192,7 +192,7 @@ test("SubclassConstructor", () => { super(field + 1); } } - return new b(10).field;`, + return new b(10).field;` ); expect(result).toBe(11); @@ -211,7 +211,7 @@ test("classSuper", () => { super(5); } } - return new b().field;`, + return new b().field;` ); expect(result).toBe(5); @@ -235,7 +235,7 @@ test("classSuperSuper", () => { super(5); } } - return new c().field;`, + return new c().field;` ); expect(result).toBe(10); @@ -256,7 +256,7 @@ test("classSuperSkip", () => { super(5); } } - return new c().field;`, + return new c().field;` ); expect(result).toBe(5); @@ -278,7 +278,7 @@ test("renamedClassExtends", () => { const A = Classes.Base; class B extends A { constructor(){ super(); } - };`, + };` ); expect(result).toBe(3); @@ -292,7 +292,7 @@ test("ClassMethodCall", () => { } } let inst = new a(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -306,7 +306,7 @@ test("ClassNumericLiteralMethodCall", () => { } } let inst = new a(); - return inst[1]();`, + return inst[1]();` ); expect(result).toBe(4); @@ -320,7 +320,7 @@ test("ClassStringLiteralMethodCall", () => { } } let inst = new a(); - return inst["method"]();`, + return inst["method"]();` ); expect(result).toBe(4); @@ -335,7 +335,7 @@ test("ClassComputedMethodCall", () => { } } let inst = new a(); - return inst[method]();`, + return inst[method]();` ); expect(result).toBe(4); @@ -349,7 +349,7 @@ test("ClassToString", () => { } } let inst = new a(); - return inst.toString();`, + return inst.toString();` ); expect(result).toBe("instance of a"); @@ -363,7 +363,7 @@ test("HasOwnProperty true", () => { } let inst = new a(); inst["prop"] = 17; - return inst.hasOwnProperty("prop");`, + return inst.hasOwnProperty("prop");` ); expect(result).toBe(true); @@ -377,7 +377,7 @@ test("HasOwnProperty false", () => { } let inst = new a(); inst["prop"] = 17; - return inst.hasOwnProperty("test");`, + return inst.hasOwnProperty("test");` ); expect(result).toBe(false); @@ -398,7 +398,7 @@ test("CastClassMethodCall", () => { let result = {val : 0}; (inst as a).method(result); (inst as a).method(result); - return result.val;`, + return result.val;` ); expect(result).toBe(4); @@ -411,7 +411,7 @@ test("ClassPropertyFunctionThis", () => { public method: () => number = () => this.n; } let inst = new a(4); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -426,7 +426,7 @@ test("ClassInheritedMethodCall", () => { } class b extends a {} let inst = new b(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -442,7 +442,7 @@ test("ClassDoubleInheritedMethodCall", () => { class b extends a {} class c extends b {} let inst = new c(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -458,7 +458,7 @@ test("ClassInheritedMethodCall2", () => { } class c extends b {} let inst = new c(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -477,7 +477,7 @@ test("ClassMethodOverride", () => { } } let inst = new b(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(4); @@ -491,7 +491,7 @@ test("methodDefaultParameters", () => { } } let inst = new a(); - return inst.method(4);`, + return inst.method(4);` ); expect(result).toBe(9); @@ -500,9 +500,9 @@ test("methodDefaultParameters", () => { test("Class without name error", () => { const transformer = util.makeTestTransformer(); - expect(() => - transformer.transformClassDeclaration({} as ts.ClassDeclaration), - ).toThrowExactError(TSTLErrors.MissingClassName(util.nodeStub)); + expect(() => transformer.transformClassDeclaration({} as ts.ClassDeclaration)).toThrowExactError( + TSTLErrors.MissingClassName(util.nodeStub) + ); }); test("CallSuperMethodNoArgs", () => { @@ -525,7 +525,7 @@ test("CallSuperMethodNoArgs", () => { } } let inst = new b(6); - return inst.method();`, + return inst.method();` ); expect(result).toBe(6); @@ -551,7 +551,7 @@ test("CallSuperMethodArgs", () => { } } let inst = new b(6); - return inst.method(4);`, + return inst.method(4);` ); expect(result).toBe(10); @@ -575,7 +575,7 @@ test("CallSuperExpressionMethod", () => { inst.method(); inst.method(); inst.method(); - return i;`, + return i;` ); expect(result).toBe(1); @@ -609,7 +609,7 @@ test("CallSuperSuperMethod", () => { } } let inst = new c(6); - return inst.method();`, + return inst.method();` ); expect(result).toBe(6); @@ -628,7 +628,7 @@ test("classExpression", () => { } } let inst = new b(); - return inst.method();`, + return inst.method();` ); expect(result).toBe("instance of b"); @@ -642,7 +642,7 @@ test("Named Class Expression", () => { } } let inst = new a(); - return inst.method();`, + return inst.method();` ); expect(result).toBe("foo"); @@ -658,7 +658,7 @@ test("classExpressionBaseClassMethod", () => { const b = class extends a { } let inst = new b(); - return inst.method();`, + return inst.method();` ); expect(result).toBe(42); @@ -676,7 +676,7 @@ test("Class Method Runtime Override", () => { inst.method = () => { return 8; } - return inst.method();`, + return inst.method();` ); expect(result).toBe(8); @@ -709,7 +709,7 @@ test.each([{ input: "(new Foo())", expectResult: "foo" }, { input: "Foo", expect return ${input}.method(); `; expect(util.transpileAndExecute(code)).toBe(expectResult); - }, + } ); test.each(["extension", "metaExtension"])("Class extends extension (%p)", extensionType => { @@ -719,9 +719,7 @@ test.each(["extension", "metaExtension"])("Class extends extension (%p)", extens class B extends A {} class C extends B {} `; - expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.InvalidExtendsExtension(util.nodeStub), - ); + expect(() => util.transpileString(code)).toThrowExactError(TSTLErrors.InvalidExtendsExtension(util.nodeStub)); }); test.each(["extension", "metaExtension"])("Class construct extension (%p)", extensionType => { @@ -732,7 +730,7 @@ test.each(["extension", "metaExtension"])("Class construct extension (%p)", exte const b = new B(); `; expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.InvalidNewExpressionOnExtension(util.nodeStub), + TSTLErrors.InvalidNewExpressionOnExtension(util.nodeStub) ); }); @@ -830,7 +828,7 @@ test("Class cannot have static new method", () => { static new() {} }`; expect(() => util.transpileAndExecute(code)).toThrow( - TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message, + TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message ); }); @@ -840,7 +838,7 @@ test("Class cannot have static new property", () => { static new = "foobar"; }`; expect(() => util.transpileAndExecute(code)).toThrow( - TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message, + TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message ); }); @@ -850,7 +848,7 @@ test("Class cannot have static new get accessor", () => { static get new() { return "foobar" } }`; expect(() => util.transpileAndExecute(code)).toThrow( - TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message, + TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message ); }); @@ -860,6 +858,6 @@ test("Class cannot have static new set accessor", () => { static set new(value: string) {} }`; expect(() => util.transpileAndExecute(code)).toThrow( - TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message, + TSTLErrors.ForbiddenStaticClassPropertyName(ts.createEmptyStatement(), "new").message ); }); diff --git a/test/unit/classDecorator.spec.ts b/test/unit/classDecorator.spec.ts index 3575284df..8e9eff3d7 100644 --- a/test/unit/classDecorator.spec.ts +++ b/test/unit/classDecorator.spec.ts @@ -162,9 +162,7 @@ test("Class decorators are applied in order and executed in reverse order", () = `; const result = util.transpileAndExecute(source); - expect(result).toBe( - "eval fox eval jumped eval over dog execute over dog execute jumped execute fox", - ); + expect(result).toBe("eval fox eval jumped eval over dog execute over dog execute jumped execute fox"); }); test("Throws error if decorator function has void context", () => { @@ -184,9 +182,7 @@ test("Throws error if decorator function has void context", () => { return classInstance.decoratorBool; `; - expect(() => util.transpileAndExecute(source)).toThrowExactError( - TSTLErrors.InvalidDecoratorContext(util.nodeStub), - ); + expect(() => util.transpileAndExecute(source)).toThrowExactError(TSTLErrors.InvalidDecoratorContext(util.nodeStub)); }); test("Exported class decorator", () => { diff --git a/test/unit/commandLineParser.spec.ts b/test/unit/commandLineParser.spec.ts index 8572f7c58..0f4942d9c 100644 --- a/test/unit/commandLineParser.spec.ts +++ b/test/unit/commandLineParser.spec.ts @@ -136,9 +136,7 @@ describe("tsconfig", () => { const rootLevel = parseConfigFileContent({ noHeader: true }); const namespaced = parseConfigFileContent({ tstl: { noHeader: true } }); - expect(rootLevel.errors).toEqual([ - expect.objectContaining({ category: ts.DiagnosticCategory.Warning }), - ]); + expect(rootLevel.errors).toEqual([expect.objectContaining({ category: ts.DiagnosticCategory.Warning })]); expect(rootLevel.options).toEqual(namespaced.options); }); diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index d09d54a7f..428066db6 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -8,36 +8,30 @@ test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }])("if (%p)", ({ inp, if (input === 0) { return 0; } - return 1;`, + return 1;` ); expect(result).toBe(expected); }); -test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }])( - "ifelse (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let input: number = ${inp}; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }])("ifelse (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let input: number = ${inp}; if (input === 0) { return 0; } else { return 1; - }`, - ); + }` + ); - expect(result).toBe(expected); - }, -); + expect(result).toBe(expected); +}); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: 3 }, -])("ifelseif (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let input: number = ${inp}; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: 3 }])( + "ifelseif (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let input: number = ${inp}; if (input === 0) { return 0; } else if (input === 1){ @@ -45,20 +39,18 @@ test.each([ } else if (input === 2){ return 2; } - return 3;`, - ); + return 3;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: 3 }, -])("ifelseifelse (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let input: number = ${inp}; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: 3 }])( + "ifelseifelse (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let input: number = ${inp}; if (input === 0) { return 0; } else if (input === 1){ @@ -67,20 +59,18 @@ test.each([ return 2; } else { return 3; - }`, - ); + }` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -1 }, -])("switch (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -1 }])( + "switch (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: @@ -93,20 +83,18 @@ test.each([ result = 2; break; } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -2 }, -])("switchdefault (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -2 }])( + "switchdefault (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: @@ -122,11 +110,12 @@ test.each([ result = -2; break; } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); test.each([ { inp: 0, expected: 1 }, @@ -163,20 +152,17 @@ test.each([ result = -2; break; } - return result;`, + return result;` ); expect(result).toBe(expected); }); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -2 }, -])("nestedSwitch (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -2 }])( + "nestedSwitch (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: @@ -202,11 +188,12 @@ test.each([ result = -2; break; } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 2 }, { inp: 2, expected: 2 }])( "switchLocalScope (%p)", @@ -230,21 +217,18 @@ test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 2 }, { inp: 2, expected: break; } } - return result;`, + return result;` ); expect(result).toBe(expected); - }, + } ); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -1 }, -])("switchReturn (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `const result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -1 }])( + "switchReturn (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `const result: number = -1; switch (${inp}) { case 0: @@ -256,20 +240,18 @@ test.each([ return 2; break; } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -1 }, -])("switchWithBrackets (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -1 }])( + "switchWithBrackets (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: { @@ -285,20 +267,18 @@ test.each([ break; } } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 0 }, - { inp: 1, expected: 1 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -1 }, -])("switchWithBracketsBreakInConditional (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 0 }, { inp: 1, expected: 1 }, { inp: 2, expected: 2 }, { inp: 3, expected: -1 }])( + "switchWithBracketsBreakInConditional (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: { @@ -315,20 +295,18 @@ test.each([ break; } } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); -test.each([ - { inp: 0, expected: 4 }, - { inp: 1, expected: 0 }, - { inp: 2, expected: 2 }, - { inp: 3, expected: -1 }, -])("switchWithBracketsBreakInInternalLoop (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let result: number = -1; +test.each([{ inp: 0, expected: 4 }, { inp: 1, expected: 0 }, { inp: 2, expected: 2 }, { inp: 3, expected: -1 }])( + "switchWithBracketsBreakInInternalLoop (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let result: number = -1; switch (${inp}) { case 0: { @@ -351,11 +329,12 @@ test.each([ break; } } - return result;`, - ); + return result;` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); test("If dead code after return", () => { const result = util.transpileAndExecute(`if (true) { return 3; const b = 8; }`); @@ -365,16 +344,14 @@ test("If dead code after return", () => { test("switch dead code after return", () => { const result = util.transpileAndExecute( - `switch ("abc") { case "def": return 4; let abc = 4; case "abc": return 5; let def = 6; }`, + `switch ("abc") { case "def": return 4; let abc = 4; case "abc": return 5; let def = 6; }` ); expect(result).toBe(5); }); test("switch not allowed in 5.1", () => { - expect(() => - util.transpileString(`switch ("abc") {}`, { luaTarget: tstl.LuaTarget.Lua51 }), - ).toThrowExactError( - TSTLErrors.UnsupportedForTarget("Switch statements", tstl.LuaTarget.Lua51, util.nodeStub), + expect(() => util.transpileString(`switch ("abc") {}`, { luaTarget: tstl.LuaTarget.Lua51 })).toThrowExactError( + TSTLErrors.UnsupportedForTarget("Switch statements", tstl.LuaTarget.Lua51, util.nodeStub) ); }); diff --git a/test/unit/console.spec.ts b/test/unit/console.spec.ts index 5734b6440..729a4440c 100644 --- a/test/unit/console.spec.ts +++ b/test/unit/console.spec.ts @@ -5,22 +5,22 @@ const compilerOptions = { lib: ["lib.es2015.d.ts", "lib.dom.d.ts"] }; test.each([ { inp: "console.log()", expected: "print()" }, { inp: 'console.log("Hello")', expected: 'print("Hello")' }, - { - inp: 'console.log("Hello %s", "there")', - expected: 'print(string.format("Hello %s", "there"))', - }, - { - inp: 'console.log("Hello %%s", "there")', - expected: 'print(string.format("Hello %%s", "there"))', - }, + { inp: 'console.log("Hello %s", "there")', expected: 'print(string.format("Hello %s", "there"))' }, + { inp: 'console.log("Hello %%s", "there")', expected: 'print(string.format("Hello %%s", "there"))' }, { inp: 'console.log("Hello", "There")', expected: 'print("Hello", "There")' }, ])("console.log (%p)", ({ inp, expected }) => { expect(util.transpileString(inp, compilerOptions)).toBe(expected); }); test.each([ - { inp: "console.trace()", expected: "print(debug.traceback())" }, - { inp: 'console.trace("message")', expected: 'print(debug.traceback("message"))' }, + { + inp: "console.trace()", + expected: "print(debug.traceback())", + }, + { + inp: 'console.trace("message")', + expected: 'print(debug.traceback("message"))', + }, { inp: 'console.trace("Hello %s", "there")', expected: 'print(debug.traceback(string.format("Hello %s", "there")))', @@ -38,8 +38,14 @@ test.each([ }); test.each([ - { inp: "console.assert(false)", expected: "assert(false)" }, - { inp: 'console.assert(false, "message")', expected: 'assert(false, "message")' }, + { + inp: "console.assert(false)", + expected: "assert(false)", + }, + { + inp: 'console.assert(false, "message")', + expected: 'assert(false, "message")', + }, { inp: 'console.assert(false, "message %s", "info")', expected: 'assert(false, string.format("message %s", "info"))', @@ -71,7 +77,7 @@ test("console.differentiation", () => { export const result = test(); `, "result", - compilerOptions, + compilerOptions ); expect(result).toBe(42); }); diff --git a/test/unit/curry.spec.ts b/test/unit/curry.spec.ts index 639336a47..b39d2f3c6 100644 --- a/test/unit/curry.spec.ts +++ b/test/unit/curry.spec.ts @@ -3,7 +3,7 @@ import * as util from "../util"; test.each([{ x: 2, y: 3 }, { x: 5, y: 4 }])("curryingAdd (%p)", ({ x, y }) => { const result = util.transpileAndExecute( `let add = (x: number) => (y: number) => x + y; - return add(${x})(${y})`, + return add(${x})(${y})` ); expect(result).toBe(x + y); diff --git a/test/unit/decoratorCustomConstructor.spec.ts b/test/unit/decoratorCustomConstructor.spec.ts index 9ff43c51d..71052406e 100644 --- a/test/unit/decoratorCustomConstructor.spec.ts +++ b/test/unit/decoratorCustomConstructor.spec.ts @@ -19,12 +19,7 @@ test("CustomCreate", () => { } `; - const result = util.transpileAndExecute( - `return new Point2D(1, 2).x;`, - undefined, - luaHeader, - tsHeader, - ); + const result = util.transpileAndExecute(`return new Point2D(1, 2).x;`, undefined, luaHeader, tsHeader); expect(result).toBe(1); }); @@ -41,7 +36,5 @@ test("IncorrectUsage", () => { } return new Point2D(1, 2).x; `); - }).toThrowExactError( - TSTLErrors.InvalidDecoratorArgumentNumber("@customConstructor", 0, 1, util.nodeStub), - ); + }).toThrowExactError(TSTLErrors.InvalidDecoratorArgumentNumber("@customConstructor", 0, 1, util.nodeStub)); }); diff --git a/test/unit/decoratorMetaExtension.spec.ts b/test/unit/decoratorMetaExtension.spec.ts index eb574cc62..6057fb202 100644 --- a/test/unit/decoratorMetaExtension.spec.ts +++ b/test/unit/decoratorMetaExtension.spec.ts @@ -19,7 +19,7 @@ test("MetaExtension", () => { `return debug.getregistry()["_LOADED"].test();`, undefined, undefined, - tsHeader, + tsHeader ); expect(result).toBe(5); diff --git a/test/unit/enum.spec.ts b/test/unit/enum.spec.ts index c067d04fb..ad063a6ba 100644 --- a/test/unit/enum.spec.ts +++ b/test/unit/enum.spec.ts @@ -85,7 +85,7 @@ test("Enum identifier value internal", () => { ghi = def, jkl, } - return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi},\${testEnum.jkl}\`;`, + return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi},\${testEnum.jkl}\`;` ); expect(result).toBe("0,1,1,2"); @@ -99,7 +99,7 @@ test("Enum identifier value internal recursive", () => { ghi = def, jkl = ghi, } - return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi},\${testEnum.jkl}\`;`, + return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi},\${testEnum.jkl}\`;` ); expect(result).toBe("0,1,1,1"); @@ -113,7 +113,7 @@ test("Enum identifier value external", () => { def, ghi = ext, } - return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi}\`;`, + return \`\${testEnum.abc},\${testEnum.def},\${testEnum.ghi}\`;` ); expect(result).toBe("0,1,6"); @@ -126,7 +126,7 @@ test("Enum reverse mapping", () => { def, ghi } - return testEnum[testEnum.abc] + testEnum[testEnum.ghi]`, + return testEnum[testEnum.abc] + testEnum[testEnum.ghi]` ); expect(result).toBe("abcghi"); @@ -139,7 +139,7 @@ test("Const enum index", () => { def, ghi } - return testEnum["def"];`, + return testEnum["def"];` ); expect(result).toBe(1); @@ -153,7 +153,7 @@ test("Const enum index identifier value", () => { ghi, jkl = ghi } - return testEnum["jkl"];`, + return testEnum["jkl"];` ); expect(result).toBe(5); @@ -167,7 +167,7 @@ test("Const enum index identifier chain", () => { ghi = def, jkl = ghi, } - return testEnum["ghi"];`, + return testEnum["ghi"];` ); expect(result).toBe(4); diff --git a/test/unit/error.spec.ts b/test/unit/error.spec.ts index e53407bc8..fe5eacf5e 100644 --- a/test/unit/error.spec.ts +++ b/test/unit/error.spec.ts @@ -42,7 +42,7 @@ test.each([{ i: 0, expected: "A" }, { i: 1, expected: "B" }, { i: 2, expected: " `; const result = util.transpileAndExecute(source); expect(result).toBe(expected); - }, + } ); test("re-throw (no catch var)", () => { diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 28f758a98..23d137f50 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -11,15 +11,9 @@ test.each([ { input: "!a", lua: "local ____ = not a" }, { input: "-a", lua: "local ____ = -a" }, { input: "+a", lua: "local ____ = a" }, - { - input: "let a = delete tbl['test']", - lua: "local a = (function()\n tbl.test = nil\n return true\nend)()", - }, + { input: "let a = delete tbl['test']", lua: "local a = (function()\n tbl.test = nil\n return true\nend)()" }, { input: "delete tbl['test']", lua: "tbl.test = nil" }, - { - input: "let a = delete tbl.test", - lua: "local a = (function()\n tbl.test = nil\n return true\nend)()", - }, + { input: "let a = delete tbl.test", lua: "local a = (function()\n tbl.test = nil\n return true\nend)()" }, { input: "delete tbl.test", lua: "tbl.test = nil" }, ])("Unary expressions basic (%p)", ({ input, lua }) => { expect(util.transpileString(input)).toBe(lua); @@ -56,17 +50,14 @@ test.each([ expect(result).toBe(expected); }); -test.each(["'key' in obj", "'existingKey' in obj", "0 in obj", "9 in obj"])( - "Binary expression in (%p)", - input => { - const tsHeader = "declare var obj: any;"; - const tsSource = `return ${input}`; - const luaHeader = "obj = { existingKey = 1 }"; - const result = util.transpileAndExecute(tsSource, undefined, luaHeader, tsHeader); +test.each(["'key' in obj", "'existingKey' in obj", "0 in obj", "9 in obj"])("Binary expression in (%p)", input => { + const tsHeader = "declare var obj: any;"; + const tsSource = `return ${input}`; + const luaHeader = "obj = { existingKey = 1 }"; + const result = util.transpileAndExecute(tsSource, undefined, luaHeader, tsHeader); - expect(result).toBe(eval(`let obj = { existingKey: 1 }; ${input}`)); - }, -); + expect(result).toBe(eval(`let obj = { existingKey: 1 }; ${input}`)); +}); test.each([ { input: "a+=b", expected: 5 + 3 }, @@ -101,7 +92,7 @@ test.each([ util.transpileString(input, { luaTarget: tstl.LuaTarget.Lua51, luaLibImport: tstl.LuaLibImportKind.None, - }), + }) ).toThrow(); }); @@ -165,13 +156,13 @@ test.each(["a>>b", "a>>=b"])("Unsupported bitop 5.3 (%p)", input => { util.transpileString(input, { luaTarget: tstl.LuaTarget.Lua53, luaLibImport: tstl.LuaLibImportKind.None, - }), + }) ).toThrowExactError( TSTLErrors.UnsupportedKind( "right shift operator (use >>> instead)", ts.SyntaxKind.GreaterThanGreaterThanToken, - util.nodeStub, - ), + util.nodeStub + ) ); }); @@ -225,26 +216,14 @@ test.each([ { input: "true ? maybeUndefinedValue : true" }, { input: "true ? maybeBooleanValue : true", expected: false }, { input: "true ? maybeUndefinedValue : true", options: { strictNullChecks: true } }, - { - input: "true ? maybeBooleanValue : true", - expected: false, - options: { strictNullChecks: true }, - }, + { input: "true ? maybeBooleanValue : true", expected: false, options: { strictNullChecks: true } }, { input: "true ? undefined : true", options: { strictNullChecks: true } }, { input: "true ? null : true", options: { strictNullChecks: true } }, { input: "true ? false : true", expected: false, options: { luaTarget: tstl.LuaTarget.Lua51 } }, { input: "false ? false : true", expected: true, options: { luaTarget: tstl.LuaTarget.Lua51 } }, { input: "true ? undefined : true", options: { luaTarget: tstl.LuaTarget.Lua51 } }, - { - input: "true ? false : true", - expected: false, - options: { luaTarget: tstl.LuaTarget.LuaJIT }, - }, - { - input: "false ? false : true", - expected: true, - options: { luaTarget: tstl.LuaTarget.LuaJIT }, - }, + { input: "true ? false : true", expected: false, options: { luaTarget: tstl.LuaTarget.LuaJIT } }, + { input: "false ? false : true", expected: true, options: { luaTarget: tstl.LuaTarget.LuaJIT } }, { input: "true ? undefined : true", options: { luaTarget: tstl.LuaTarget.LuaJIT } }, ])("Ternary operator (%p)", ({ input, expected, options }) => { const result = util.transpileAndExecute( @@ -253,7 +232,7 @@ test.each([ let maybeBooleanValue:string|boolean = false; let maybeUndefinedValue:string|undefined; return ${input};`, - options, + options ); expect(result).toBe(expected); @@ -352,7 +331,7 @@ test.each([ `class A{ get value(){ return this.v || 1; } set value(v){ this.v = v; } v: number; } class B{ get value(){ return this.v || 2; } set value(v){ this.v = v; } v: number; } let x: A|B = new A(); - ${expression}`, + ${expression}` ); expect(result).toBe(expected); @@ -385,7 +364,7 @@ test.each([{ expression: "x = y", expected: "y" }, { expression: "x += y", expec ({ expression, expected }) => { const result = util.transpileAndExecute(`let x = "x"; let y = "y"; return ${expression};`); expect(result).toBe(expected); - }, + } ); test.each([ @@ -399,7 +378,7 @@ test.each([ let y = "y"; let o = {p: "o"}; let a = ["a"]; - return ${expression};`, + return ${expression};` ); expect(result).toBe(expected); }); @@ -414,7 +393,7 @@ test.each([ `let x = "x"; let o = {p: "o"}; let a = ["a"]; - return ${expression};`, + return ${expression};` ); expect(result).toBe(expected); }); @@ -434,7 +413,7 @@ test.each([ /** @tupleReturn */ function tr(): [string, string] { return ["tr0", "tr1"] }; const r = ${expression}; - return \`\${r[0]},\${r[1]}\``, + return \`\${r[0]},\${r[1]}\`` ); expect(result).toBe(expected); }); @@ -462,13 +441,9 @@ test("Unknown unary postfix error", () => { }; expect(() => - transformer.transformPostfixUnaryExpression(mockExpression as ts.PostfixUnaryExpression), + transformer.transformPostfixUnaryExpression(mockExpression as ts.PostfixUnaryExpression) ).toThrowExactError( - TSTLErrors.UnsupportedKind( - "unary postfix operator", - ts.SyntaxKind.AsteriskToken, - util.nodeStub, - ), + TSTLErrors.UnsupportedKind("unary postfix operator", ts.SyntaxKind.AsteriskToken, util.nodeStub) ); }); @@ -481,45 +456,33 @@ test("Unknown unary postfix error", () => { }; expect(() => - transformer.transformPrefixUnaryExpression(mockExpression as ts.PrefixUnaryExpression), + transformer.transformPrefixUnaryExpression(mockExpression as ts.PrefixUnaryExpression) ).toThrowExactError( - TSTLErrors.UnsupportedKind( - "unary prefix operator", - ts.SyntaxKind.AsteriskToken, - util.nodeStub, - ), + TSTLErrors.UnsupportedKind("unary prefix operator", ts.SyntaxKind.AsteriskToken, util.nodeStub) ); }); test("Incompatible fromCodePoint expression error", () => { expect(() => util.transpileString("const abc = String.fromCodePoint(123);")).toThrowExactError( - TSTLErrors.UnsupportedForTarget( - "string property fromCodePoint", - tstl.LuaTarget.Lua53, - util.nodeStub, - ), + TSTLErrors.UnsupportedForTarget("string property fromCodePoint", tstl.LuaTarget.Lua53, util.nodeStub) ); }); test("Unknown string expression error", () => { expect(() => util.transpileString("const abc = String.abcd();")).toThrowExactError( - TSTLErrors.UnsupportedForTarget( - "string property abcd", - tstl.LuaTarget.Lua53, - util.nodeStub, - ), + TSTLErrors.UnsupportedForTarget("string property abcd", tstl.LuaTarget.Lua53, util.nodeStub) ); }); test("Unsupported array function error", () => { expect(() => util.transpileString("const abc = [].unknownFunction();")).toThrowExactError( - TSTLErrors.UnsupportedProperty("array", "unknownFunction", util.nodeStub), + TSTLErrors.UnsupportedProperty("array", "unknownFunction", util.nodeStub) ); }); test("Unsupported math property error", () => { expect(() => util.transpileString("const abc = Math.unknownProperty;")).toThrowExactError( - TSTLErrors.UnsupportedProperty("math", "unknownProperty", util.nodeStub), + TSTLErrors.UnsupportedProperty("math", "unknownProperty", util.nodeStub) ); }); @@ -535,14 +498,8 @@ test("Unsupported object literal element error", () => { ], }; - expect(() => - transformer.transformObjectLiteral(mockObject as ts.ObjectLiteralExpression), - ).toThrowExactError( - TSTLErrors.UnsupportedKind( - "object literal element", - ts.SyntaxKind.FalseKeyword, - util.nodeStub, - ), + expect(() => transformer.transformObjectLiteral(mockObject as ts.ObjectLiteralExpression)).toThrowExactError( + TSTLErrors.UnsupportedKind("object literal element", ts.SyntaxKind.FalseKeyword, util.nodeStub) ); }); diff --git a/test/unit/functions.spec.ts b/test/unit/functions.spec.ts index 98aa48ca4..cbcd4ad87 100644 --- a/test/unit/functions.spec.ts +++ b/test/unit/functions.spec.ts @@ -14,9 +14,7 @@ test.each([ { lambda: "++i", expected: 15 }, { lambda: "--i", expected: 5 }, ])("Arrow function unary expression (%p)", ({ lambda, expected }) => { - const result = util.transpileAndExecute( - `let i = 10; [1,2,3,4,5].forEach(() => ${lambda}); return i;`, - ); + const result = util.transpileAndExecute(`let i = 10; [1,2,3,4,5].forEach(() => ${lambda}); return i;`); expect(result).toBe(expected); }); @@ -46,16 +44,14 @@ test.each([{ inp: [] }, { inp: [5] }, { inp: [1, 2] }])("Arrow Default Values (% const result = util.transpileAndExecute( `let add = (a: number = 3, b: number = 4) => a+b; - return add(${callArgs});`, + return add(${callArgs});` ); expect(result).toBe(v1 + v2); }); test("Function Expression", () => { - const result = util.transpileAndExecute( - `let add = function(a, b) {return a+b}; return add(1,2);`, - ); + const result = util.transpileAndExecute(`let add = function(a, b) {return a+b}; return add(1,2);`); expect(result).toBe(3); }); @@ -75,24 +71,21 @@ test("Function default parameter", () => { expect(result).toBe("abcdef"); }); -test.each([{ inp: [] }, { inp: [5] }, { inp: [1, 2] }])( - "Function Default Values (%p)", - ({ inp }) => { - // Default value is 3 for v1 - const v1 = inp.length > 0 ? inp[0] : 3; - // Default value is 4 for v2 - const v2 = inp.length > 1 ? inp[1] : 4; +test.each([{ inp: [] }, { inp: [5] }, { inp: [1, 2] }])("Function Default Values (%p)", ({ inp }) => { + // Default value is 3 for v1 + const v1 = inp.length > 0 ? inp[0] : 3; + // Default value is 4 for v2 + const v2 = inp.length > 1 ? inp[1] : 4; - const callArgs = inp.join(","); + const callArgs = inp.join(","); - const result = util.transpileAndExecute( - `let add = function(a: number = 3, b: number = 4) { return a+b; }; - return add(${callArgs});`, - ); + const result = util.transpileAndExecute( + `let add = function(a: number = 3, b: number = 4) { return a+b; }; + return add(${callArgs});` + ); - expect(result).toBe(v1 + v2); - }, -); + expect(result).toBe(v1 + v2); +}); test("Function default array binding parameter", () => { const code = ` @@ -231,22 +224,20 @@ test("Invalid property access call transpilation", () => { expression: ts.createLiteral("abc"), }; - expect(() => - transformer.transformPropertyCall(mockObject as ts.CallExpression), - ).toThrowExactError(TSTLErrors.InvalidPropertyCall(util.nodeStub)); + expect(() => transformer.transformPropertyCall(mockObject as ts.CallExpression)).toThrowExactError( + TSTLErrors.InvalidPropertyCall(util.nodeStub) + ); }); test("Function dead code after return", () => { - const result = util.transpileAndExecute( - `function abc() { return 3; const a = 5; } return abc();`, - ); + const result = util.transpileAndExecute(`function abc() { return 3; const a = 5; } return abc();`); expect(result).toBe(3); }); test("Method dead code after return", () => { const result = util.transpileAndExecute( - `class def { public static abc() { return 3; const a = 5; } } return def.abc();`, + `class def { public static abc() { return 3; const a = 5; } } return def.abc();` ); expect(result).toBe(3); @@ -267,7 +258,7 @@ test("Recursive function expression", () => { test("Wrapped recursive function expression", () => { const result = util.transpileAndExecute( `function wrap(fn: T) { return fn; } - let f = wrap(function() { return typeof f; }); return f();`, + let f = wrap(function() { return typeof f; }); return f();` ); expect(result).toBe("function"); @@ -282,7 +273,7 @@ test("Recursive arrow function", () => { test("Wrapped recursive arrow function", () => { const result = util.transpileAndExecute( `function wrap(fn: T) { return fn; } - let f = wrap(() => typeof f); return f();`, + let f = wrap(() => typeof f); return f();` ); expect(result).toBe("function"); @@ -290,16 +281,15 @@ test("Wrapped recursive arrow function", () => { test("Object method declaration", () => { const result = util.transpileAndExecute( - `let o = { v: 4, m(i: number): number { return this.v * i; } }; return o.m(3);`, + `let o = { v: 4, m(i: number): number { return this.v * i; } }; return o.m(3);` ); expect(result).toBe(12); }); -test.each([ - { args: ["bar"], expectResult: "foobar" }, - { args: ["baz", "bar"], expectResult: "bazbar" }, -])("Function overload (%p)", ({ args, expectResult }) => { - const code = ` +test.each([{ args: ["bar"], expectResult: "foobar" }, { args: ["baz", "bar"], expectResult: "bazbar" }])( + "Function overload (%p)", + ({ args, expectResult }) => { + const code = ` class O { prop = "foo"; method(s: string): string; @@ -314,9 +304,10 @@ test.each([ const o = new O(); return o.method(${args.map(a => '"' + a + '"').join(", ")}); `; - const result = util.transpileAndExecute(code); - expect(result).toBe(expectResult); -}); + const result = util.transpileAndExecute(code); + expect(result).toBe(expectResult); + } +); test("Nested Function", () => { const code = ` @@ -338,10 +329,8 @@ test("Nested Function", () => { expect(result).toBe("foobar"); }); -test.each([{ s1: "abc", s2: "abc" }, { s1: "abc", s2: "def" }])( - "Dot vs Colon method call (%p)", - ({ s1, s2 }) => { - const result = util.transpileAndExecute(` +test.each([{ s1: "abc", s2: "abc" }, { s1: "abc", s2: "def" }])("Dot vs Colon method call (%p)", ({ s1, s2 }) => { + const result = util.transpileAndExecute(` class MyClass { dotMethod(this: void, s: string) { return s; @@ -353,9 +342,8 @@ test.each([{ s1: "abc", s2: "abc" }, { s1: "abc", s2: "def" }])( const inst = new MyClass(); return inst.dotMethod("${s1}") == inst.colonMethod("${s2}"); `); - expect(result).toBe(s1 === s2); - }, -); + expect(result).toBe(s1 === s2); +}); test("Element access call", () => { const code = ` @@ -442,7 +430,7 @@ test.each([{ iterations: 1, expectedResult: 1 }, { iterations: 2, expectedResult `; const result = util.transpileAndExecute(code); expect(result).toBe(expectedResult); - }, + } ); test.each([{ iterations: 1, expectedResult: false }, { iterations: 2, expectedResult: true }])( @@ -463,7 +451,7 @@ test.each([{ iterations: 1, expectedResult: false }, { iterations: 2, expectedRe `; const result = util.transpileAndExecute(code); expect(result).toBe(expectedResult); - }, + } ); test("Generator for..of", () => { diff --git a/test/unit/hoisting.spec.ts b/test/unit/hoisting.spec.ts index 37d893335..cf07a7c15 100644 --- a/test/unit/hoisting.spec.ts +++ b/test/unit/hoisting.spec.ts @@ -116,11 +116,10 @@ test.each([ expect(result).toBe(expectResult); }); -test.each([ - { initializer: "", expectResult: "foofoo" }, - { initializer: ' = "bar"', expectResult: "barbar" }, -])("Var hoisting from child scope (%p)", ({ initializer, expectResult }) => { - const code = ` +test.each([{ initializer: "", expectResult: "foofoo" }, { initializer: ' = "bar"', expectResult: "barbar" }])( + "Var hoisting from child scope (%p)", + ({ initializer, expectResult }) => { + const code = ` foo = "foo"; let result: string; if (true) { @@ -129,9 +128,10 @@ test.each([ } return foo + result; `; - const result = util.transpileAndExecute(code); - expect(result).toBe(expectResult); -}); + const result = util.transpileAndExecute(code); + expect(result).toBe(expectResult); + } +); test("Hoisting due to reference from hoisted function", () => { const code = ` @@ -228,10 +228,7 @@ test.each([ { code: `const foo = bar(); function bar() { return "bar"; }`, identifier: "bar" }, { code: `export const foo = bar(); function bar() { return "bar"; }`, identifier: "bar" }, { code: `const foo = bar(); export function bar() { return "bar"; }`, identifier: "bar" }, - { - code: `function bar() { return NS.foo; } namespace NS { export let foo = "foo"; }`, - identifier: "NS", - }, + { code: `function bar() { return NS.foo; } namespace NS { export let foo = "foo"; }`, identifier: "NS" }, { code: `export namespace O { export function f() { return I.foo; } namespace I { export let foo = "foo"; } }`, identifier: "I", @@ -240,7 +237,7 @@ test.each([ { code: `function bar() { return E.A; } enum E { A = "foo" }`, identifier: "E" }, ])("No Hoisting (%p)", ({ code, identifier }) => { expect(() => util.transpileString(code, { noHoisting: true })).toThrowExactError( - TSTLErrors.ReferencedBeforeDeclaration(ts.createIdentifier(identifier)), + TSTLErrors.ReferencedBeforeDeclaration(ts.createIdentifier(identifier)) ); }); diff --git a/test/unit/identifiers.spec.ts b/test/unit/identifiers.spec.ts index 7191a986e..8aa2bc432 100644 --- a/test/unit/identifiers.spec.ts +++ b/test/unit/identifiers.spec.ts @@ -62,19 +62,16 @@ test.each(invalidLuaNames)("lua keyword or invalid identifier as method call (%p expect(util.transpileAndExecute(code)).toBe("foobar"); }); -test.each(invalidLuaNames)( - "lua keyword or invalid identifier as complex method call (%p)", - name => { - const code = ` +test.each(invalidLuaNames)("lua keyword or invalid identifier as complex method call (%p)", name => { + const code = ` const foo = { ${name}(arg: string) { return "foo" + arg; } }; function getFoo() { return foo; } return getFoo().${name}("bar");`; - expect(util.transpileAndExecute(code)).toBe("foobar"); - }, -); + expect(util.transpileAndExecute(code)).toBe("foobar"); +}); test.each([ "var local: any;", @@ -92,7 +89,7 @@ test.each([ const foo = local;`; expect(() => util.transpileString(code)).toThrow( - TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier("local")).message, + TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier("local")).message ); }); @@ -112,7 +109,7 @@ test.each([ const foo = $$$;`; expect(() => util.transpileString(code)).toThrow( - TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier("$$$")).message, + TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier("$$$")).message ); }); @@ -124,38 +121,32 @@ test.each(validTsInvalidLuaNames)( const foo = { ${name} };`; expect(() => util.transpileString(code)).toThrow( - TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message, + TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message ); - }, + } ); -test.each(validTsInvalidLuaNames)( - "undeclared identifier must be a valid lua identifier (%p)", - name => { - expect(() => util.transpileString(`const foo = ${name};`)).toThrow( - TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message, - ); - }, -); +test.each(validTsInvalidLuaNames)("undeclared identifier must be a valid lua identifier (%p)", name => { + expect(() => util.transpileString(`const foo = ${name};`)).toThrow( + TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message + ); +}); test.each(validTsInvalidLuaNames)( "undeclared identifier must be a valid lua identifier (object literal shorthand) (%p)", name => { expect(() => util.transpileString(`const foo = { ${name} };`)).toThrow( - TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message, + TSTLErrors.InvalidAmbientIdentifierName(ts.createIdentifier(name)).message ); - }, + } ); -test.each(validTsInvalidLuaNames)( - "exported values with invalid lua identifier names (%p)", - name => { - const code = `export const ${name} = "foobar";`; - const lua = util.transpileString(code); - expect(lua.indexOf(`"${name}"`)).toBeGreaterThanOrEqual(0); - expect(util.executeLua(`return (function() ${lua} end)()["${name}"]`)).toBe("foobar"); - }, -); +test.each(validTsInvalidLuaNames)("exported values with invalid lua identifier names (%p)", name => { + const code = `export const ${name} = "foobar";`; + const lua = util.transpileString(code); + expect(lua.indexOf(`"${name}"`)).toBeGreaterThanOrEqual(0); + expect(util.executeLua(`return (function() ${lua} end)()["${name}"]`)).toBe("foobar"); +}); test.each(validTsInvalidLuaNames)("class with invalid lua name has correct name property", name => { const code = ` @@ -339,9 +330,7 @@ describe("lua keyword as identifier doesn't interfere with lua's value", () => { const compilerOptions = { lib: ["lib.es2015.d.ts", "lib.dom.d.ts"] }; - expect(() => util.transpileAndExecute(code, compilerOptions)).toThrow( - /^LUA ERROR: .+ foobar$/, - ); + expect(() => util.transpileAndExecute(code, compilerOptions)).toThrow(/^LUA ERROR: .+ foobar$/); }); test("variable (debug)", () => { @@ -362,7 +351,7 @@ describe("lua keyword as identifier doesn't interfere with lua's value", () => { const compilerOptions = { lib: ["lib.es2015.d.ts", "lib.dom.d.ts"] }; expect(util.transpileAndExecute(code, compilerOptions, luaHeader, tsHeader)).toMatch( - /^foobar\nstack traceback.+/, + /^foobar\nstack traceback.+/ ); }); @@ -597,21 +586,18 @@ describe("lua keyword as identifier doesn't interfere with lua's value", () => { expect(util.transpileExecuteAndReturnExport(code, returnExport)).toBe(expectResult); }); - test.each(["type", "type as type"])( - "re-exported variable with lua keyword as name (%p)", - importName => { - const code = ` + test.each(["type", "type as type"])("re-exported variable with lua keyword as name (%p)", importName => { + const code = ` export { ${importName} } from "someModule"`; - const lua = ` + const lua = ` package.loaded.someModule = {type = "foobar"} return (function() ${util.transpileString(code)} end)().type`; - expect(util.executeLua(lua)).toBe("foobar"); - }, - ); + expect(util.executeLua(lua)).toBe("foobar"); + }); test("class", () => { const code = ` @@ -678,9 +664,7 @@ describe("lua keyword as identifier doesn't interfere with lua's value", () => { const code = ` return typeof type.foo + "|" + type.foo`; - expect(util.transpileAndExecute(code, undefined, undefined, tsHeader)).toBe( - "string|foobar", - ); + expect(util.transpileAndExecute(code, undefined, undefined, tsHeader)).toBe("string|foobar"); }); test.each([ @@ -715,9 +699,7 @@ describe("lua keyword as identifier doesn't interfere with lua's value", () => { const t = new type(); return \`\${t.method()}|\${type.staticMethod()}|\${typeof type.foo}|\${type.foo}|\${type.bar}\`;`; - expect(util.transpileAndExecute(code, undefined, undefined, tsHeader)).toBe( - "number|boolean|string|foo|bar", - ); + expect(util.transpileAndExecute(code, undefined, undefined, tsHeader)).toBe("number|boolean|string|foo|bar"); }); test.each([ diff --git a/test/unit/json.spec.ts b/test/unit/json.spec.ts index e651f71d6..d7064edcc 100644 --- a/test/unit/json.spec.ts +++ b/test/unit/json.spec.ts @@ -8,20 +8,17 @@ const jsonOptions = { moduleResolution: ts.ModuleResolutionKind.NodeJs, }; -test.each(["0", '""', "[]", '[1, "2", []]', '{ "a": "b" }', '{ "a": { "b": "c" } }'])( - "JSON (%p)", - json => { - const lua = util - .transpileString({ "main.json": json }, jsonOptions, false) - .replace(/^return ([\s\S]+)$/, "return JSONStringify($1)"); +test.each(["0", '""', "[]", '[1, "2", []]', '{ "a": "b" }', '{ "a": { "b": "c" } }'])("JSON (%p)", json => { + const lua = util + .transpileString({ "main.json": json }, jsonOptions, false) + .replace(/^return ([\s\S]+)$/, "return JSONStringify($1)"); - const result = util.executeLua(lua); - expect(JSON.parse(result)).toEqual(JSON.parse(json)); - }, -); + const result = util.executeLua(lua); + expect(JSON.parse(result)).toEqual(JSON.parse(json)); +}); test("Empty JSON", () => { expect(() => util.transpileString({ "main.json": "" }, jsonOptions, false)).toThrowExactError( - TSTLErrors.InvalidJsonFileContent(util.nodeStub), + TSTLErrors.InvalidJsonFileContent(util.nodeStub) ); }); diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index b36ff10ff..6c2bae455 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -11,17 +11,15 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("while (%p)", ({ inp, arrTest[i] = arrTest[i] + 1; i++; } - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); expect(result).toBe(JSON.stringify(expected)); }); -test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])( - "while with continue (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])("while with continue (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i = 0; while (i < arrTest.length) { if (i % 2 == 0) { @@ -40,18 +38,15 @@ test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])( i++; } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])( - "dowhile with continue (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])("dowhile with continue (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i = 0; do { if (i % 2 == 0) { @@ -70,12 +65,11 @@ test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 1, 2, 1, 4] }])( i++; } while (i < arrTest.length) - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("for (%p)", ({ inp, expected }) => { const result = util.transpileAndExecute( @@ -83,31 +77,26 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("for (%p)", ({ inp, e for (let i = 0; i < arrTest.length; ++i) { arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); expect(result).toBe(JSON.stringify(expected)); }); -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( - "for with expression (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("for with expression (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i: number; for (i = 0 * 1; i < arrTest.length; ++i) { arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, - ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + return JSONStringify(arrTest);` + ); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])( - "for with continue (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])("for with continue (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; for (let i = 0; i < arrTest.length; i++) { if (i % 2 == 0) { continue; @@ -120,27 +109,23 @@ test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])( arrTest[i] = j; } } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( - "forMirror (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forMirror (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; for (let i = 0; arrTest.length > i; i++) { arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); test.each([{ inp: [0, 1, 2, 3], expected: [0, 1, 2, 3] }])("forBreak (%p)", ({ inp, expected }) => { const result = util.transpileAndExecute( @@ -149,33 +134,28 @@ test.each([{ inp: [0, 1, 2, 3], expected: [0, 1, 2, 3] }])("forBreak (%p)", ({ i break; arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); expect(result).toBe(JSON.stringify(expected)); }); -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( - "forNoDeclarations (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forNoDeclarations (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i = 0; for (; i < arrTest.length; ++i) { arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( - "forNoCondition (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forNoCondition (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i = 0; for (;; ++i) { if (i >= arrTest.length) { @@ -184,18 +164,15 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( - "forNoPostExpression (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forNoPostExpression (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; let i = 0; for (;;) { if (i >= arrTest.length) { @@ -206,49 +183,28 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])( i++; } - return JSONStringify(arrTest);`, - ); + return JSONStringify(arrTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); test.each([ { inp: [0, 1, 2, 3], expected: [1, 2, 3, 4], header: "let i = 0; i < arrTest.length; i++" }, - { - inp: [0, 1, 2, 3], - expected: [1, 2, 3, 4], - header: "let i = 0; i <= arrTest.length - 1; i++", - }, + { inp: [0, 1, 2, 3], expected: [1, 2, 3, 4], header: "let i = 0; i <= arrTest.length - 1; i++" }, { inp: [0, 1, 2, 3], expected: [1, 2, 3, 4], header: "let i = 0; arrTest.length > i; i++" }, - { - inp: [0, 1, 2, 3], - expected: [1, 2, 3, 4], - header: "let i = 0; arrTest.length - 1 >= i; i++", - }, + { inp: [0, 1, 2, 3], expected: [1, 2, 3, 4], header: "let i = 0; arrTest.length - 1 >= i; i++" }, { inp: [0, 1, 2, 3], expected: [1, 1, 3, 3], header: "let i = 0; i < arrTest.length; i += 2" }, - { - inp: [0, 1, 2, 3], - expected: [1, 2, 3, 4], - header: "let i = arrTest.length - 1; i >= 0; i--", - }, - { - inp: [0, 1, 2, 3], - expected: [0, 2, 2, 4], - header: "let i = arrTest.length - 1; i >= 0; i -= 2", - }, - { - inp: [0, 1, 2, 3], - expected: [0, 2, 2, 4], - header: "let i = arrTest.length - 1; i > 0; i -= 2", - }, + { inp: [0, 1, 2, 3], expected: [1, 2, 3, 4], header: "let i = arrTest.length - 1; i >= 0; i--" }, + { inp: [0, 1, 2, 3], expected: [0, 2, 2, 4], header: "let i = arrTest.length - 1; i >= 0; i -= 2" }, + { inp: [0, 1, 2, 3], expected: [0, 2, 2, 4], header: "let i = arrTest.length - 1; i > 0; i -= 2" }, ])("forheader (%p)", ({ inp, expected, header }) => { const result = util.transpileAndExecute( `let arrTest = ${JSON.stringify(inp)}; for (${header}) { arrTest[i] = arrTest[i] + 1; } - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); expect(result).toBe(JSON.stringify(expected)); @@ -274,7 +230,7 @@ test.each([ for (let key in objTest) { objTest[key] = objTest[key] + 1; } - return JSONStringify(objTest);`, + return JSONStringify(objTest);` ); expect(JSON.parse(result)).toEqual(expected); @@ -286,8 +242,8 @@ test.each([{ inp: [1, 2, 3] }])("forin[Array] (%p)", ({ inp }) => { `let arrTest = ${JSON.stringify(inp)}; for (let key in arrTest) { arrTest[key]++; - }`, - ), + }` + ) ).toThrowExactError(TSTLErrors.ForbiddenForIn(util.nodeStub)); }); @@ -303,11 +259,11 @@ test.each([{ inp: { a: 0, b: 1, c: 2, d: 3, e: 4 }, expected: { a: 0, b: 0, c: 2 obj[i] = 0; } - return JSONStringify(obj);`, + return JSONStringify(obj);` ); expect(result).toBe(JSON.stringify(expected)); - }, + } ); test.each([{ inp: [0, 1, 2], expected: [1, 2, 3] }])("forof (%p)", ({ inp, expected }) => { @@ -317,44 +273,38 @@ test.each([{ inp: [0, 1, 2], expected: [1, 2, 3] }])("forof (%p)", ({ inp, expec for (let value of objTest) { arrResultTest.push(value + 1) } - return JSONStringify(arrResultTest);`, + return JSONStringify(arrResultTest);` ); expect(result).toBe(JSON.stringify(expected)); }); -test.each([{ inp: [0, 1, 2], expected: [1, 2, 3] }])( - "forof existing variable (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let objTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2], expected: [1, 2, 3] }])("forof existing variable (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let objTest = ${JSON.stringify(inp)}; let arrResultTest = []; let value: number; for (value of objTest) { arrResultTest.push(value + 1) } - return JSONStringify(arrResultTest);`, - ); + return JSONStringify(arrResultTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); -test.each([{ inp: [[1, 2], [2, 3], [3, 4]], expected: [3, 5, 7] }])( - "forof destructing (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let objTest = ${JSON.stringify(inp)}; +test.each([{ inp: [[1, 2], [2, 3], [3, 4]], expected: [3, 5, 7] }])("forof destructing (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let objTest = ${JSON.stringify(inp)}; let arrResultTest = []; for (let [a,b] of objTest) { arrResultTest.push(a + b) } - return JSONStringify(arrResultTest);`, - ); + return JSONStringify(arrResultTest);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); test.each([{ inp: [[1, 2], [2, 3], [3, 4]], expected: [3, 5, 7] }])( "forof destructing with existing variables (%p)", @@ -367,18 +317,16 @@ test.each([{ inp: [[1, 2], [2, 3], [3, 4]], expected: [3, 5, 7] }])( for ([a,b] of objTest) { arrResultTest.push(a + b) } - return JSONStringify(arrResultTest);`, + return JSONStringify(arrResultTest);` ); expect(result).toBe(JSON.stringify(expected)); - }, + } ); -test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])( - "forof with continue (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let testArr = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])("forof with continue (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let testArr = ${JSON.stringify(inp)}; let a = 0; for (let i of testArr) { if (i % 2 == 0) { @@ -394,12 +342,11 @@ test.each([{ inp: [0, 1, 2, 3, 4], expected: [0, 0, 2, 0, 4] }])( } a++; } - return JSONStringify(testArr);`, - ); + return JSONStringify(testArr);` + ); - expect(result).toBe(JSON.stringify(expected)); - }, -); + expect(result).toBe(JSON.stringify(expected)); +}); test("forof with iterator", () => { const code = ` @@ -531,7 +478,7 @@ test.each([ for (${initializer} of arr) {}`; expect(() => util.transpileString(code)).toThrow( - TSTLErrors.UnsupportedObjectDestructuringInForOf(ts.createEmptyStatement()).message, + TSTLErrors.UnsupportedObjectDestructuringInForOf(ts.createEmptyStatement()).message ); }); @@ -728,7 +675,7 @@ test("forof lua iterator tuple-return single variable", () => { target: ts.ScriptTarget.ES2015, }; expect(() => util.transpileString(code, compilerOptions)).toThrowExactError( - TSTLErrors.UnsupportedNonDestructuringLuaIterator(util.nodeStub), + TSTLErrors.UnsupportedNonDestructuringLuaIterator(util.nodeStub) ); }); @@ -747,7 +694,7 @@ test("forof lua iterator tuple-return single existing variable", () => { target: ts.ScriptTarget.ES2015, }; expect(() => util.transpileString(code, compilerOptions)).toThrowExactError( - TSTLErrors.UnsupportedNonDestructuringLuaIterator(util.nodeStub), + TSTLErrors.UnsupportedNonDestructuringLuaIterator(util.nodeStub) ); }); @@ -820,11 +767,7 @@ test.each([ const luajit = { luaTarget: tstl.LuaTarget.LuaJIT }; expect(() => util.transpileString(loop, lua51)).toThrowExactError( - TSTLErrors.UnsupportedForTarget( - "Continue statement", - tstl.LuaTarget.Lua51, - ts.createContinue(), - ), + TSTLErrors.UnsupportedForTarget("Continue statement", tstl.LuaTarget.Lua51, ts.createContinue()) ); expect(util.transpileString(loop, lua52).indexOf("::__continue1::") !== -1).toBe(true); expect(util.transpileString(loop, lua53).indexOf("::__continue1::") !== -1).toBe(true); @@ -832,17 +775,13 @@ test.each([ }); test("for dead code after return", () => { - const result = util.transpileAndExecute( - `for (let i = 0; i < 10; i++) { return 3; const b = 8; }`, - ); + const result = util.transpileAndExecute(`for (let i = 0; i < 10; i++) { return 3; const b = 8; }`); expect(result).toBe(3); }); test("for..in dead code after return", () => { - const result = util.transpileAndExecute( - `for (let a in {"a": 5, "b": 8}) { return 3; const b = 8; }`, - ); + const result = util.transpileAndExecute(`for (let a in {"a": 5, "b": 8}) { return 3; const b = 8; }`); expect(result).toBe(3); }); diff --git a/test/unit/luaTable.spec.ts b/test/unit/luaTable.spec.ts index 1ea3d2f9b..aa15f32ac 100644 --- a/test/unit/luaTable.spec.ts +++ b/test/unit/luaTable.spec.ts @@ -26,34 +26,29 @@ declare let tbl: Table; `; test.each([tableLibClass])("LuaTables cannot be constructed with arguments", tableLib => { - expect(() => - util.transpileString(tableLib + `const table = new Table(true);`), - ).toThrowExactError( + expect(() => util.transpileString(tableLib + `const table = new Table(true);`)).toThrowExactError( TSTLErrors.ForbiddenLuaTableUseException( "No parameters are allowed when constructing a LuaTable object.", - util.nodeStub, - ), + util.nodeStub + ) ); }); -test.each([tableLibClass, tableLibInterface])( - "LuaTable set() cannot be used in an expression position", - tableLib => { - expect(() => - util.transpileString(tableLib + `const exp = tbl.set("value", 5)`), - ).toThrowExactError(TSTLErrors.ForbiddenLuaTableSetExpression(util.nodeStub)); - }, -); +test.each([tableLibClass, tableLibInterface])("LuaTable set() cannot be used in an expression position", tableLib => { + expect(() => util.transpileString(tableLib + `const exp = tbl.set("value", 5)`)).toThrowExactError( + TSTLErrors.ForbiddenLuaTableSetExpression(util.nodeStub) + ); +}); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other methods", tableLib => { expect(() => util.transpileString(tableLib + `tbl.other()`)).toThrowExactError( - TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", util.nodeStub), + TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", util.nodeStub) ); }); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other methods", tableLib => { expect(() => util.transpileString(tableLib + `let x = tbl.other()`)).toThrowExactError( - TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", util.nodeStub), + TSTLErrors.ForbiddenLuaTableUseException("Unsupported method.", util.nodeStub) ); }); @@ -70,10 +65,7 @@ test.each([tableLibClass])("LuaTable length", tableLib => { test.each([tableLibClass, tableLibInterface])("Cannot set LuaTable length", tableLib => { expect(() => util.transpileString(tableLib + `tbl.length = 2;`)).toThrowExactError( - TSTLErrors.ForbiddenLuaTableUseException( - "A LuaTable object's length cannot be re-assigned.", - util.nodeStub, - ), + TSTLErrors.ForbiddenLuaTableUseException("A LuaTable object's length cannot be re-assigned.", util.nodeStub) ); }); @@ -87,7 +79,7 @@ test.each([tableLibClass, tableLibInterface])("Forbidden LuaTable use", tableLib [`tbl.set("field", ...[0, 1])`, "Arguments cannot be spread."], ])("Forbidden LuaTable use (%p)", (invalidCode, errorDescription) => { expect(() => util.transpileString(tableLib + invalidCode)).toThrowExactError( - TSTLErrors.ForbiddenLuaTableUseException(errorDescription, util.nodeStub), + TSTLErrors.ForbiddenLuaTableUseException(errorDescription, util.nodeStub) ); }); }); @@ -97,9 +89,9 @@ test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { "Cannot extend LuaTable class (%p)", code => { expect(() => util.transpileString(tableLib + code)).toThrowExactError( - TSTLErrors.InvalidExtendsLuaTable(util.nodeStub), + TSTLErrors.InvalidExtendsLuaTable(util.nodeStub) ); - }, + } ); }); @@ -109,14 +101,14 @@ test.each([ `/** @luaTable */ const c = class Table {}`, ])("LuaTable classes must be ambient (%p)", code => { expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.ForbiddenLuaTableNonDeclaration(util.nodeStub), + TSTLErrors.ForbiddenLuaTableNonDeclaration(util.nodeStub) ); }); test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { test.each([`tbl instanceof Table`])("Cannot use instanceof on a LuaTable class (%p)", code => { expect(() => util.transpileString(tableLib + code)).toThrowExactError( - TSTLErrors.InvalidInstanceOfLuaTable(util.nodeStub), + TSTLErrors.InvalidInstanceOfLuaTable(util.nodeStub) ); }); }); @@ -126,13 +118,8 @@ test.each([tableLibClass])("LuaTable functional tests", tableLib => { [`const t = new Table(); t.set("field", "value"); return t.get("field");`, "value"], [`const t = new Table(); t.set("field", 0); return t.get("field");`, 0], [`const t = new Table(); t.set(1, true); return t.length`, 1], - [ - `const t = new Table(); t.set(t.length + 1, true); t.set(t.length + 1, true); return t.length`, - 2, - ], + [`const t = new Table(); t.set(t.length + 1, true); t.set(t.length + 1, true); return t.length`, 2], ])("LuaTable test (%p)", (code, expectedReturnValue) => { - expect(util.transpileAndExecute(code, undefined, undefined, tableLib)).toBe( - expectedReturnValue, - ); + expect(util.transpileAndExecute(code, undefined, undefined, tableLib)).toBe(expectedReturnValue); }); }); diff --git a/test/unit/lualib/inlining.spec.ts b/test/unit/lualib/inlining.spec.ts index fcb5ba938..b7a73fc57 100644 --- a/test/unit/lualib/inlining.spec.ts +++ b/test/unit/lualib/inlining.spec.ts @@ -16,7 +16,7 @@ test("map foreach keys", () => { let count = 0; mymap.forEach((value, key) => { count += key; }); return count;`, - { luaLibImport: LuaLibImportKind.Inline }, + { luaLibImport: LuaLibImportKind.Inline } ); expect(result).toBe(18); @@ -25,7 +25,7 @@ test("map foreach keys", () => { test("set constructor", () => { const result = util.transpileAndExecute( `class abc {} let def = new abc(); let myset = new Set(); return myset.size;`, - { luaLibImport: LuaLibImportKind.Inline }, + { luaLibImport: LuaLibImportKind.Inline } ); expect(result).toBe(0); @@ -37,7 +37,7 @@ test("set foreach keys", () => { let count = 0; myset.forEach((value, key) => { count += key; }); return count;`, - { luaLibImport: LuaLibImportKind.Inline }, + { luaLibImport: LuaLibImportKind.Inline } ); expect(result).toBe(9); diff --git a/test/unit/lualib/lualib.spec.ts b/test/unit/lualib/lualib.spec.ts index eaf54d1f8..f2b5db912 100644 --- a/test/unit/lualib/lualib.spec.ts +++ b/test/unit/lualib/lualib.spec.ts @@ -6,7 +6,7 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forEach (%p)", ({ in arrTest.forEach((elem, index) => { arrTest[index] = arrTest[index] + 1; }) - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); expect(result).toBe(JSON.stringify(expected)); @@ -21,25 +21,25 @@ test.each([ `let arrTest = ${JSON.stringify(inp)}; return JSONStringify(arrTest.findIndex((elem, index) => { return elem === ${searchEl}; - }));`, + }));` ); expect(result).toBe(expected); }); -test.each([ - { inp: [0, 2, 4, 8], expected: 3, value: 8 }, - { inp: [0, 2, 4, 8], expected: 1, value: 2 }, -])("array.findIndex[index] (%p)", ({ inp, expected, value }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 2, 4, 8], expected: 3, value: 8 }, { inp: [0, 2, 4, 8], expected: 1, value: 2 }])( + "array.findIndex[index] (%p)", + ({ inp, expected, value }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; return JSONStringify(arrTest.findIndex((elem, index, arr) => { return index === ${expected} && arr[${expected}] === ${value}; - }));`, - ); + }));` + ); - expect(result).toBe(expected); -}); + expect(result).toBe(expected); + } +); test.each([ { inp: [], func: "x => x" }, @@ -49,9 +49,7 @@ test.each([ { inp: [0, 1, 2, 3], func: "x => x+2" }, { inp: [0, 1, 2, 3], func: "x => x%2 == 0 ? x + 1 : x - 1" }, ])("array.map (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].map(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].map(${func}))`); expect(result).toBe(JSON.stringify(inp.map(eval(func)))); }); @@ -65,9 +63,7 @@ test.each([ { inp: [0, 1, 2, 3], func: "() => true" }, { inp: [0, 1, 2, 3], func: "() => false" }, ])("array.filter (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].filter(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].filter(${func}))`); expect(result).toBe(JSON.stringify(inp.filter(eval(func)))); }); @@ -78,9 +74,7 @@ test.each([ { inp: [false, true, false], func: "x => x" }, { inp: [true, true, true], func: "x => x" }, ])("array.every (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].every(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].every(${func}))`); expect(result).toBe(JSON.stringify(inp.every(eval(func)))); }); @@ -91,9 +85,7 @@ test.each([ { inp: [false, true, false], func: "x => x" }, { inp: [true, true, true], func: "x => x" }, ])("array.some (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].some(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].some(${func}))`); expect(result).toBe(JSON.stringify(inp.some(eval(func)))); }); @@ -107,9 +99,7 @@ test.each([ { inp: [0, 1, 2, 3, 4, 5], start: 1, end: 3 }, { inp: [0, 1, 2, 3, 4, 5], start: 3 }, ])("array.slice (%p)", ({ inp, start, end }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`); expect(result).toBe(JSON.stringify(inp.slice(start, end))); }); @@ -126,7 +116,7 @@ test.each([ const result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); inp.splice(start, deleteCount, ...newElements); @@ -147,13 +137,13 @@ test.each([ result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); } else { result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); } @@ -182,7 +172,7 @@ test.each([ const result = util.transpileAndExecute( `let concatTestTable: any[] = ${JSON.stringify(arr)}; - return JSONStringify(concatTestTable.concat(${argStr}));`, + return JSONStringify(concatTestTable.concat(${argStr}));` ); const concatArr = arr.concat(...args); @@ -206,7 +196,7 @@ test.each([ } const result = util.transpileAndExecute( `let joinTestTable = ${JSON.stringify(inp)}; - return joinTestTable.join(${separatorLua});`, + return joinTestTable.join(${separatorLua});` ); const joinedInp = inp.join(separator); @@ -238,46 +228,46 @@ test.each([{ inp: [1, 2, 3], expected: 3 }, { inp: [1, 2, 3, 4, 5], expected: 3 ({ inp, expected }) => { const result = util.transpileAndExecute( `let [x, y, z] = ${JSON.stringify(inp)} - return z;`, + return z;` ); expect(result).toBe(expected); - }, + } ); test.each([{ inp: [1] }, { inp: [1, 2, 3] }])("array.push (%p)", ({ inp }) => { const result = util.transpileAndExecute( `let testArray = [0]; testArray.push(${inp.join(", ")}); - return JSONStringify(testArray);`, + return JSONStringify(testArray);` ); expect(result).toBe(JSON.stringify([0].concat(inp))); }); -test.each([ - { array: "[1, 2, 3]", expected: [3, 2] }, - { array: "[1, 2, 3, null]", expected: [3, 2] }, -])("array.pop (%p)", ({ array, expected }) => { - { - const result = util.transpileAndExecute( - `let testArray = ${array}; +test.each([{ array: "[1, 2, 3]", expected: [3, 2] }, { array: "[1, 2, 3, null]", expected: [3, 2] }])( + "array.pop (%p)", + ({ array, expected }) => { + { + const result = util.transpileAndExecute( + `let testArray = ${array}; let val = testArray.pop(); - return val`, - ); + return val` + ); - expect(result).toBe(expected[0]); - } - { - const result = util.transpileAndExecute( - `let testArray = ${array}; + expect(result).toBe(expected[0]); + } + { + const result = util.transpileAndExecute( + `let testArray = ${array}; testArray.pop(); - return testArray.length`, - ); + return testArray.length` + ); - expect(result).toBe(expected[1]); + expect(result).toBe(expected[1]); + } } -}); +); test.each([ { array: "[1, 2, 3]", expected: [3, 2, 1] }, @@ -289,7 +279,7 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.reverse(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); expect(result).toBe(JSON.stringify(expected)); }); @@ -305,7 +295,7 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.shift(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); expect(result).toBe(JSON.stringify(expectedArray)); } @@ -314,7 +304,7 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.shift(); - return val`, + return val` ); expect(result).toBe(expectedValue); @@ -331,7 +321,7 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; testArray.unshift(${toUnshift}); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); expect(result).toBe(JSON.stringify(expected)); @@ -346,14 +336,18 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; testArray.sort(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); expect(result).toBe(JSON.stringify(expected)); }); test.each([ - { array: [1, 2, 3, 4, 5], compareStr: "a - b", compareFn: (a: any, b: any) => a - b }, + { + array: [1, 2, 3, 4, 5], + compareStr: "a - b", + compareFn: (a: any, b: any) => a - b, + }, { array: ["4", "5", "3", "2", "1"], compareStr: "tonumber(a) - tonumber(b)", @@ -371,7 +365,7 @@ test.each([ return JSONStringify(testArray)`, undefined, undefined, - `declare function tonumber(this: void, e: any): number`, + `declare function tonumber(this: void, e: any): number` ); expect(result).toBe(JSON.stringify(array.sort(compareFn))); @@ -429,7 +423,7 @@ test.each([ `let a = 3; let delay = () => ${condition} ? a + 3 : a + 5; a = 8; - return delay();`, + return delay();` ); expect(result).toBe(expected); @@ -533,7 +527,7 @@ test.each([ return JSONStringify(obj);`, undefined, undefined, - objectFromEntriesDeclaration, + objectFromEntriesDeclaration ); expect(JSON.parse(result)).toEqual(expected); @@ -546,7 +540,7 @@ test("Object.fromEntries (Map)", () => { return JSONStringify(obj);`, undefined, undefined, - objectFromEntriesDeclaration, + objectFromEntriesDeclaration ); expect(JSON.parse(result)).toEqual({ foo: "bar" }); diff --git a/test/unit/lualib/map.spec.ts b/test/unit/lualib/map.spec.ts index 149ee258f..fc989628c 100644 --- a/test/unit/lualib/map.spec.ts +++ b/test/unit/lualib/map.spec.ts @@ -9,7 +9,7 @@ test("map constructor", () => { test("map iterable constructor", () => { const result = util.transpileAndExecute( `let mymap = new Map([["a", "c"],["b", "d"]]); - return mymap.has("a") && mymap.has("b");`, + return mymap.has("a") && mymap.has("b");` ); expect(result).toBe(true); @@ -44,7 +44,7 @@ test("map entries", () => { `let mymap = new Map([[5, 2],[6, 3],[7, 4]]); let count = 0; for (var [key, value] of mymap.entries()) { count += key + value; } - return count;`, + return count;` ); expect(result).toBe(27); }); @@ -54,7 +54,7 @@ test("map foreach", () => { `let mymap = new Map([["a", 2],["b", 3],["c", 4]]); let count = 0; mymap.forEach(i => count += i); - return count;`, + return count;` ); expect(result).toBe(9); @@ -65,31 +65,25 @@ test("map foreach keys", () => { `let mymap = new Map([[5, 2],[6, 3],[7, 4]]); let count = 0; mymap.forEach((value, key) => { count += key; }); - return count;`, + return count;` ); expect(result).toBe(18); }); test("map get", () => { - const result = util.transpileAndExecute( - `let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("a");`, - ); + const result = util.transpileAndExecute(`let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("a");`); expect(result).toBe("c"); }); test("map get missing", () => { - const result = util.transpileAndExecute( - `let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("c");`, - ); + const result = util.transpileAndExecute(`let mymap = new Map([["a", "c"],["b", "d"]]); return mymap.get("c");`); expect(result).toBe(undefined); }); test("map has", () => { - const contains = util.transpileAndExecute( - `let mymap = new Map([["a", "c"]]); return mymap.has("a");`, - ); + const contains = util.transpileAndExecute(`let mymap = new Map([["a", "c"]]); return mymap.has("a");`); expect(contains).toBe(true); }); @@ -99,9 +93,7 @@ test("map has false", () => { }); test("map has null", () => { - const contains = util.transpileAndExecute( - `let mymap = new Map([["a", "c"]]); return mymap.has(null);`, - ); + const contains = util.transpileAndExecute(`let mymap = new Map([["a", "c"]]); return mymap.has(null);`); expect(contains).toBe(false); }); @@ -110,7 +102,7 @@ test("map keys", () => { `let mymap = new Map([[5, 2],[6, 3],[7, 4]]); let count = 0; for (var key of mymap.keys()) { count += key; } - return count;`, + return count;` ); expect(result).toBe(18); @@ -130,7 +122,7 @@ test("map values", () => { `let mymap = new Map([[5, 2],[6, 3],[7, 4]]); let count = 0; for (var value of mymap.values()) { count += value; } - return count;`, + return count;` ); expect(result).toBe(9); @@ -140,10 +132,6 @@ test("map size", () => { expect(util.transpileAndExecute(`let m = new Map(); return m.size;`)).toBe(0); expect(util.transpileAndExecute(`let m = new Map(); m.set(1,3); return m.size;`)).toBe(1); expect(util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); return m.size;`)).toBe(2); - expect( - util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); m.clear(); return m.size;`), - ).toBe(0); - expect( - util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); m.delete(3); return m.size;`), - ).toBe(1); + expect(util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); m.clear(); return m.size;`)).toBe(0); + expect(util.transpileAndExecute(`let m = new Map([[1,2],[3,4]]); m.delete(3); return m.size;`)).toBe(1); }); diff --git a/test/unit/lualib/set.spec.ts b/test/unit/lualib/set.spec.ts index 1fce6ceb7..6018d42cf 100644 --- a/test/unit/lualib/set.spec.ts +++ b/test/unit/lualib/set.spec.ts @@ -9,7 +9,7 @@ test("set constructor", () => { test("set iterable constructor", () => { const result = util.transpileAndExecute( `let myset = new Set(["a", "b"]); - return myset.has("a") || myset.has("b");`, + return myset.has("a") || myset.has("b");` ); expect(result).toBe(true); @@ -18,16 +18,14 @@ test("set iterable constructor", () => { test("set iterable constructor set", () => { const result = util.transpileAndExecute( `let myset = new Set(new Set(["a", "b"])); - return myset.has("a") || myset.has("b");`, + return myset.has("a") || myset.has("b");` ); expect(result).toBe(true); }); test("set add", () => { - const has = util.transpileAndExecute( - `let myset = new Set(); myset.add("a"); return myset.has("a");`, - ); + const has = util.transpileAndExecute(`let myset = new Set(); myset.add("a"); return myset.has("a");`); expect(has).toBe(true); }); @@ -51,7 +49,7 @@ test("set entries", () => { `let myset = new Set([5, 6, 7]); let count = 0; for (var [key, value] of myset.entries()) { count += key + value; } - return count;`, + return count;` ); expect(result).toBe(36); @@ -62,7 +60,7 @@ test("set foreach", () => { `let myset = new Set([2, 3, 4]); let count = 0; myset.forEach(i => { count += i; }); - return count;`, + return count;` ); expect(result).toBe(9); }); @@ -72,16 +70,14 @@ test("set foreach keys", () => { `let myset = new Set([2, 3, 4]); let count = 0; myset.forEach((value, key) => { count += key; }); - return count;`, + return count;` ); expect(result).toBe(9); }); test("set has", () => { - const contains = util.transpileAndExecute( - `let myset = new Set(["a", "c"]); return myset.has("a");`, - ); + const contains = util.transpileAndExecute(`let myset = new Set(["a", "c"]); return myset.has("a");`); expect(contains).toBe(true); }); @@ -91,9 +87,7 @@ test("set has false", () => { }); test("set has null", () => { - const contains = util.transpileAndExecute( - `let myset = new Set(["a", "c"]); return myset.has(null);`, - ); + const contains = util.transpileAndExecute(`let myset = new Set(["a", "c"]); return myset.has(null);`); expect(contains).toBe(false); }); @@ -102,7 +96,7 @@ test("set keys", () => { `let myset = new Set([5, 6, 7]); let count = 0; for (var key of myset.keys()) { count += key; } - return count;`, + return count;` ); expect(result).toBe(18); @@ -113,7 +107,7 @@ test("set values", () => { `let myset = new Set([5, 6, 7]); let count = 0; for (var value of myset.values()) { count += value; } - return count;`, + return count;` ); expect(result).toBe(18); diff --git a/test/unit/lualib/symbol.spec.ts b/test/unit/lualib/symbol.spec.ts index 51be6c70e..857a9918a 100644 --- a/test/unit/lualib/symbol.spec.ts +++ b/test/unit/lualib/symbol.spec.ts @@ -1,26 +1,20 @@ import * as util from "../../util"; -test.each([{}, { description: 1 }, { description: "name" }])( - "symbol.toString() (%p)", - ({ description }) => { - const result = util.transpileAndExecute(` +test.each([{}, { description: 1 }, { description: "name" }])("symbol.toString() (%p)", ({ description }) => { + const result = util.transpileAndExecute(` return Symbol(${JSON.stringify(description)}).toString(); `); - expect(result).toBe(`Symbol(${description || ""})`); - }, -); + expect(result).toBe(`Symbol(${description || ""})`); +}); -test.each([{}, { description: 1 }, { description: "name" }])( - "symbol.description (%p)", - ({ description }) => { - const result = util.transpileAndExecute(` +test.each([{}, { description: 1 }, { description: "name" }])("symbol.description (%p)", ({ description }) => { + const result = util.transpileAndExecute(` return Symbol(${JSON.stringify(description)}).description; `); - expect(result).toBe(description); - }, -); + expect(result).toBe(description); +}); test("symbol uniqueness", () => { const result = util.transpileAndExecute(` diff --git a/test/unit/lualib/weakMap.spec.ts b/test/unit/lualib/weakMap.spec.ts index 51b5df8d8..71cabdbe1 100644 --- a/test/unit/lualib/weakMap.spec.ts +++ b/test/unit/lualib/weakMap.spec.ts @@ -118,5 +118,5 @@ test.each(["clear()", "keys()", "values()", "entries()", "forEach(() => {})"])( "weakMap has no map features (%p)", call => { expect(() => util.transpileAndExecute(`(new WeakMap() as any).${call}`)).toThrow(); - }, + } ); diff --git a/test/unit/lualib/weakSet.spec.ts b/test/unit/lualib/weakSet.spec.ts index 1b50a4756..1b86e960c 100644 --- a/test/unit/lualib/weakSet.spec.ts +++ b/test/unit/lualib/weakSet.spec.ts @@ -75,5 +75,5 @@ test.each(["clear()", "keys()", "values()", "entries()", "forEach(() => {})"])( "weakSet has no set features (%p)", call => { expect(() => util.transpileAndExecute(`(new WeakSet() as any).${call}`)).toThrow(); - }, + } ); diff --git a/test/unit/math.spec.ts b/test/unit/math.spec.ts index 46c23b0f4..9ff3442f7 100644 --- a/test/unit/math.spec.ts +++ b/test/unit/math.spec.ts @@ -18,15 +18,12 @@ test.each([ expect(lua).toBe(expected); }); -test.each(["E", "LN10", "LN2", "LOG10E", "LOG2E", "SQRT1_2", "SQRT2"])( - "Math constant (%p)", - constant => { - const epsilon = 0.000001; - const jsValue: number = (Math as Math & { [key: string]: any })[constant]; - const code = `return Math.abs(Math.${constant} - ${jsValue}) <= ${epsilon}`; - expect(util.transpileAndExecute(code)).toBe(true); - }, -); +test.each(["E", "LN10", "LN2", "LOG10E", "LOG2E", "SQRT1_2", "SQRT2"])("Math constant (%p)", constant => { + const epsilon = 0.000001; + const jsValue: number = (Math as Math & { [key: string]: any })[constant]; + const code = `return Math.abs(Math.${constant} - ${jsValue}) <= ${epsilon}`; + expect(util.transpileAndExecute(code)).toBe(true); +}); test.each([ { statement: "++x", expected: "x=4;y=6" }, @@ -49,7 +46,7 @@ test.each([ `let x = 3; let y = 6; ${statement}; - return \`x=\${x};y=\${y}\``, + return \`x=\${x};y=\${y}\`` ); expect(result).toBe(expected); }); @@ -75,7 +72,7 @@ test.each([ `let o = {p: 3}; let a = [6]; ${statement}; - return \`o=\${o.p};a=\${a[0]}\``, + return \`o=\${o.p};a=\${a[0]}\`` ); expect(result).toBe(expected); }); @@ -101,7 +98,7 @@ test.each([ `let o = {p: {d: 3}}; let a = [[6,11], [7,13]]; ${statement}; - return \`o=\${o.p.d};a=[\${a[0][0]},\${a[0][1]}],[\${a[1][0]},\${a[1][1]}]\``, + return \`o=\${o.p.d};a=[\${a[0][0]},\${a[0][1]}],[\${a[1][0]},\${a[1][1]}]\`` ); expect(result).toBe(expected); }); @@ -130,7 +127,7 @@ test.each([ function af() { return a; } function i() { return 0; } ${statement}; - return \`o=\${o.p};a=\${a[0]}\``, + return \`o=\${o.p};a=\${a[0]}\`` ); expect(result).toBe(expected); }); @@ -160,7 +157,7 @@ test.each([ let _i = 0; function i() { return _i++; } ${statement}; - return \`o=\${o.p.d};a=[\${a[0][0]},\${a[0][1]}],[\${a[1][0]},\${a[1][1]}];i=\${_i}\``, + return \`o=\${o.p.d};a=[\${a[0][0]},\${a[0][1]}],[\${a[1][0]},\${a[1][1]}];i=\${_i}\`` ); expect(result).toBe(expected); }); @@ -189,7 +186,7 @@ test.each([ `let x = 3; let y = 6; const r = ${expression}; - return \`\${r};x=\${x};y=\${y}\``, + return \`\${r};x=\${x};y=\${y}\`` ); expect(result).toBe(expected); }); @@ -218,7 +215,7 @@ test.each([ `let o = {p: 3}; let a = [6]; const r = ${expression}; - return \`\${r};o=\${o.p};a=\${a[0]}\``, + return \`\${r};o=\${o.p};a=\${a[0]}\`` ); expect(result).toBe(expected); }); @@ -250,7 +247,7 @@ test.each([ function af() { return a; } function i() { return 0; } const r = ${expression}; - return \`\${r};o=\${o.p};a=\${a[0]}\``, + return \`\${r};o=\${o.p};a=\${a[0]}\`` ); expect(result).toBe(expected); }); diff --git a/test/unit/modules.spec.ts b/test/unit/modules.spec.ts index 3869beadd..c47409707 100644 --- a/test/unit/modules.spec.ts +++ b/test/unit/modules.spec.ts @@ -11,11 +11,7 @@ describe("module import/export elision", () => { `; const expectToElideImport = (code: string) => { - const lua = util.transpileString( - { "module.d.ts": moduleDeclaration, "main.ts": code }, - undefined, - false, - ); + const lua = util.transpileString({ "module.d.ts": moduleDeclaration, "main.ts": code }, undefined, false); expect(() => util.executeLua(lua)).not.toThrow(); }; @@ -60,7 +56,7 @@ test.each([ "export { default as x } from '...';", ])("Export default keyword disallowed (%p)", exportStatement => { expect(() => util.transpileString(exportStatement)).toThrowExactError( - TSTLErrors.UnsupportedDefaultExport(util.nodeStub), + TSTLErrors.UnsupportedDefaultExport(util.nodeStub) ); }); @@ -78,7 +74,7 @@ test.each(["ke-bab", "dollar$", "singlequote'", "hash#", "s p a c e", "ɥɣɎɌ return foo;`; expect(util.executeLua(lua)).toBe("bar"); - }, + } ); test("defaultImport", () => { @@ -110,21 +106,20 @@ test("Non-exported module", () => { "return g.test();", undefined, undefined, - "module g { export function test() { return 3; } }", + "module g { export function test() { return 3; } }" ); expect(result).toBe(3); }); -test.each([ - tstl.LuaLibImportKind.Inline, - tstl.LuaLibImportKind.None, - tstl.LuaLibImportKind.Require, -])("LuaLib no uses? No code (%p)", luaLibImport => { - const lua = util.transpileString(``, { luaLibImport }); +test.each([tstl.LuaLibImportKind.Inline, tstl.LuaLibImportKind.None, tstl.LuaLibImportKind.Require])( + "LuaLib no uses? No code (%p)", + luaLibImport => { + const lua = util.transpileString(``, { luaLibImport }); - expect(lua).toBe(``); -}); + expect(lua).toBe(``); + } +); test("Nested module with dot in name", () => { const code = `module a.b { diff --git a/test/unit/numbers.spec.ts b/test/unit/numbers.spec.ts index e3f78ff10..ecda5d93a 100644 --- a/test/unit/numbers.spec.ts +++ b/test/unit/numbers.spec.ts @@ -19,14 +19,10 @@ test("NaN reassignment", () => { expect(result).toBe(NaN); }); -test.each([ - "Infinity", - "Infinity - Infinity", - "Infinity / -1", - "Infinity * -1", - "Infinity + 1", - "Infinity - 1", -])("%s", code => expect(util.transpileAndExecute(`return ${code}`)).toBe(eval(code))); +test.each(["Infinity", "Infinity - Infinity", "Infinity / -1", "Infinity * -1", "Infinity + 1", "Infinity - 1"])( + "%s", + code => expect(util.transpileAndExecute(`return ${code}`)).toBe(eval(code)) +); test("Infinity reassignment", () => { const result = util.transpileAndExecute(`const Infinity = 1; return Infinity`); diff --git a/test/unit/objectLiteral.spec.ts b/test/unit/objectLiteral.spec.ts index b199d3bf5..54323e528 100644 --- a/test/unit/objectLiteral.spec.ts +++ b/test/unit/objectLiteral.spec.ts @@ -34,7 +34,7 @@ describe("property shorthand", () => { `return ({ _G })._G.foobar;`, undefined, `foobar = "foobar"`, - "declare const _G: any;", + "declare const _G: any;" ); expect(result).toBe("foobar"); diff --git a/test/unit/overloads.spec.ts b/test/unit/overloads.spec.ts index 482cdd089..f911eeb2f 100644 --- a/test/unit/overloads.spec.ts +++ b/test/unit/overloads.spec.ts @@ -11,7 +11,7 @@ test("overload function1", () => { return def; } } - return abc(3);`, + return abc(3);` ); expect(result).toBe("jkl9"); @@ -28,7 +28,7 @@ test("overload function2", () => { return def; } } - return abc("ghj");`, + return abc("ghj");` ); expect(result).toBe("ghj"); @@ -47,7 +47,7 @@ test("overload method1", () => { } } } - return myclass.abc(3);`, + return myclass.abc(3);` ); expect(result).toBe("jkl9"); @@ -66,7 +66,7 @@ test("overload method2", () => { } } } - return myclass.abc("ghj");`, + return myclass.abc("ghj");` ); expect(result).toBe("ghj"); @@ -89,7 +89,7 @@ test("constructor1", () => { } } const inst = new myclass(3); - return inst.num`, + return inst.num` ); expect(result).toBe(3); @@ -112,7 +112,7 @@ test("constructor2", () => { } } const inst = new myclass("ghj"); - return inst.str`, + return inst.str` ); expect(result).toBe("ghj"); diff --git a/test/unit/require.spec.ts b/test/unit/require.spec.ts index 183bac892..bb9903a1b 100644 --- a/test/unit/require.spec.ts +++ b/test/unit/require.spec.ts @@ -86,13 +86,10 @@ test.each([ expect(match[1]).toBe(expectedPath); } } - }, + } ); -test.each([ - { comment: "", expectedPath: "src.fake" }, - { comment: "/** @noResolution */", expectedPath: "fake" }, -])( +test.each([{ comment: "", expectedPath: "src.fake" }, { comment: "/** @noResolution */", expectedPath: "fake" }])( "noResolution on ambient modules causes no path alterations (%p)", ({ comment, expectedPath }) => { const lua = util.transpileString({ @@ -105,5 +102,5 @@ test.each([ if (util.expectToBeDefined(match)) { expect(match[1]).toBe(expectedPath); } - }, + } ); diff --git a/test/unit/semicolons.spec.ts b/test/unit/semicolons.spec.ts index 7142fe548..2cbe3ecb6 100644 --- a/test/unit/semicolons.spec.ts +++ b/test/unit/semicolons.spec.ts @@ -1,17 +1,15 @@ import * as util from "../util"; -test.each([ - "const a = 1; const b = a;", - "const a = 1; let b: number; b = a;", - "{}", - "function bar() {} bar();", -])("semicolon insertion (%p)", leadingStatement => { - const code = ` +test.each(["const a = 1; const b = a;", "const a = 1; let b: number; b = a;", "{}", "function bar() {} bar();"])( + "semicolon insertion (%p)", + leadingStatement => { + const code = ` let result = ""; function foo() { result = "foo"; } ${leadingStatement} (foo)(); return result; `; - expect(util.transpileAndExecute(code)).toEqual("foo"); -}); + expect(util.transpileAndExecute(code)).toEqual("foo"); + } +); diff --git a/test/unit/sourcemaps.spec.ts b/test/unit/sourcemaps.spec.ts index 5d571f0d2..94cf8aca1 100644 --- a/test/unit/sourcemaps.spec.ts +++ b/test/unit/sourcemaps.spec.ts @@ -181,7 +181,7 @@ test("sourceMapTraceback saves sourcemap in _G", () => { typeScriptSource, options, undefined, - "declare const _G: {__TS__sourcemap: any};", + "declare const _G: {__TS__sourcemap: any};" ); // Assert @@ -225,9 +225,7 @@ test("Inline sourcemaps", () => { const { file } = util.transpileStringResult(typeScriptSource, compilerOptions); if (!util.expectToBeDefined(file.lua)) return; - const inlineSourceMapMatch = file.lua.match( - /--# sourceMappingURL=data:application\/json;base64,([A-Za-z0-9+/=]+)/, - ); + const inlineSourceMapMatch = file.lua.match(/--# sourceMappingURL=data:application\/json;base64,([A-Za-z0-9+/=]+)/); if (util.expectToBeDefined(inlineSourceMapMatch)) { const inlineSourceMap = Buffer.from(inlineSourceMapMatch[1], "base64").toString(); diff --git a/test/unit/spreadElement.spec.ts b/test/unit/spreadElement.spec.ts index ad50137ef..1177ff262 100644 --- a/test/unit/spreadElement.spec.ts +++ b/test/unit/spreadElement.spec.ts @@ -1,15 +1,12 @@ import * as tstl from "../../src"; import * as util from "../util"; -test.each([{ inp: [] }, { inp: [1, 2, 3] }, { inp: [1, "test", 3] }])( - "Spread Element Push (%p)", - ({ inp }) => { - const result = util.transpileAndExecute( - `return JSONStringify(([] as Array).push(...${JSON.stringify(inp)}));`, - ); - expect(result).toBe(([] as Array).push(...inp)); - }, -); +test.each([{ inp: [] }, { inp: [1, 2, 3] }, { inp: [1, "test", 3] }])("Spread Element Push (%p)", ({ inp }) => { + const result = util.transpileAndExecute( + `return JSONStringify(([] as Array).push(...${JSON.stringify(inp)}));` + ); + expect(result).toBe(([] as Array).push(...inp)); +}); test("Spread Element Lua 5.1", () => { // Cant test functional because our VM doesn't run on 5.1 diff --git a/test/unit/string.spec.ts b/test/unit/string.spec.ts index 17a340975..910303891 100644 --- a/test/unit/string.spec.ts +++ b/test/unit/string.spec.ts @@ -4,19 +4,12 @@ import * as util from "../util"; test("Unsuported string function", () => { expect(() => { util.transpileString(`return "test".testThisIsNoMember()`); - }).toThrowExactError( - TSTLErrors.UnsupportedProperty("string", "testThisIsNoMember", util.nodeStub), - ); + }).toThrowExactError(TSTLErrors.UnsupportedProperty("string", "testThisIsNoMember", util.nodeStub)); }); test("Suported lua string function", () => { expect( - util.transpileAndExecute( - `return "test".upper()`, - undefined, - undefined, - `interface String { upper(): string; }`, - ), + util.transpileAndExecute(`return "test".upper()`, undefined, undefined, `interface String { upper(): string; }`) ).toBe("TEST"); }); @@ -26,7 +19,7 @@ test.each([{ inp: [] }, { inp: [65] }, { inp: [65, 66] }, { inp: [65, 66, 67] }] const result = util.transpileAndExecute(`return String.fromCharCode(${inp.toString()})`); expect(result).toBe(String.fromCharCode(...inp)); - }, + } ); test.each([ @@ -99,9 +92,7 @@ test.each([ ])("string.replace (%p)", ({ inp, searchValue, replaceValue }) => { const replaceValueString = typeof replaceValue === "string" ? JSON.stringify(replaceValue) : replaceValue.toString(); - const result = util.transpileAndExecute( - `return "${inp}".replace("${searchValue}", ${replaceValueString});`, - ); + const result = util.transpileAndExecute(`return "${inp}".replace("${searchValue}", ${replaceValueString});`); // https://github.com/Microsoft/TypeScript/issues/22378 if (typeof replaceValue === "string") { @@ -158,16 +149,14 @@ test.each([ expect(result).toBe(inp.indexOf(searchValue, offset)); }); -test.each([ - { inp: "hello test", searchValue: "t", x: 4, y: 3 }, - { inp: "hello test", searchValue: "h", x: 3, y: 4 }, -])("string.indexOf with offset expression (%p)", ({ inp, searchValue, x, y }) => { - const result = util.transpileAndExecute( - `return "${inp}".indexOf("${searchValue}", 2 > 1 && ${x} || ${y})`, - ); - - expect(result).toBe(inp.indexOf(searchValue, x)); -}); +test.each([{ inp: "hello test", searchValue: "t", x: 4, y: 3 }, { inp: "hello test", searchValue: "h", x: 3, y: 4 }])( + "string.indexOf with offset expression (%p)", + ({ inp, searchValue, x, y }) => { + const result = util.transpileAndExecute(`return "${inp}".indexOf("${searchValue}", 2 > 1 && ${x} || ${y})`); + + expect(result).toBe(inp.indexOf(searchValue, x)); + } +); test.each([ { inp: "hello test" }, @@ -194,15 +183,15 @@ test.each([ expect(result).toBe(inp.substring(start, end)); }); -test.each([ - { inp: "hello test", start: 1, ignored: 0 }, - { inp: "hello test", start: 3, ignored: 0, end: 5 }, -])("string.substring with expression (%p)", ({ inp, start, ignored, end }) => { - const paramStr = `2 > 1 && ${start} || ${ignored}` + (end ? `, ${end}` : ""); - const result = util.transpileAndExecute(`return "${inp}".substring(${paramStr})`); +test.each([{ inp: "hello test", start: 1, ignored: 0 }, { inp: "hello test", start: 3, ignored: 0, end: 5 }])( + "string.substring with expression (%p)", + ({ inp, start, ignored, end }) => { + const paramStr = `2 > 1 && ${start} || ${ignored}` + (end ? `, ${end}` : ""); + const result = util.transpileAndExecute(`return "${inp}".substring(${paramStr})`); - expect(result).toBe(inp.substring(start, end)); -}); + expect(result).toBe(inp.substring(start, end)); + } +); test.each([ { inp: "hello test", start: 0 }, @@ -216,15 +205,15 @@ test.each([ expect(result).toBe(inp.substr(start, end)); }); -test.each([ - { inp: "hello test", start: 1, ignored: 0 }, - { inp: "hello test", start: 3, ignored: 0, end: 2 }, -])("string.substr with expression (%p)", ({ inp, start, ignored, end }) => { - const paramStr = `2 > 1 && ${start} || ${ignored}` + (end ? `, ${end}` : ""); - const result = util.transpileAndExecute(`return "${inp}".substr(${paramStr})`); +test.each([{ inp: "hello test", start: 1, ignored: 0 }, { inp: "hello test", start: 3, ignored: 0, end: 2 }])( + "string.substr with expression (%p)", + ({ inp, start, ignored, end }) => { + const paramStr = `2 > 1 && ${start} || ${ignored}` + (end ? `, ${end}` : ""); + const result = util.transpileAndExecute(`return "${inp}".substr(${paramStr})`); - expect(result).toBe(inp.substr(start, end)); -}); + expect(result).toBe(inp.substr(start, end)); + } +); test.each(["", "h", "hello"])("string.length (%p)", input => { const result = util.transpileAndExecute(`return "${input}".length`); @@ -269,15 +258,14 @@ test.each([ expect(result).toBe(inp.charAt(index)); }); -test.each([ - { inp: "hello test", index: 1 }, - { inp: "hello test", index: 2 }, - { inp: "hello test", index: 3 }, -])("string.charCodeAt (%p)", ({ inp, index }) => { - const result = util.transpileAndExecute(`return "${inp}".charCodeAt(${index})`); +test.each([{ inp: "hello test", index: 1 }, { inp: "hello test", index: 2 }, { inp: "hello test", index: 3 }])( + "string.charCodeAt (%p)", + ({ inp, index }) => { + const result = util.transpileAndExecute(`return "${inp}".charCodeAt(${index})`); - expect(result).toBe(inp.charCodeAt(index)); -}); + expect(result).toBe(inp.charCodeAt(index)); + } +); test.each([ { inp: "hello test", index: 1, ignored: 0 }, @@ -285,9 +273,7 @@ test.each([ { inp: "hello test", index: 3, ignored: 2 }, { inp: "hello test", index: 3, ignored: 99 }, ])("string.charAt with expression (%p)", ({ inp, index, ignored }) => { - const result = util.transpileAndExecute( - `return "${inp}".charAt(2 > 1 && ${index} || ${ignored})`, - ); + const result = util.transpileAndExecute(`return "${inp}".charAt(2 > 1 && ${index} || ${ignored})`); expect(result).toBe(inp.charAt(index)); }); diff --git a/test/unit/tuples.spec.ts b/test/unit/tuples.spec.ts index 08fbad709..0f6aa6a39 100644 --- a/test/unit/tuples.spec.ts +++ b/test/unit/tuples.spec.ts @@ -5,7 +5,7 @@ test("Tuple loop", () => { `const tuple: [number, number, number] = [3,5,1]; let count = 0; for (const value of tuple) { count += value; } - return count;`, + return count;` ); expect(result).toBe(9); @@ -16,7 +16,7 @@ test("Tuple foreach", () => { `const tuple: [number, number, number] = [3,5,1]; let count = 0; tuple.forEach(v => count += v); - return count;`, + return count;` ); expect(result).toBe(9); @@ -25,7 +25,7 @@ test("Tuple foreach", () => { test("Tuple access", () => { const result = util.transpileAndExecute( `const tuple: [number, number, number] = [3,5,1]; - return tuple[1];`, + return tuple[1];` ); expect(result).toBe(5); @@ -35,7 +35,7 @@ test("Tuple union access", () => { const result = util.transpileAndExecute( `function makeTuple(): [number, number, number] | [string, string, string] { return [3,5,1]; } const tuple = makeTuple(); - return tuple[1];`, + return tuple[1];` ); expect(result).toBe(5); }); @@ -49,7 +49,7 @@ test("Tuple intersection access", () => { return (t as I); } const tuple = makeTuple(); - return tuple[1];`, + return tuple[1];` ); expect(result).toBe(5); }); @@ -58,7 +58,7 @@ test("Tuple Destruct", () => { const result = util.transpileAndExecute( `function tuple(): [number, number, number] { return [3,5,1]; } const [a,b,c] = tuple(); - return b;`, + return b;` ); expect(result).toBe(5); @@ -91,7 +91,7 @@ test("Tuple Destruct Array Literal Extra Values", () => { test("Tuple length", () => { const result = util.transpileAndExecute( `const tuple: [number, number, number] = [3,5,1]; - return tuple.length;`, + return tuple.length;` ); expect(result).toBe(3); diff --git a/test/unit/typechecking.spec.ts b/test/unit/typechecking.spec.ts index 8088994b0..3d5014336 100644 --- a/test/unit/typechecking.spec.ts +++ b/test/unit/typechecking.spec.ts @@ -26,9 +26,7 @@ test.each(["{}", "[]"])("typeof object literal (%p)", inp => { }); test("typeof class instance", () => { - const result = util.transpileAndExecute( - `class myClass {} let inst = new myClass(); return typeof inst;`, - ); + const result = util.transpileAndExecute(`class myClass {} let inst = new myClass(); return typeof inst;`); expect(result).toBe("object"); }); @@ -47,7 +45,7 @@ test.each(["null", "undefined"])("typeof undefined (%p)", inp => { test("instanceof", () => { const result = util.transpileAndExecute( - "class myClass {} let inst = new myClass(); return inst instanceof myClass;", + "class myClass {} let inst = new myClass(); return inst instanceof myClass;" ); expect(result).toBe(true); @@ -98,9 +96,7 @@ test("instanceof undefined", () => { }); test("null instanceof Class", () => { - const result = util.transpileAndExecute( - "class myClass {} return (null as any) instanceof myClass;", - ); + const result = util.transpileAndExecute("class myClass {} return (null as any) instanceof myClass;"); expect(result).toBe(false); }); @@ -113,9 +109,7 @@ test.each(["extension", "metaExtension"])("instanceof extension (%p)", extension declare const foo: any; const result = foo instanceof B; `; - expect(() => util.transpileString(code)).toThrowExactError( - TSTLErrors.InvalidInstanceOfExtension(util.nodeStub), - ); + expect(() => util.transpileString(code)).toThrowExactError(TSTLErrors.InvalidInstanceOfExtension(util.nodeStub)); }); test("instanceof export", () => { @@ -123,7 +117,7 @@ test("instanceof export", () => { `export class myClass {} let inst = new myClass(); export const result = inst instanceof myClass;`, - "result", + "result" ); expect(result).toBe(true); diff --git a/test/util.ts b/test/util.ts index 43b748907..3da13b395 100644 --- a/test/util.ts +++ b/test/util.ts @@ -9,7 +9,7 @@ export const nodeStub = ts.createNode(ts.SyntaxKind.Unknown); export function transpileString( str: string | { [filename: string]: string }, options: tstl.CompilerOptions = {}, - ignoreDiagnostics = true, + ignoreDiagnostics = true ): string { const { diagnostics, file } = transpileStringResult(str, options); if (!expectToBeDefined(file) || !expectToBeDefined(file.lua)) return ""; @@ -22,7 +22,7 @@ export function transpileString( export function transpileStringResult( input: string | Record, - options: tstl.CompilerOptions = {}, + options: tstl.CompilerOptions = {} ): Required { const optionsWithDefaults = { luaTarget: tstl.LuaTarget.Lua53, @@ -36,7 +36,7 @@ export function transpileStringResult( const { diagnostics, transpiledFiles } = tstl.transpileVirtualProject( typeof input === "string" ? { "main.ts": input } : input, - optionsWithDefaults, + optionsWithDefaults ); const file = transpiledFiles.find(({ fileName }) => /\bmain\.[a-z]+$/.test(fileName)); @@ -47,10 +47,7 @@ export function transpileStringResult( return { diagnostics, file }; } -const lualibContent = fs.readFileSync( - path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"), - "utf8", -); +const lualibContent = fs.readFileSync(path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua"), "utf8"); const minimalTestLib = fs.readFileSync(path.join(__dirname, "json.lua"), "utf8") + "\n"; export function executeLua(luaStr: string, withLib = true): any { luaStr = luaStr.replace(/require\("lualib_bundle"\)/g, lualibContent); @@ -73,10 +70,7 @@ export function executeLua(luaStr: string, withLib = true): any { } else if (lua.lua_isstring(L, -1)) { return lua.lua_tojsstring(L, -1); } else { - throw new Error( - "Unsupported lua return type: " + - to_jsstring(lua.lua_typename(L, lua.lua_type(L, -1))), - ); + throw new Error("Unsupported lua return type: " + to_jsstring(lua.lua_typename(L, lua.lua_type(L, -1)))); } } else { // If the lua VM did not terminate with status code LUA_OK an error occurred. @@ -96,7 +90,7 @@ export function transpileAndExecute( tsStr: string, compilerOptions?: tstl.CompilerOptions, luaHeader?: string, - tsHeader?: string, + tsHeader?: string ): any { const wrappedTsString = `${tsHeader ? tsHeader : ""} declare function JSONStringify(this: void, p: any): string; @@ -113,7 +107,7 @@ export function transpileExecuteAndReturnExport( tsStr: string, returnExport: string, compilerOptions?: tstl.CompilerOptions, - luaHeader?: string, + luaHeader?: string ): any { const wrappedTsString = `declare function JSONStringify(this: void, p: any): string; ${tsStr}`; @@ -128,7 +122,7 @@ export function transpileExecuteAndReturnExport( export function parseTypeScript( typescript: string, - target: tstl.LuaTarget = tstl.LuaTarget.Lua53, + target: tstl.LuaTarget = tstl.LuaTarget.Lua53 ): [ts.SourceFile, ts.TypeChecker] { const program = tstl.createVirtualProgram({ "main.ts": typescript }, { luaTarget: target }); const sourceFile = program.getSourceFile("main.ts"); @@ -140,10 +134,7 @@ export function parseTypeScript( return [sourceFile, program.getTypeChecker()]; } -export function findFirstChild( - node: ts.Node, - predicate: (node: ts.Node) => boolean, -): ts.Node | undefined { +export function findFirstChild(node: ts.Node, predicate: (node: ts.Node) => boolean): ts.Node | undefined { for (const child of node.getChildren()) { if (predicate(child)) { return child; diff --git a/tslint.json b/tslint.json index 178f3066d..2bf168c59 100644 --- a/tslint.json +++ b/tslint.json @@ -1,30 +1,53 @@ { - "extends": "./test/tslint.json", "rules": { - "arrow-parens": [true, "ban-single-arg-parens"], - "import-spacing": true, - "max-line-length": [true, 120], - "new-parens": true, - "no-trailing-whitespace": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "trailing-comma": [ + "array-type": [true, "array-simple"], + "arrow-return-shorthand": true, + "ban": [ true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "never", - "typeLiterals": "always" - }, - "esSpecCompliant": true - } + { "name": "parseInt", "message": "tsstyle#type-coercion" }, + { "name": "parseFloat", "message": "tsstyle#type-coercion" }, + { "name": "Array", "message": "tsstyle#array-constructor" } ], - "whitespace": [ + "ban-types": [ true, - "check-type-operator", - "check-decl", - "check-rest-spread", - "check-typecast" - ] + ["Object", "Use {} instead."], + ["String", "Use 'string' instead."], + ["Number", "Use 'number' instead."], + ["Boolean", "Use 'boolean' instead."] + ], + "class-name": true, + "curly": [true, "ignore-same-line"], + "deprecation": true, + "forin": false, + "interface-name": [true, "never-prefix"], + "jsdoc-format": true, + "label-position": true, + "max-classes-per-file": [true, 1], + "member-access": true, + "no-angle-bracket-type-assertion": true, + "no-any": false, + "no-arg": true, + "no-conditional-assignment": true, + "no-construct": true, + "no-debugger": true, + "no-default-export": true, + "no-duplicate-switch-case": true, + "no-duplicate-variable": true, + "no-inferrable-types": true, + "no-namespace": [true, "allow-declarations"], + "no-null-keyword": true, + "no-reference": true, + "no-string-throw": true, + "no-unused-expression": true, + "no-var-keyword": true, + "object-literal-shorthand": true, + "only-arrow-functions": [true, "allow-declarations", "allow-named-functions"], + "prefer-const": [true, { "destructuring": "all" }], + "radix": true, + "switch-default": false, + "triple-equals": [true, "allow-null-check"], + "typedef": [true, "call-signature", "property-declaration"], + "use-isnan": true, + "variable-name": [true, "check-format", "ban-keywords", "allow-leading-underscore", "allow-pascal-case"] } }