diff --git a/.github/workflows/check_updates.yml b/.github/workflows/check_updates.yml new file mode 100644 index 0000000..4b8f9a3 --- /dev/null +++ b/.github/workflows/check_updates.yml @@ -0,0 +1,37 @@ +name: check_updates + +on: + workflow_dispatch: + schedule: + # do this once per day + - cron: "0 7 * * *" + +jobs: + build: + name: check updates + if: github.repository == 'dprint/dprint-plugin-sql' + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Clone repository + uses: actions/checkout@v6 + with: + token: ${{ secrets.GH_DPRINTBOT_PAT }} + + - uses: denoland/setup-deno@v2 + - uses: dsherret/rust-toolchain-file@v1 + + - name: Run script + run: | + git config user.email "dprintbot@users.noreply.github.com" + git config user.name "dprintbot" + deno run -A ./scripts/update.ts + # This is necessary to prevent GH automatically disabling this workflow after 60 days. + workflow-keepalive: + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + permissions: + actions: write + steps: + - uses: liskin/gh-workflow-keepalive@f72ff1a1336129f29bf0166c0fd0ca6cf1bcb38c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2e250f..dcb0da8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,126 +1,96 @@ -name: CI - -on: [push, pull_request] - -jobs: - build: - name: ${{ matrix.config.kind }} ${{ matrix.config.os }} - runs-on: ${{ matrix.config.os }} - strategy: - matrix: - config: - - os: ubuntu-latest - kind: test_release - - os: ubuntu-latest - kind: test_debug - - env: - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: full - - steps: - - uses: actions/checkout@v3 - - uses: dsherret/rust-toolchain-file@v1 - - name: Install wasm32 target - if: matrix.config.kind == 'test_release' - run: rustup target add wasm32-unknown-unknown - - - uses: Swatinem/rust-cache@v2 - with: - save-if: ${{ github.ref == 'refs/heads/main' }} - - - name: Build debug - if: matrix.config.kind == 'test_debug' - run: cargo build --verbose - - name: Build release - if: matrix.config.kind == 'test_release' - run: cargo build --target wasm32-unknown-unknown --features wasm --release --verbose - - - name: Test debug - if: matrix.config.kind == 'test_debug' - run: cargo test --verbose - - name: Test release - if: matrix.config.kind == 'test_release' - run: cargo test --release --verbose - - - name: Get tag version - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - id: get_tag_version - run: echo ::set-output name=TAG_VERSION::${GITHUB_REF/refs\/tags\//} - - # NPM - - uses: actions/setup-node@v2 - if: matrix.config.kind == 'test_release' - with: - node-version: '18.x' - registry-url: 'https://registry.npmjs.org' - - - name: Setup and test npm deployment - if: matrix.config.kind == 'test_release' - run: | - cd deployment/npm - npm install - node setup.js ${{ steps.get_tag_version.outputs.TAG_VERSION }} - npm run test - - - name: npm publish - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - cd deployment/npm - npm publish --access public - git reset --hard - - # CARGO PUBLISH - - name: Cargo login - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - run: cargo login ${{ secrets.CRATES_TOKEN }} - - - name: Cargo publish - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - run: cargo publish - - # GITHUB RELEASE - - name: Pre-release - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - run: | - # update config schema to have version - sed -i 's/sql\/0.0.0/sql\/${{ steps.get_tag_version.outputs.TAG_VERSION }}/' deployment/schema.json - # rename the wasm file - (cd target/wasm32-unknown-unknown/release/ && mv dprint_plugin_sql.wasm plugin.wasm) - - name: Release - uses: softprops/action-gh-release@v1 - if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - files: | - target/wasm32-unknown-unknown/release/plugin.wasm - deployment/schema.json - body: | - ## Install - - [Install](https://dprint.dev/install/) and [setup](https://dprint.dev/setup/) dprint. - - Then in your project's dprint configuration file: - - 1. Specify the plugin url in the `"plugins"` array. - 2. Add a `"sql"` configuration property if desired. - ```jsonc - { - // ...etc... - "sql": { - // sql config goes here - }, - "plugins": [ - "https://plugins.dprint.dev/sql-${{ steps.get_tag_version.outputs.TAG_VERSION }}.wasm" - ] - } - ``` - - ## JS Formatting API - - * [JS Formatter](https://github.com/dprint/js-formatter) - Browser/Deno and Node - * [npm package](https://www.npmjs.com/package/@dprint/sql) - draft: false +name: CI + +on: + push: + branches: [main] + tags: + - '*' + pull_request: + branches: [main] + +jobs: + build: + name: ${{ matrix.config.kind }} ${{ matrix.config.os }} + runs-on: ${{ matrix.config.os }} + strategy: + matrix: + config: + - os: ubuntu-latest + kind: test_release + - os: ubuntu-latest + kind: test_debug + + env: + CARGO_INCREMENTAL: 0 + RUST_BACKTRACE: full + + steps: + - uses: actions/checkout@v6 + - uses: dsherret/rust-toolchain-file@v1 + - name: Install wasm32 target + if: matrix.config.kind == 'test_release' + run: rustup target add wasm32-unknown-unknown + + - uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} + + - name: Build debug + if: matrix.config.kind == 'test_debug' + run: cargo build + - name: Build release + if: matrix.config.kind == 'test_release' + run: cargo build --target wasm32-unknown-unknown --features wasm --release + + - name: Test debug + if: matrix.config.kind == 'test_debug' + run: cargo test + - name: Test release + if: matrix.config.kind == 'test_release' + run: cargo test --release + + - name: Get tag version + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + id: get_tag_version + run: echo "TAG_VERSION=${GITHUB_REF/refs\/tags\//}" >> "$GITHUB_OUTPUT" + + # NPM + - uses: actions/setup-node@v6 + if: matrix.config.kind == 'test_release' + with: + node-version: '24.x' + registry-url: 'https://registry.npmjs.org' + + - name: Setup and test npm deployment + if: matrix.config.kind == 'test_release' + run: | + cd deployment/npm + npm install + node setup.js + npm run test + + # GITHUB RELEASE + - uses: denoland/setup-deno@v2 + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + with: + deno-version: v2.x + - name: Pre-release + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + run: | + # update config schema to have version + sed -i 's/sql\/0.0.0/sql\/${{ steps.get_tag_version.outputs.TAG_VERSION }}/' deployment/schema.json + # rename the wasm file + (cd target/wasm32-unknown-unknown/release/ && mv dprint_plugin_sql.wasm plugin.wasm) + # create release notes + deno run -A ./scripts/generateReleaseNotes.ts ${{ steps.get_tag_version.outputs.TAG_VERSION }} > ${{ github.workspace }}-CHANGELOG.txt + - name: Release + uses: softprops/action-gh-release@v2 + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + files: | + target/wasm32-unknown-unknown/release/plugin.wasm + deployment/schema.json + body_path: ${{ github.workspace }}-CHANGELOG.txt + draft: false diff --git a/.github/workflows/publish_npm.yml b/.github/workflows/publish_npm.yml new file mode 100644 index 0000000..560b519 --- /dev/null +++ b/.github/workflows/publish_npm.yml @@ -0,0 +1,38 @@ +name: publish npm + +on: + workflow_dispatch: + push: + tags: + - '*' + +permissions: + id-token: write + contents: read + +jobs: + build: + name: publish-npm + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: dsherret/rust-toolchain-file@v1 + - name: Install wasm32 target + run: rustup target add wasm32-unknown-unknown + - name: Build release + run: cargo build --target wasm32-unknown-unknown --features wasm --release + + - uses: actions/setup-node@v6 + with: + node-version: '24.x' + registry-url: 'https://registry.npmjs.org' + - name: Setup and test npm deployment + run: | + cd deployment/npm + npm install + node setup.js sync-version + npm run test + - name: npm publish + run: | + cd deployment/npm + npm publish --access public diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd63194..b46b0fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,11 +20,11 @@ jobs: steps: - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: token: ${{ secrets.GH_DPRINTBOT_PAT }} - - uses: denoland/setup-deno@v1 + - uses: denoland/setup-deno@v2 - uses: dsherret/rust-toolchain-file@v1 - name: Bump version and tag @@ -34,4 +34,4 @@ jobs: run: | git config user.email "${{ github.actor }}@users.noreply.github.com" git config user.name "${{ github.actor }}" - deno run -A https://raw.githubusercontent.com/dprint/automation/0.5.1/tasks/publish_release.ts --${{github.event.inputs.releaseKind}} + deno run -A https://raw.githubusercontent.com/dprint/automation/0.10.0/tasks/publish_release.ts --${{github.event.inputs.releaseKind}} diff --git a/.gitignore b/.gitignore index fe96a74..37f8a93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ +.claude /target Cargo.lock -deployment/npm/buffer.generated.js +deployment/npm/plugin.wasm deployment/npm/node_modules diff --git a/.rustfmt.toml b/.rustfmt.toml index 804c215..8287757 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,3 +1,3 @@ max_width = 120 tab_spaces = 2 -edition = "2021" +edition = "2024" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..22fed07 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,45 @@ +# dprint-plugin-sql + +Wrapper around [sqlformat-rs](https://github.com/shssoichiro/sqlformat-rs) for use as a dprint formatting plugin. + +## Commands + +- `cargo test` — run all tests +- `cargo build --target wasm32-unknown-unknown --features wasm --release` — build the wasm plugin +- `cd deployment/npm && node setup.js && npm test` — test the npm package (requires wasm build first) + +## Architecture + +- `src/format_text.rs` — core formatting logic, delegates to `sqlformat::format()` +- `src/wasm_plugin.rs` — dprint wasm plugin interface (compiled only for wasm32 target with `wasm` feature) +- `src/configuration/` — config types, resolution, and builder +- `deployment/npm/` — npm package that ships `plugin.wasm` +- `deployment/schema.json` — JSON schema for plugin configuration +- `scripts/update.ts` — Deno script that checks crates.io for new sqlformat versions and auto-publishes +- `scripts/generateReleaseNotes.ts` — generates changelog for GitHub releases + +## Adding a new config option + +When sqlformat-rs adds new options: + +1. Add the field to `Configuration` in `src/configuration/configuration.rs` (add enums with `generate_str_to_from!` if needed) +2. Add resolution in `src/configuration/resolve_config.rs` using `get_value()` +3. Add a builder method in `src/configuration/builder.rs` and update the `check_all_values_set` test +4. Wire it through in `src/format_text.rs` when constructing `FormatOptions` +5. Add the property to `deployment/schema.json` +6. Add a spec test file in `tests/specs/Config/` + +## Test specs + +Spec files live in `tests/specs/` and use the dprint-development format: + +- `== message ==` starts a test case +- `[expect]` separates input from expected output +- `~~ key: value, key: value ~~` at the top of a file sets config for all specs in that file +- Each config variation needs its own file since config is file-level + +## Releases + +- Manual: trigger the `release` workflow with patch/minor +- Automatic: `check_updates` workflow runs daily, detects new sqlformat versions, and auto-publishes +- On tag push: CI creates a GitHub release with `plugin.wasm`, and `publish_npm` publishes to npm diff --git a/Cargo.toml b/Cargo.toml index d8e100e..f87b740 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "dprint-plugin-sql" version = "0.2.0" authors = ["David Sherret "] -edition = "2021" +edition = "2024" homepage = "https://github.com/dprint/dprint-plugin-sql" keywords = ["formatting", "formatter", "sql"] license = "MIT" @@ -25,11 +25,11 @@ wasm = ["serde_json", "dprint-core/wasm"] [dependencies] anyhow = "1.0.51" -dprint-core = { version = "0.62.1", features = ["formatting"] } +dprint-core = { version = "0.67.4", default-features = false } serde = { version = "1.0.88", features = ["derive"] } serde_json = { version = "1.0", optional = true } -sqlformat = "0.3.5" +sqlformat = "0.5.0" [dev-dependencies] -dprint-development = "0.9.3" +dprint-development = "0.10.1" serde_json = { version = "1.0" } diff --git a/LICENSE b/LICENSE index c40f5a1..4d08264 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2021-2022 David Sherret +Copyright (c) 2021 David Sherret Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..4ee8a57 --- /dev/null +++ b/deno.json @@ -0,0 +1,6 @@ +{ + "imports": { + "automation": "https://raw.githubusercontent.com/dprint/automation/0.10.0/mod.ts", + "automation/": "https://raw.githubusercontent.com/dprint/automation/0.10.0/" + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..737e7b6 --- /dev/null +++ b/deno.lock @@ -0,0 +1,90 @@ +{ + "version": "5", + "specifiers": { + "jsr:@david/dax@0.42.0": "0.42.0", + "jsr:@david/path@0.2": "0.2.0", + "jsr:@david/which@~0.4.1": "0.4.1", + "jsr:@std/assert@0.221": "0.221.0", + "jsr:@std/bytes@0.221": "0.221.0", + "jsr:@std/fmt@1": "1.0.9", + "jsr:@std/fs@1": "1.0.23", + "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/io@0.221": "0.221.0", + "jsr:@std/path@1": "1.1.4", + "jsr:@std/path@^1.1.4": "1.1.4", + "jsr:@std/semver@1": "1.0.8", + "jsr:@std/streams@0.221": "0.221.0" + }, + "jsr": { + "@david/dax@0.42.0": { + "integrity": "0c547c9a20577a6072b90def194c159c9ddab82280285ebfd8268a4ebefbd80b", + "dependencies": [ + "jsr:@david/path", + "jsr:@david/which", + "jsr:@std/fmt", + "jsr:@std/fs", + "jsr:@std/io", + "jsr:@std/path@1", + "jsr:@std/streams" + ] + }, + "@david/path@0.2.0": { + "integrity": "f2d7aa7f02ce5a55e27c09f9f1381794acb09d328f8d3c8a2e3ab3ffc294dccd", + "dependencies": [ + "jsr:@std/fs", + "jsr:@std/path@1" + ] + }, + "@david/which@0.4.1": { + "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" + }, + "@std/assert@0.221.0": { + "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" + }, + "@std/bytes@0.221.0": { + "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" + }, + "@std/fmt@1.0.9": { + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" + }, + "@std/fs@1.0.23": { + "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", + "dependencies": [ + "jsr:@std/internal", + "jsr:@std/path@^1.1.4" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/io@0.221.0": { + "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/bytes" + ] + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/semver@1.0.8": { + "integrity": "dc830e8b8b6a380c895d53fbfd1258dc253704ca57bbe1629ac65fd7830179b7" + }, + "@std/streams@0.221.0": { + "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61", + "dependencies": [ + "jsr:@std/io" + ] + } + }, + "remote": { + "https://raw.githubusercontent.com/dprint/automation/0.10.0/cargo.ts": "09cde3f879a9363a6d47bd2eebe7a78ed337172be5a133c72ba975674157c17d", + "https://raw.githubusercontent.com/dprint/automation/0.10.0/deps.ts": "4153d1d241c9d43b73bce43377b4e4ac828184e0dcef8d6c934c50c0dfaaefec", + "https://raw.githubusercontent.com/dprint/automation/0.10.0/hash.ts": "b81cab5700a6d7b6a0a4ff5b60bf0e26a2827eafd747ddd4c10bc6a4887d8d94", + "https://raw.githubusercontent.com/dprint/automation/0.10.0/mod.ts": "5f330d62cc675f3b6c464b186809d30df12830a1e4d4cbb64e1a494d058c6163", + "https://raw.githubusercontent.com/dprint/automation/0.10.0/process_plugin.ts": "232420b223baf7f21d31cfc103407ae229ec82b6e38676949994310ea9396909" + } +} diff --git a/deployment/npm/index.js b/deployment/npm/index.js index 8f35196..4cf0ee3 100644 --- a/deployment/npm/index.js +++ b/deployment/npm/index.js @@ -1,32 +1,12 @@ -/** - * Gets a buffer representing the WASM module. - * @returns {ArrayBuffer} - */ -function getBuffer() { - const encodedBuffer = require("./buffer.generated").encodedBuffer; - return decodeEncodedBuffer(encodedBuffer); -} +const fs = require("fs"); +const path = require("path"); /** - * @param {string} encodedBuffer + * Gets a buffer representing the Wasm module. * @returns {ArrayBuffer} */ -function decodeEncodedBuffer(encodedBuffer) { - // https://stackoverflow.com/a/51473757/188246 - const binaryString = toBinaryString(); - const bytes = new Uint8Array(binaryString.length); - for (let i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i); - } - return bytes.buffer; - - function toBinaryString() { - if (typeof atob === "function") { - return atob(encodedBuffer); - } else { - return Buffer.from(encodedBuffer, "base64").toString("binary"); - } - } +function getBuffer() { + return fs.readFileSync(path.join(__dirname, "plugin.wasm")); } module.exports = { diff --git a/deployment/npm/index.test.js b/deployment/npm/index.test.js index ade62d0..6369522 100644 --- a/deployment/npm/index.test.js +++ b/deployment/npm/index.test.js @@ -4,6 +4,9 @@ const createFromBuffer = require("@dprint/formatter").createFromBuffer; const getBuffer = require("./index").getBuffer; const formatter = createFromBuffer(getBuffer()); -const result = formatter.formatText("file.sql", "SELECT * FROM dbo.Test"); +const result = formatter.formatText({ + filePath: "file.sql", + fileText: "SELECT * FROM dbo.Test", +}); assert.strictEqual(result, "SELECT\n *\nFROM\n dbo.Test\n"); diff --git a/deployment/npm/package-lock.json b/deployment/npm/package-lock.json index 584578e..6ed6db0 100644 --- a/deployment/npm/package-lock.json +++ b/deployment/npm/package-lock.json @@ -1,14 +1,23 @@ -{ - "name": "@dprint/sql", - "version": "0.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@dprint/formatter": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@dprint/formatter/-/formatter-0.1.4.tgz", - "integrity": "sha512-L7PifpVn+u1fH+5jUNv6W2Ie5LYvG5rlXCB9hn/byozAj1WOjaZczwvWmYWNS2zObF3d+PjKf6ON+HCPHjqNvQ==", - "dev": true - } - } -} +{ + "name": "@dprint/sql", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@dprint/sql", + "version": "0.0.0", + "license": "MIT", + "devDependencies": { + "@dprint/formatter": "~0.4.0" + } + }, + "node_modules/@dprint/formatter": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@dprint/formatter/-/formatter-0.4.1.tgz", + "integrity": "sha512-IB/GXdlMOvi0UhQQ9mcY15Fxcrc2JPadmo6tqefCNV0bptFq7YBpggzpqYXldBXDa04CbKJ+rDwO2eNRPE2+/g==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/deployment/npm/package.json b/deployment/npm/package.json index d476a26..2f1a26a 100644 --- a/deployment/npm/package.json +++ b/deployment/npm/package.json @@ -24,6 +24,6 @@ "test": "node index.test.js" }, "devDependencies": { - "@dprint/formatter": "~0.1.4" + "@dprint/formatter": "~0.4.0" } } diff --git a/deployment/npm/setup.js b/deployment/npm/setup.js index 79cd844..c666ddb 100644 --- a/deployment/npm/setup.js +++ b/deployment/npm/setup.js @@ -3,19 +3,24 @@ const fs = require("fs"); const path = require("path"); const args = process.argv.slice(2); const wasmPath = path.join(__dirname, "../../target/wasm32-unknown-unknown/release/dprint_plugin_sql.wasm"); -const wasmBytes = fs.readFileSync(wasmPath); - -let output = "module.exports.encodedBuffer = \""; -output += wasmBytes.toString("base64"); -output += "\";\n"; - -fs.writeFileSync(path.join(__dirname, "buffer.generated.js"), output); +const targetPath = path.join(__dirname, "plugin.wasm"); +fs.copyFileSync(wasmPath, targetPath); if (args.length > 0) { // update the version based on the first argument const packageJsonPath = path.join(__dirname, "package.json"); const packageJsonText = fs.readFileSync(packageJsonPath, "utf8"); const packageJson = JSON.parse(packageJsonText); - packageJson.version = args[0]; + if (args[0] === "sync-version") { + const cargoTomlPath = path.join(__dirname, "../../Cargo.toml"); + const cargoTomlText = fs.readFileSync(cargoTomlPath, "utf8"); + const versionMatch = cargoTomlText.match(/^version\s*=\s*"([^"]+)"/m); + if (!versionMatch) { + throw new Error("Could not find version in Cargo.toml"); + } + packageJson.version = versionMatch[1]; + } else { + packageJson.version = args[0]; + } fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, undefined, 2) + "\n"); } diff --git a/deployment/schema.json b/deployment/schema.json index a9a10d1..d47d859 100644 --- a/deployment/schema.json +++ b/deployment/schema.json @@ -47,14 +47,49 @@ "$ref": "#/definitions/newLineKind" }, "uppercase": { - "description": "Use ALL CAPS for reserved words.", + "description": "Deprecated. Use 'casing' instead. Use ALL CAPS for reserved words.", "default": false, "type": "boolean" }, + "casing": { + "description": "Controls the casing of reserved words.", + "type": "string", + "default": "preserve", + "oneOf": [{ + "const": "preserve", + "description": "Preserves the original casing of reserved words." + }, { + "const": "upper", + "description": "Converts reserved words to UPPERCASE." + }, { + "const": "lower", + "description": "Converts reserved words to lowercase." + }] + }, "linesBetweenQueries": { - "description": "Number of line breaks between quries.", + "description": "Number of line breaks between queries.", "default": 1, "type": "number" + }, + "joinsAsTopLevel": { + "description": "Consider JOIN statements as top-level keywords instead of reserved keywords.", + "default": false, + "type": "boolean" + }, + "dialect": { + "description": "The SQL dialect to use for parsing.", + "type": "string", + "default": "generic", + "oneOf": [{ + "const": "generic", + "description": "Generic SQL syntax." + }, { + "const": "postgresql", + "description": "PostgreSQL syntax with array syntax and operators." + }, { + "const": "sqlserver", + "description": "SQL Server syntax with bracketed identifiers and @variables." + }] } } } diff --git a/dprint.json b/dprint.json index 6660f7e..de96a9f 100644 --- a/dprint.json +++ b/dprint.json @@ -1,7 +1,10 @@ { "exec": { - "associations": "**/*.rs", - "rustfmt": "rustfmt" + "cwd": "${configDir}", + "commands": [{ + "command": "rustfmt", + "exts": ["rs"] + }] }, "excludes": [ "**/node_modules", @@ -9,10 +12,10 @@ "**/target" ], "plugins": [ - "https://plugins.dprint.dev/typescript-0.85.1.wasm", - "https://plugins.dprint.dev/json-0.17.4.wasm", - "https://plugins.dprint.dev/markdown-0.15.3.wasm", - "https://plugins.dprint.dev/toml-0.5.4.wasm", - "https://plugins.dprint.dev/exec-0.3.5.json@d687dda57be0fe9a0088ccdaefa5147649ff24127d8b3ea227536c68ee7abeab" + "https://plugins.dprint.dev/typescript-0.95.13.wasm", + "https://plugins.dprint.dev/json-0.21.0.wasm", + "https://plugins.dprint.dev/markdown-0.20.0.wasm", + "https://plugins.dprint.dev/toml-0.7.0.wasm", + "https://plugins.dprint.dev/exec-0.6.0.json@a054130d458f124f9b5c91484833828950723a5af3f8ff2bd1523bd47b83b364" ] } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c05dd69..711b3a4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.86" +channel = "1.92.0" components = ["clippy", "rustfmt"] diff --git a/scripts/generateReleaseNotes.ts b/scripts/generateReleaseNotes.ts new file mode 100644 index 0000000..c92b67b --- /dev/null +++ b/scripts/generateReleaseNotes.ts @@ -0,0 +1,27 @@ +import { generateChangeLog } from "automation/changelog.ts"; + +const version = Deno.args[0]; +const changelog = await generateChangeLog({ + versionTo: version, +}); +const text = `## Changes + +${changelog} + +## Install + +[Install](https://dprint.dev/install/) and [setup](https://dprint.dev/setup/) dprint. + +Then in your project's directory with a dprint.json file, run: + +\`\`\`shellsession +dprint config add sql +\`\`\` + +## JS Formatting API + +* [JS Formatter](https://github.com/dprint/js-formatter) - Browser/Deno and Node +* [npm package](https://www.npmjs.com/package/@dprint/sql) +`; + +console.log(text); diff --git a/scripts/update.ts b/scripts/update.ts new file mode 100644 index 0000000..70a7c93 --- /dev/null +++ b/scripts/update.ts @@ -0,0 +1,71 @@ +/** + * This script checks for any sqlformat updates and then automatically + * publishes a new version of the plugin if so. + */ +import { $, CargoToml, semver } from "automation"; + +const rootDirPath = $.path(import.meta.dirname!).parentOrThrow(); +const cargoToml = new CargoToml(rootDirPath.join("Cargo.toml")); +const currentVersion = getSqlformatVersion(cargoToml.text()); + +$.logStep("Getting latest version..."); +const latestVersion = await getLatestSqlformatVersion(); +if (semver.compare(currentVersion, latestVersion) >= 0) { + $.log("No new update found. Exiting."); + Deno.exit(0); +} + +$.log("Found new version."); +$.logStep("Updating Cargo.toml..."); +const isPatchBump = currentVersion.major === latestVersion.major + && currentVersion.minor === latestVersion.minor; +const currentVersionStr = `${currentVersion.major}.${currentVersion.minor}.${currentVersion.patch}`; +const latestVersionStr = `${latestVersion.major}.${latestVersion.minor}.${latestVersion.patch}`; +cargoToml.replaceAll(`sqlformat = "${currentVersionStr}"`, `sqlformat = "${latestVersionStr}"`); + +// run the tests +$.logStep("Running tests..."); +await $`cargo test`; + +if (Deno.args.includes("--skip-publish")) { + Deno.exit(0); +} + +$.logStep(`Committing sqlformat version bump commit...`); +await $`git add .`; +const message = `${isPatchBump ? "fix" : "feat"}: update to sqlformat ${latestVersionStr}`; +await $`git commit -m ${message}`; + +$.logStep("Bumping version in Cargo.toml..."); +cargoToml.bumpCargoTomlVersion(isPatchBump ? "patch" : "minor"); + +// release +const newVersion = cargoToml.version(); +$.logStep(`Committing and publishing ${newVersion}...`); +await $`git add .`; +await $`git commit -m ${newVersion}`; +await $`git push origin main`; +await $`git tag ${newVersion}`; +await $`git push origin ${newVersion}`; + +function getSqlformatVersion(text: string) { + const match = text.match(/sqlformat\s*=\s*"([^"]+)"/); + const version = match?.[1]; + if (version == null) { + throw new Error("Could not find sqlformat version in Cargo.toml."); + } + $.logLight("Found sqlformat version in Cargo.toml:", version); + return semver.parse(version); +} + +async function getLatestSqlformatVersion() { + const response = await fetch("https://crates.io/api/v1/crates/sqlformat", { + headers: { + "User-Agent": "dprint-plugin-sql update script", + }, + }); + const data = await response.json(); + const version = data.crate.max_stable_version ?? data.crate.max_version; + $.logLight("Latest sqlformat version:", version); + return semver.parse(version); +} diff --git a/src/configuration/builder.rs b/src/configuration/builder.rs index a1a1104..a8c2abd 100644 --- a/src/configuration/builder.rs +++ b/src/configuration/builder.rs @@ -12,7 +12,7 @@ use super::*; /// use dprint_plugin_sql::configuration::*; /// /// let config = ConfigurationBuilder::new() -/// .uppercase(true) +/// .casing(UppercaseKind::Upper) /// .build(); /// ``` pub struct ConfigurationBuilder { @@ -34,7 +34,7 @@ impl ConfigurationBuilder { if let Some(global_config) = &self.global_config { resolve_config(self.config.clone(), global_config).config } else { - let global_config = resolve_global_config(Default::default(), &Default::default()).config; + let global_config = resolve_global_config(&mut Default::default()).config; resolve_config(self.config.clone(), &global_config).config } } @@ -54,7 +54,7 @@ impl ConfigurationBuilder { /// The number of columns for an indent. /// - /// Default: `4` + /// Default: `2` pub fn indent_width(&mut self, value: u8) -> &mut Self { self.insert("indentWidth", (value as i32).into()) } @@ -65,10 +65,10 @@ impl ConfigurationBuilder { self.insert("newLineKind", value.to_string().into()) } - /// Use ALL CAPS for reserved words. - /// Default: `false` - pub fn uppercase(&mut self, value: bool) -> &mut Self { - self.insert("uppercase", value.into()) + /// Controls casing of reserved words. + /// Default: `UppercaseKind::Preserve` + pub fn casing(&mut self, value: UppercaseKind) -> &mut Self { + self.insert("casing", value.to_string().into()) } /// Number of line breaks between queries. @@ -77,6 +77,18 @@ impl ConfigurationBuilder { self.insert("linesBetweenQueries", (value as i32).into()) } + /// Consider JOIN statements as top-level keywords. + /// Default: `false` + pub fn joins_as_top_level(&mut self, value: bool) -> &mut Self { + self.insert("joinsAsTopLevel", value.into()) + } + + /// The SQL dialect to use. + /// Default: `Dialect::Generic` + pub fn dialect(&mut self, value: Dialect) -> &mut Self { + self.insert("dialect", value.to_string().into()) + } + #[cfg(test)] pub(super) fn get_inner_config(&self) -> ConfigKeyMap { self.config.clone() @@ -101,14 +113,16 @@ mod tests { .new_line_kind(NewLineKind::CarriageReturnLineFeed) .use_tabs(true) .indent_width(4) - .uppercase(true) - .lines_between_queries(2); + .casing(UppercaseKind::Upper) + .lines_between_queries(2) + .joins_as_top_level(true) + .dialect(Dialect::PostgreSql); let inner_config = config.get_inner_config(); - assert_eq!(inner_config.len(), 5); + assert_eq!(inner_config.len(), 7); let diagnostics = resolve_config( inner_config, - &resolve_global_config(Default::default(), &Default::default()).config, + &resolve_global_config(&mut Default::default()).config, ) .diagnostics; assert_eq!(diagnostics.len(), 0); @@ -119,7 +133,7 @@ mod tests { let mut global_config = ConfigKeyMap::new(); global_config.insert(String::from("newLineKind"), "crlf".into()); global_config.insert(String::from("useTabs"), true.into()); - let global_config = resolve_global_config(global_config, &Default::default()).config; + let global_config = resolve_global_config(&mut global_config).config; let mut config_builder = ConfigurationBuilder::new(); let config = config_builder.global_config(global_config).build(); assert_eq!(config.new_line_kind == NewLineKind::CarriageReturnLineFeed, true); @@ -128,7 +142,7 @@ mod tests { #[test] fn use_defaults_when_global_not_set() { - let global_config = resolve_global_config(Default::default(), &Default::default()).config; + let global_config = resolve_global_config(&mut Default::default()).config; let mut config_builder = ConfigurationBuilder::new(); let config = config_builder.global_config(global_config).build(); assert_eq!(config.indent_width, 2); diff --git a/src/configuration/configuration.rs b/src/configuration/configuration.rs index 454541c..7e7c639 100644 --- a/src/configuration/configuration.rs +++ b/src/configuration/configuration.rs @@ -1,12 +1,52 @@ use dprint_core::configuration::NewLineKind; +use dprint_core::configuration::ParseConfigurationError; +use dprint_core::generate_str_to_from; use serde::{Deserialize, Serialize}; +#[derive(Clone, PartialEq, Copy, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum UppercaseKind { + /// Preserve original keyword casing. + Preserve, + /// Convert reserved words to UPPERCASE. + Upper, + /// Convert reserved words to lowercase. + Lower, +} + +generate_str_to_from![ + UppercaseKind, + [Preserve, "preserve"], + [Upper, "upper"], + [Lower, "lower"] +]; + +#[derive(Clone, PartialEq, Copy, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Dialect { + /// Generic SQL syntax. + Generic, + /// PostgreSQL syntax. + PostgreSql, + /// SQL Server syntax. + SqlServer, +} + +generate_str_to_from![ + Dialect, + [Generic, "generic"], + [PostgreSql, "postgresql"], + [SqlServer, "sqlserver"] +]; + #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Configuration { pub use_tabs: bool, pub indent_width: u8, pub new_line_kind: NewLineKind, - pub uppercase: bool, + pub uppercase: UppercaseKind, pub lines_between_queries: u8, + pub joins_as_top_level: bool, + pub dialect: Dialect, } diff --git a/src/configuration/resolve_config.rs b/src/configuration/resolve_config.rs index d15e3d6..206ce7f 100644 --- a/src/configuration/resolve_config.rs +++ b/src/configuration/resolve_config.rs @@ -1,4 +1,6 @@ use super::Configuration; +use super::Dialect; +use super::UppercaseKind; use dprint_core::configuration::*; /// Resolves configuration from a collection of key value strings. @@ -10,8 +12,8 @@ use dprint_core::configuration::*; /// use dprint_core::configuration::resolve_global_config; /// use dprint_plugin_sql::configuration::resolve_config; /// -/// let config_map = ConfigKeyMap::new(); // get a collection of key value pairs from somewhere -/// let global_config_result = resolve_global_config(config_map, &Default::default()); +/// let mut config_map = ConfigKeyMap::new(); // get a collection of key value pairs from somewhere +/// let global_config_result = resolve_global_config(&mut config_map); /// /// // check global_config_result.diagnostics here... /// @@ -30,6 +32,15 @@ pub fn resolve_config( let mut diagnostics = Vec::new(); let mut config = config; + // handle legacy "uppercase" boolean config + let uppercase_default = if let Some(ConfigKeyValue::Bool(value)) = config.get("uppercase") { + let value = *value; + config.shift_remove("uppercase"); + if value { UppercaseKind::Upper } else { UppercaseKind::Preserve } + } else { + UppercaseKind::Preserve + }; + let resolved_config = Configuration { use_tabs: get_value( &mut config, @@ -55,8 +66,10 @@ pub fn resolve_config( .unwrap_or(RECOMMENDED_GLOBAL_CONFIGURATION.new_line_kind), &mut diagnostics, ), - uppercase: get_value(&mut config, "uppercase", false, &mut diagnostics), + uppercase: get_value(&mut config, "casing", uppercase_default, &mut diagnostics), lines_between_queries: get_value(&mut config, "linesBetweenQueries", 1, &mut diagnostics), + joins_as_top_level: get_value(&mut config, "joinsAsTopLevel", false, &mut diagnostics), + dialect: get_value(&mut config, "dialect", Dialect::Generic, &mut diagnostics), }; diagnostics.extend(get_unknown_property_diagnostics(config)); diff --git a/src/format_text.rs b/src/format_text.rs index 82c814a..36e7845 100644 --- a/src/format_text.rs +++ b/src/format_text.rs @@ -1,4 +1,5 @@ use super::configuration::Configuration; +use super::configuration::UppercaseKind; use anyhow::Result; use dprint_core::configuration::resolve_new_line_kind; @@ -18,8 +19,18 @@ pub fn format_text(_file_path: &Path, text: &str, config: &Configuration) -> Res } else { Indent::Spaces(config.indent_width) }, - uppercase: Some(config.uppercase), + uppercase: match config.uppercase { + UppercaseKind::Preserve => None, + UppercaseKind::Upper => Some(true), + UppercaseKind::Lower => Some(false), + }, lines_between_queries: config.lines_between_queries, + joins_as_top_level: config.joins_as_top_level, + dialect: match config.dialect { + super::configuration::Dialect::Generic => sqlformat::Dialect::Generic, + super::configuration::Dialect::PostgreSql => sqlformat::Dialect::PostgreSql, + super::configuration::Dialect::SqlServer => sqlformat::Dialect::SQLServer, + }, ..Default::default() }, ); diff --git a/src/wasm_plugin.rs b/src/wasm_plugin.rs index 40f1198..b8f950f 100644 --- a/src/wasm_plugin.rs +++ b/src/wasm_plugin.rs @@ -1,27 +1,38 @@ use super::configuration::{resolve_config, Configuration}; -use dprint_core::configuration::{ConfigKeyMap, GlobalConfiguration, ResolveConfigurationResult}; +use dprint_core::configuration::{ConfigKeyMap, GlobalConfiguration}; use dprint_core::generate_plugin_code; +use dprint_core::plugins::CheckConfigUpdatesMessage; +use dprint_core::plugins::ConfigChange; +use dprint_core::plugins::FileMatchingInfo; use dprint_core::plugins::FormatResult; use dprint_core::plugins::PluginInfo; +use dprint_core::plugins::PluginResolveConfigurationResult; +use dprint_core::plugins::SyncFormatRequest; +use dprint_core::plugins::SyncHostFormatRequest; use dprint_core::plugins::SyncPluginHandler; -use std::path::Path; -struct SqlPluginHandler {} - -impl SqlPluginHandler { - pub const fn new() -> Self { - Self {} - } -} +struct SqlPluginHandler; impl SyncPluginHandler for SqlPluginHandler { fn resolve_config( &mut self, config: ConfigKeyMap, global_config: &GlobalConfiguration, - ) -> ResolveConfigurationResult { - resolve_config(config, global_config) + ) -> PluginResolveConfigurationResult { + let result = resolve_config(config, global_config); + PluginResolveConfigurationResult { + config: result.config, + diagnostics: result.diagnostics, + file_matching: FileMatchingInfo { + file_extensions: vec!["sql".to_string()], + file_names: vec![], + }, + } + } + + fn check_config_updates(&self, _message: CheckConfigUpdatesMessage) -> anyhow::Result> { + Ok(Vec::new()) } fn plugin_info(&mut self) -> PluginInfo { @@ -30,8 +41,6 @@ impl SyncPluginHandler for SqlPluginHandler { name: env!("CARGO_PKG_NAME").to_string(), version: version.clone(), config_key: "sql".to_string(), - file_extensions: vec!["sql".to_string()], - file_names: vec![], help_url: "https://dprint.dev/plugins/sql".to_string(), config_schema_url: format!( "https://plugins.dprint.dev/dprint/dprint-plugin-sql/{}/schema.json", @@ -47,13 +56,17 @@ impl SyncPluginHandler for SqlPluginHandler { fn format( &mut self, - file_path: &Path, - file_text: &str, - config: &Configuration, - _format_with_host: impl FnMut(&Path, String, &ConfigKeyMap) -> FormatResult, + request: SyncFormatRequest, + _format_with_host: impl FnMut(SyncHostFormatRequest) -> FormatResult, ) -> FormatResult { - super::format_text(file_path, file_text, config) + if request.range.is_some() { + return Ok(None); // not implemented + } + + let text = String::from_utf8_lossy(&request.file_bytes); + let maybe_text = super::format_text(request.file_path, &text, request.config)?; + Ok(maybe_text.map(|t| t.into_bytes())) } } -generate_plugin_code!(SqlPluginHandler, SqlPluginHandler::new()); +generate_plugin_code!(SqlPluginHandler, SqlPluginHandler); diff --git a/tests/specs/Basic/Basic_All.txt b/tests/specs/Basic/Basic_All.txt index aff2bd3..931e751 100644 --- a/tests/specs/Basic/Basic_All.txt +++ b/tests/specs/Basic/Basic_All.txt @@ -1,22 +1,84 @@ -== should format basic == -SELECT * FROM dbo.Test WHERE test = 'asdf' -GO - - - -update dbo.Test Set test=1 -GO - -[expect] -SELECT - * -FROM - dbo.Test -WHERE - test = 'asdf' -GO -update - dbo.Test -Set - test = 1 -GO +== should format basic == +SELECT * FROM dbo.Test WHERE test = 'asdf' +GO + + + +update dbo.Test Set test=1 +GO + +[expect] +SELECT + * +FROM + dbo.Test +WHERE + test = 'asdf' +GO +update + dbo.Test +Set + test = 1 +GO + +== should format subquery == +SELECT * FROM (SELECT id, name FROM users WHERE active = 1) AS t WHERE t.id > 10 + +[expect] +SELECT + * +FROM + ( + SELECT + id, + name + FROM + users + WHERE + active = 1 + ) AS t +WHERE + t.id > 10 + +== should format insert == +INSERT INTO users (id, name, email) VALUES (1, 'test', 'test@example.com') + +[expect] +INSERT INTO + users (id, name, email) +VALUES + (1, 'test', 'test@example.com') + +== should format join == +SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id WHERE o.total > 100 + +[expect] +SELECT + u.name, + o.total +FROM + users u + INNER JOIN orders o ON u.id = o.user_id +WHERE + o.total > 100 + +== should format create table == +CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE) + +[expect] +CREATE TABLE users ( + id INT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) UNIQUE +) + +== should format multiple queries == +SELECT 1; SELECT 2; SELECT 3 + +[expect] +SELECT + 1; +SELECT + 2; +SELECT + 3 diff --git a/tests/specs/Config/Casing.txt b/tests/specs/Config/Casing.txt new file mode 100644 index 0000000..16f8803 --- /dev/null +++ b/tests/specs/Config/Casing.txt @@ -0,0 +1,10 @@ +== should preserve casing by default == +SELECT * FROM users WHERE id = 1 + +[expect] +SELECT + * +FROM + users +WHERE + id = 1 diff --git a/tests/specs/Config/CasingLower.txt b/tests/specs/Config/CasingLower.txt new file mode 100644 index 0000000..87cf894 --- /dev/null +++ b/tests/specs/Config/CasingLower.txt @@ -0,0 +1,11 @@ +~~ casing: lower ~~ +== should lowercase with casing lower == +SELECT * FROM users WHERE id = 1 + +[expect] +select + * +from + users +where + id = 1 diff --git a/tests/specs/Config/CasingUpper.txt b/tests/specs/Config/CasingUpper.txt new file mode 100644 index 0000000..a2fbac3 --- /dev/null +++ b/tests/specs/Config/CasingUpper.txt @@ -0,0 +1,11 @@ +~~ casing: upper ~~ +== should uppercase with casing upper == +select * from users where id = 1 + +[expect] +SELECT + * +FROM + users +WHERE + id = 1 diff --git a/tests/specs/Config/Indent.txt b/tests/specs/Config/Indent.txt new file mode 100644 index 0000000..6aebf84 --- /dev/null +++ b/tests/specs/Config/Indent.txt @@ -0,0 +1,11 @@ +~~ useTabs: true ~~ +== should use tabs == +SELECT * FROM users WHERE id = 1 + +[expect] +SELECT + * +FROM + users +WHERE + id = 1 diff --git a/tests/specs/Config/IndentWidth.txt b/tests/specs/Config/IndentWidth.txt new file mode 100644 index 0000000..49643a1 --- /dev/null +++ b/tests/specs/Config/IndentWidth.txt @@ -0,0 +1,11 @@ +~~ indentWidth: 4 ~~ +== should use 4 space indent == +SELECT * FROM users WHERE id = 1 + +[expect] +SELECT + * +FROM + users +WHERE + id = 1 diff --git a/tests/specs/Config/JoinsAsTopLevel.txt b/tests/specs/Config/JoinsAsTopLevel.txt new file mode 100644 index 0000000..de3695e --- /dev/null +++ b/tests/specs/Config/JoinsAsTopLevel.txt @@ -0,0 +1,14 @@ +~~ joinsAsTopLevel: true ~~ +== should treat joins as top level == +SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id LEFT JOIN payments p ON o.id = p.order_id + +[expect] +SELECT + u.name, + o.total +FROM + users u +INNER JOIN + orders o ON u.id = o.user_id +LEFT JOIN + payments p ON o.id = p.order_id diff --git a/tests/specs/Config/LinesBetweenQueries.txt b/tests/specs/Config/LinesBetweenQueries.txt new file mode 100644 index 0000000..45de593 --- /dev/null +++ b/tests/specs/Config/LinesBetweenQueries.txt @@ -0,0 +1,10 @@ +~~ linesBetweenQueries: 2 ~~ +== should use 2 lines between queries == +SELECT 1; SELECT 2 + +[expect] +SELECT + 1; + +SELECT + 2 diff --git a/tests/specs/Config/UppercaseLegacy.txt b/tests/specs/Config/UppercaseLegacy.txt new file mode 100644 index 0000000..4bf0946 --- /dev/null +++ b/tests/specs/Config/UppercaseLegacy.txt @@ -0,0 +1,11 @@ +~~ uppercase: true ~~ +== should support legacy uppercase boolean == +select * from users where id = 1 + +[expect] +SELECT + * +FROM + users +WHERE + id = 1 diff --git a/tests/test.rs b/tests/test.rs index 9a31348..49a1ec6 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2,6 +2,7 @@ extern crate dprint_development; extern crate dprint_plugin_sql; use std::path::PathBuf; +use std::sync::Arc; use dprint_core::configuration::*; use dprint_development::*; @@ -10,7 +11,7 @@ use dprint_plugin_sql::*; #[test] fn test_specs() { - let global_config = resolve_global_config(Default::default(), &Default::default()).config; + let global_config = GlobalConfiguration::default(); run_specs( &PathBuf::from("./tests/specs"), @@ -23,14 +24,15 @@ fn test_specs() { }, { let global_config = global_config.clone(); - move |file_path, file_text, spec_config| { - let config_result = resolve_config(parse_config_key_map(spec_config), &global_config); + Arc::new(move |file_path, file_text, spec_config| { + let spec_config: ConfigKeyMap = serde_json::from_value(spec_config.clone().into()).unwrap(); + let config_result = resolve_config(spec_config, &global_config); ensure_no_diagnostics(&config_result.diagnostics); format_text(file_path, &file_text, &config_result.config) - } + }) }, - move |_file_path, _file_text, _spec_config| panic!("Plugin does not support dprint-core tracing."), + Arc::new(move |_file_path, _file_text, _spec_config| panic!("Plugin does not support dprint-core tracing.")), ) }