From 64e3b9d7eca5db3cb108b7f3ab50e77b6a1c05c1 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Tue, 20 Jan 2026 18:40:32 +0800 Subject: [PATCH 1/2] Remove wasm workaround --- Cargo.lock | 37 +++++++----------- Cargo.toml | 2 +- wasm/.gitignore | 4 +- wasm/build-wasm.sh | 42 ++++++++++++++++---- wasm/package.json | 69 +++++++++++---------------------- wasm/src/stylua_lib_node.cjs | 7 ---- wasm/stylua_lib.d.cts | 2 - wasm/stylua_lib.d.mts | 2 - wasm/stylua_lib.mjs | 7 ---- wasm/stylua_lib_bundler.d.ts | 2 - wasm/stylua_lib_bundler.js | 7 ---- wasm/stylua_lib_bundler_wbg.cjs | 1 - 12 files changed, 74 insertions(+), 108 deletions(-) delete mode 100644 wasm/src/stylua_lib_node.cjs delete mode 100644 wasm/stylua_lib.d.cts delete mode 100644 wasm/stylua_lib.d.mts delete mode 100644 wasm/stylua_lib.mjs delete mode 100644 wasm/stylua_lib_bundler.d.ts delete mode 100644 wasm/stylua_lib_bundler.js delete mode 100644 wasm/stylua_lib_bundler_wbg.cjs diff --git a/Cargo.lock b/Cargo.lock index 57416163..14ecf1af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1174,34 +1174,22 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.100", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1209,22 +1197,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.100", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" diff --git a/Cargo.toml b/Cargo.toml index e81111fa..ec7da229 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ lsp-types = { version = "0.97", optional = true } lsp-textdocument = { version = "0.4.2", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen = { version = "0.2.81", optional = true } +wasm-bindgen = { version = "0.2.108", optional = true } # full-moon should be compiled to release optimisations in debug mode due to stack overflows # https://github.com/Kampfkarren/full-moon/issues/140 diff --git a/wasm/.gitignore b/wasm/.gitignore index c5163388..fb7c89f1 100644 --- a/wasm/.gitignore +++ b/wasm/.gitignore @@ -1,5 +1,5 @@ -stylua.web/ -stylua_lib.cjs +stylua.* +stylua_* LICENSE.md README.md *.tgz diff --git a/wasm/build-wasm.sh b/wasm/build-wasm.sh index 08c630dd..370b2036 100755 --- a/wasm/build-wasm.sh +++ b/wasm/build-wasm.sh @@ -1,10 +1,38 @@ +PROJECT_ROOT=$(dirname $0)/.. +CURRENT_DIR=$PROJECT_ROOT/wasm + # TODO: Ensure that version is up to date -cp README.md wasm/ -cp LICENSE.md wasm/ -npx wasm-pack@0.10.3 build --target web --out-dir wasm/stylua.web -- --features lua52,lua53,lua54,luajit,luau,cfxlua +cp $PROJECT_ROOT/README.md $CURRENT_DIR/ +cp $PROJECT_ROOT/LICENSE.md $CURRENT_DIR/ + +cargo build --target wasm32-unknown-unknown --release --features lua52,lua53,lua54,luajit,luau,cfxlua + +WASM_PATH=$PROJECT_ROOT/target/wasm32-unknown-unknown/release/stylua_lib.wasm + +# install wasm-bindgen if needed +command -v wasm-bindgen || cargo install wasm-bindgen-cli + +# check wasm-bindgen version +wasm-bindgen --version + +wasm-bindgen $WASM_PATH --target bundler --out-dir $CURRENT_DIR/stylua.bundler +wasm-bindgen $WASM_PATH --target nodejs --out-dir $CURRENT_DIR/stylua.node-cjs +wasm-bindgen $WASM_PATH --target experimental-nodejs-module --out-dir $CURRENT_DIR/stylua.node-esm +wasm-bindgen $WASM_PATH --target deno --out-dir $CURRENT_DIR/stylua.deno +wasm-bindgen $WASM_PATH --target web --out-dir $CURRENT_DIR/stylua.web + +cp -R $CURRENT_DIR/stylua.bundler/. $CURRENT_DIR/ + +cp $CURRENT_DIR/stylua.node-cjs/stylua_lib.js $CURRENT_DIR/stylua_lib_node.cjs +cp $CURRENT_DIR/stylua.node-cjs/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_node.d.cts + +cp $CURRENT_DIR/stylua.node-esm/stylua_lib.js $CURRENT_DIR/stylua_lib_node.mjs +cp $CURRENT_DIR/stylua.node-esm/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_node.d.mts + +cp $CURRENT_DIR/stylua.deno/stylua_lib.js $CURRENT_DIR/stylua_lib_deno.js +cp $CURRENT_DIR/stylua.deno/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_deno.d.ts -# workaround for bundler usage -echo "export { getImports as __getImports, finalizeInit as __finalizeInit }" >> wasm/stylua.web/stylua_lib.js +cp $CURRENT_DIR/stylua.web/stylua_lib.js $CURRENT_DIR/stylua_lib_web.js +cp $CURRENT_DIR/stylua.web/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_web.d.ts -# bundle for node CommonJS -npx rollup@4.9.5 wasm/src/stylua_lib_node.cjs --file wasm/stylua_lib.cjs --format cjs +echo "Done" diff --git a/wasm/package.json b/wasm/package.json index 9e2dbe7b..3fe162bc 100644 --- a/wasm/package.json +++ b/wasm/package.json @@ -12,65 +12,40 @@ "url": "https://github.com/johnnymorganz/stylua" }, "files": [ - "stylua.web/stylua_lib_bg.wasm.d.ts", - "stylua.web/stylua_lib_bg.wasm", - "stylua.web/stylua_lib.d.ts", - "stylua.web/stylua_lib.js", - "stylua_lib_bundler_wbg.cjs", - "stylua_lib_bundler.d.ts", - "stylua_lib_bundler.js", - "stylua_lib.cjs", - "stylua_lib.d.cts", - "stylua_lib.d.mts", - "stylua_lib.mjs", - "LICENSE.md" + "stylua_lib_*", + "stylua_lib.*", + "*.md" ], "type": "module", - "main": "stylua_lib.cjs", - "module": "stylua_lib_bundler.js", - "types": "stylua.web/stylua_lib.d.ts", + "main": "stylua_lib_node.cjs", + "module": "stylua_lib.js", + "types": "stylua_lib.d.ts", "exports": { ".": { - "webpack": { - "node": "./stylua_lib.mjs", - "default": "./stylua_lib_bundler.js" - }, - "require": { - "types": "./stylua_lib.d.cts", - "default": "./stylua_lib.cjs" - }, + "types": "./stylua_lib.d.ts", + "webpack": "./stylua_lib.js", "node": { - "types": "./stylua_lib.d.mts", - "default": "./stylua_lib.mjs" - }, - "deno": { - "types": "./stylua_lib.d.mts", - "default": "./stylua_lib.mjs" + "module-sync": "./stylua_lib_node.mjs", + "require": "./stylua_lib_node.cjs", + "default": "./stylua_lib_node.mjs" }, - "bun": { - "types": "./stylua_lib.d.mts", - "default": "./stylua_lib.mjs" - }, - "default": { - "types": "./stylua_lib_bundler.d.ts", - "default": "./stylua_lib_bundler.js" - } + "deno": "./stylua_lib_deno.js", + "bun": "./stylua_lib_node.mjs", + "default": "./stylua_lib.js" }, "./web": { - "types": "./stylua.web/stylua_lib.d.ts", - "default": "./stylua.web/stylua_lib.js" + "types": "./stylua_lib_web.d.ts", + "default": "./stylua_lib_web.js" }, - "./web/*": "./stylua.web/*", - "./stylua_lib_bg.wasm": "./stylua.web/stylua_lib_bg.wasm", - "./package.josn": "./package.josn", + "./stylua_lib_bg.wasm": "./stylua_lib_bg.wasm", + "./package.json": "./package.json", "./*": "./*" }, - "browser": { - "wbg": "./stylua_lib_bundler_wbg.cjs" - }, "sideEffects": [ - "stylua_lib.mjs", - "stylua_lib_bundler.js" + "./stylua_lib.js", + "./stylua_lib_node.mjs", + "./stylua_lib_node.cjs", + "./stylua_lib_deno.js" ], "keywords": [ "cli", diff --git a/wasm/src/stylua_lib_node.cjs b/wasm/src/stylua_lib_node.cjs deleted file mode 100644 index 7853d558..00000000 --- a/wasm/src/stylua_lib_node.cjs +++ /dev/null @@ -1,7 +0,0 @@ -export * from "../stylua.web/stylua_lib.js"; -import { initSync } from "../stylua.web/stylua_lib.js"; - -const path = require("path").join(__dirname, "stylua.web/stylua_lib_bg.wasm"); -const bytes = require("fs").readFileSync(path); - -initSync(bytes); diff --git a/wasm/stylua_lib.d.cts b/wasm/stylua_lib.d.cts deleted file mode 100644 index 533f4e60..00000000 --- a/wasm/stylua_lib.d.cts +++ /dev/null @@ -1,2 +0,0 @@ -export type * from "./stylua.web/stylua_lib"; -export declare const initSync: never; diff --git a/wasm/stylua_lib.d.mts b/wasm/stylua_lib.d.mts deleted file mode 100644 index 533f4e60..00000000 --- a/wasm/stylua_lib.d.mts +++ /dev/null @@ -1,2 +0,0 @@ -export type * from "./stylua.web/stylua_lib"; -export declare const initSync: never; diff --git a/wasm/stylua_lib.mjs b/wasm/stylua_lib.mjs deleted file mode 100644 index 196e3558..00000000 --- a/wasm/stylua_lib.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import fs from "node:fs"; -import { initSync } from "./stylua.web/stylua_lib.js"; - -const wasm = new URL("./stylua.web/stylua_lib_bg.wasm", import.meta.url); -initSync(fs.readFileSync(wasm)); - -export * from "./stylua.web/stylua_lib.js"; diff --git a/wasm/stylua_lib_bundler.d.ts b/wasm/stylua_lib_bundler.d.ts deleted file mode 100644 index 533f4e60..00000000 --- a/wasm/stylua_lib_bundler.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type * from "./stylua.web/stylua_lib"; -export declare const initSync: never; diff --git a/wasm/stylua_lib_bundler.js b/wasm/stylua_lib_bundler.js deleted file mode 100644 index 6622d86b..00000000 --- a/wasm/stylua_lib_bundler.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as wasm from "./stylua.web/stylua_lib_bg.wasm"; - -import { __finalizeInit } from "./stylua.web/stylua_lib.js"; - -__finalizeInit({ exports: wasm }); - -export * from "./stylua.web/stylua_lib.js"; diff --git a/wasm/stylua_lib_bundler_wbg.cjs b/wasm/stylua_lib_bundler_wbg.cjs deleted file mode 100644 index 9137e89f..00000000 --- a/wasm/stylua_lib_bundler_wbg.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./stylua.web/stylua_lib.js").__getImports().wbg; From c100c18ccafd2d454341188d0d2ac2f01bbd2f39 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 24 Jan 2026 13:02:04 +0000 Subject: [PATCH 2/2] Add smoketests --- .github/workflows/ci.yml | 6 +- wasm/build-wasm.sh | 11 +- wasm/package.json | 3 + wasm/tests/smoke.test.cjs | 118 +++++++++++++++ wasm/tests/smoke.test.mjs | 305 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 439 insertions(+), 4 deletions(-) create mode 100644 wasm/tests/smoke.test.cjs create mode 100644 wasm/tests/smoke.test.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f2cd456..0957c230 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,13 +92,13 @@ jobs: - name: Setup Node uses: actions/setup-node@v4 with: - node-version: "16.x" + node-version: "24.x" registry-url: "https://registry.npmjs.org" - - name: Test Build (wasm-pack) + - name: Test (WASM Build) run: | chmod u+x ./wasm/build-wasm.sh - ./wasm/build-wasm.sh + ./wasm/build-wasm.sh --test test_docker_build: runs-on: ubuntu-latest diff --git a/wasm/build-wasm.sh b/wasm/build-wasm.sh index 370b2036..4db19dc3 100755 --- a/wasm/build-wasm.sh +++ b/wasm/build-wasm.sh @@ -1,3 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail + PROJECT_ROOT=$(dirname $0)/.. CURRENT_DIR=$PROJECT_ROOT/wasm @@ -35,4 +38,10 @@ cp $CURRENT_DIR/stylua.deno/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_deno.d.ts cp $CURRENT_DIR/stylua.web/stylua_lib.js $CURRENT_DIR/stylua_lib_web.js cp $CURRENT_DIR/stylua.web/stylua_lib.d.ts $CURRENT_DIR/stylua_lib_web.d.ts -echo "Done" +echo "Build complete!" + +# Run smoke tests if --test flag is passed +if [ "$1" = "--test" ]; then + echo "Running smoke tests..." + cd $CURRENT_DIR && npm test +fi diff --git a/wasm/package.json b/wasm/package.json index 3fe162bc..0aa6d873 100644 --- a/wasm/package.json +++ b/wasm/package.json @@ -11,6 +11,9 @@ "type": "git", "url": "https://github.com/johnnymorganz/stylua" }, + "scripts": { + "test": "node --test tests/smoke.test.mjs tests/smoke.test.cjs" + }, "files": [ "stylua_lib_*", "stylua_lib.*", diff --git a/wasm/tests/smoke.test.cjs b/wasm/tests/smoke.test.cjs new file mode 100644 index 00000000..158a9fb2 --- /dev/null +++ b/wasm/tests/smoke.test.cjs @@ -0,0 +1,118 @@ +/** + * Smoke tests for StyLua WASM module (CommonJS) + * These tests verify that the CJS WASM bindings work correctly after build + */ + +const assert = require("node:assert"); +const { describe, it } = require("node:test"); + +// Import the Node.js CJS version +const stylua = require("../stylua_lib_node.cjs"); + +describe("StyLua WASM Smoke Tests (CJS)", () => { + describe("Module exports", () => { + it("should export formatCode function", () => { + assert.strictEqual(typeof stylua.formatCode, "function"); + }); + + it("should export Config class", () => { + assert.strictEqual(typeof stylua.Config, "function"); + }); + + it("should export Range class", () => { + assert.strictEqual(typeof stylua.Range, "function"); + }); + + it("should export SortRequiresConfig class", () => { + assert.strictEqual(typeof stylua.SortRequiresConfig, "function"); + }); + + it("should export OutputVerification enum", () => { + assert.ok(stylua.OutputVerification !== undefined); + }); + + it("should export LuaVersion enum", () => { + assert.ok(stylua.LuaVersion !== undefined); + }); + + it("should export IndentType enum", () => { + assert.ok(stylua.IndentType !== undefined); + }); + }); + + describe("Config", () => { + it("should create a default config", () => { + const config = stylua.Config.new(); + assert.ok(config !== undefined); + }); + + it("should have default column_width of 120", () => { + const config = stylua.Config.new(); + assert.strictEqual(config.column_width, 120); + }); + + it("should have default indent_width of 4", () => { + const config = stylua.Config.new(); + assert.strictEqual(config.indent_width, 4); + }); + }); + + describe("formatCode", () => { + it("should format simple Lua code", () => { + const config = stylua.Config.new(); + const result = stylua.formatCode( + "local x = 1", + config, + undefined, + stylua.OutputVerification.None + ); + assert.strictEqual(result, "local x = 1\n"); + }); + + it("should format code with custom config", () => { + const config = stylua.Config.new(); + config.indent_type = stylua.IndentType.Spaces; + config.indent_width = 2; + const code = "if true then\nreturn 1\nend"; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes(" return")); + }); + + it("should throw on invalid Lua code", () => { + const config = stylua.Config.new(); + assert.throws(() => { + stylua.formatCode( + "local x = ", + config, + undefined, + stylua.OutputVerification.None + ); + }); + }); + + it("should format with OutputVerification.Full", () => { + const config = stylua.Config.new(); + const result = stylua.formatCode( + "local x = 1", + config, + undefined, + stylua.OutputVerification.Full + ); + assert.strictEqual(result, "local x = 1\n"); + }); + }); + + describe("Range", () => { + it("should create a range from values", () => { + const range = stylua.Range.from_values(0, 100); + assert.ok(range !== undefined); + assert.strictEqual(range.start, 0); + assert.strictEqual(range.end, 100); + }); + }); +}); diff --git a/wasm/tests/smoke.test.mjs b/wasm/tests/smoke.test.mjs new file mode 100644 index 00000000..46a8757f --- /dev/null +++ b/wasm/tests/smoke.test.mjs @@ -0,0 +1,305 @@ +/** + * Smoke tests for StyLua WASM module + * These tests verify that the WASM bindings work correctly after build + */ + +import assert from "node:assert"; +import { describe, it } from "node:test"; + +// Import the Node.js ESM version +import * as stylua from "../stylua_lib_node.mjs"; + +describe("StyLua WASM Smoke Tests (ESM)", () => { + describe("Module exports", () => { + it("should export formatCode function", () => { + assert.strictEqual(typeof stylua.formatCode, "function"); + }); + + it("should export Config class", () => { + assert.strictEqual(typeof stylua.Config, "function"); + }); + + it("should export Range class", () => { + assert.strictEqual(typeof stylua.Range, "function"); + }); + + it("should export SortRequiresConfig class", () => { + assert.strictEqual(typeof stylua.SortRequiresConfig, "function"); + }); + + it("should export OutputVerification enum", () => { + assert.ok(stylua.OutputVerification !== undefined); + assert.strictEqual(typeof stylua.OutputVerification.Full, "number"); + assert.strictEqual(typeof stylua.OutputVerification.None, "number"); + }); + + it("should export LuaVersion enum", () => { + assert.ok(stylua.LuaVersion !== undefined); + assert.strictEqual(typeof stylua.LuaVersion.All, "number"); + assert.strictEqual(typeof stylua.LuaVersion.Lua51, "number"); + }); + + it("should export IndentType enum", () => { + assert.ok(stylua.IndentType !== undefined); + assert.strictEqual(typeof stylua.IndentType.Tabs, "number"); + assert.strictEqual(typeof stylua.IndentType.Spaces, "number"); + }); + + it("should export LineEndings enum", () => { + assert.ok(stylua.LineEndings !== undefined); + assert.strictEqual(typeof stylua.LineEndings.Unix, "number"); + assert.strictEqual(typeof stylua.LineEndings.Windows, "number"); + }); + + it("should export QuoteStyle enum", () => { + assert.ok(stylua.QuoteStyle !== undefined); + assert.strictEqual(typeof stylua.QuoteStyle.AutoPreferDouble, "number"); + assert.strictEqual(typeof stylua.QuoteStyle.AutoPreferSingle, "number"); + assert.strictEqual(typeof stylua.QuoteStyle.ForceDouble, "number"); + assert.strictEqual(typeof stylua.QuoteStyle.ForceSingle, "number"); + }); + + it("should export CallParenType enum", () => { + assert.ok(stylua.CallParenType !== undefined); + assert.strictEqual(typeof stylua.CallParenType.Always, "number"); + assert.strictEqual(typeof stylua.CallParenType.NoSingleString, "number"); + assert.strictEqual(typeof stylua.CallParenType.NoSingleTable, "number"); + assert.strictEqual(typeof stylua.CallParenType.None, "number"); + assert.strictEqual(typeof stylua.CallParenType.Input, "number"); + }); + + it("should export CollapseSimpleStatement enum", () => { + assert.ok(stylua.CollapseSimpleStatement !== undefined); + assert.strictEqual(typeof stylua.CollapseSimpleStatement.Never, "number"); + assert.strictEqual( + typeof stylua.CollapseSimpleStatement.FunctionOnly, + "number" + ); + assert.strictEqual( + typeof stylua.CollapseSimpleStatement.ConditionalOnly, + "number" + ); + assert.strictEqual( + typeof stylua.CollapseSimpleStatement.Always, + "number" + ); + }); + + it("should export SpaceAfterFunctionNames enum", () => { + assert.ok(stylua.SpaceAfterFunctionNames !== undefined); + assert.strictEqual( + typeof stylua.SpaceAfterFunctionNames.Never, + "number" + ); + assert.strictEqual( + typeof stylua.SpaceAfterFunctionNames.Definitions, + "number" + ); + assert.strictEqual(typeof stylua.SpaceAfterFunctionNames.Calls, "number"); + assert.strictEqual( + typeof stylua.SpaceAfterFunctionNames.Always, + "number" + ); + }); + }); + + describe("Config", () => { + it("should create a default config", () => { + const config = stylua.Config.new(); + assert.ok(config !== undefined); + }); + + it("should have default column_width of 120", () => { + const config = stylua.Config.new(); + assert.strictEqual(config.column_width, 120); + }); + + it("should have default indent_width of 4", () => { + const config = stylua.Config.new(); + assert.strictEqual(config.indent_width, 4); + }); + + it("should allow modifying config values", () => { + const config = stylua.Config.new(); + config.column_width = 80; + config.indent_width = 2; + config.indent_type = stylua.IndentType.Spaces; + assert.strictEqual(config.column_width, 80); + assert.strictEqual(config.indent_width, 2); + assert.strictEqual(config.indent_type, stylua.IndentType.Spaces); + }); + }); + + describe("Range", () => { + it("should create a range from values", () => { + const range = stylua.Range.from_values(0, 100); + assert.ok(range !== undefined); + assert.strictEqual(range.start, 0); + assert.strictEqual(range.end, 100); + }); + + it("should support undefined start/end", () => { + const range = stylua.Range.from_values(undefined, 50); + assert.ok(range !== undefined); + assert.strictEqual(range.start, undefined); + assert.strictEqual(range.end, 50); + }); + }); + + describe("SortRequiresConfig", () => { + it("should create a default sort requires config", () => { + const config = stylua.SortRequiresConfig.new(); + assert.ok(config !== undefined); + assert.strictEqual(config.enabled, false); + }); + + it("should allow setting enabled", () => { + const config = stylua.SortRequiresConfig.new(); + const newConfig = config.set_enabled(true); + assert.strictEqual(newConfig.enabled, true); + }); + }); + + describe("formatCode", () => { + it("should format simple Lua code", () => { + const config = stylua.Config.new(); + const result = stylua.formatCode( + "local x = 1", + config, + undefined, + stylua.OutputVerification.None + ); + assert.strictEqual(result, "local x = 1\n"); + }); + + it("should format code with custom column width", () => { + const config = stylua.Config.new(); + config.column_width = 40; + const code = + 'local very_long_variable_name = "some very long string value here"'; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes("\n")); // Should wrap due to narrow column width + }); + + it("should format code with spaces instead of tabs", () => { + const config = stylua.Config.new(); + config.indent_type = stylua.IndentType.Spaces; + config.indent_width = 2; + const code = "if true then\nreturn 1\nend"; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes(" return")); // 2 spaces for indent + }); + + it("should throw on invalid Lua code", () => { + const config = stylua.Config.new(); + assert.throws(() => { + stylua.formatCode( + "local x = ", + config, + undefined, + stylua.OutputVerification.None + ); + }); + }); + + it("should format with OutputVerification.Full", () => { + const config = stylua.Config.new(); + const result = stylua.formatCode( + "local x = 1", + config, + undefined, + stylua.OutputVerification.Full + ); + assert.strictEqual(result, "local x = 1\n"); + }); + + it("should format a range of code", () => { + const config = stylua.Config.new(); + const range = stylua.Range.from_values(0, 10); + const result = stylua.formatCode( + "local x = 1\nlocal y = 2", + config, + range, + stylua.OutputVerification.None + ); + assert.ok(result !== undefined); + }); + + it("should format Lua tables", () => { + const config = stylua.Config.new(); + const code = "local t = {a=1,b=2,c=3}"; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes("a = 1")); + assert.ok(result.includes("b = 2")); + assert.ok(result.includes("c = 3")); + }); + + it("should format function definitions", () => { + const config = stylua.Config.new(); + const code = "function foo(a,b,c) return a+b+c end"; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes("function foo(a, b, c)")); + }); + + it("should handle different quote styles", () => { + const config = stylua.Config.new(); + config.quote_style = stylua.QuoteStyle.ForceSingle; + const code = 'local x = "hello"'; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes("'hello'")); + }); + }); + + describe("Lua syntax versions", () => { + it("should format with Lua51 syntax", () => { + const config = stylua.Config.new(); + config.syntax = stylua.LuaVersion.Lua51; + const result = stylua.formatCode( + "local x = 1", + config, + undefined, + stylua.OutputVerification.None + ); + assert.strictEqual(result, "local x = 1\n"); + }); + + it("should format with Luau syntax", () => { + const config = stylua.Config.new(); + config.syntax = stylua.LuaVersion.Luau; + // Luau-specific type annotation + const code = "local x: number = 1"; + const result = stylua.formatCode( + code, + config, + undefined, + stylua.OutputVerification.None + ); + assert.ok(result.includes("local x: number = 1")); + }); + }); +});