diff --git a/.cursorignore b/.cursorignore
deleted file mode 100644
index 32948baf..00000000
--- a/.cursorignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
-libpg_query/
-lib/tree_sitter_sql/tree-sitter-sql/
\ No newline at end of file
diff --git a/.env b/.env
deleted file mode 100644
index dda71743..00000000
--- a/.env
+++ /dev/null
@@ -1 +0,0 @@
-DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5432/postgres
diff --git a/.github/ISSUE_TEMPLATE/1.Bug_report.md b/.github/ISSUE_TEMPLATE/1.Bug_report.md
deleted file mode 100644
index 239bef02..00000000
--- a/.github/ISSUE_TEMPLATE/1.Bug_report.md
+++ /dev/null
@@ -1,51 +0,0 @@
----
-name: Bug report
-about: Create a bug report for one of the supabase repos or examples.
-labels: bug
----
-
-# Bug report
-
-
-
-- [ ] I confirm this is a bug with Supabase, not with my own application.
-- [ ] I confirm I have searched the [Docs](https://docs.supabase.com), GitHub [Discussions](https://github.com/supabase/supabase/discussions), and [Discord](https://discord.supabase.com).
-
-## Describe the bug
-
-A clear and concise description of what the bug is.
-
-## To Reproduce
-
-Steps to reproduce the behavior, please provide code snippets or a repository:
-
-1. Go to '…'
-2. Click on '…'
-3. Scroll down to '…'
-4. See error
-
-## Expected behavior
-
-A clear and concise description of what you expected to happen.
-
-## Screenshots
-
-If applicable, add screenshots to help explain your problem.
-
-## System information
-
-- OS: [e.g. macOS, Windows]
-
-## Additional context
-
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/2.Improve_docs.md b/.github/ISSUE_TEMPLATE/2.Improve_docs.md
deleted file mode 100644
index b7001e33..00000000
--- a/.github/ISSUE_TEMPLATE/2.Improve_docs.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Improve documentation
-about: Suggest an improvement to our documentation
-labels: documentation
----
-
-# Improve documentation
-
-## Link
-
-Add a link to the page which needs improvement (if relevant)
-
-## Describe the problem
-
-Is the documentation missing? Or is it confusing? Why is it confusing?
-
-## Describe the improvement
-
-A clear and concise description of the improvement.
-
-## Additional context
-
-Add any other context or screenshots that help clarify your question.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/3.Create_a_chore.md b/.github/ISSUE_TEMPLATE/3.Create_a_chore.md
deleted file mode 100644
index 249d1793..00000000
--- a/.github/ISSUE_TEMPLATE/3.Create_a_chore.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-name: Create a chore
-about: Changes to build processes, tools, refactors.
-labels: chore
----
-
-# Chore
-
-## Describe the chore
-
-A clear and concise description of what the chore is.
-
-## Additional context
-
-Add any other context or screenshots that help clarify the task.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/4.Planned_work.md b/.github/ISSUE_TEMPLATE/4.Planned_work.md
deleted file mode 100644
index dc08e5b2..00000000
--- a/.github/ISSUE_TEMPLATE/4.Planned_work.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Planned work
-about: Planned feature work. Limited to contributors only.
-labels: planned
----
-
-# Planned Work
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 49086d4a..00000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-blank_issues_enabled: false
-contact_links:
- - name: Feature request
- url: https://github.com/supabase/postgres_lsp/discussions/categories/ideas
- about: Request a new feature or example.
- - name: Ask a question
- url: https://github.com/supabase/postgres_lsp/discussions/categories/q-a
- about: Ask questions and discuss with other community members.
- - name: Want to work with us?
- url: https://supabase.io/humans.txt
- about: Want to work with us? Get in touch!
diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml
deleted file mode 100644
index c55bf403..00000000
--- a/.github/actions/free-disk-space/action.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: Free Disk Space
-description: Free up disk space on the runner
-runs:
- using: composite
- steps:
- - name: Free Disk Space (Ubuntu)
- if: runner.os == 'Linux'
- uses: jlumbroso/free-disk-space@main
- with:
- # We need to reclaim some space, but uninstalling everyting takes
- # too long. So we'll just remove some of the larger packages.
- # https://github.com/jlumbroso/free-disk-space/pull/26
- android: true
- dotnet: true
- haskell: true
- large-packages: false
diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml
deleted file mode 100644
index aabd75cd..00000000
--- a/.github/workflows/deploy_docs.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-name: Build and Deploy Documentation
-
-on:
- release:
- types: [released]
- workflow_dispatch:
-
-permissions:
- contents: write
- pages: write
- id-token: write
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Install uv
- uses: astral-sh/setup-uv@v5
- with:
- enable-cache: true
-
- - name: Set up Python
- run: uv python install
-
- - name: Install the project
- run: uv sync --all-extras --dev
-
- - run: uv run mkdocs gh-deploy --force
-
- deploy:
- needs: build
- environment:
- name: github-pages
- url: ${{ steps.deployment.outputs.page_url }}
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- ref: gh-pages
- - name: Setup Pages
- uses: actions/configure-pages@v5
- - name: Upload artifact
- uses: actions/upload-pages-artifact@v3
- with:
- path: '.'
- - name: Deploy to GitHub Pages
- id: deployment
- uses: actions/deploy-pages@v4
diff --git a/.github/workflows/publish.dispatch.yml b/.github/workflows/publish.dispatch.yml
deleted file mode 100644
index 0f1b3d5f..00000000
--- a/.github/workflows/publish.dispatch.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: Publish NPM (Manual)
-
-on:
- workflow_dispatch:
- inputs:
- release-tag:
- type: string
- required: true
- description: Release Tag to Publish
-
-jobs:
- validate_tag:
- runs-on: ubuntu-latest
- outputs:
- is-prerelease: ${{ steps.validate-release.outputs.is-prerelease }}
- steps:
- - uses: actions/github-script@v7
- id: validate-release
- with:
- script: |
- /** the "core" module does not have access to workflow_dispatch inputs */
- const tag = '${{ inputs.release-tag }}';
-
- /** Releases don't have a guaranteed order, so we'll have to paginate */
- let exhausted = false;
- let page = 1;
- while (!exhausted) {
- const releases = await github.rest.repos.listReleases({
- owner: context.repo.owner,
- repo: context.repo.repo,
- page,
- per_page: 100,
- }).then(r => r.data);
-
- const matchingRelease = releases.find(r => r.tag_name === tag);
- if (matchingRelease) {
- core.setOutput('has-release', 'true');
- core.setOutput('is-prerelease', matchingRelease.prerelease.toString());
- return;
- }
-
- if (releases.length < 100) {
- exhausted = true;
- } else if (page >= 10) {
- throw new Error("We iterated over 10 pages. Does the script work?");
- } else {
- page++
- }
-
- }
-
- core.setOutput('has-release', 'false');
- core.setOutput('is-prerelease', 'false');
-
- - name: Abort
- if: steps.validate-release.outputs.has-release != 'true'
- run: |
- {
- echo "Tag ${{ github.event.inputs.release-tag }} not found."
- exit 1
- }
-
- publish_npm:
- needs: validate_tag
- uses: ./.github/workflows/publish.reusable.yml
- permissions:
- contents: write
- id-token: write
- with:
- release-tag: ${{ github.event.inputs.release-tag }}
- is-prerelease: ${{ needs.validate_tag.outputs.is-prerelease }}
- secrets: inherit
diff --git a/.github/workflows/publish.reusable.yml b/.github/workflows/publish.reusable.yml
deleted file mode 100644
index 31e625d7..00000000
--- a/.github/workflows/publish.reusable.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-name: Publish to NPM & Brew
-
-on:
- workflow_call:
- inputs:
- release-tag:
- type: string
- required: true
- is-prerelease:
- type: string
- required: true
-
-jobs:
- publish:
- name: Publish All the Things
- runs-on: ubuntu-latest
- permissions:
- contents: write
- id-token: write
- steps:
- - uses: actions/checkout@v4
-
- - name: Install Node
- uses: actions/setup-node@v4
- with:
- node-version: lts/*
- registry-url: "https://registry.npmjs.org"
-
- - name: Generate Packages
- id: generate-packages
- run: node packages/@postgrestools/postgrestools/scripts/generate-packages.mjs
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- RELEASE_TAG: ${{ inputs.release-tag }}
- PRERELEASE: ${{ inputs.is-prerelease }}
-
- - name: Verify NPM TOKEN exists
- run: |
- if [ -z "${{ secrets.NPM_TOKEN }}" ]; then
- echo "Secret is not defined"
- exit 1
- else
- echo "Secret is defined"
- fi
-
- - name: Print package.json
- run: |
- cat packages/@postgrestools/postgrestools/package.json
-
- - name: Publish npm packages as nightly
- if: inputs.is-prerelease == 'true'
- run: |
- for package in packages/@postgrestools/*; do
- npm publish "$package" --tag nightly --access public --provenance
- done
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} #
-
- - name: Publish npm packages as latest
- if: inputs.is-prerelease != 'true'
- run: |
- for package in packages/@postgrestools/*; do
- npm publish "$package" --tag latest --access public --provenance
- done
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/publish.trigger.yml b/.github/workflows/publish.trigger.yml
deleted file mode 100644
index b2a102a5..00000000
--- a/.github/workflows/publish.trigger.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: Publish NPM (Automatic)
-
-on:
- release:
- types: [released, prereleased]
-
-jobs:
- publish_npm:
- uses: ./.github/workflows/publish.reusable.yml
- permissions:
- contents: write
- id-token: write
- with:
- release-tag: ${{ github.event.release.tag_name }}
- is-prerelease: ${{ github.event.release.prerelease }}
- secrets: inherit
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
deleted file mode 100644
index f79392b7..00000000
--- a/.github/workflows/pull_request.yml
+++ /dev/null
@@ -1,243 +0,0 @@
-name: Pull Request
-
-on:
- workflow_dispatch:
- pull_request:
- paths: # Only run when changes are made to rust code or root Cargo
- - "crates/**"
- - "lib/**"
- - "fuzz/**"
- - "xtask/**"
- - "Cargo.toml"
- - "Cargo.lock"
- - "rust-toolchain.toml"
- - "rustfmt.toml"
- # or in js packages
- - "packages/**"
- # or in workflows
- - ".github/workflows/**"
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- RUST_LOG: info
- RUST_BACKTRACE: 1
- RUSTUP_WINDOWS_PATH_ADD_BIN: 1
-
-jobs:
- format:
- name: Format
- runs-on: ubuntu-latest
- steps:
- - name: Checkout PR branch
- uses: actions/checkout@v4
-
- - name: Free Disk Space
- uses: ./.github/actions/free-disk-space
-
- - name: Install toolchain
- uses: moonrepo/setup-rust@v1
- with:
- components: rustfmt
- bins: taplo-cli
- cache-base: main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Setup Bun
- uses: oven-sh/setup-bun@v2
-
- - name: Install JS dependencies
- run: bun install
-
- - name: Setup Just
- uses: extractions/setup-just@v3
-
- - name: Echo Tool Versions
- run: |
- just format-ci-versions
-
- - name: Run format
- run: |
- just format-ci
-
- actionlint:
- name: Lint GitHub Actions
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Download actionlint
- id: get_actionlint
- run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
- shell: bash
- - name: Check workflow files
- run: ${{ steps.get_actionlint.outputs.executable }} -color
- shell: bash
-
- lint:
- name: Lint Project
- runs-on: ubuntu-latest
- services:
- postgres:
- image: postgres:latest
- env:
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- POSTGRES_DB: postgres
- ports:
- - 5432:5432
- steps:
- - name: Checkout PR Branch
- uses: actions/checkout@v4
- with:
- submodules: true
- - name: Free Disk Space
- uses: ./.github/actions/free-disk-space
- - name: Install toolchain
- uses: moonrepo/setup-rust@v1
- with:
- components: clippy
- cache-base: main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Setup sqlx-cli
- run: cargo install sqlx-cli
-
- - name: Setup Bun
- uses: oven-sh/setup-bun@v2
-
- - name: Install JS dependencies
- run: bun install
-
- - name: Setup Just
- uses: extractions/setup-just@v3
-
- - name: Echo Tool Versions
- run: |
- just lint-ci-versions
-
- - name: Run Lints
- run: |
- just lint-ci
-
- - name: Check for changes
- run: |
- if [[ $(git status --porcelain) ]]; then
- git status
- git diff
- exit 1
- fi
-
- test:
- name: Test
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- include:
- # use the same images we use for compiling
- - os: windows-2022
- - os: ubuntu-22.04
- steps:
- - name: Checkout PR branch
- uses: actions/checkout@v4
- with:
- submodules: true
- - name: Free Disk Space
- uses: ./.github/actions/free-disk-space
- - name: Install toolchain
- uses: moonrepo/setup-rust@v1
- with:
- cache-base: main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # running containers via `services` only works on linux
- # https://github.com/actions/runner/issues/1866
- - name: Setup postgres
- uses: ikalnytskyi/action-setup-postgres@v7
- - name: Run tests
- run: cargo test --workspace
-
- test-js-bindings:
- name:
- Test JS Bindings
- # use the same image we use for compiling
- runs-on: ubuntu-22.04
- services:
- postgres:
- image: postgres:latest
- env:
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- POSTGRES_DB: postgres
- ports:
- - 5432:5432
- steps:
- - name: Checkout PR branch
- uses: actions/checkout@v4
- with:
- submodules: true
- - name: Free Disk Space
- uses: ./.github/actions/free-disk-space
- - name: Install toolchain
- uses: moonrepo/setup-rust@v1
- with:
- cache-base: main
- - name: Build main binary
- run: cargo build -p pgt_cli --release
- - name: Setup Bun
- uses: oven-sh/setup-bun@v2
- - name: Install JS dependencies
- run: bun install
- - name: Build TypeScript code
- working-directory: packages/@postgrestools/backend-jsonrpc
- run: bun run build
- - name: Run JS tests
- working-directory: packages/@postgrestools/backend-jsonrpc
- run: bun run test
-
- codegen:
- name: Check Codegen
- runs-on: ubuntu-22.04
- services:
- postgres:
- image: postgres:latest
- env:
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- POSTGRES_DB: postgres
- ports:
- - 5432:5432
- steps:
- - name: Checkout PR branch
- uses: actions/checkout@v4
- with:
- submodules: true
- - name: Free Disk Space
- uses: ./.github/actions/free-disk-space
- - name: Install toolchain
- uses: moonrepo/setup-rust@v1
- with:
- cache-base: main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - name: Ensure RustFMT on nightly toolchain
- run: rustup component add rustfmt --toolchain nightly
- - name: echo toolchain
- run: rustup show
- - name: Run the analyser codegen
- run: cargo run -p xtask_codegen -- analyser
- - name: Run the configuration codegen
- run: cargo run -p xtask_codegen -- configuration
- - name: Run the docs codegen
- run: cargo run -p docs_codegen
- - name: Check for git diff -- run "just ready" if you see an error
- run: |
- if [[ $(git status --porcelain) ]]; then
- git status
- git diff
- exit 1
- fi
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 934edba9..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,168 +0,0 @@
-name: Release Binary
-
-on:
- workflow_dispatch:
-
-permissions:
- contents: write
-
-env:
- # Need these guys for cross-compilation
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: aarch64-linux-gnu-gcc
-
-jobs:
- # windows does not run git cliff so we need to do it here
- extract_version:
- name: Extract Version
- runs-on: ubuntu-latest
- outputs:
- version: ${{ steps.set_version.outputs.version }}
-
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Set up git-cliff
- uses: kenji-miyake/setup-git-cliff@v1
-
- - name: Set version name
- id: set_version
- run: echo "version=$(git cliff --bumped-version)" >> "$GITHUB_OUTPUT"
-
- build_and_test:
- name: Build & Test for ${{ matrix.config.target }}
- needs: extract_version
- strategy:
- matrix:
- config:
- - { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu }
- - { os: ubuntu-22.04, target: aarch64-unknown-linux-gnu }
- - { os: macos-14, target: x86_64-apple-darwin }
- - { os: macos-14, target: aarch64-apple-darwin }
- - { os: windows-2022, target: x86_64-pc-windows-msvc }
- - { os: windows-2022, target: aarch64-pc-windows-msvc }
-
- runs-on: ${{ matrix.config.os }}
-
- outputs:
- artifact_url: ${{ steps.upload-artifacts.outputs.artifact-url }}
-
- steps:
- - uses: actions/checkout@v4
- with:
- submodules: true
- - uses: actions-rust-lang/setup-rust-toolchain@v1
- with:
- target: ${{ matrix.config.target }}
-
- - uses: Swatinem/rust-cache@v2
- id: rust-cache
-
- # The Aarch64 Linux is a special snowflake, we need to install its toolchain
- - name: Install arm64 toolchain
- if: matrix.config.target == 'aarch64-unknown-linux-gnu'
- run: |
- sudo apt-get update
- sudo apt-get install -y gcc-aarch64-linux-gnu
-
- # running containers via `services` only works on linux
- # https://github.com/actions/runner/issues/1866
- - name: 🐘 Setup postgres
- uses: ikalnytskyi/action-setup-postgres@v7
-
- - name: 🧪 Run Tests
- run: cargo test --release
- env:
- DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
-
- - name: 🛠️ Run Build
- run: cargo build -p pgt_cli --release --target ${{ matrix.config.target }}
- env:
- # Strip all debug symbols from the resulting binaries
- RUSTFLAGS: "-C strip=symbols -C codegen-units=1"
- # Inline the version in the CLI binary
- PGT_VERSION: ${{ needs.extract_version.outputs.version }}
-
- # windows is a special snowflake too, it saves binaries as .exe
- - name: 👦 Name the Binary
- if: matrix.config.os == 'windows-2022'
- run: |
- mkdir dist
- cp target/${{ matrix.config.target }}/release/postgrestools.exe ./dist/postgrestools_${{ matrix.config.target }}
- - name: 👦 Name the Binary
- if: matrix.config.os != 'windows-2022'
- run: |
- mkdir dist
- cp target/${{ matrix.config.target }}/release/postgrestools ./dist/postgrestools_${{ matrix.config.target }}
-
- # It is not possible to return the artifacts from the matrix jobs individually: Matrix outputs overwrite each other.
- # A common workaround is to upload and download the resulting artifacts.
- - name: 👆 Upload Artifacts
- id: upload-artifacts
- uses: actions/upload-artifact@v4
- with:
- name: postgrestools_${{ matrix.config.target }}
- path: ./dist/postgrestools_*
- # The default compression level is 6; this took the binary down from 350 to 330MB.
- # It is recommended to use a lower level for binaries, since the compressed result is not much smaller,
- # and the higher levels of compression take much longer.
- compression-level: 2
- if-no-files-found: error
-
- create_changelog_and_release:
- runs-on: ubuntu-latest
- needs: [extract_version, build_and_test] # make sure that tests & build work correctly
- steps:
- - name: Checkout Repo
- uses: actions/checkout@v4
- with:
- # we need all commits to create a changelog
- fetch-depth: 0
-
- - name: 📝 Create Changelog
- uses: orhun/git-cliff-action@v3
- id: create_changelog
- with:
- config: cliff.toml
- args: --bump --unreleased
- env:
- GITHUB_REPO: ${{ github.repository }}
-
- - name: Ensure tag matches
- if: steps.create_changelog.outputs.version != needs.extract_version.outputs.version
- run: exit 1
-
- - name: 👇 Download Artifacts
- uses: actions/download-artifact@v4
- id: download
- with:
- merge-multiple: true
- pattern: postgrestools_*
-
- - name: 📂 Create Release
- uses: softprops/action-gh-release@v2
- id: create-release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- body: ${{ steps.create_changelog.outputs.content }}
- tag_name: ${{ steps.create_changelog.outputs.version }}
- files: |
- postgrestools_*
- docs/schemas/latest/schema.json
- fail_on_unmatched_files: true
- draft: true
-
- - name: ✅ Output Link to Workflow Summary
- run: |
- {
- echo "# 🚀 Release completed!"
- echo ""
- echo "Here is the URL to the Release Draft:"
- echo ""
- echo "[Link](${{ steps.create-release.outputs.url }})"
- echo ""
- } >> "$GITHUB_STEP_SUMMARY"
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index b16dfab6..00000000
--- a/.gitignore
+++ /dev/null
@@ -1,25 +0,0 @@
-# Generated by Cargo
-# will have compiled files and executables
-debug/
-target/
-
-# These are backup files generated by rustfmt
-**/*.rs.bk
-
-# MSVC Windows builds of rustc generate these, which store debugging information
-*.pdb
-
-
-# Added by cargo
-
-/target
-
-# File system
-.DS_Store
-desktop.ini
-
-*.log
-
-node_modules/
-
-**/dist/
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 4b56d748..00000000
--- a/.gitmodules
+++ /dev/null
@@ -1,8 +0,0 @@
-[submodule "libpg_query"]
- path = libpg_query
- url = https://github.com/pganalyze/libpg_query.git
- branch = 17-latest
-[submodule "crates/tree_sitter_sql/tree-sitter-sql"]
- path = lib/tree_sitter_sql/tree-sitter-sql
- url = https://github.com/DerekStride/tree-sitter-sql
- branch = gh-pages
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 00000000..e69de29b
diff --git a/.sqlx/query-1c29eca62591ae2597581be806dd572b3d79c7b8b9b7ffa8915806c947095a96.json b/.sqlx/query-1c29eca62591ae2597581be806dd572b3d79c7b8b9b7ffa8915806c947095a96.json
deleted file mode 100644
index fcd4901e..00000000
--- a/.sqlx/query-1c29eca62591ae2597581be806dd572b3d79c7b8b9b7ffa8915806c947095a96.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select\n t.oid :: int8 as \"id!\",\n t.typname as name,\n n.nspname as \"schema!\",\n format_type (t.oid, null) as \"format!\",\n coalesce(t_enums.enums, '[]') as enums,\n coalesce(t_attributes.attributes, '[]') as attributes,\n obj_description (t.oid, 'pg_type') as comment\nfrom\n pg_type t\n left join pg_namespace n on n.oid = t.typnamespace\n left join (\n select\n enumtypid,\n jsonb_agg(\n enumlabel\n order by\n enumsortorder\n ) as enums\n from\n pg_enum\n group by\n enumtypid\n ) as t_enums on t_enums.enumtypid = t.oid\n left join (\n select\n oid,\n jsonb_agg(\n jsonb_build_object('name', a.attname, 'type_id', a.atttypid :: int8)\n order by\n a.attnum asc\n ) as attributes\n from\n pg_class c\n join pg_attribute a on a.attrelid = c.oid\n where\n c.relkind = 'c'\n and not a.attisdropped\n group by\n c.oid\n ) as t_attributes on t_attributes.oid = t.typrelid\nwhere\n (\n t.typrelid = 0\n or (\n select\n c.relkind = 'c'\n from\n pg_class c\n where\n c.oid = t.typrelid\n )\n );",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 1,
- "name": "name",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "schema!",
- "type_info": "Name"
- },
- {
- "ordinal": 3,
- "name": "format!",
- "type_info": "Text"
- },
- {
- "ordinal": 4,
- "name": "enums",
- "type_info": "Jsonb"
- },
- {
- "ordinal": 5,
- "name": "attributes",
- "type_info": "Jsonb"
- },
- {
- "ordinal": 6,
- "name": "comment",
- "type_info": "Text"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- null,
- false,
- true,
- null,
- null,
- null,
- null
- ]
- },
- "hash": "1c29eca62591ae2597581be806dd572b3d79c7b8b9b7ffa8915806c947095a96"
-}
diff --git a/.sqlx/query-36862f7f9d2d1c50ba253b28a7648e76ff7e255960a4ce5466674ff35a97b151.json b/.sqlx/query-36862f7f9d2d1c50ba253b28a7648e76ff7e255960a4ce5466674ff35a97b151.json
deleted file mode 100644
index 6255c9b9..00000000
--- a/.sqlx/query-36862f7f9d2d1c50ba253b28a7648e76ff7e255960a4ce5466674ff35a97b151.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select\n n.oid :: int8 as \"id!\",\n n.nspname as name,\n u.rolname as \"owner!\"\nfrom\n pg_namespace n,\n pg_roles u\nwhere\n n.nspowner = u.oid\n and (\n pg_has_role(n.nspowner, 'USAGE')\n or has_schema_privilege(n.oid, 'CREATE, USAGE')\n )\n and not pg_catalog.starts_with(n.nspname, 'pg_temp_')\n and not pg_catalog.starts_with(n.nspname, 'pg_toast_temp_');",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 1,
- "name": "name",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "owner!",
- "type_info": "Name"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- null,
- false,
- true
- ]
- },
- "hash": "36862f7f9d2d1c50ba253b28a7648e76ff7e255960a4ce5466674ff35a97b151"
-}
diff --git a/.sqlx/query-47bbad9dc2cec0231ef726790a9b0a5d9c628c6a2704f5523fb9ee45414350c7.json b/.sqlx/query-47bbad9dc2cec0231ef726790a9b0a5d9c628c6a2704f5523fb9ee45414350c7.json
deleted file mode 100644
index 01d857f8..00000000
--- a/.sqlx/query-47bbad9dc2cec0231ef726790a9b0a5d9c628c6a2704f5523fb9ee45414350c7.json
+++ /dev/null
@@ -1,62 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select \n schemaname as \"schema_name!\", \n tablename as \"table_name!\", \n policyname as \"name!\", \n permissive as \"is_permissive!\", \n roles as \"role_names!\", \n cmd as \"command!\", \n qual as \"security_qualification\", \n with_check\nfrom \n pg_catalog.pg_policies;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "schema_name!",
- "type_info": "Name"
- },
- {
- "ordinal": 1,
- "name": "table_name!",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "name!",
- "type_info": "Name"
- },
- {
- "ordinal": 3,
- "name": "is_permissive!",
- "type_info": "Text"
- },
- {
- "ordinal": 4,
- "name": "role_names!",
- "type_info": "NameArray"
- },
- {
- "ordinal": 5,
- "name": "command!",
- "type_info": "Text"
- },
- {
- "ordinal": 6,
- "name": "security_qualification",
- "type_info": "Text"
- },
- {
- "ordinal": 7,
- "name": "with_check",
- "type_info": "Text"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ]
- },
- "hash": "47bbad9dc2cec0231ef726790a9b0a5d9c628c6a2704f5523fb9ee45414350c7"
-}
diff --git a/.sqlx/query-5e12c1d242ea9fcc68c20807b72300a7e131d2fb17fc74bd7f40a60b68df56c0.json b/.sqlx/query-5e12c1d242ea9fcc68c20807b72300a7e131d2fb17fc74bd7f40a60b68df56c0.json
deleted file mode 100644
index fa456c71..00000000
--- a/.sqlx/query-5e12c1d242ea9fcc68c20807b72300a7e131d2fb17fc74bd7f40a60b68df56c0.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select \n rolname as \"name!\", \n rolsuper as \"is_super_user!\", \n rolcreatedb as \"can_create_db!\", \n rolcanlogin as \"can_login!\",\n rolbypassrls as \"can_bypass_rls!\"\nfrom pg_catalog.pg_roles;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "name!",
- "type_info": "Name"
- },
- {
- "ordinal": 1,
- "name": "is_super_user!",
- "type_info": "Bool"
- },
- {
- "ordinal": 2,
- "name": "can_create_db!",
- "type_info": "Bool"
- },
- {
- "ordinal": 3,
- "name": "can_login!",
- "type_info": "Bool"
- },
- {
- "ordinal": 4,
- "name": "can_bypass_rls!",
- "type_info": "Bool"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- true,
- true,
- true,
- true,
- true
- ]
- },
- "hash": "5e12c1d242ea9fcc68c20807b72300a7e131d2fb17fc74bd7f40a60b68df56c0"
-}
diff --git a/.sqlx/query-64d9718b07516f3d2720cb7aa79e496f5337cadbad7a3fb03ccd3e3c21b71389.json b/.sqlx/query-64d9718b07516f3d2720cb7aa79e496f5337cadbad7a3fb03ccd3e3c21b71389.json
deleted file mode 100644
index 43d63459..00000000
--- a/.sqlx/query-64d9718b07516f3d2720cb7aa79e496f5337cadbad7a3fb03ccd3e3c21b71389.json
+++ /dev/null
@@ -1,104 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "with functions as (\n select\n oid,\n proname,\n prosrc,\n prorettype,\n proretset,\n provolatile,\n prosecdef,\n prolang,\n pronamespace,\n proconfig,\n -- proargmodes is null when all arg modes are IN\n coalesce(\n p.proargmodes,\n array_fill(\n 'i' :: text,\n array [cardinality(coalesce(p.proallargtypes, p.proargtypes))]\n )\n ) as arg_modes,\n -- proargnames is null when all args are unnamed\n coalesce(\n p.proargnames,\n array_fill(\n '' :: text,\n array [cardinality(coalesce(p.proallargtypes, p.proargtypes))]\n )\n ) as arg_names,\n -- proallargtypes is null when all arg modes are IN\n coalesce(p.proallargtypes, p.proargtypes) as arg_types,\n array_cat(\n array_fill(false, array [pronargs - pronargdefaults]),\n array_fill(true, array [pronargdefaults])\n ) as arg_has_defaults\n from\n pg_proc as p\n where\n p.prokind = 'f'\n)\nselect\n f.oid :: int8 as \"id!\",\n n.nspname as \"schema!\",\n f.proname as \"name!\",\n l.lanname as \"language!\",\n case\n when l.lanname = 'internal' then null\n else f.prosrc\n end as body,\n case\n when l.lanname = 'internal' then null\n else pg_get_functiondef(f.oid)\n end as definition,\n coalesce(f_args.args, '[]') as args,\n nullif(pg_get_function_arguments(f.oid), '') as argument_types,\n nullif(pg_get_function_identity_arguments(f.oid), '') as identity_argument_types,\n f.prorettype :: int8 as \"return_type_id!\",\n pg_get_function_result(f.oid) as \"return_type!\",\n nullif(rt.typrelid :: int8, 0) as return_type_relation_id,\n f.proretset as is_set_returning_function,\n case\n when f.provolatile = 'i' then 'IMMUTABLE'\n when f.provolatile = 's' then 'STABLE'\n when f.provolatile = 'v' then 'VOLATILE'\n end as behavior,\n f.prosecdef as security_definer\nfrom\n functions f\n left join pg_namespace n on f.pronamespace = n.oid\n left join pg_language l on f.prolang = l.oid\n left join pg_type rt on rt.oid = f.prorettype\n left join (\n select\n oid,\n jsonb_object_agg(param, value) filter (\n where\n param is not null\n ) as config_params\n from\n (\n select\n oid,\n (string_to_array(unnest(proconfig), '=')) [1] as param,\n (string_to_array(unnest(proconfig), '=')) [2] as value\n from\n functions\n ) as t\n group by\n oid\n ) f_config on f_config.oid = f.oid\n left join (\n select\n oid,\n jsonb_agg(\n jsonb_build_object(\n 'mode',\n t2.mode,\n 'name',\n name,\n 'type_id',\n type_id,\n 'has_default',\n has_default\n )\n ) as args\n from\n (\n select\n oid,\n unnest(arg_modes) as mode,\n unnest(arg_names) as name,\n unnest(arg_types) :: int8 as type_id,\n unnest(arg_has_defaults) as has_default\n from\n functions\n ) as t1,\n lateral (\n select\n case\n when t1.mode = 'i' then 'in'\n when t1.mode = 'o' then 'out'\n when t1.mode = 'b' then 'inout'\n when t1.mode = 'v' then 'variadic'\n else 'table'\n end as mode\n ) as t2\n group by\n t1.oid\n ) f_args on f_args.oid = f.oid;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 1,
- "name": "schema!",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "name!",
- "type_info": "Name"
- },
- {
- "ordinal": 3,
- "name": "language!",
- "type_info": "Name"
- },
- {
- "ordinal": 4,
- "name": "body",
- "type_info": "Text"
- },
- {
- "ordinal": 5,
- "name": "definition",
- "type_info": "Text"
- },
- {
- "ordinal": 6,
- "name": "args",
- "type_info": "Jsonb"
- },
- {
- "ordinal": 7,
- "name": "argument_types",
- "type_info": "Text"
- },
- {
- "ordinal": 8,
- "name": "identity_argument_types",
- "type_info": "Text"
- },
- {
- "ordinal": 9,
- "name": "return_type_id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 10,
- "name": "return_type!",
- "type_info": "Text"
- },
- {
- "ordinal": 11,
- "name": "return_type_relation_id",
- "type_info": "Int8"
- },
- {
- "ordinal": 12,
- "name": "is_set_returning_function",
- "type_info": "Bool"
- },
- {
- "ordinal": 13,
- "name": "behavior",
- "type_info": "Text"
- },
- {
- "ordinal": 14,
- "name": "security_definer",
- "type_info": "Bool"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- null,
- true,
- false,
- true,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- false,
- null,
- false
- ]
- },
- "hash": "64d9718b07516f3d2720cb7aa79e496f5337cadbad7a3fb03ccd3e3c21b71389"
-}
diff --git a/.sqlx/query-66d92238c94b5f1c99fbf068a0b5cf4c296b594fe9e6cebbdc382acde73f4fb9.json b/.sqlx/query-66d92238c94b5f1c99fbf068a0b5cf4c296b594fe9e6cebbdc382acde73f4fb9.json
deleted file mode 100644
index 447ba93b..00000000
--- a/.sqlx/query-66d92238c94b5f1c99fbf068a0b5cf4c296b594fe9e6cebbdc382acde73f4fb9.json
+++ /dev/null
@@ -1,86 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select\n c.oid :: int8 as \"id!\",\n nc.nspname as schema,\n c.relname as name,\n c.relkind as table_kind,\n c.relrowsecurity as rls_enabled,\n c.relforcerowsecurity as rls_forced,\n case\n when c.relreplident = 'd' then 'DEFAULT'\n when c.relreplident = 'i' then 'INDEX'\n when c.relreplident = 'f' then 'FULL'\n else 'NOTHING'\n end as \"replica_identity!\",\n pg_total_relation_size(format('%I.%I', nc.nspname, c.relname)) :: int8 as \"bytes!\",\n pg_size_pretty(\n pg_total_relation_size(format('%I.%I', nc.nspname, c.relname))\n ) as \"size!\",\n pg_stat_get_live_tuples(c.oid) as \"live_rows_estimate!\",\n pg_stat_get_dead_tuples(c.oid) as \"dead_rows_estimate!\",\n obj_description(c.oid) as comment\nfrom\n pg_namespace nc\n join pg_class c on nc.oid = c.relnamespace\nwhere\n c.relkind in ('r', 'p', 'v', 'm')\n and not pg_is_other_temp_schema(nc.oid)\n and (\n pg_has_role(c.relowner, 'USAGE')\n or has_table_privilege(\n c.oid,\n 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER'\n )\n or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')\n )\ngroup by\n c.oid,\n c.relname,\n c.relrowsecurity,\n c.relforcerowsecurity,\n c.relreplident,\n nc.nspname;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 1,
- "name": "schema",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "name",
- "type_info": "Name"
- },
- {
- "ordinal": 3,
- "name": "table_kind",
- "type_info": "Char"
- },
- {
- "ordinal": 4,
- "name": "rls_enabled",
- "type_info": "Bool"
- },
- {
- "ordinal": 5,
- "name": "rls_forced",
- "type_info": "Bool"
- },
- {
- "ordinal": 6,
- "name": "replica_identity!",
- "type_info": "Text"
- },
- {
- "ordinal": 7,
- "name": "bytes!",
- "type_info": "Int8"
- },
- {
- "ordinal": 8,
- "name": "size!",
- "type_info": "Text"
- },
- {
- "ordinal": 9,
- "name": "live_rows_estimate!",
- "type_info": "Int8"
- },
- {
- "ordinal": 10,
- "name": "dead_rows_estimate!",
- "type_info": "Int8"
- },
- {
- "ordinal": 11,
- "name": "comment",
- "type_info": "Text"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- null,
- false,
- false,
- false,
- false,
- false,
- null,
- null,
- null,
- null,
- null,
- null
- ]
- },
- "hash": "66d92238c94b5f1c99fbf068a0b5cf4c296b594fe9e6cebbdc382acde73f4fb9"
-}
diff --git a/.sqlx/query-d61f2f56ce777c99593df240b3a126cacb3c9ed5f915b7e98052d58df98d480b.json b/.sqlx/query-d61f2f56ce777c99593df240b3a126cacb3c9ed5f915b7e98052d58df98d480b.json
deleted file mode 100644
index d1766e30..00000000
--- a/.sqlx/query-d61f2f56ce777c99593df240b3a126cacb3c9ed5f915b7e98052d58df98d480b.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "select\n version(),\n current_setting('server_version_num') :: int8 AS version_num,\n (\n select\n count(*) :: int8 AS active_connections\n FROM\n pg_stat_activity\n ) AS active_connections,\n current_setting('max_connections') :: int8 AS max_connections;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "version",
- "type_info": "Text"
- },
- {
- "ordinal": 1,
- "name": "version_num",
- "type_info": "Int8"
- },
- {
- "ordinal": 2,
- "name": "active_connections",
- "type_info": "Int8"
- },
- {
- "ordinal": 3,
- "name": "max_connections",
- "type_info": "Int8"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- null,
- null,
- null,
- null
- ]
- },
- "hash": "d61f2f56ce777c99593df240b3a126cacb3c9ed5f915b7e98052d58df98d480b"
-}
diff --git a/.sqlx/query-df57cc22f7d63847abce1d0d15675ba8951faa1be2ea6b2bf6714b1aa9127a6f.json b/.sqlx/query-df57cc22f7d63847abce1d0d15675ba8951faa1be2ea6b2bf6714b1aa9127a6f.json
deleted file mode 100644
index b6fd2fc8..00000000
--- a/.sqlx/query-df57cc22f7d63847abce1d0d15675ba8951faa1be2ea6b2bf6714b1aa9127a6f.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "-- we need to join tables from the pg_catalog since \"TRUNCATE\" triggers are \n-- not available in the information_schema.trigger table.\nselect \n t.tgname as \"name!\",\n c.relname as \"table_name!\",\n p.proname as \"proc_name!\",\n n.nspname as \"schema_name!\",\n t.tgtype as \"details_bitmask!\"\nfrom \n pg_catalog.pg_trigger t \n left join pg_catalog.pg_proc p on t.tgfoid = p.oid\n left join pg_catalog.pg_class c on t.tgrelid = c.oid\n left join pg_catalog.pg_namespace n on c.relnamespace = n.oid\nwhere \n -- triggers enforcing constraints (e.g. unique fields) should not be included.\n t.tgisinternal = false and \n t.tgconstraint = 0;\n",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "name!",
- "type_info": "Name"
- },
- {
- "ordinal": 1,
- "name": "table_name!",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "proc_name!",
- "type_info": "Name"
- },
- {
- "ordinal": 3,
- "name": "schema_name!",
- "type_info": "Name"
- },
- {
- "ordinal": 4,
- "name": "details_bitmask!",
- "type_info": "Int2"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- false,
- true,
- true,
- true,
- false
- ]
- },
- "hash": "df57cc22f7d63847abce1d0d15675ba8951faa1be2ea6b2bf6714b1aa9127a6f"
-}
diff --git a/.sqlx/query-fa065a78ad10eeace15f64083f4d944b9d45eb6c60d7eece8878ed26b3530484.json b/.sqlx/query-fa065a78ad10eeace15f64083f4d944b9d45eb6c60d7eece8878ed26b3530484.json
deleted file mode 100644
index 36723330..00000000
--- a/.sqlx/query-fa065a78ad10eeace15f64083f4d944b9d45eb6c60d7eece8878ed26b3530484.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "with\n available_tables as (\n select\n c.relname as table_name,\n c.oid as table_oid,\n c.relkind as class_kind,\n n.nspname as schema_name\n from\n pg_catalog.pg_class c\n join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n where\n -- r: normal tables\n -- v: views\n -- m: materialized views\n -- f: foreign tables\n -- p: partitioned tables\n c.relkind in ('r', 'v', 'm', 'f', 'p')\n ),\n available_indexes as (\n select\n unnest (ix.indkey) as attnum,\n ix.indisprimary as is_primary,\n ix.indisunique as is_unique,\n ix.indrelid as table_oid\n from\n pg_catalog.pg_class c\n join pg_catalog.pg_index ix on c.oid = ix.indexrelid\n where\n c.relkind = 'i'\n )\nselect\n atts.attname as name,\n ts.table_name,\n ts.table_oid :: int8 as \"table_oid!\",\n ts.class_kind :: char as \"class_kind!\",\n ts.schema_name,\n atts.atttypid :: int8 as \"type_id!\",\n tps.typname as \"type_name\",\n not atts.attnotnull as \"is_nullable!\",\n nullif(\n information_schema._pg_char_max_length (atts.atttypid, atts.atttypmod),\n -1\n ) as varchar_length,\n pg_get_expr (def.adbin, def.adrelid) as default_expr,\n coalesce(ix.is_primary, false) as \"is_primary_key!\",\n coalesce(ix.is_unique, false) as \"is_unique!\",\n pg_catalog.col_description (ts.table_oid, atts.attnum) as comment\nfrom\n pg_catalog.pg_attribute atts\n join available_tables ts on atts.attrelid = ts.table_oid\n left join available_indexes ix on atts.attrelid = ix.table_oid\n and atts.attnum = ix.attnum\n left join pg_catalog.pg_attrdef def on atts.attrelid = def.adrelid\n and atts.attnum = def.adnum\n left join pg_catalog.pg_type tps on atts.atttypid = tps.oid\nwhere\n -- system columns, such as `cmax` or `tableoid`, have negative `attnum`s\n atts.attnum >= 0 and atts.atttypid is not null and tps.oid is not null\norder by\n schema_name desc,\n table_name,\n atts.attnum;",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "name",
- "type_info": "Name"
- },
- {
- "ordinal": 1,
- "name": "table_name",
- "type_info": "Name"
- },
- {
- "ordinal": 2,
- "name": "table_oid!",
- "type_info": "Int8"
- },
- {
- "ordinal": 3,
- "name": "class_kind!",
- "type_info": "Bpchar"
- },
- {
- "ordinal": 4,
- "name": "schema_name",
- "type_info": "Name"
- },
- {
- "ordinal": 5,
- "name": "type_id!",
- "type_info": "Int8"
- },
- {
- "ordinal": 6,
- "name": "type_name",
- "type_info": "Name"
- },
- {
- "ordinal": 7,
- "name": "is_nullable!",
- "type_info": "Bool"
- },
- {
- "ordinal": 8,
- "name": "varchar_length",
- "type_info": "Int4"
- },
- {
- "ordinal": 9,
- "name": "default_expr",
- "type_info": "Text"
- },
- {
- "ordinal": 10,
- "name": "is_primary_key!",
- "type_info": "Bool"
- },
- {
- "ordinal": 11,
- "name": "is_unique!",
- "type_info": "Bool"
- },
- {
- "ordinal": 12,
- "name": "comment",
- "type_info": "Text"
- }
- ],
- "parameters": {
- "Left": []
- },
- "nullable": [
- false,
- false,
- null,
- null,
- false,
- null,
- false,
- null,
- null,
- null,
- null,
- null,
- null
- ]
- },
- "hash": "fa065a78ad10eeace15f64083f4d944b9d45eb6c60d7eece8878ed26b3530484"
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 43994f87..00000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "postgrestools.bin": "./target/debug/postgrestools"
-}
diff --git a/404.html b/404.html
new file mode 100644
index 00000000..3e5728e8
--- /dev/null
+++ b/404.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+ Postgres Language Server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
deleted file mode 100644
index 5a10be2d..00000000
--- a/ARCHITECTURE.md
+++ /dev/null
@@ -1,71 +0,0 @@
-## Architecture
-
-This document describes the high-level architecture of postgres_lsp. If you want to familiarize yourself with the code base, you are just in the right place!
-
-> Since the project still evolves rapidly, this document may not be up-to-date. If you find any inconsistency, please let us know by creating an issue.
-
-### Bird's Eye View
-
-On the highest level, the postgres language server is a thing which accepts input source code, cuts it into individual sql statements and parses and analyses each. In addition, it connects to a postgres database and stores an im-memory schema cache with all required type information such as tables, columns and functions. The result of the parsing is used alongside the schema cache to answer queries about a statement.
-
-The client can submit a delta of input data (typically, a change to a single file), and the server will update the affected statements and their analysis accordingly. The underlying engine makes sure that we only re-parse and re-analyse what is necessary.
-
-### Entry Points
-
-The main entry point is as of now the `pg_lsp` crate, especially the `main.rs` function. It spawns the language server and starts listening for incoming messages. The server is implemented in the `server` module.
-
-There might be an additional entry point for a CLI tool in the future.
-
-### Code Map
-
-This section talks briefly about various important directories and data structures.
-
-#### `lib/`
-
-Independent libraries that are used by the project but are not specific for postgres.
-
-#### `crates/pg_lsp`
-
-The main entry point of the language server. It contains the server implementation and the main loop.
-
-#### `crates/pg_workspace`
-
-> This crate will grow significantly in near future. The current implementation just contains the base data structures and stores the diagnostic results from various features.
-
-The main API for consumers of the IDE. It stores the internal state of the workspace, such as the schema cache and the parsed statements and their analysis.
-
-#### `crates/pg_lexer`
-
-Simple lexer that tokenizes the input source code. Enhances the output of the `pg_query` tokenizer with the missing whitespace tokens.
-
-#### `crates/pg_statement_splitter`
-
-Implements the statement splitter, which cuts the input source code into individual statements.
-
-#### `crates/pg_base_db`
-
-Implements the base data structures and defines how documents and statements are stored and updated efficiently.
-
-#### `crates/pg_schema_cache`
-
-We store an in-memory representation of the database schema to efficiently resolve types.
-
-#### `crates/pg_query_ext`
-
-Simple wrapper crate for `pg_query` to expose types and a function to get the root node for an SQL statement. It also host any "extensions" to the `pg_query` crate that are not yet contributed upstream. Once all extensions are contributed upstream, this crate will be removed.
-
-#### `crates/pg_query_proto_parser`
-
-We use procedural macros a lot to generate repetitive code from the protobuf definition provided by `libg_query`. The `pg_query_proto_parser` crate is used to parse the proto file into a more usable data structure.
-
-#### `crates/pg_syntax`
-
-Implements the CST parser and AST enhancer. The CST parser is what is described in [this blog post](https://supabase.com/blog/postgres-language-server-implementing-parser). The AST enhancer takes in the CST and enriches the AST returned by `pg_query` with a range for each node.
-
-#### `crates/pg_type_resolver`
-
-Utility crate used by the feature crates listed below to resolve the source types to the actual types in the schema cache.
-
-#### `crates/pg_commands`, `crates/pg_completions`, `crates/pg_hover`, `crates/pg_inlay_hints`, `crates/pg_lint`, `crates/pg_typecheck`
-
-These crates implement the various features of the language server. They are all independent of each other and always operate on the schema cache and a single statement and its parse results. They are intentionally implemented in separate creates and without any language server flavour to make them reusable eg in a later cli.
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index 4771c8a1..00000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,5229 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "addr2line"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-
-[[package]]
-name = "ahash"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
-dependencies = [
- "cfg-if",
- "getrandom",
- "once_cell",
- "version_check",
- "zerocopy",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "allocator-api2"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
-
-[[package]]
-name = "anes"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
-
-[[package]]
-name = "anstream"
-version = "0.6.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
-dependencies = [
- "anstyle",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
-
-[[package]]
-name = "assert_cmd"
-version = "2.0.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d"
-dependencies = [
- "anstyle",
- "bstr",
- "doc-comment",
- "libc",
- "predicates",
- "predicates-core",
- "predicates-tree",
- "wait-timeout",
-]
-
-[[package]]
-name = "async-channel"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
-dependencies = [
- "concurrent-queue",
- "event-listener 2.5.3",
- "futures-core",
-]
-
-[[package]]
-name = "async-channel"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
-dependencies = [
- "concurrent-queue",
- "event-listener-strategy",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-executor"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
-dependencies = [
- "async-task",
- "concurrent-queue",
- "fastrand 2.3.0",
- "futures-lite 2.5.0",
- "slab",
-]
-
-[[package]]
-name = "async-global-executor"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
-dependencies = [
- "async-channel 2.3.1",
- "async-executor",
- "async-io 2.4.0",
- "async-lock 3.4.0",
- "blocking",
- "futures-lite 2.5.0",
- "once_cell",
-]
-
-[[package]]
-name = "async-io"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
-dependencies = [
- "async-lock 2.8.0",
- "autocfg",
- "cfg-if",
- "concurrent-queue",
- "futures-lite 1.13.0",
- "log",
- "parking",
- "polling 2.8.0",
- "rustix 0.37.28",
- "slab",
- "socket2 0.4.10",
- "waker-fn",
-]
-
-[[package]]
-name = "async-io"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059"
-dependencies = [
- "async-lock 3.4.0",
- "cfg-if",
- "concurrent-queue",
- "futures-io",
- "futures-lite 2.5.0",
- "parking",
- "polling 3.7.4",
- "rustix 0.38.42",
- "slab",
- "tracing",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "async-lock"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
-dependencies = [
- "event-listener 2.5.3",
-]
-
-[[package]]
-name = "async-lock"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
-dependencies = [
- "event-listener 5.3.1",
- "event-listener-strategy",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-std"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615"
-dependencies = [
- "async-channel 1.9.0",
- "async-global-executor",
- "async-io 2.4.0",
- "async-lock 3.4.0",
- "crossbeam-utils",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-lite 2.5.0",
- "gloo-timers",
- "kv-log-macro",
- "log",
- "memchr",
- "once_cell",
- "pin-project-lite",
- "pin-utils",
- "slab",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "async-task"
-version = "4.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
-
-[[package]]
-name = "async-trait"
-version = "0.1.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "atoi"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "atomic-waker"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-
-[[package]]
-name = "auto_impl"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
-[[package]]
-name = "backtrace"
-version = "0.3.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
-dependencies = [
- "addr2line",
- "cfg-if",
- "libc",
- "miniz_oxide",
- "object",
- "rustc-demangle",
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "base64"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "base64ct"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
-
-[[package]]
-name = "bindgen"
-version = "0.66.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7"
-dependencies = [
- "bitflags 2.6.0",
- "cexpr",
- "clang-sys",
- "lazy_static",
- "lazycell",
- "log",
- "peeking_take_while",
- "prettyplease",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash 1.1.0",
- "shlex",
- "syn 2.0.90",
- "which",
-]
-
-[[package]]
-name = "biome_console"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c672a9e31e47f8df74549a570ea3245a93ce3404115c724bb16762fcbbfe17e1"
-dependencies = [
- "biome_markup",
- "biome_text_size",
- "schemars",
- "serde",
- "termcolor",
- "unicode-segmentation",
- "unicode-width",
-]
-
-[[package]]
-name = "biome_deserialize"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b4443260d505148169f5fb35634c2a60d8489882f8c9c3f1db8b7cf0cb57632"
-dependencies = [
- "biome_console",
- "biome_deserialize_macros 0.5.7",
- "biome_diagnostics",
- "biome_json_parser",
- "biome_json_syntax",
- "biome_rowan",
- "bitflags 2.6.0",
- "indexmap 1.9.3",
- "serde",
- "serde_json",
- "tracing",
-]
-
-[[package]]
-name = "biome_deserialize"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6f619dc8ca0595ed8850d729ebc71722d4233aba68c5aec7d9993a53e59f3fe"
-dependencies = [
- "biome_console",
- "biome_deserialize_macros 0.6.0",
- "biome_diagnostics",
- "biome_json_parser",
- "biome_json_syntax",
- "biome_rowan",
- "bitflags 2.6.0",
- "indexmap 2.7.0",
- "schemars",
- "serde",
-]
-
-[[package]]
-name = "biome_deserialize_macros"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fc1244cc5f0cc267bd26b601e9ccd6851c6a4d395bba07e27c2de641dc84479"
-dependencies = [
- "convert_case",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "biome_deserialize_macros"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07c12826fff87ac09f63bbacf8bdf5225dfdf890da04d426f758cbcacf068e3e"
-dependencies = [
- "biome_string_case",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "biome_diagnostics"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe1317b6d610541c4e6a0e1f803a946f153ace3468bbc77a8f273dcb04ee526f"
-dependencies = [
- "backtrace",
- "biome_console",
- "biome_diagnostics_categories",
- "biome_diagnostics_macros",
- "biome_rowan",
- "biome_text_edit",
- "biome_text_size",
- "bitflags 2.6.0",
- "bpaf",
- "oxc_resolver",
- "serde",
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
-name = "biome_diagnostics_categories"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "832080d68a2ee2f198d98ff5d26fc0f5c2566907f773d105a4a049ee07664d19"
-dependencies = [
- "quote",
- "serde",
-]
-
-[[package]]
-name = "biome_diagnostics_macros"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "540fec04d2e789fb992128c63d111b650733274afffff1cb3f26c8dff5167d3b"
-dependencies = [
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "biome_formatter"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d351a9dc49ae024220a83c44329ab14a9e66887a7ca51fc7ae875e9e56f626c"
-dependencies = [
- "biome_console",
- "biome_deserialize 0.5.7",
- "biome_deserialize_macros 0.5.7",
- "biome_diagnostics",
- "biome_rowan",
- "cfg-if",
- "countme",
- "drop_bomb",
- "indexmap 1.9.3",
- "rustc-hash 1.1.0",
- "tracing",
- "unicode-width",
-]
-
-[[package]]
-name = "biome_js_factory"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c9847f4dfd16ee242d12b90f96f6b2eb33238dfc4eac7b5c045e14eebe717b7"
-dependencies = [
- "biome_js_syntax",
- "biome_rowan",
-]
-
-[[package]]
-name = "biome_js_formatter"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bc1f8b67a8fa45555a7a9ea1004eca73c159b7f1941050311d35e312cff3bb8"
-dependencies = [
- "biome_console",
- "biome_deserialize 0.5.7",
- "biome_deserialize_macros 0.5.7",
- "biome_diagnostics_categories",
- "biome_formatter",
- "biome_js_factory",
- "biome_js_syntax",
- "biome_json_syntax",
- "biome_rowan",
- "biome_text_size",
- "biome_unicode_table",
- "cfg-if",
- "smallvec",
- "tracing",
- "unicode-width",
-]
-
-[[package]]
-name = "biome_js_syntax"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38a524bd8b1f5f7b3355dfe2744196227ee15e9aa3446d562deb9ed511cf2015"
-dependencies = [
- "biome_console",
- "biome_diagnostics",
- "biome_rowan",
- "serde",
-]
-
-[[package]]
-name = "biome_json_factory"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e409eb289040f3660689dad178b00b6ac8cfa9a7fffd8225f35cb6b3d36437cf"
-dependencies = [
- "biome_json_syntax",
- "biome_rowan",
-]
-
-[[package]]
-name = "biome_json_parser"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c6d23fb9b683e6356c094b4a0cb38f8aa0acee60ce9c3ef24628d21a204de4d"
-dependencies = [
- "biome_console",
- "biome_diagnostics",
- "biome_json_factory",
- "biome_json_syntax",
- "biome_parser",
- "biome_rowan",
- "biome_unicode_table",
- "tracing",
- "unicode-bom",
-]
-
-[[package]]
-name = "biome_json_syntax"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2645ca57f75680d3d390b2482c35db5850b1d849e1f96151a12f15f4abdb097"
-dependencies = [
- "biome_rowan",
- "serde",
-]
-
-[[package]]
-name = "biome_markup"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a7f11cf91599594528e97d216044ef4e410a103327212d909f215cbafe2fd9c"
-dependencies = [
- "proc-macro-error",
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "biome_parser"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955dd999f32c086371d5c0e64b4ea1a50f50c98f1f31a3b9fe17ef47198de19b"
-dependencies = [
- "biome_console",
- "biome_diagnostics",
- "biome_rowan",
- "bitflags 2.6.0",
- "drop_bomb",
-]
-
-[[package]]
-name = "biome_rowan"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3c2dc25a7ba6ae89526340034abed6c89fac35b79060786771e32ed4aac77e7"
-dependencies = [
- "biome_text_edit",
- "biome_text_size",
- "countme",
- "hashbrown 0.12.3",
- "memoffset",
- "rustc-hash 1.1.0",
- "tracing",
-]
-
-[[package]]
-name = "biome_string_case"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5868798da491b19a5b27a0bad5d8727e1e65060fa2dac360b382df00ff520774"
-
-[[package]]
-name = "biome_text_edit"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d486fdd96d5dad6428213ce64e6b9eb5bfb2fce6387fe901e844d386283de509"
-dependencies = [
- "biome_text_size",
- "serde",
- "similar",
-]
-
-[[package]]
-name = "biome_text_size"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ec604d15cefdced636255400359aeacfdea5d1e79445efc7aa32a0de7f0319b"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "biome_unicode_table"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87e8604d34b02180a58af1dbdaac166f1805f27f5370934142a3246f83870952"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "blocking"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
-dependencies = [
- "async-channel 2.3.1",
- "async-task",
- "futures-io",
- "futures-lite 2.5.0",
- "piper",
-]
-
-[[package]]
-name = "bpaf"
-version = "0.9.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50fd5174866dc2fa2ddc96e8fb800852d37f064f32a45c7b7c2f8fa2c64c77fa"
-dependencies = [
- "bpaf_derive",
- "owo-colors",
- "supports-color",
-]
-
-[[package]]
-name = "bpaf_derive"
-version = "0.5.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf95d9c7e6aba67f8fc07761091e93254677f4db9e27197adecebc7039a58722"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "bstr"
-version = "1.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22"
-dependencies = [
- "memchr",
- "regex-automata 0.4.9",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
-
-[[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
-name = "bytes"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
-
-[[package]]
-name = "cast"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
-
-[[package]]
-name = "cc"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
-dependencies = [
- "shlex",
-]
-
-[[package]]
-name = "cexpr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "ciborium"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
-dependencies = [
- "ciborium-io",
- "ciborium-ll",
- "serde",
-]
-
-[[package]]
-name = "ciborium-io"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
-
-[[package]]
-name = "ciborium-ll"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
-dependencies = [
- "ciborium-io",
- "half",
-]
-
-[[package]]
-name = "clang-sys"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "clap"
-version = "4.5.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
-dependencies = [
- "clap_builder",
- "clap_derive",
-]
-
-[[package]]
-name = "clap_builder"
-version = "4.5.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
-dependencies = [
- "anstream",
- "anstyle",
- "clap_lex",
- "strsim",
-]
-
-[[package]]
-name = "clap_derive"
-version = "4.5.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "clap_lex"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
-
-[[package]]
-name = "colorchoice"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
-
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "console"
-version = "0.15.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
-dependencies = [
- "encode_unicode",
- "lazy_static",
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "const-oid"
-version = "0.9.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
-
-[[package]]
-name = "convert_case"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "countme"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
-
-[[package]]
-name = "cpufeatures"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crc"
-version = "3.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
-dependencies = [
- "crc-catalog",
-]
-
-[[package]]
-name = "crc-catalog"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
-
-[[package]]
-name = "crc32fast"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "criterion"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
-dependencies = [
- "anes",
- "cast",
- "ciborium",
- "clap",
- "criterion-plot",
- "is-terminal",
- "itertools 0.10.5",
- "num-traits",
- "once_cell",
- "oorandom",
- "plotters",
- "rayon",
- "regex",
- "serde",
- "serde_derive",
- "serde_json",
- "tinytemplate",
- "walkdir",
-]
-
-[[package]]
-name = "criterion-plot"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
-dependencies = [
- "cast",
- "itertools 0.10.5",
-]
-
-[[package]]
-name = "crossbeam"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
-dependencies = [
- "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-epoch",
- "crossbeam-queue",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
-dependencies = [
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-queue"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
-
-[[package]]
-name = "crunchy"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
-
-[[package]]
-name = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "typenum",
-]
-
-[[package]]
-name = "dashmap"
-version = "5.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
-dependencies = [
- "cfg-if",
- "hashbrown 0.14.5",
- "lock_api",
- "once_cell",
- "parking_lot_core",
-]
-
-[[package]]
-name = "dashmap"
-version = "6.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
- "hashbrown 0.14.5",
- "lock_api",
- "once_cell",
- "parking_lot_core",
-]
-
-[[package]]
-name = "der"
-version = "0.7.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
-dependencies = [
- "const-oid",
- "pem-rfc7468",
- "zeroize",
-]
-
-[[package]]
-name = "deranged"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
-dependencies = [
- "powerfmt",
-]
-
-[[package]]
-name = "difflib"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
-
-[[package]]
-name = "digest"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
-dependencies = [
- "block-buffer",
- "const-oid",
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "directories"
-version = "5.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
-dependencies = [
- "dirs-sys",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
-[[package]]
-name = "docs_codegen"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "biome_string_case",
- "bpaf",
- "pgt_analyse",
- "pgt_analyser",
- "pgt_cli",
- "pgt_configuration",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_flags",
- "pgt_query_ext",
- "pgt_statement_splitter",
- "pgt_workspace",
- "pulldown-cmark",
- "regex",
- "schemars",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "dotenv"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
-
-[[package]]
-name = "dotenvy"
-version = "0.15.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
-
-[[package]]
-name = "drop_bomb"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
-
-[[package]]
-name = "dunce"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
-
-[[package]]
-name = "dyn-clone"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
-
-[[package]]
-name = "either"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "encode_unicode"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
-
-[[package]]
-name = "enumflags2"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147"
-dependencies = [
- "enumflags2_derive",
-]
-
-[[package]]
-name = "enumflags2_derive"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "env_filter"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
-dependencies = [
- "log",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.11.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697"
-dependencies = [
- "anstream",
- "anstyle",
- "env_filter",
- "log",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
-
-[[package]]
-name = "errno"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "etcetera"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
-dependencies = [
- "cfg-if",
- "home",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "event-listener"
-version = "2.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
-
-[[package]]
-name = "event-listener"
-version = "5.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "event-listener-strategy"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
-dependencies = [
- "event-listener 5.3.1",
- "pin-project-lite",
-]
-
-[[package]]
-name = "fastrand"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
-dependencies = [
- "instant",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
-
-[[package]]
-name = "fixedbitset"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
-
-[[package]]
-name = "flate2"
-version = "1.0.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "float-cmp"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "flume"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
-dependencies = [
- "futures-core",
- "futures-sink",
- "spin",
-]
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "fs_extra"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-intrusive"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
-dependencies = [
- "futures-core",
- "lock_api",
- "parking_lot",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-lite"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
-dependencies = [
- "fastrand 1.9.0",
- "futures-core",
- "futures-io",
- "memchr",
- "parking",
- "pin-project-lite",
- "waker-fn",
-]
-
-[[package]]
-name = "futures-lite"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1"
-dependencies = [
- "fastrand 2.3.0",
- "futures-core",
- "futures-io",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "fuzzy-matcher"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
-dependencies = [
- "thread_local",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
-]
-
-[[package]]
-name = "gethostname"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "getopts"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "gimli"
-version = "0.31.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-
-[[package]]
-name = "glob"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
-
-[[package]]
-name = "globset"
-version = "0.4.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
-dependencies = [
- "aho-corasick",
- "bstr",
- "log",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "globwalk"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
-dependencies = [
- "bitflags 2.6.0",
- "ignore",
- "walkdir",
-]
-
-[[package]]
-name = "gloo-timers"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
-dependencies = [
- "futures-channel",
- "futures-core",
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "half"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
-dependencies = [
- "cfg-if",
- "crunchy",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-dependencies = [
- "ahash",
- "allocator-api2",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
-
-[[package]]
-name = "hashlink"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
-dependencies = [
- "hashbrown 0.14.5",
-]
-
-[[package]]
-name = "hdrhistogram"
-version = "7.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d"
-dependencies = [
- "byteorder",
- "num-traits",
-]
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
-[[package]]
-name = "hermit-abi"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
-
-[[package]]
-name = "hermit-abi"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "hkdf"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
-dependencies = [
- "hmac",
-]
-
-[[package]]
-name = "hmac"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "home"
-version = "0.5.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "httparse"
-version = "1.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
-
-[[package]]
-name = "icu_collections"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
-
-[[package]]
-name = "icu_normalizer"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "utf16_iter",
- "utf8_iter",
- "write16",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
-
-[[package]]
-name = "icu_properties"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locid_transform",
- "icu_properties_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
-
-[[package]]
-name = "icu_provider"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_provider_macros",
- "stable_deref_trait",
- "tinystr",
- "writeable",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "idna"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "ignore"
-version = "0.4.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"
-dependencies = [
- "crossbeam-deque",
- "globset",
- "log",
- "memchr",
- "regex-automata 0.4.9",
- "same-file",
- "walkdir",
- "winapi-util",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
- "serde",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
-dependencies = [
- "equivalent",
- "hashbrown 0.15.2",
- "serde",
-]
-
-[[package]]
-name = "insta"
-version = "1.42.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71c1b125e30d93896b365e156c33dadfffab45ee8400afcbba4752f59de08a86"
-dependencies = [
- "console",
- "linked-hash-map",
- "once_cell",
- "pin-project",
- "similar",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
-dependencies = [
- "hermit-abi 0.3.9",
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "is-terminal"
-version = "0.4.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
-dependencies = [
- "hermit-abi 0.5.0",
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "is_ci"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
-
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
-[[package]]
-name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
-
-[[package]]
-name = "js-sys"
-version = "0.3.76"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
-dependencies = [
- "once_cell",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "json-strip-comments"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b271732a960335e715b6b2ae66a086f115c74eb97360e996d2bd809bfc063bba"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "kv-log-macro"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
-dependencies = [
- "log",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-dependencies = [
- "spin",
-]
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
-name = "libc"
-version = "0.2.168"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
-
-[[package]]
-name = "libloading"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
-dependencies = [
- "cfg-if",
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "libm"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
-
-[[package]]
-name = "libmimalloc-sys"
-version = "0.1.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "libredox"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
-dependencies = [
- "bitflags 2.6.0",
- "libc",
-]
-
-[[package]]
-name = "libsqlite3-sys"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
-dependencies = [
- "cc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "linked-hash-map"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
-
-[[package]]
-name = "litemap"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
-
-[[package]]
-name = "lock_api"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "log"
-version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
-dependencies = [
- "value-bag",
-]
-
-[[package]]
-name = "lsp-types"
-version = "0.94.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1"
-dependencies = [
- "bitflags 1.3.2",
- "serde",
- "serde_json",
- "serde_repr",
- "url",
-]
-
-[[package]]
-name = "matchers"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
-dependencies = [
- "regex-automata 0.1.10",
-]
-
-[[package]]
-name = "md-5"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
-dependencies = [
- "cfg-if",
- "digest",
-]
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "memoffset"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "mimalloc"
-version = "0.1.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633"
-dependencies = [
- "libmimalloc-sys",
-]
-
-[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
-dependencies = [
- "adler2",
-]
-
-[[package]]
-name = "mio"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
-dependencies = [
- "libc",
- "wasi",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "multimap"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
-
-[[package]]
-name = "newtype-uuid"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8781e2ef64806278a55ad223f0bc875772fd40e1fe6e73e8adbf027817229d"
-dependencies = [
- "uuid",
-]
-
-[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
-name = "normalize-line-endings"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
-
-[[package]]
-name = "ntest"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb183f0a1da7a937f672e5ee7b7edb727bf52b8a52d531374ba8ebb9345c0330"
-dependencies = [
- "ntest_test_cases",
- "ntest_timeout",
-]
-
-[[package]]
-name = "ntest_test_cases"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16d0d3f2a488592e5368ebbe996e7f1d44aa13156efad201f5b4d84e150eaa93"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "ntest_timeout"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc7c92f190c97f79b4a332f5e81dcf68c8420af2045c936c9be0bc9de6f63b5"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "nu-ansi-term"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
-dependencies = [
- "overload",
- "winapi",
-]
-
-[[package]]
-name = "nu-ansi-term"
-version = "0.50.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "num-bigint-dig"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
-dependencies = [
- "byteorder",
- "lazy_static",
- "libm",
- "num-integer",
- "num-iter",
- "num-traits",
- "rand",
- "smallvec",
- "zeroize",
-]
-
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
-[[package]]
-name = "num-integer"
-version = "0.1.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-iter"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
- "libm",
-]
-
-[[package]]
-name = "num_threads"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "object"
-version = "0.36.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.20.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
-
-[[package]]
-name = "oorandom"
-version = "11.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
-
-[[package]]
-name = "option-ext"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
-
-[[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
-[[package]]
-name = "owo-colors"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
-
-[[package]]
-name = "oxc_resolver"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c20bb345f290c46058ba650fef7ca2b579612cf2786b927ebad7b8bec0845a7"
-dependencies = [
- "cfg-if",
- "dashmap 6.1.0",
- "dunce",
- "indexmap 2.7.0",
- "json-strip-comments",
- "once_cell",
- "rustc-hash 2.1.0",
- "serde",
- "serde_json",
- "simdutf8",
- "thiserror 1.0.69",
- "tracing",
-]
-
-[[package]]
-name = "parking"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
-
-[[package]]
-name = "parking_lot"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
-dependencies = [
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
-dependencies = [
- "cfg-if",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "paste"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-[[package]]
-name = "path-absolutize"
-version = "3.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5"
-dependencies = [
- "path-dedot",
-]
-
-[[package]]
-name = "path-dedot"
-version = "3.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "peeking_take_while"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-
-[[package]]
-name = "pem-rfc7468"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
-dependencies = [
- "base64ct",
-]
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
-
-[[package]]
-name = "petgraph"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
-dependencies = [
- "fixedbitset",
- "indexmap 2.7.0",
-]
-
-[[package]]
-name = "pg_query"
-version = "6.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f71c7c56dfe299ec6f98aa210aa23458be3b0610c485be60a5873c2f3627c40e"
-dependencies = [
- "bindgen",
- "cc",
- "fs_extra",
- "glob",
- "itertools 0.10.5",
- "prost",
- "prost-build",
- "serde",
- "serde_json",
- "thiserror 1.0.69",
-]
-
-[[package]]
-name = "pgt_analyse"
-version = "0.0.0"
-dependencies = [
- "biome_deserialize 0.6.0",
- "biome_deserialize_macros 0.6.0",
- "enumflags2",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_query_ext",
- "pgt_text_size",
- "rustc-hash 2.1.0",
- "schemars",
- "serde",
-]
-
-[[package]]
-name = "pgt_analyser"
-version = "0.0.0"
-dependencies = [
- "insta",
- "pgt_analyse",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_query_ext",
- "pgt_test_macros",
- "serde",
- "termcolor",
-]
-
-[[package]]
-name = "pgt_cli"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "assert_cmd",
- "biome_deserialize 0.6.0",
- "biome_deserialize_macros 0.6.0",
- "bpaf",
- "crossbeam",
- "dashmap 5.5.3",
- "hdrhistogram",
- "libc",
- "mimalloc",
- "path-absolutize",
- "pgt_analyse",
- "pgt_configuration",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_flags",
- "pgt_fs",
- "pgt_lsp",
- "pgt_text_edit",
- "pgt_workspace",
- "predicates",
- "quick-junit",
- "rayon",
- "rustc-hash 2.1.0",
- "serde",
- "serde_json",
- "tikv-jemallocator",
- "tokio",
- "tracing",
- "tracing-appender",
- "tracing-bunyan-formatter",
- "tracing-subscriber",
- "tracing-tree",
-]
-
-[[package]]
-name = "pgt_completions"
-version = "0.0.0"
-dependencies = [
- "async-std",
- "criterion",
- "fuzzy-matcher",
- "pgt_schema_cache",
- "pgt_test_utils",
- "pgt_text_size",
- "pgt_treesitter_queries",
- "schemars",
- "serde",
- "serde_json",
- "sqlx",
- "tokio",
- "tracing",
- "tree-sitter",
- "tree_sitter_sql",
-]
-
-[[package]]
-name = "pgt_configuration"
-version = "0.0.0"
-dependencies = [
- "biome_deserialize 0.6.0",
- "biome_deserialize_macros 0.6.0",
- "bpaf",
- "indexmap 2.7.0",
- "pgt_analyse",
- "pgt_analyser",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_text_size",
- "rustc-hash 2.1.0",
- "schemars",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "pgt_console"
-version = "0.0.0"
-dependencies = [
- "pgt_markup",
- "pgt_text_size",
- "schemars",
- "serde",
- "termcolor",
- "trybuild",
- "unicode-segmentation",
- "unicode-width",
-]
-
-[[package]]
-name = "pgt_diagnostics"
-version = "0.0.0"
-dependencies = [
- "backtrace",
- "bpaf",
- "enumflags2",
- "pgt_console",
- "pgt_diagnostics_categories",
- "pgt_diagnostics_macros",
- "pgt_text_edit",
- "pgt_text_size",
- "schemars",
- "serde",
- "serde_json",
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
-name = "pgt_diagnostics_categories"
-version = "0.0.0"
-dependencies = [
- "quote",
- "schemars",
- "serde",
-]
-
-[[package]]
-name = "pgt_diagnostics_macros"
-version = "0.0.0"
-dependencies = [
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "pgt_flags"
-version = "0.0.0"
-dependencies = [
- "pgt_console",
-]
-
-[[package]]
-name = "pgt_fs"
-version = "0.0.0"
-dependencies = [
- "crossbeam",
- "directories",
- "enumflags2",
- "parking_lot",
- "pgt_diagnostics",
- "rayon",
- "rustc-hash 2.1.0",
- "schemars",
- "serde",
- "smallvec",
- "tracing",
-]
-
-[[package]]
-name = "pgt_lexer"
-version = "0.0.0"
-dependencies = [
- "insta",
- "pg_query",
- "pgt_diagnostics",
- "pgt_lexer_codegen",
- "pgt_text_size",
- "regex",
-]
-
-[[package]]
-name = "pgt_lexer_codegen"
-version = "0.0.0"
-dependencies = [
- "pgt_query_proto_parser",
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "pgt_lsp"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "biome_deserialize 0.6.0",
- "futures",
- "pgt_analyse",
- "pgt_completions",
- "pgt_configuration",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_fs",
- "pgt_test_utils",
- "pgt_text_edit",
- "pgt_text_size",
- "pgt_workspace",
- "rustc-hash 2.1.0",
- "serde",
- "serde_json",
- "sqlx",
- "strum",
- "test-log",
- "tokio",
- "tower",
- "tower-lsp",
- "tracing",
-]
-
-[[package]]
-name = "pgt_markup"
-version = "0.0.0"
-dependencies = [
- "proc-macro-error",
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "pgt_query_ext"
-version = "0.0.0"
-dependencies = [
- "petgraph",
- "pg_query",
- "pgt_diagnostics",
- "pgt_lexer",
- "pgt_query_ext_codegen",
- "pgt_text_size",
-]
-
-[[package]]
-name = "pgt_query_ext_codegen"
-version = "0.0.0"
-dependencies = [
- "pgt_query_proto_parser",
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "pgt_query_proto_parser"
-version = "0.0.0"
-dependencies = [
- "convert_case",
- "protobuf",
- "protobuf-parse",
-]
-
-[[package]]
-name = "pgt_schema_cache"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "async-std",
- "futures-util",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_test_utils",
- "serde",
- "serde_json",
- "sqlx",
- "strum",
- "tokio",
-]
-
-[[package]]
-name = "pgt_statement_splitter"
-version = "0.0.0"
-dependencies = [
- "ntest",
- "pgt_diagnostics",
- "pgt_lexer",
- "pgt_query_ext",
- "pgt_text_size",
- "regex",
-]
-
-[[package]]
-name = "pgt_test_macros"
-version = "0.0.0"
-dependencies = [
- "globwalk",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "pgt_test_utils"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "clap",
- "dotenv",
- "sqlx",
- "tree-sitter",
- "tree_sitter_sql",
- "uuid",
-]
-
-[[package]]
-name = "pgt_text_edit"
-version = "0.0.0"
-dependencies = [
- "pgt_text_size",
- "schemars",
- "serde",
- "similar",
-]
-
-[[package]]
-name = "pgt_text_size"
-version = "0.0.0"
-dependencies = [
- "schemars",
- "serde",
- "serde_test",
- "static_assertions",
-]
-
-[[package]]
-name = "pgt_treesitter_queries"
-version = "0.0.0"
-dependencies = [
- "clap",
- "tree-sitter",
- "tree_sitter_sql",
-]
-
-[[package]]
-name = "pgt_type_resolver"
-version = "0.0.0"
-dependencies = [
- "pgt_query_ext",
- "pgt_schema_cache",
-]
-
-[[package]]
-name = "pgt_typecheck"
-version = "0.0.0"
-dependencies = [
- "insta",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_query_ext",
- "pgt_schema_cache",
- "pgt_test_utils",
- "pgt_text_size",
- "pgt_treesitter_queries",
- "sqlx",
- "tokio",
- "tree-sitter",
- "tree_sitter_sql",
-]
-
-[[package]]
-name = "pgt_workspace"
-version = "0.0.0"
-dependencies = [
- "biome_deserialize 0.6.0",
- "biome_js_factory",
- "biome_js_syntax",
- "biome_rowan",
- "dashmap 5.5.3",
- "futures",
- "globset",
- "ignore",
- "pgt_analyse",
- "pgt_analyser",
- "pgt_completions",
- "pgt_configuration",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_fs",
- "pgt_lexer",
- "pgt_query_ext",
- "pgt_schema_cache",
- "pgt_statement_splitter",
- "pgt_text_size",
- "pgt_typecheck",
- "rustc-hash 2.1.0",
- "schemars",
- "serde",
- "serde_json",
- "sqlx",
- "strum",
- "tempfile",
- "tokio",
- "tracing",
- "tree-sitter",
- "tree_sitter_sql",
-]
-
-[[package]]
-name = "pin-project"
-version = "1.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
-dependencies = [
- "pin-project-internal",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "1.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "piper"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
-dependencies = [
- "atomic-waker",
- "fastrand 2.3.0",
- "futures-io",
-]
-
-[[package]]
-name = "pkcs1"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
-dependencies = [
- "der",
- "pkcs8",
- "spki",
-]
-
-[[package]]
-name = "pkcs8"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
-dependencies = [
- "der",
- "spki",
-]
-
-[[package]]
-name = "pkg-config"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
-
-[[package]]
-name = "plotters"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
-dependencies = [
- "num-traits",
- "plotters-backend",
- "plotters-svg",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "plotters-backend"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
-
-[[package]]
-name = "plotters-svg"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
-dependencies = [
- "plotters-backend",
-]
-
-[[package]]
-name = "polling"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
-dependencies = [
- "autocfg",
- "bitflags 1.3.2",
- "cfg-if",
- "concurrent-queue",
- "libc",
- "log",
- "pin-project-lite",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "polling"
-version = "3.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
-dependencies = [
- "cfg-if",
- "concurrent-queue",
- "hermit-abi 0.4.0",
- "pin-project-lite",
- "rustix 0.38.42",
- "tracing",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
-dependencies = [
- "zerocopy",
-]
-
-[[package]]
-name = "predicates"
-version = "3.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
-dependencies = [
- "anstyle",
- "difflib",
- "float-cmp",
- "normalize-line-endings",
- "predicates-core",
- "regex",
-]
-
-[[package]]
-name = "predicates-core"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
-
-[[package]]
-name = "predicates-tree"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
-dependencies = [
- "predicates-core",
- "termtree",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
-dependencies = [
- "proc-macro2",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
-dependencies = [
- "toml_edit",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "prost"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
-dependencies = [
- "bytes",
- "prost-derive",
-]
-
-[[package]]
-name = "prost-build"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
-dependencies = [
- "heck",
- "itertools 0.14.0",
- "log",
- "multimap",
- "once_cell",
- "petgraph",
- "prettyplease",
- "prost",
- "prost-types",
- "regex",
- "syn 2.0.90",
- "tempfile",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
-dependencies = [
- "anyhow",
- "itertools 0.14.0",
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
-dependencies = [
- "prost",
-]
-
-[[package]]
-name = "protobuf"
-version = "3.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72"
-dependencies = [
- "once_cell",
- "protobuf-support",
- "thiserror 1.0.69",
-]
-
-[[package]]
-name = "protobuf-parse"
-version = "3.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257"
-dependencies = [
- "anyhow",
- "indexmap 2.7.0",
- "log",
- "protobuf",
- "protobuf-support",
- "tempfile",
- "thiserror 1.0.69",
- "which",
-]
-
-[[package]]
-name = "protobuf-support"
-version = "3.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252"
-dependencies = [
- "thiserror 1.0.69",
-]
-
-[[package]]
-name = "pulldown-cmark"
-version = "0.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
-dependencies = [
- "bitflags 2.6.0",
- "getopts",
- "memchr",
- "pulldown-cmark-escape",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark-escape"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
-
-[[package]]
-name = "quick-junit"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed1a693391a16317257103ad06a88c6529ac640846021da7c435a06fffdacd7"
-dependencies = [
- "chrono",
- "indexmap 2.7.0",
- "newtype-uuid",
- "quick-xml",
- "strip-ansi-escapes",
- "thiserror 2.0.6",
- "uuid",
-]
-
-[[package]]
-name = "quick-xml"
-version = "0.37.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f22f29bdff3987b4d8632ef95fd6424ec7e4e0a57e2f4fc63e489e75357f6a03"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rayon"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
-dependencies = [
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
-dependencies = [
- "crossbeam-deque",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
-dependencies = [
- "bitflags 2.6.0",
-]
-
-[[package]]
-name = "redox_users"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
-dependencies = [
- "getrandom",
- "libredox",
- "thiserror 1.0.69",
-]
-
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-dependencies = [
- "regex-syntax 0.6.29",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
-[[package]]
-name = "rsa"
-version = "0.9.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
-dependencies = [
- "const-oid",
- "digest",
- "num-bigint-dig",
- "num-integer",
- "num-traits",
- "pkcs1",
- "pkcs8",
- "rand_core",
- "signature",
- "spki",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "rules_check"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "pgt_analyse",
- "pgt_analyser",
- "pgt_console",
- "pgt_diagnostics",
- "pgt_query_ext",
- "pgt_statement_splitter",
- "pgt_workspace",
- "pulldown-cmark",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustc-hash"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
-
-[[package]]
-name = "rustix"
-version = "0.37.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6"
-dependencies = [
- "bitflags 1.3.2",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys 0.3.8",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
-dependencies = [
- "bitflags 2.6.0",
- "errno",
- "libc",
- "linux-raw-sys 0.4.14",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
-
-[[package]]
-name = "ryu"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "schemars"
-version = "0.8.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
-dependencies = [
- "dyn-clone",
- "indexmap 1.9.3",
- "indexmap 2.7.0",
- "schemars_derive",
- "serde",
- "serde_json",
- "smallvec",
-]
-
-[[package]]
-name = "schemars_derive"
-version = "0.8.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde_derive_internals",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
-name = "serde"
-version = "1.0.215"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.215"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "serde_derive_internals"
-version = "0.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.133"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
-dependencies = [
- "indexmap 2.7.0",
- "itoa",
- "memchr",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "serde_repr"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "serde_spanned"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "serde_test"
-version = "1.0.177"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "serde_urlencoded"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
-dependencies = [
- "form_urlencoded",
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "sha2"
-version = "0.10.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "sharded-slab"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "signature"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
-dependencies = [
- "digest",
- "rand_core",
-]
-
-[[package]]
-name = "simdutf8"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
-
-[[package]]
-name = "similar"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
-dependencies = [
- "bstr",
- "unicode-segmentation",
-]
-
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "socket2"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "socket2"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "spin"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
-dependencies = [
- "lock_api",
-]
-
-[[package]]
-name = "spki"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
-dependencies = [
- "base64ct",
- "der",
-]
-
-[[package]]
-name = "sqlformat"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
-dependencies = [
- "nom",
- "unicode_categories",
-]
-
-[[package]]
-name = "sqlx"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e"
-dependencies = [
- "sqlx-core",
- "sqlx-macros",
- "sqlx-mysql",
- "sqlx-postgres",
- "sqlx-sqlite",
-]
-
-[[package]]
-name = "sqlx-core"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e"
-dependencies = [
- "async-io 1.13.0",
- "async-std",
- "atoi",
- "byteorder",
- "bytes",
- "crc",
- "crossbeam-queue",
- "either",
- "event-listener 5.3.1",
- "futures-channel",
- "futures-core",
- "futures-intrusive",
- "futures-io",
- "futures-util",
- "hashbrown 0.14.5",
- "hashlink",
- "hex",
- "indexmap 2.7.0",
- "log",
- "memchr",
- "once_cell",
- "paste",
- "percent-encoding",
- "serde",
- "serde_json",
- "sha2",
- "smallvec",
- "sqlformat",
- "thiserror 1.0.69",
- "tokio",
- "tokio-stream",
- "tracing",
- "url",
-]
-
-[[package]]
-name = "sqlx-macros"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657"
-dependencies = [
- "proc-macro2",
- "quote",
- "sqlx-core",
- "sqlx-macros-core",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "sqlx-macros-core"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5"
-dependencies = [
- "async-std",
- "dotenvy",
- "either",
- "heck",
- "hex",
- "once_cell",
- "proc-macro2",
- "quote",
- "serde",
- "serde_json",
- "sha2",
- "sqlx-core",
- "sqlx-mysql",
- "sqlx-postgres",
- "sqlx-sqlite",
- "syn 2.0.90",
- "tempfile",
- "tokio",
- "url",
-]
-
-[[package]]
-name = "sqlx-mysql"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a"
-dependencies = [
- "atoi",
- "base64",
- "bitflags 2.6.0",
- "byteorder",
- "bytes",
- "crc",
- "digest",
- "dotenvy",
- "either",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-util",
- "generic-array",
- "hex",
- "hkdf",
- "hmac",
- "itoa",
- "log",
- "md-5",
- "memchr",
- "once_cell",
- "percent-encoding",
- "rand",
- "rsa",
- "serde",
- "sha1",
- "sha2",
- "smallvec",
- "sqlx-core",
- "stringprep",
- "thiserror 1.0.69",
- "tracing",
- "whoami",
-]
-
-[[package]]
-name = "sqlx-postgres"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8"
-dependencies = [
- "atoi",
- "base64",
- "bitflags 2.6.0",
- "byteorder",
- "crc",
- "dotenvy",
- "etcetera",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-util",
- "hex",
- "hkdf",
- "hmac",
- "home",
- "itoa",
- "log",
- "md-5",
- "memchr",
- "once_cell",
- "rand",
- "serde",
- "serde_json",
- "sha2",
- "smallvec",
- "sqlx-core",
- "stringprep",
- "thiserror 1.0.69",
- "tracing",
- "whoami",
-]
-
-[[package]]
-name = "sqlx-sqlite"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680"
-dependencies = [
- "atoi",
- "flume",
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-intrusive",
- "futures-util",
- "libsqlite3-sys",
- "log",
- "percent-encoding",
- "serde",
- "serde_urlencoded",
- "sqlx-core",
- "tracing",
- "url",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "stringprep"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
-dependencies = [
- "unicode-bidi",
- "unicode-normalization",
- "unicode-properties",
-]
-
-[[package]]
-name = "strip-ansi-escapes"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa"
-dependencies = [
- "vte",
-]
-
-[[package]]
-name = "strsim"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
-
-[[package]]
-name = "strum"
-version = "0.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
-dependencies = [
- "strum_macros",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "subtle"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-
-[[package]]
-name = "supports-color"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
-dependencies = [
- "is_ci",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.90"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "target-triple"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078"
-
-[[package]]
-name = "tempfile"
-version = "3.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
-dependencies = [
- "cfg-if",
- "fastrand 2.3.0",
- "getrandom",
- "once_cell",
- "rustix 0.38.42",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "termtree"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
-
-[[package]]
-name = "test-log"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f"
-dependencies = [
- "env_logger",
- "test-log-macros",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "test-log-macros"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
-dependencies = [
- "thiserror-impl 1.0.69",
-]
-
-[[package]]
-name = "thiserror"
-version = "2.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47"
-dependencies = [
- "thiserror-impl 2.0.6",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "2.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
-dependencies = [
- "cfg-if",
- "once_cell",
-]
-
-[[package]]
-name = "tikv-jemalloc-sys"
-version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "tikv-jemallocator"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865"
-dependencies = [
- "libc",
- "tikv-jemalloc-sys",
-]
-
-[[package]]
-name = "time"
-version = "0.3.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
-dependencies = [
- "deranged",
- "itoa",
- "libc",
- "num-conv",
- "num_threads",
- "powerfmt",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
-
-[[package]]
-name = "time-macros"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
-dependencies = [
- "num-conv",
- "time-core",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "tinytemplate"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
-[[package]]
-name = "tokio"
-version = "1.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
-dependencies = [
- "backtrace",
- "bytes",
- "libc",
- "mio",
- "parking_lot",
- "pin-project-lite",
- "signal-hook-registry",
- "socket2 0.5.8",
- "tokio-macros",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "tokio-macros"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "tokio-stream"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
-dependencies = [
- "futures-core",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.7.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
-dependencies = [
- "bytes",
- "futures-core",
- "futures-sink",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "toml"
-version = "0.8.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
-dependencies = [
- "serde",
- "serde_spanned",
- "toml_datetime",
- "toml_edit",
-]
-
-[[package]]
-name = "toml_datetime"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml_edit"
-version = "0.22.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
-dependencies = [
- "indexmap 2.7.0",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "winnow",
-]
-
-[[package]]
-name = "tower"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
-dependencies = [
- "futures-core",
- "futures-util",
- "pin-project",
- "pin-project-lite",
- "tokio",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tower-layer"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
-
-[[package]]
-name = "tower-lsp"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508"
-dependencies = [
- "async-trait",
- "auto_impl",
- "bytes",
- "dashmap 5.5.3",
- "futures",
- "httparse",
- "lsp-types",
- "memchr",
- "serde",
- "serde_json",
- "tokio",
- "tokio-util",
- "tower",
- "tower-lsp-macros",
- "tracing",
-]
-
-[[package]]
-name = "tower-lsp-macros"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "tower-service"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
-
-[[package]]
-name = "tracing"
-version = "0.1.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
-dependencies = [
- "log",
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-appender"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
-dependencies = [
- "crossbeam-channel",
- "thiserror 1.0.69",
- "time",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "tracing-bunyan-formatter"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d637245a0d8774bd48df6482e086c59a8b5348a910c3b0579354045a9d82411"
-dependencies = [
- "ahash",
- "gethostname",
- "log",
- "serde",
- "serde_json",
- "time",
- "tracing",
- "tracing-core",
- "tracing-log 0.1.4",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
-dependencies = [
- "once_cell",
- "valuable",
-]
-
-[[package]]
-name = "tracing-log"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2"
-dependencies = [
- "log",
- "once_cell",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-log"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
-dependencies = [
- "log",
- "once_cell",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-serde"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
-dependencies = [
- "serde",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-subscriber"
-version = "0.3.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
-dependencies = [
- "matchers",
- "nu-ansi-term 0.46.0",
- "once_cell",
- "regex",
- "serde",
- "serde_json",
- "sharded-slab",
- "smallvec",
- "thread_local",
- "tracing",
- "tracing-core",
- "tracing-log 0.2.0",
- "tracing-serde",
-]
-
-[[package]]
-name = "tracing-tree"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c"
-dependencies = [
- "nu-ansi-term 0.50.1",
- "time",
- "tracing-core",
- "tracing-log 0.2.0",
- "tracing-subscriber",
-]
-
-[[package]]
-name = "tree-sitter"
-version = "0.20.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e747b1f9b7b931ed39a548c1fae149101497de3c1fc8d9e18c62c1a66c683d3d"
-dependencies = [
- "cc",
- "regex",
-]
-
-[[package]]
-name = "tree_sitter_sql"
-version = "0.0.0"
-dependencies = [
- "cc",
- "tree-sitter",
-]
-
-[[package]]
-name = "trybuild"
-version = "1.0.101"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4"
-dependencies = [
- "glob",
- "serde",
- "serde_derive",
- "serde_json",
- "target-triple",
- "termcolor",
- "toml",
-]
-
-[[package]]
-name = "typenum"
-version = "1.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
-
-[[package]]
-name = "unicase"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
-
-[[package]]
-name = "unicode-bidi"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
-
-[[package]]
-name = "unicode-bom"
-version = "2.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "unicode-properties"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
-
-[[package]]
-name = "unicode_categories"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
-
-[[package]]
-name = "url"
-version = "2.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf16_iter"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "utf8parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
-
-[[package]]
-name = "uuid"
-version = "1.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "valuable"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
-
-[[package]]
-name = "value-bag"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
-
-[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
-name = "version_check"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
-
-[[package]]
-name = "vte"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
-dependencies = [
- "utf8parse",
- "vte_generate_state_changes",
-]
-
-[[package]]
-name = "vte_generate_state_changes"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "wait-timeout"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "waker-fn"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
-
-[[package]]
-name = "walkdir"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
-dependencies = [
- "same-file",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasite"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
-dependencies = [
- "cfg-if",
- "once_cell",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
-dependencies = [
- "bumpalo",
- "log",
- "proc-macro2",
- "quote",
- "syn 2.0.90",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.49"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2"
-dependencies = [
- "cfg-if",
- "js-sys",
- "once_cell",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
-
-[[package]]
-name = "web-sys"
-version = "0.3.76"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "which"
-version = "4.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
-dependencies = [
- "either",
- "home",
- "once_cell",
- "rustix 0.38.42",
-]
-
-[[package]]
-name = "whoami"
-version = "1.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
-dependencies = [
- "redox_syscall",
- "wasite",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "winnow"
-version = "0.6.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "write-json"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118"
-
-[[package]]
-name = "write16"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
-
-[[package]]
-name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
-[[package]]
-name = "xflags"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944"
-dependencies = [
- "xflags-macros",
-]
-
-[[package]]
-name = "xflags-macros"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
-
-[[package]]
-name = "xshell"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d"
-dependencies = [
- "xshell-macros",
-]
-
-[[package]]
-name = "xshell-macros"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547"
-
-[[package]]
-name = "xtask"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "flate2",
- "time",
- "write-json",
- "xflags",
- "xshell",
- "zip",
-]
-
-[[package]]
-name = "xtask_codegen"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "biome_js_factory",
- "biome_js_formatter",
- "biome_js_syntax",
- "biome_rowan",
- "biome_string_case",
- "bpaf",
- "pgt_analyse",
- "pgt_analyser",
- "pgt_workspace",
- "proc-macro2",
- "pulldown-cmark",
- "quote",
- "xtask",
-]
-
-[[package]]
-name = "yoke"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
- "synstructure",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "byteorder",
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
- "synstructure",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
-
-[[package]]
-name = "zerovec"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.90",
-]
-
-[[package]]
-name = "zip"
-version = "0.6.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
-dependencies = [
- "byteorder",
- "crc32fast",
- "crossbeam-utils",
- "flate2",
- "time",
-]
diff --git a/Cargo.toml b/Cargo.toml
deleted file mode 100644
index aaaa9035..00000000
--- a/Cargo.toml
+++ /dev/null
@@ -1,87 +0,0 @@
-[workspace]
-members = ["crates/*", "lib/*", "xtask/codegen", "xtask/rules_check", "docs/codegen"]
-resolver = "2"
-
-[workspace.package]
-authors = ["Supabase Communnity"]
-categories = ["development-tools", "postgres", "supabase"]
-edition = "2024"
-homepage = "https://supabase.com/"
-keywords = ["linter", "typechecker", "postgres", "language-server"]
-license = "MIT"
-repository = "https://github.com/supabase-community/postgres-language-server"
-rust-version = "1.86.0"
-
-[workspace.dependencies]
-# supporting crates unrelated to postgres
-anyhow = "1.0.92"
-biome_deserialize = "0.6.0"
-biome_deserialize_macros = "0.6.0"
-biome_js_factory = "0.5.7"
-biome_js_formatter = "0.5.7"
-biome_js_syntax = "0.5.7"
-biome_rowan = "0.5.7"
-biome_string_case = "0.5.8"
-bpaf = { version = "0.9.15", features = ["derive"] }
-crossbeam = "0.8.4"
-enumflags2 = "0.7.11"
-ignore = "0.4.23"
-indexmap = { version = "2.6.0", features = ["serde"] }
-insta = "1.31.0"
-pg_query = "6.1.0"
-proc-macro2 = "1.0.66"
-quote = "1.0.33"
-rayon = "1.10.0"
-regex = "1.11.1"
-rustc-hash = "2.0.0"
-schemars = { version = "0.8.22", features = ["indexmap2", "smallvec"] }
-serde = "1.0.195"
-serde_json = "1.0.114"
-similar = "2.6.0"
-smallvec = { version = "1.13.2", features = ["union", "const_new", "serde"] }
-strum = { version = "0.27.1", features = ["derive"] }
-# this will use tokio if available, otherwise async-std
-sqlx = { version = "0.8.2", features = ["runtime-tokio", "runtime-async-std", "postgres", "json"] }
-syn = "1.0.109"
-termcolor = "1.4.1"
-test-log = "0.2.17"
-tokio = { version = "1.40.0", features = ["full"] }
-tracing = { version = "0.1.40", default-features = false, features = ["std"] }
-tracing-bunyan-formatter = { version = "0.3.10 " }
-tracing-subscriber = "0.3.18"
-tree-sitter = "0.20.10"
-tree_sitter_sql = { path = "./lib/tree_sitter_sql", version = "0.0.0" }
-unicode-width = "0.1.12"
-
-# postgres specific crates
-pgt_analyse = { path = "./crates/pgt_analyse", version = "0.0.0" }
-pgt_analyser = { path = "./crates/pgt_analyser", version = "0.0.0" }
-pgt_cli = { path = "./crates/pgt_cli", version = "0.0.0" }
-pgt_completions = { path = "./crates/pgt_completions", version = "0.0.0" }
-pgt_configuration = { path = "./crates/pgt_configuration", version = "0.0.0" }
-pgt_console = { path = "./crates/pgt_console", version = "0.0.0" }
-pgt_diagnostics = { path = "./crates/pgt_diagnostics", version = "0.0.0" }
-pgt_diagnostics_categories = { path = "./crates/pgt_diagnostics_categories", version = "0.0.0" }
-pgt_diagnostics_macros = { path = "./crates/pgt_diagnostics_macros", version = "0.0.0" }
-pgt_flags = { path = "./crates/pgt_flags", version = "0.0.0" }
-pgt_fs = { path = "./crates/pgt_fs", version = "0.0.0" }
-pgt_lexer = { path = "./crates/pgt_lexer", version = "0.0.0" }
-pgt_lexer_codegen = { path = "./crates/pgt_lexer_codegen", version = "0.0.0" }
-pgt_lsp = { path = "./crates/pgt_lsp", version = "0.0.0" }
-pgt_markup = { path = "./crates/pgt_markup", version = "0.0.0" }
-pgt_query_ext = { path = "./crates/pgt_query_ext", version = "0.0.0" }
-pgt_query_ext_codegen = { path = "./crates/pgt_query_ext_codegen", version = "0.0.0" }
-pgt_query_proto_parser = { path = "./crates/pgt_query_proto_parser", version = "0.0.0" }
-pgt_schema_cache = { path = "./crates/pgt_schema_cache", version = "0.0.0" }
-pgt_statement_splitter = { path = "./crates/pgt_statement_splitter", version = "0.0.0" }
-pgt_text_edit = { path = "./crates/pgt_text_edit", version = "0.0.0" }
-pgt_text_size = { path = "./crates/pgt_text_size", version = "0.0.0" }
-pgt_treesitter_queries = { path = "./crates/pgt_treesitter_queries", version = "0.0.0" }
-pgt_typecheck = { path = "./crates/pgt_typecheck", version = "0.0.0" }
-pgt_workspace = { path = "./crates/pgt_workspace", version = "0.0.0" }
-
-pgt_test_macros = { path = "./crates/pgt_test_macros" }
-pgt_test_utils = { path = "./crates/pgt_test_utils" }
-
-[profile.dev.package]
-insta.opt-level = 3
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 065fae0f..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Philipp Steinrötter
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
deleted file mode 100644
index 162bb9c0..00000000
--- a/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-# Postgres Language Server
-
-A collection of language tools and a Language Server Protocol (LSP) implementation for Postgres, focusing on developer experience and reliable SQL tooling.
-
-Docs: [pgtools.dev](https://pgtools.dev/)
-
-Install: [instructions](https://pgtools.dev/#installation)
-
-- [CLI releases](https://github.com/supabase-community/postgres-language-server/releases)
-- [VSCode](https://marketplace.visualstudio.com/items?itemName=Supabase.postgrestools)
-- [Neovim](https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#postgres_lsp)
-- [Zed](https://github.com/LoamStudios/zed-postgres-language-server)
-
-## Overview
-LSP Demo | CLI Demo
-:-------------------------:|:-------------------------:
- | 
-
-This project provides a toolchain for Postgres development, built on Postgres' own parser `libpg_query` to ensure 100% syntax compatibility. It is built on a Server-Client architecture with a transport-agnostic design. This means all features can be accessed not only through the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), but also through other interfaces like a CLI, HTTP APIs, or a WebAssembly module. The goal is to make all the great Postgres tooling out there as accessible as possible, and to build anything that is missing ourselves.
-
-The following features are implemented:
-- Autocompletion
-- Syntax Error Highlighting
-- Type-checking (via `EXPLAIN` error insights)
-- Linter, inspired by [Squawk](https://squawkhq.com)
-
-Our current focus is on refining and enhancing these core features while building a robust and easily accessible infrastructure. For future plans and opportunities to contribute, please check out the issues and discussions. Any contributions are welcome!
-
-## Contributors
-
-- [psteinroe](https://github.com/psteinroe)
-- [juleswritescode](https://github.com/juleswritescode)
-
-## Acknowledgements
-
-A big thanks to the following projects, without which this project wouldn't have been possible:
-
-- [libpg_query](https://github.com/pganalyze/libpg_query): For extracting the Postgres' parser
-- [Biome](https://github.com/biomejs/biome): For implementing a toolchain infrastructure we could copy from
-- [Squawk](https://github.com/sbdchd/squawk): For the linter inspiration
diff --git a/biome.jsonc b/biome.jsonc
deleted file mode 100644
index 582bee9b..00000000
--- a/biome.jsonc
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
- "vcs": {
- "enabled": false,
- "clientKind": "git",
- "useIgnoreFile": true
- },
- "files": {
- "ignoreUnknown": false,
- "ignore": [],
- "include": ["/packages/**/*"]
- },
- "formatter": {
- "enabled": true,
- "indentStyle": "tab"
- },
- "organizeImports": {
- "enabled": true
- },
- "linter": {
- "enabled": true,
- "rules": {
- "recommended": true
- }
- },
- "javascript": {
- "formatter": {
- "quoteStyle": "double"
- }
- }
-}
diff --git a/bun.lock b/bun.lock
deleted file mode 100644
index 705686b7..00000000
--- a/bun.lock
+++ /dev/null
@@ -1,166 +0,0 @@
-{
- "lockfileVersion": 1,
- "workspaces": {
- "": {
- "name": "postgres_lsp",
- "devDependencies": {
- "@biomejs/biome": "1.9.4",
- "@types/bun": "latest"
- },
- "peerDependencies": {
- "typescript": "^5"
- }
- },
- "packages/@postgrestools/backend-jsonrpc": {
- "name": "@postgrestools/backend-jsonrpc",
- "optionalDependencies": {
- "@postgrestools/cli-darwin-arm64": "",
- "@postgrestools/cli-darwin-x64": "",
- "@postgrestools/cli-linux-arm64": "",
- "@postgrestools/cli-linux-x64": "",
- "@postgrestools/cli-win32-arm64": "",
- "@postgrestools/cli-win32-x64": ""
- }
- },
- "packages/@postgrestools/postgrestools": {
- "name": "@postgrestools/postgrestools",
- "bin": {
- "postgrestools": "bin/postgrestools"
- },
- "optionalDependencies": {
- "@postgrestools/cli-aarch64-apple-darwin": "",
- "@postgrestools/cli-aarch64-linux-gnu": "",
- "@postgrestools/cli-aarch64-windows-msvc": "",
- "@postgrestools/cli-x86_64-apple-darwin": "",
- "@postgrestools/cli-x86_64-linux-gnu": "",
- "@postgrestools/cli-x86_64-windows-msvc": ""
- }
- }
- },
- "packages": {
- "@biomejs/biome": [
- "@biomejs/biome@1.9.4",
- "",
- {
- "optionalDependencies": {
- "@biomejs/cli-darwin-arm64": "1.9.4",
- "@biomejs/cli-darwin-x64": "1.9.4",
- "@biomejs/cli-linux-arm64": "1.9.4",
- "@biomejs/cli-linux-arm64-musl": "1.9.4",
- "@biomejs/cli-linux-x64": "1.9.4",
- "@biomejs/cli-linux-x64-musl": "1.9.4",
- "@biomejs/cli-win32-arm64": "1.9.4",
- "@biomejs/cli-win32-x64": "1.9.4"
- },
- "bin": { "biome": "bin/biome" }
- },
- "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="
- ],
-
- "@biomejs/cli-darwin-arm64": [
- "@biomejs/cli-darwin-arm64@1.9.4",
- "",
- { "os": "darwin", "cpu": "arm64" },
- "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="
- ],
-
- "@biomejs/cli-darwin-x64": [
- "@biomejs/cli-darwin-x64@1.9.4",
- "",
- { "os": "darwin", "cpu": "x64" },
- "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="
- ],
-
- "@biomejs/cli-linux-arm64": [
- "@biomejs/cli-linux-arm64@1.9.4",
- "",
- { "os": "linux", "cpu": "arm64" },
- "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="
- ],
-
- "@biomejs/cli-linux-arm64-musl": [
- "@biomejs/cli-linux-arm64-musl@1.9.4",
- "",
- { "os": "linux", "cpu": "arm64" },
- "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="
- ],
-
- "@biomejs/cli-linux-x64": [
- "@biomejs/cli-linux-x64@1.9.4",
- "",
- { "os": "linux", "cpu": "x64" },
- "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="
- ],
-
- "@biomejs/cli-linux-x64-musl": [
- "@biomejs/cli-linux-x64-musl@1.9.4",
- "",
- { "os": "linux", "cpu": "x64" },
- "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="
- ],
-
- "@biomejs/cli-win32-arm64": [
- "@biomejs/cli-win32-arm64@1.9.4",
- "",
- { "os": "win32", "cpu": "arm64" },
- "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="
- ],
-
- "@biomejs/cli-win32-x64": [
- "@biomejs/cli-win32-x64@1.9.4",
- "",
- { "os": "win32", "cpu": "x64" },
- "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="
- ],
-
- "@postgrestools/backend-jsonrpc": [
- "@postgrestools/backend-jsonrpc@workspace:packages/@postgrestools/backend-jsonrpc"
- ],
-
- "@postgrestools/postgrestools": [
- "@postgrestools/postgrestools@workspace:packages/@postgrestools/postgrestools"
- ],
-
- "@types/bun": [
- "@types/bun@1.2.5",
- "",
- { "dependencies": { "bun-types": "1.2.5" } },
- "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="
- ],
-
- "@types/node": [
- "@types/node@22.13.10",
- "",
- { "dependencies": { "undici-types": "~6.20.0" } },
- "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="
- ],
-
- "@types/ws": [
- "@types/ws@8.5.14",
- "",
- { "dependencies": { "@types/node": "*" } },
- "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="
- ],
-
- "bun-types": [
- "bun-types@1.2.5",
- "",
- { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } },
- "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="
- ],
-
- "typescript": [
- "typescript@5.8.2",
- "",
- { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } },
- "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="
- ],
-
- "undici-types": [
- "undici-types@6.20.0",
- "",
- {},
- "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
- ]
- }
-}
diff --git a/checking_migrations/index.html b/checking_migrations/index.html
new file mode 100644
index 00000000..61d626e7
--- /dev/null
+++ b/checking_migrations/index.html
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+ Linting Migrations - Postgres Language Server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Postgres Language Server
+
+
+
+
+
+
+
+
Linting Migrations
+
Postgres Language Tools comes with a check
command that can be integrated into your development workflow to catch problematic schema changes and encourage best practices.
+
To run it, simply point at your migrations directory.
+
postgrestools check supabase/migrations
+
+
When you are setting it up in an existing project, you might want to ignore all migrations that are already applied. To do so, add migrationsDir
and after
to your postgrestools.jsonc
file
+
{
+ "migrations": {
+ "migrationsDir": "supabase/migrations",
+ "after": 1740868021
+ }
+}
+
+
Alternatively, pass them directly.
+
postgrestools check supabase/migrations --migrations-dir="supabase/migrations" --after=1740868021
+
+
This will only check migrations after the specified timestamp.
+
For pre-commit hooks and when working locally, use --staged
to only lint files that have been staged. In CI environments, you most likely want to use --changed
to only lint files that have been changed compared to your vcs.default_branch
configuration. If default_branch
is not set in your postgrestools.jsonc
, use --since=REF
to specify the base branch to compare against.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cli_reference/index.html b/cli_reference/index.html
new file mode 100644
index 00000000..eb684311
--- /dev/null
+++ b/cli_reference/index.html
@@ -0,0 +1,376 @@
+
+
+
+
+
+
+
+ CLI - Postgres Language Server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Postgres Language Server
+
+
+
+
+
+
+
+
CLI Reference
+
Command summary
+
+
postgrestools
+
PostgresTools official CLI. Use it to check the health of your project or run it to check single files.
+
Usage : postgrestools
COMMAND ...
+
Available options:
+
+-h
, --help
—
+ Prints help information
+-V
, --version
—
+ Prints version information
+
+
Available commands:
+
+version
—
+ Shows the version information and quit.
+check
—
+ Runs everything to the requested files.
+start
—
+ Starts the daemon server process.
+stop
—
+ Stops the daemon server process.
+init
—
+ Bootstraps a new project. Creates a configuration file with some defaults.
+lsp-proxy
—
+ Acts as a server for the Language Server Protocol over stdin/stdout.
+clean
—
+ Cleans the logs emitted by the daemon.
+
+
postgrestools version
+
Shows the version information and quit.
+
Usage : postgrestools
version
+
Global options applied to all commands
+
+--colors
=<off|force>
—
+ Set the formatting mode for markup: "off" prints everything as plain text, "force" forces the formatting of markup using ANSI even if the console output is determined to be incompatible
+--use-server
—
+ Connect to a running instance of the daemon server.
+--skip-db
—
+ Skip connecting to the database and only run checks that don't require a database connection.
+--verbose
—
+ Print additional diagnostics, and some diagnostics show more information. Also, print out what files were processed and which ones were modified.
+--config-path
=PATH
—
+ Set the file path to the configuration file, or the directory path to find postgrestools.jsonc
. If used, it disables the default configuration file resolution.
+--max-diagnostics
=<none|<NUMBER>>
—
+ Cap the amount of diagnostics displayed. When none
is provided, the limit is lifted.
+ [default: 20]
+--skip-errors
—
+ Skip over files containing syntax errors instead of emitting an error diagnostic.
+--no-errors-on-unmatched
—
+ Silence errors that would be emitted in case no files were processed during the execution of the command.
+--error-on-warnings
—
+ Tell Postgres Tools to exit with an error code if some diagnostics emit warnings.
+--reporter
=<json|json-pretty|github|junit|summary|gitlab>
—
+ Allows to change how diagnostics and summary are reported.
+--log-level
=<none|debug|info|warn|error>
—
+ The level of logging. In order, from the most verbose to the least verbose: debug, info, warn, error.
+
+
The value none
won't show any logging.
+
[default: none]
+
+--log-kind
=<pretty|compact|json>
—
+ How the log should look like.
+ [default: pretty]
+--diagnostic-level
=<info|warn|error>
—
+ The level of diagnostics to show. In order, from the lowest to the most important: info, warn, error. Passing --diagnostic-level=error
will cause Postgres Tools to print only diagnostics that contain only errors.
+ [default: info]
+
+
Available options:
+
+-h
, --help
—
+ Prints help information
+
+
postgrestools check
+
Runs everything to the requested files.
+
Usage : postgrestools
check
[--staged
] [--changed
] [--since
=REF
] [PATH
]...
+
The configuration that is contained inside the configuration file.
+
+--vcs-enabled
=<true|false>
—
+ Whether we should integrate itself with the VCS client
+--vcs-client-kind
=<git>
—
+ The kind of client.
+--vcs-use-ignore-file
=<true|false>
—
+ Whether we should use the VCS ignore file. When [true], we will ignore the files specified in the ignore file.
+--vcs-root
=PATH
—
+ The folder where we should check for VCS files. By default, we will use the same folder where postgrestools.jsonc
was found.
+
+
If we can't find the configuration, it will attempt to use the current working directory. If no current working directory can't be found, we won't use the VCS integration, and a diagnostic will be emitted
+
+--vcs-default-branch
=BRANCH
—
+ The main branch of the project
+--files-max-size
=NUMBER
—
+ The maximum allowed size for source code files in bytes. Files above this limit will be ignored for performance reasons. Defaults to 1 MiB
+--migrations-dir
=ARG
—
+ The directory where the migration files are stored
+--after
=ARG
—
+ Ignore any migrations before this timestamp
+--host
=ARG
—
+ The host of the database.
+--port
=ARG
—
+ The port of the database.
+--username
=ARG
—
+ The username to connect to the database.
+--password
=ARG
—
+ The password to connect to the database.
+--database
=ARG
—
+ The name of the database.
+--conn_timeout_secs
=ARG
—
+ The connection timeout in seconds.
+ [default: Some(10)]
+
+
Global options applied to all commands
+
+--colors
=<off|force>
—
+ Set the formatting mode for markup: "off" prints everything as plain text, "force" forces the formatting of markup using ANSI even if the console output is determined to be incompatible
+--use-server
—
+ Connect to a running instance of the daemon server.
+--skip-db
—
+ Skip connecting to the database and only run checks that don't require a database connection.
+--verbose
—
+ Print additional diagnostics, and some diagnostics show more information. Also, print out what files were processed and which ones were modified.
+--config-path
=PATH
—
+ Set the file path to the configuration file, or the directory path to find postgrestools.jsonc
. If used, it disables the default configuration file resolution.
+--max-diagnostics
=<none|<NUMBER>>
—
+ Cap the amount of diagnostics displayed. When none
is provided, the limit is lifted.
+ [default: 20]
+--skip-errors
—
+ Skip over files containing syntax errors instead of emitting an error diagnostic.
+--no-errors-on-unmatched
—
+ Silence errors that would be emitted in case no files were processed during the execution of the command.
+--error-on-warnings
—
+ Tell Postgres Tools to exit with an error code if some diagnostics emit warnings.
+--reporter
=<json|json-pretty|github|junit|summary|gitlab>
—
+ Allows to change how diagnostics and summary are reported.
+--log-level
=<none|debug|info|warn|error>
—
+ The level of logging. In order, from the most verbose to the least verbose: debug, info, warn, error.
+
+
The value none
won't show any logging.
+
[default: none]
+
+--log-kind
=<pretty|compact|json>
—
+ How the log should look like.
+ [default: pretty]
+--diagnostic-level
=<info|warn|error>
—
+ The level of diagnostics to show. In order, from the lowest to the most important: info, warn, error. Passing --diagnostic-level=error
will cause Postgres Tools to print only diagnostics that contain only errors.
+ [default: info]
+
+
Available positional items:
+
+PATH
—
+ Single file, single path or list of paths
+
+
Available options:
+
+--stdin-file-path
=PATH
—
+ Use this option when you want to format code piped from stdin
, and print the output to stdout
.
+
+
The file doesn't need to exist on disk, what matters is the extension of the file. Based on the extension, we know how to check the code.
+
Example: echo 'let a;' | pgt_cli check --stdin-file-path=test.sql
+
+--staged
—
+ When set to true, only the files that have been staged (the ones prepared to be committed) will be linted. This option should be used when working locally.
+--changed
—
+ When set to true, only the files that have been changed compared to your defaultBranch
configuration will be linted. This option should be used in CI environments.
+--since
=REF
—
+ Use this to specify the base branch to compare against when you're using the --changed flag and the defaultBranch
is not set in your postgrestools.jsonc
+-h
, --help
—
+ Prints help information
+
+
postgrestools start
+
Starts the daemon server process.
+
Usage : postgrestools
start
[--config-path
=PATH
]
+
Available options:
+
+--log-prefix-name
=STRING
—
+ Allows to change the prefix applied to the file name of the logs.
+ Uses environment variable PGT_LOG_PREFIX_NAME
+ [default: server.log]
+--log-path
=PATH
—
+ Allows to change the folder where logs are stored.
+ Uses environment variable PGT_LOG_PATH
+--config-path
=PATH
—
+ Allows to set a custom file path to the configuration file, or a custom directory path to find postgrestools.jsonc
+ Uses environment variable PGT_LOG_PREFIX_NAME
+-h
, --help
—
+ Prints help information
+
+
postgrestools stop
+
Stops the daemon server process.
+
Usage : postgrestools
stop
+
Available options:
+
+-h
, --help
—
+ Prints help information
+
+
postgrestools init
+
Bootstraps a new project. Creates a configuration file with some defaults.
+
Usage : postgrestools
init
+
Available options:
+
+-h
, --help
—
+ Prints help information
+
+
postgrestools lsp-proxy
+
Acts as a server for the Language Server Protocol over stdin/stdout.
+
Usage : postgrestools
lsp-proxy
[--config-path
=PATH
]
+
Available options:
+
+--log-prefix-name
=STRING
—
+ Allows to change the prefix applied to the file name of the logs.
+ Uses environment variable PGT_LOG_PREFIX_NAME
+ [default: server.log]
+--log-path
=PATH
—
+ Allows to change the folder where logs are stored.
+ Uses environment variable PGT_LOG_PATH
+--config-path
=PATH
—
+ Allows to set a custom file path to the configuration file, or a custom directory path to find postgrestools.jsonc
+ Uses environment variable PGT_CONFIG_PATH
+-h
, --help
—
+ Prints help information
+
+
postgrestools clean
+
Cleans the logs emitted by the daemon.
+
Usage : postgrestools
clean
+
Available options:
+
+-h
, --help
—
+ Prints help information
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cliff.toml b/cliff.toml
deleted file mode 100644
index 3406b80c..00000000
--- a/cliff.toml
+++ /dev/null
@@ -1,91 +0,0 @@
-# git-cliff ~ default configuration file
-# https://git-cliff.org/docs/configuration
-#
-# Lines starting with "#" are comments.
-# Configuration options are organized into tables and keys.
-# See documentation for more information on available options.
-
-[changelog]
-# template for the changelog header
-header = """
-# Postgres Language Server\n
-A collection of language tools and a Language Server Protocol (LSP) implementation for Postgres, focusing on developer experience and reliable SQL tooling.\n
-"""
-# template for the changelog body
-# https://keats.github.io/tera/docs/#introduction
-body = """
-{% if version %}\
- ## {{ version | trim_start_matches(pat="v") }}
-{% else %}\
- ## [unreleased]
-{% endif %}\
-{% for group, commits in commits | group_by(attribute="group") %}
- ### {{ group | striptags | trim | upper_first }}
- {% for commit in commits %}
- - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
- {% if commit.breaking %}[**breaking**] {% endif %}\
- {{ commit.message | upper_first }}\
- {% endfor %}
-{% endfor %}\n
-
-## Contributors
-{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
- * @{{ contributor.username }} made their first contribution in #{{ contributor.pr_number }} 🎉
-{%- endfor -%}
-{% for contributor in github.contributors | filter(attribute="is_first_time", value=false) %}
- * @{{ contributor.username }}
-{%- endfor -%}\n
-"""
-# template for the changelog footer
-footer = """
-"""
-# remove the leading and trailing s
-trim = true
-# postprocessors
-postprocessors = [
- # { pattern = '', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
-]
-# render body even when there are no releases to process
-# render_always = true
-# output file path
-# output = "test.md"
-
-[git]
-# parse the commits based on https://www.conventionalcommits.org
-conventional_commits = true
-# filter out the commits that are not conventional
-filter_unconventional = true
-# process each line of a commit as an individual commit
-split_commits = false
-# regex for preprocessing the commit messages
-commit_preprocessors = [
- # Replace issue numbers
- #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"},
- # Check spelling of the commit with https://github.com/crate-ci/typos
- # If the spelling is incorrect, it will be automatically fixed.
- #{ pattern = '.*', replace_command = 'typos --write-changes -' },
-]
-# regex for parsing and grouping commits
-commit_parsers = [
- { message = "^feat", group = "🚀 Features" },
- { message = "^fix", group = "🐛 Bug Fixes" },
- { message = "^doc", group = "📚 Documentation" },
- { message = "^perf", group = "⚡ Performance" },
- { message = "^refactor", group = "🚜 Refactor" },
- { message = "^style", group = "🎨 Styling" },
- { message = "^test", group = "🧪 Testing" },
- { message = "^chore\\(release\\): prepare for", skip = true },
- { message = "^chore\\(deps.*\\)", skip = true },
- { message = "^chore\\(pr\\)", skip = true },
- { message = "^chore\\(pull\\)", skip = true },
- { message = "^chore|^ci", group = "⚙️ Miscellaneous Tasks" },
- { body = ".*security", group = "🛡️ Security" },
- { message = "^revert", group = "◀️ Revert" },
- { message = ".*", group = "💼 Other" },
-]
-# filter out the commits that are not matched by commit parsers
-filter_commits = false
-# sort the tags topologically
-topo_order = false
-# sort the commits inside sections by oldest/newest order
-sort_commits = "oldest"
diff --git a/clippy.toml b/clippy.toml
deleted file mode 100644
index 4296655a..00000000
--- a/clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-allow-dbg-in-tests = true
diff --git a/docs/codegen/Cargo.toml b/codegen/Cargo.toml
similarity index 100%
rename from docs/codegen/Cargo.toml
rename to codegen/Cargo.toml
diff --git a/docs/codegen/src/cli_doc.rs b/codegen/src/cli_doc.rs
similarity index 100%
rename from docs/codegen/src/cli_doc.rs
rename to codegen/src/cli_doc.rs
diff --git a/docs/codegen/src/default_configuration.rs b/codegen/src/default_configuration.rs
similarity index 100%
rename from docs/codegen/src/default_configuration.rs
rename to codegen/src/default_configuration.rs
diff --git a/docs/codegen/src/env_variables.rs b/codegen/src/env_variables.rs
similarity index 100%
rename from docs/codegen/src/env_variables.rs
rename to codegen/src/env_variables.rs
diff --git a/docs/codegen/src/lib.rs b/codegen/src/lib.rs
similarity index 100%
rename from docs/codegen/src/lib.rs
rename to codegen/src/lib.rs
diff --git a/docs/codegen/src/main.rs b/codegen/src/main.rs
similarity index 100%
rename from docs/codegen/src/main.rs
rename to codegen/src/main.rs
diff --git a/docs/codegen/src/rules_docs.rs b/codegen/src/rules_docs.rs
similarity index 100%
rename from docs/codegen/src/rules_docs.rs
rename to codegen/src/rules_docs.rs
diff --git a/docs/codegen/src/rules_index.rs b/codegen/src/rules_index.rs
similarity index 100%
rename from docs/codegen/src/rules_index.rs
rename to codegen/src/rules_index.rs
diff --git a/docs/codegen/src/rules_sources.rs b/codegen/src/rules_sources.rs
similarity index 100%
rename from docs/codegen/src/rules_sources.rs
rename to codegen/src/rules_sources.rs
diff --git a/docs/codegen/src/schema.rs b/codegen/src/schema.rs
similarity index 100%
rename from docs/codegen/src/schema.rs
rename to codegen/src/schema.rs
diff --git a/docs/codegen/src/utils.rs b/codegen/src/utils.rs
similarity index 100%
rename from docs/codegen/src/utils.rs
rename to codegen/src/utils.rs
diff --git a/crates/pgt_analyse/Cargo.toml b/crates/pgt_analyse/Cargo.toml
deleted file mode 100644
index 75eb0211..00000000
--- a/crates/pgt_analyse/Cargo.toml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-[package]
-authors.workspace = true
-categories.workspace = true
-description = ""
-edition.workspace = true
-homepage.workspace = true
-keywords.workspace = true
-license.workspace = true
-name = "pgt_analyse"
-repository.workspace = true
-version = "0.0.0"
-
-
-[dependencies]
-pgt_console.workspace = true
-pgt_diagnostics.workspace = true
-pgt_query_ext.workspace = true
-rustc-hash = { workspace = true }
-
-biome_deserialize = { workspace = true, optional = true }
-biome_deserialize_macros = { workspace = true, optional = true }
-enumflags2.workspace = true
-pgt_text_size.workspace = true
-schemars = { workspace = true, optional = true }
-serde = { workspace = true, features = ["derive"], optional = true }
-
-[features]
-schema = ["dep:schemars"]
-serde = ["dep:serde", "dep:biome_deserialize", "dep:biome_deserialize_macros"]
diff --git a/crates/pgt_analyse/src/categories.rs b/crates/pgt_analyse/src/categories.rs
deleted file mode 100644
index e5dd51c2..00000000
--- a/crates/pgt_analyse/src/categories.rs
+++ /dev/null
@@ -1,327 +0,0 @@
-use enumflags2::{BitFlags, bitflags};
-use std::borrow::Cow;
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
-pub enum RuleCategory {
- /// This rule performs static analysis of the source code to detect
- /// invalid or error-prone patterns, and emits diagnostics along with
- /// proposed fixes
- Lint,
- /// This rule detects refactoring opportunities and emits code action
- /// signals
- Action,
- /// This rule detects transformations that should be applied to the code
- Transformation,
-}
-
-/// Actions that suppress rules should start with this string
-pub const SUPPRESSION_ACTION_CATEGORY: &str = "quickfix.suppressRule";
-
-/// The category of a code action, this type maps directly to the
-/// [CodeActionKind] type in the Language Server Protocol specification
-///
-/// [CodeActionKind]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeActionKind
-#[derive(Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
-pub enum ActionCategory {
- /// Base kind for quickfix actions: 'quickfix'.
- ///
- /// This action provides a fix to the diagnostic emitted by the same signal
- QuickFix(Cow<'static, str>),
- /// Base kind for refactoring actions: 'refactor'.
- ///
- /// This action provides an optional refactor opportunity
- Refactor(RefactorKind),
- /// Base kind for source actions: `source`.
- ///
- /// Source code actions apply to the entire file.
- Source(SourceActionKind),
- /// This action is using a base kind not covered by any of the previous
- /// variants
- Other(Cow<'static, str>),
-}
-
-impl ActionCategory {
- /// Returns true if this category matches the provided filter
- ///
- /// ## Examples
- ///
- /// ```
- /// use std::borrow::Cow;
- /// use pgt_analyse::{ActionCategory, RefactorKind};
- ///
- /// assert!(ActionCategory::QuickFix(Cow::from("quickfix")).matches("quickfix"));
- ///
- /// assert!(ActionCategory::Refactor(RefactorKind::None).matches("refactor"));
- /// assert!(!ActionCategory::Refactor(RefactorKind::None).matches("refactor.extract"));
- ///
- /// assert!(ActionCategory::Refactor(RefactorKind::Extract).matches("refactor"));
- /// assert!(ActionCategory::Refactor(RefactorKind::Extract).matches("refactor.extract"));
- /// ```
- pub fn matches(&self, filter: &str) -> bool {
- self.to_str().starts_with(filter)
- }
-
- /// Returns the representation of this [ActionCategory] as a `CodeActionKind` string
- pub fn to_str(&self) -> Cow<'static, str> {
- match self {
- ActionCategory::QuickFix(tag) => {
- if tag.is_empty() {
- Cow::Borrowed("quickfix.pgt")
- } else {
- Cow::Owned(format!("quickfix.pgt.{tag}"))
- }
- }
-
- ActionCategory::Refactor(RefactorKind::None) => Cow::Borrowed("refactor.pgt"),
- ActionCategory::Refactor(RefactorKind::Extract) => {
- Cow::Borrowed("refactor.extract.pgt")
- }
- ActionCategory::Refactor(RefactorKind::Inline) => Cow::Borrowed("refactor.inline.pgt"),
- ActionCategory::Refactor(RefactorKind::Rewrite) => {
- Cow::Borrowed("refactor.rewrite.pgt")
- }
- ActionCategory::Refactor(RefactorKind::Other(tag)) => {
- Cow::Owned(format!("refactor.{tag}.pgt"))
- }
-
- ActionCategory::Source(SourceActionKind::None) => Cow::Borrowed("source.pgt"),
- ActionCategory::Source(SourceActionKind::FixAll) => Cow::Borrowed("source.fixAll.pgt"),
- ActionCategory::Source(SourceActionKind::OrganizeImports) => {
- Cow::Borrowed("source.organizeImports.pgt")
- }
- ActionCategory::Source(SourceActionKind::Other(tag)) => {
- Cow::Owned(format!("source.{tag}.pgt"))
- }
-
- ActionCategory::Other(tag) => Cow::Owned(format!("{tag}.pgt")),
- }
- }
-}
-
-/// The sub-category of a refactor code action.
-///
-/// [Check the LSP spec](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeActionKind) for more information:
-#[derive(Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
-pub enum RefactorKind {
- /// This action describes a refactor with no particular sub-category
- None,
- /// Base kind for refactoring extraction actions: 'refactor.extract'.
- ///
- /// Example extract actions:
- /// - Extract method
- /// - Extract function
- /// - Extract variable
- /// - Extract interface from class
- Extract,
- /// Base kind for refactoring inline actions: 'refactor.inline'.
- ///
- /// Example inline actions:
- /// - Inline function
- /// - Inline variable
- /// - Inline constant
- /// - ...
- Inline,
- /// Base kind for refactoring rewrite actions: 'refactor.rewrite'.
- ///
- /// Example rewrite actions:
- /// - Convert JavaScript function to class
- /// - Add or remove parameter
- /// - Encapsulate field
- /// - Make method static
- /// - Move method to base class
- /// - ...
- Rewrite,
- /// This action is using a refactor kind not covered by any of the previous
- /// variants
- Other(Cow<'static, str>),
-}
-
-/// The sub-category of a source code action
-#[derive(Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
-pub enum SourceActionKind {
- /// This action describes a source action with no particular sub-category
- None,
- // Base kind for a 'fix all' source action: `source.fixAll`.
- //
- // 'Fix all' actions automatically fix errors that have a clear fix that
- // do not require user input. They should not suppress errors or perform
- // unsafe fixes such as generating new types or classes.
- FixAll,
- /// Base kind for an organize imports source action: `source.organizeImports`.
- OrganizeImports,
- /// This action is using a source action kind not covered by any of the
- /// previous variants
- Other(Cow<'static, str>),
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-#[bitflags]
-#[repr(u8)]
-pub(crate) enum Categories {
- Lint = 1 << RuleCategory::Lint as u8,
- Action = 1 << RuleCategory::Action as u8,
- Transformation = 1 << RuleCategory::Transformation as u8,
-}
-
-#[derive(Debug, Copy, Clone)]
-/// The categories supported by the analyser.
-///
-/// The default implementation of this type returns an instance with all the categories.
-///
-/// Use [RuleCategoriesBuilder] to generate the categories you want to query.
-pub struct RuleCategories(BitFlags);
-
-impl RuleCategories {
- pub fn empty() -> Self {
- let empty: BitFlags = BitFlags::empty();
- Self(empty)
- }
-
- pub fn all() -> Self {
- let empty: BitFlags = BitFlags::all();
- Self(empty)
- }
-
- /// Checks whether the current categories contain a specific [RuleCategories]
- pub fn contains(&self, other: impl Into) -> bool {
- self.0.contains(other.into().0)
- }
-}
-
-impl Default for RuleCategories {
- fn default() -> Self {
- Self::all()
- }
-}
-
-impl From for RuleCategories {
- fn from(input: RuleCategory) -> Self {
- match input {
- RuleCategory::Lint => RuleCategories(BitFlags::from_flag(Categories::Lint)),
- RuleCategory::Action => RuleCategories(BitFlags::from_flag(Categories::Action)),
- RuleCategory::Transformation => {
- RuleCategories(BitFlags::from_flag(Categories::Transformation))
- }
- }
- }
-}
-
-#[cfg(feature = "serde")]
-impl serde::Serialize for RuleCategories {
- fn serialize(&self, serializer: S) -> Result
- where
- S: serde::Serializer,
- {
- let mut flags = Vec::new();
-
- if self.0.contains(Categories::Lint) {
- flags.push(RuleCategory::Lint);
- }
-
- if self.0.contains(Categories::Action) {
- flags.push(RuleCategory::Action);
- }
-
- if self.0.contains(Categories::Transformation) {
- flags.push(RuleCategory::Transformation);
- }
-
- serializer.collect_seq(flags)
- }
-}
-
-#[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for RuleCategories {
- fn deserialize(deserializer: D) -> Result
- where
- D: serde::Deserializer<'de>,
- {
- use serde::de::{self, SeqAccess};
- use std::fmt::{self, Formatter};
-
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = RuleCategories;
-
- fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
- write!(formatter, "RuleCategories")
- }
-
- fn visit_seq(self, mut seq: A) -> Result
- where
- A: SeqAccess<'de>,
- {
- let mut result = RuleCategories::empty();
-
- while let Some(item) = seq.next_element::()? {
- result.0 |= RuleCategories::from(item).0;
- }
-
- Ok(result)
- }
- }
-
- deserializer.deserialize_seq(Visitor)
- }
-}
-
-#[cfg(feature = "schema")]
-impl schemars::JsonSchema for RuleCategories {
- fn schema_name() -> String {
- String::from("RuleCategories")
- }
-
- fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
- >::json_schema(r#gen)
- }
-}
-
-#[derive(Debug, Default)]
-/// A convenient type create a [RuleCategories] type
-///
-/// ```
-/// use pgt_analyse::{RuleCategoriesBuilder, RuleCategory};
-/// let mut categories = RuleCategoriesBuilder::default().with_lint().build();
-///
-/// assert!(categories.contains(RuleCategory::Lint));
-/// assert!(!categories.contains(RuleCategory::Action));
-/// assert!(!categories.contains(RuleCategory::Transformation));
-/// ```
-pub struct RuleCategoriesBuilder {
- flags: BitFlags,
-}
-
-impl RuleCategoriesBuilder {
- pub fn with_lint(mut self) -> Self {
- self.flags.insert(Categories::Lint);
- self
- }
-
- pub fn with_action(mut self) -> Self {
- self.flags.insert(Categories::Action);
- self
- }
-
- pub fn with_transformation(mut self) -> Self {
- self.flags.insert(Categories::Transformation);
- self
- }
-
- pub fn all(mut self) -> Self {
- self.flags = BitFlags::all();
- self
- }
-
- pub fn build(self) -> RuleCategories {
- RuleCategories(self.flags)
- }
-}
diff --git a/crates/pgt_analyse/src/context.rs b/crates/pgt_analyse/src/context.rs
deleted file mode 100644
index cd069657..00000000
--- a/crates/pgt_analyse/src/context.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use crate::{
- categories::RuleCategory,
- rule::{GroupCategory, Rule, RuleGroup, RuleMetadata},
-};
-
-pub struct RuleContext<'a, R: Rule> {
- stmt: &'a pgt_query_ext::NodeEnum,
- options: &'a R::Options,
-}
-
-impl<'a, R> RuleContext<'a, R>
-where
- R: Rule + Sized + 'static,
-{
- #[allow(clippy::too_many_arguments)]
- pub fn new(stmt: &'a pgt_query_ext::NodeEnum, options: &'a R::Options) -> Self {
- Self { stmt, options }
- }
-
- /// Returns the group that belongs to the current rule
- pub fn group(&self) -> &'static str {
- ::NAME
- }
-
- /// Returns the category that belongs to the current rule
- pub fn category(&self) -> RuleCategory {
- <::Category as GroupCategory>::CATEGORY
- }
-
- /// Returns the AST root
- pub fn stmt(&self) -> &pgt_query_ext::NodeEnum {
- self.stmt
- }
-
- /// Returns the metadata of the rule
- ///
- /// The metadata contains information about the rule, such as the name, version, language, and whether it is recommended.
- ///
- /// ## Examples
- /// ```rust,ignore
- /// declare_lint_rule! {
- /// /// Some doc
- /// pub(crate) Foo {
- /// version: "0.0.0",
- /// name: "foo",
- /// recommended: true,
- /// }
- /// }
- ///
- /// impl Rule for Foo {
- /// const CATEGORY: RuleCategory = RuleCategory::Lint;
- /// type State = ();
- /// type Signals = ();
- /// type Options = ();
- ///
- /// fn run(ctx: &RuleContext) -> Self::Signals {
- /// assert_eq!(ctx.metadata().name, "foo");
- /// }
- /// }
- /// ```
- pub fn metadata(&self) -> &RuleMetadata {
- &R::METADATA
- }
-
- /// It retrieves the options that belong to a rule, if they exist.
- ///
- /// In order to retrieve a typed data structure, you have to create a deserializable
- /// data structure and define it inside the generic type `type Options` of the [Rule]
- ///
- pub fn options(&self) -> &R::Options {
- self.options
- }
-}
diff --git a/crates/pgt_analyse/src/filter.rs b/crates/pgt_analyse/src/filter.rs
deleted file mode 100644
index 02844d3e..00000000
--- a/crates/pgt_analyse/src/filter.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-use std::fmt::{Debug, Display, Formatter};
-
-use crate::{
- categories::RuleCategories,
- rule::{GroupCategory, Rule, RuleGroup},
-};
-
-/// Allow filtering a single rule or group of rules by their names
-#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub enum RuleFilter<'a> {
- Group(&'a str),
- Rule(&'a str, &'a str),
-}
-
-/// Allows filtering the list of rules that will be executed in a run of the analyser,
-/// and at what source code range signals (diagnostics or actions) may be raised
-#[derive(Debug, Default, Clone, Copy)]
-pub struct AnalysisFilter<'a> {
- /// Only allow rules with these categories to emit signals
- pub categories: RuleCategories,
- /// Only allow rules matching these names to emit signals
- /// If `enabled_rules` is set to `None`, then all rules are enabled.
- pub enabled_rules: Option<&'a [RuleFilter<'a>]>,
- /// Do not allow rules matching these names to emit signals
- pub disabled_rules: &'a [RuleFilter<'a>],
-}
-
-impl<'analysis> AnalysisFilter<'analysis> {
- /// It creates a new filter with the set of [enabled rules](RuleFilter) passed as argument
- pub fn from_enabled_rules(enabled_rules: &'analysis [RuleFilter<'analysis>]) -> Self {
- Self {
- enabled_rules: Some(enabled_rules),
- ..AnalysisFilter::default()
- }
- }
-
- /// Return `true` if the category `C` matches this filter
- pub fn match_category(&self) -> bool {
- self.categories.contains(C::CATEGORY)
- }
-
- /// Return `true` if the group `G` matches this filter
- pub fn match_group(&self) -> bool {
- self.match_category::()
- && self.enabled_rules.is_none_or(|enabled_rules| {
- enabled_rules.iter().any(|filter| filter.match_group::())
- })
- && !self
- .disabled_rules
- .iter()
- .any(|filter| matches!(filter, RuleFilter::Group(_)) && filter.match_group::())
- }
-
- /// Return `true` if the rule `R` matches this filter
- pub fn match_rule(&self) -> bool {
- self.match_category::<::Category>()
- && self.enabled_rules.is_none_or(|enabled_rules| {
- enabled_rules.iter().any(|filter| filter.match_rule::())
- })
- && !self
- .disabled_rules
- .iter()
- .any(|filter| filter.match_rule::())
- }
-}
-
-impl<'a> RuleFilter<'a> {
- // Returns the group name of this filter.
- pub fn group(self) -> &'a str {
- match self {
- RuleFilter::Group(group) => group,
- RuleFilter::Rule(group, _) => group,
- }
- }
- /// Return `true` if the group `G` matches this filter
- pub fn match_group(self) -> bool {
- match self {
- RuleFilter::Group(group) => group == G::NAME,
- RuleFilter::Rule(group, _) => group == G::NAME,
- }
- }
-
- /// Return `true` if the rule `R` matches this filter
- pub fn match_rule(self) -> bool
- where
- R: Rule,
- {
- match self {
- RuleFilter::Group(group) => group == ::NAME,
- RuleFilter::Rule(group, rule) => {
- group == ::NAME && rule == R::METADATA.name
- }
- }
- }
-}
-
-impl Debug for RuleFilter<'_> {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- Display::fmt(self, f)
- }
-}
-
-impl Display for RuleFilter<'_> {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- RuleFilter::Group(group) => {
- write!(f, "{group}")
- }
- RuleFilter::Rule(group, rule) => {
- write!(f, "{group}/{rule}")
- }
- }
- }
-}
-
-impl pgt_console::fmt::Display for RuleFilter<'_> {
- fn fmt(&self, fmt: &mut pgt_console::fmt::Formatter) -> std::io::Result<()> {
- match self {
- RuleFilter::Group(group) => {
- write!(fmt, "{group}")
- }
- RuleFilter::Rule(group, rule) => {
- write!(fmt, "{group}/{rule}")
- }
- }
- }
-}
-
-/// Opaque identifier for a group of rule
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct GroupKey {
- group: &'static str,
-}
-
-impl GroupKey {
- pub(crate) fn new(group: &'static str) -> Self {
- Self { group }
- }
-
- pub fn group() -> Self {
- Self::new(G::NAME)
- }
-}
-
-impl From for RuleFilter<'static> {
- fn from(key: GroupKey) -> Self {
- RuleFilter::Group(key.group)
- }
-}
-
-/// Opaque identifier for a single rule
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct RuleKey {
- group: &'static str,
- rule: &'static str,
-}
-
-impl RuleKey {
- pub fn new(group: &'static str, rule: &'static str) -> Self {
- Self { group, rule }
- }
-
- pub fn rule() -> Self {
- Self::new(::NAME, R::METADATA.name)
- }
-
- pub fn group(&self) -> &'static str {
- self.group
- }
-
- pub fn rule_name(&self) -> &'static str {
- self.rule
- }
-}
-
-impl From for RuleFilter<'static> {
- fn from(key: RuleKey) -> Self {
- RuleFilter::Rule(key.group, key.rule)
- }
-}
-
-impl PartialEq for RuleFilter<'static> {
- fn eq(&self, other: &RuleKey) -> bool {
- match *self {
- RuleFilter::Group(group) => group == other.group,
- RuleFilter::Rule(group, rule) => group == other.group && rule == other.rule,
- }
- }
-}
diff --git a/crates/pgt_analyse/src/lib.rs b/crates/pgt_analyse/src/lib.rs
deleted file mode 100644
index f312de45..00000000
--- a/crates/pgt_analyse/src/lib.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-mod categories;
-pub mod context;
-mod filter;
-pub mod macros;
-pub mod options;
-mod registry;
-mod rule;
-
-// Re-exported for use in the `declare_group` macro
-pub use pgt_diagnostics::category_concat;
-
-pub use crate::categories::{
- ActionCategory, RefactorKind, RuleCategories, RuleCategoriesBuilder, RuleCategory,
- SUPPRESSION_ACTION_CATEGORY, SourceActionKind,
-};
-pub use crate::filter::{AnalysisFilter, GroupKey, RuleFilter, RuleKey};
-pub use crate::options::{AnalyserOptions, AnalyserRules};
-pub use crate::registry::{
- MetadataRegistry, RegistryRuleParams, RegistryVisitor, RuleRegistry, RuleRegistryBuilder,
-};
-pub use crate::rule::{
- GroupCategory, Rule, RuleDiagnostic, RuleGroup, RuleMeta, RuleMetadata, RuleSource,
-};
diff --git a/crates/pgt_analyse/src/macros.rs b/crates/pgt_analyse/src/macros.rs
deleted file mode 100644
index d9f70ed3..00000000
--- a/crates/pgt_analyse/src/macros.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-/// This macro is used to declare an analyser rule type, and implement the
-// [RuleMeta] trait for it
-/// # Example
-///
-/// The macro itself expect the following syntax:
-///
-/// ```rust,ignore
-///use pgt_analyse::declare_rule;
-///
-/// declare_lint_rule! {
-/// /// Documentation
-/// pub(crate) ExampleRule {
-/// version: "1.0.0",
-/// name: "rule-name",
-/// recommended: false,
-/// }
-/// }
-/// ```
-///
-/// Check [crate](module documentation) for a better
-/// understanding of how the macro works
-#[macro_export]
-macro_rules! declare_lint_rule {
- ( $( #[doc = $doc:literal] )+ $vis:vis $id:ident {
- version: $version:literal,
- name: $name:tt,
- $( $key:ident: $value:expr_2021, )*
- } ) => {
-
- pgt_analyse::declare_rule!(
- $( #[doc = $doc] )*
- $vis $id {
- version: $version,
- name: $name,
- $( $key: $value, )*
- }
- );
-
- // Declare a new `rule_category!` macro in the module context that
- // expands to the category of this rule
- // This is implemented by calling the `group_category!` macro from the
- // parent module (that should be declared by a call to `declare_group!`)
- // and providing it with the name of this rule as a string literal token
- #[allow(unused_macros)]
- macro_rules! rule_category {
- () => { super::group_category!( $name ) };
- }
- };
-}
-
-#[macro_export]
-macro_rules! declare_rule {
- ( $( #[doc = $doc:literal] )+ $vis:vis $id:ident {
- version: $version:literal,
- name: $name:tt,
- $( $key:ident: $value:expr_2021, )*
- } ) => {
- $( #[doc = $doc] )*
- $vis enum $id {}
-
- impl $crate::RuleMeta for $id {
- type Group = super::Group;
- const METADATA: $crate::RuleMetadata =
- $crate::RuleMetadata::new($version, $name, concat!( $( $doc, "\n", )* )) $( .$key($value) )*;
- }
- }
-}
-
-/// This macro is used by the codegen script to declare an analyser rule group,
-/// and implement the [RuleGroup] trait for it
-#[macro_export]
-macro_rules! declare_lint_group {
- ( $vis:vis $id:ident { name: $name:tt, rules: [ $( $( $rule:ident )::* , )* ] } ) => {
- $vis enum $id {}
-
- impl $crate::RuleGroup for $id {
- type Category = super::Category;
-
- const NAME: &'static str = $name;
-
- fn record_rules(registry: &mut V) {
- $( registry.record_rule::<$( $rule )::*>(); )*
- }
- }
-
- pub(self) use $id as Group;
-
- // Declare a `group_category!` macro in the context of this module (and
- // all its children). This macro takes the name of a rule as a string
- // literal token and expands to the category of the lint rule with this
- // name within this group.
- // This is implemented by calling the `category_concat!` macro with the
- // "lint" prefix, the name of this group, and the rule name argument
- #[allow(unused_macros)]
- macro_rules! group_category {
- ( $rule_name:tt ) => { $crate::category_concat!( "lint", $name, $rule_name ) };
- }
-
- // Re-export the macro for child modules, so `declare_rule!` can access
- // the category of its parent group by using the `super` module
- pub(self) use group_category;
- };
-}
-
-#[macro_export]
-macro_rules! declare_category {
- ( $vis:vis $id:ident { kind: $kind:ident, groups: [ $( $( $group:ident )::* , )* ] } ) => {
- $vis enum $id {}
-
- impl $crate::GroupCategory for $id {
- const CATEGORY: $crate::RuleCategory = $crate::RuleCategory::$kind;
-
- fn record_groups(registry: &mut V) {
- $( registry.record_group::<$( $group )::*>(); )*
- }
- }
-
- pub(self) use $id as Category;
- };
-}
diff --git a/crates/pgt_analyse/src/options.rs b/crates/pgt_analyse/src/options.rs
deleted file mode 100644
index 211cb1dc..00000000
--- a/crates/pgt_analyse/src/options.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use rustc_hash::FxHashMap;
-
-use crate::{Rule, RuleKey};
-use std::any::{Any, TypeId};
-use std::fmt::Debug;
-
-/// A convenient new type data structure to store the options that belong to a rule
-#[derive(Debug)]
-pub struct RuleOptions(TypeId, Box);
-
-impl RuleOptions {
- /// Creates a new [RuleOptions]
- pub fn new(options: O) -> Self {
- Self(TypeId::of::(), Box::new(options))
- }
-
- /// It returns the deserialized rule option
- pub fn value(&self) -> &O {
- let RuleOptions(type_id, value) = &self;
- let current_id = TypeId::of::();
- debug_assert_eq!(type_id, ¤t_id);
- // SAFETY: the code should fail when asserting the types.
- // If the code throws an error here, it means that the developer didn't test
- // the rule with the options
- value.downcast_ref::().unwrap()
- }
-}
-
-/// A convenient new type data structure to insert and get rules
-#[derive(Debug, Default)]
-pub struct AnalyserRules(FxHashMap);
-
-impl AnalyserRules {
- /// It tracks the options of a specific rule
- pub fn push_rule(&mut self, rule_key: RuleKey, options: RuleOptions) {
- self.0.insert(rule_key, options);
- }
-
- /// It retrieves the options of a stored rule, given its name
- pub fn get_rule_options(&self, rule_key: &RuleKey) -> Option<&O> {
- self.0.get(rule_key).map(|o| o.value::())
- }
-}
-
-/// A set of information useful to the analyser infrastructure
-#[derive(Debug, Default)]
-pub struct AnalyserOptions {
- /// A data structured derived from the [`postgrestools.jsonc`] file
- pub rules: AnalyserRules,
-}
-
-impl AnalyserOptions {
- pub fn rule_options(&self) -> Option
- where
- R: Rule + 'static,
- {
- self.rules
- .get_rule_options::(&RuleKey::rule::())
- .cloned()
- }
-}
diff --git a/crates/pgt_analyse/src/registry.rs b/crates/pgt_analyse/src/registry.rs
deleted file mode 100644
index 48b73b15..00000000
--- a/crates/pgt_analyse/src/registry.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-use std::{borrow, collections::BTreeSet};
-
-use crate::{
- AnalyserOptions,
- context::RuleContext,
- filter::{AnalysisFilter, GroupKey, RuleKey},
- rule::{GroupCategory, Rule, RuleDiagnostic, RuleGroup},
-};
-
-pub trait RegistryVisitor {
- /// Record the category `C` to this visitor
- fn record_category(&mut self) {
- C::record_groups(self);
- }
-
- /// Record the group `G` to this visitor
- fn record_group(&mut self) {
- G::record_rules(self);
- }
-
- /// Record the rule `R` to this visitor
- fn record_rule(&mut self)
- where
- R: Rule + 'static;
-}
-
-/// Key struct for a rule in the metadata map, sorted alphabetically
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct MetadataKey {
- inner: (&'static str, &'static str),
-}
-
-impl MetadataKey {
- fn into_group_key(self) -> GroupKey {
- let (group, _) = self.inner;
- GroupKey::new(group)
- }
-
- fn into_rule_key(self) -> RuleKey {
- let (group, rule) = self.inner;
- RuleKey::new(group, rule)
- }
-}
-
-impl<'a> borrow::Borrow<(&'a str, &'a str)> for MetadataKey {
- fn borrow(&self) -> &(&'a str, &'a str) {
- &self.inner
- }
-}
-
-impl borrow::Borrow for MetadataKey {
- fn borrow(&self) -> &str {
- self.inner.0
- }
-}
-
-/// Stores metadata information for all the rules in the registry, sorted
-/// alphabetically
-#[derive(Debug, Default)]
-pub struct MetadataRegistry {
- inner: BTreeSet,
-}
-
-impl MetadataRegistry {
- /// Return a unique identifier for a rule group if it's known by this registry
- pub fn find_group(&self, group: &str) -> Option {
- let key = self.inner.get(group)?;
- Some(key.into_group_key())
- }
-
- /// Return a unique identifier for a rule if it's known by this registry
- pub fn find_rule(&self, group: &str, rule: &str) -> Option {
- let key = self.inner.get(&(group, rule))?;
- Some(key.into_rule_key())
- }
-
- pub(crate) fn insert_rule(&mut self, group: &'static str, rule: &'static str) {
- self.inner.insert(MetadataKey {
- inner: (group, rule),
- });
- }
-}
-
-impl RegistryVisitor for MetadataRegistry {
- fn record_rule(&mut self)
- where
- R: Rule + 'static,
- {
- self.insert_rule(::NAME, R::METADATA.name);
- }
-}
-
-pub struct RuleRegistryBuilder<'a> {
- filter: &'a AnalysisFilter<'a>,
- // Rule Registry
- registry: RuleRegistry,
-}
-
-impl RegistryVisitor for RuleRegistryBuilder<'_> {
- fn record_category(&mut self) {
- if self.filter.match_category::() {
- C::record_groups(self);
- }
- }
-
- fn record_group(&mut self) {
- if self.filter.match_group::() {
- G::record_rules(self);
- }
- }
-
- /// Add the rule `R` to the list of rules stored in this registry instance
- fn record_rule(&mut self)
- where
- R: Rule + 'static,
- {
- if !self.filter.match_rule::() {
- return;
- }
-
- let rule = RegistryRule::new::();
-
- self.registry.rules.push(rule);
- }
-}
-
-/// The rule registry holds type-erased instances of all active analysis rules
-pub struct RuleRegistry {
- pub rules: Vec,
-}
-
-impl IntoIterator for RuleRegistry {
- type Item = RegistryRule;
- type IntoIter = std::vec::IntoIter;
-
- fn into_iter(self) -> Self::IntoIter {
- self.rules.into_iter()
- }
-}
-
-/// Internal representation of a single rule in the registry
-#[derive(Copy, Clone)]
-pub struct RegistryRule {
- pub run: RuleExecutor,
-}
-
-impl RuleRegistry {
- pub fn builder<'a>(filter: &'a AnalysisFilter<'a>) -> RuleRegistryBuilder<'a> {
- RuleRegistryBuilder {
- filter,
- registry: RuleRegistry {
- rules: Default::default(),
- },
- }
- }
-}
-
-pub struct RegistryRuleParams<'a> {
- pub root: &'a pgt_query_ext::NodeEnum,
- pub options: &'a AnalyserOptions,
-}
-
-/// Executor for rule as a generic function pointer
-type RuleExecutor = fn(&RegistryRuleParams) -> Vec;
-
-impl RegistryRule {
- fn new() -> Self
- where
- R: Rule + 'static,
- {
- /// Generic implementation of RuleExecutor for any rule type R
- fn run(params: &RegistryRuleParams) -> Vec
- where
- R: Rule + 'static,
- {
- let options = params.options.rule_options::().unwrap_or_default();
- let ctx = RuleContext::new(params.root, &options);
- R::run(&ctx)
- }
-
- Self { run: run:: }
- }
-}
-
-impl RuleRegistryBuilder<'_> {
- pub fn build(self) -> RuleRegistry {
- self.registry
- }
-}
diff --git a/crates/pgt_analyse/src/rule.rs b/crates/pgt_analyse/src/rule.rs
deleted file mode 100644
index f135705e..00000000
--- a/crates/pgt_analyse/src/rule.rs
+++ /dev/null
@@ -1,331 +0,0 @@
-use pgt_console::fmt::Display;
-use pgt_console::{MarkupBuf, markup};
-use pgt_diagnostics::advice::CodeSuggestionAdvice;
-use pgt_diagnostics::{
- Advices, Category, Diagnostic, DiagnosticTags, Location, LogCategory, MessageAndDescription,
- Visit,
-};
-use pgt_text_size::TextRange;
-use std::cmp::Ordering;
-use std::fmt::Debug;
-
-use crate::{categories::RuleCategory, context::RuleContext, registry::RegistryVisitor};
-
-#[derive(Clone, Debug)]
-#[cfg_attr(
- feature = "serde",
- derive(serde::Serialize),
- serde(rename_all = "camelCase")
-)]
-/// Static metadata containing information about a rule
-pub struct RuleMetadata {
- /// It marks if a rule is deprecated, and if so a reason has to be provided.
- pub deprecated: Option<&'static str>,
- /// The version when the rule was implemented
- pub version: &'static str,
- /// The name of this rule, displayed in the diagnostics it emits
- pub name: &'static str,
- /// The content of the documentation comments for this rule
- pub docs: &'static str,
- /// Whether a rule is recommended or not
- pub recommended: bool,
- /// The source URL of the rule
- pub sources: &'static [RuleSource],
-}
-
-impl RuleMetadata {
- pub const fn new(version: &'static str, name: &'static str, docs: &'static str) -> Self {
- Self {
- deprecated: None,
- version,
- name,
- docs,
- sources: &[],
- recommended: false,
- }
- }
-
- pub const fn recommended(mut self, recommended: bool) -> Self {
- self.recommended = recommended;
- self
- }
-
- pub const fn deprecated(mut self, deprecated: &'static str) -> Self {
- self.deprecated = Some(deprecated);
- self
- }
-
- pub const fn sources(mut self, sources: &'static [RuleSource]) -> Self {
- self.sources = sources;
- self
- }
-}
-
-pub trait RuleMeta {
- type Group: RuleGroup;
- const METADATA: RuleMetadata;
-}
-
-/// A rule group is a collection of rules under a given name, serving as a
-/// "namespace" for lint rules and allowing the entire set of rules to be
-/// disabled at once
-pub trait RuleGroup {
- type Category: GroupCategory;
- /// The name of this group, displayed in the diagnostics emitted by its rules
- const NAME: &'static str;
- /// Register all the rules belonging to this group into `registry`
- fn record_rules(registry: &mut V);
-}
-
-/// A group category is a collection of rule groups under a given category ID,
-/// serving as a broad classification on the kind of diagnostic or code action
-/// these rule emit, and allowing whole categories of rules to be disabled at
-/// once depending on the kind of analysis being performed
-pub trait GroupCategory {
- /// The category ID used for all groups and rule belonging to this category
- const CATEGORY: RuleCategory;
- /// Register all the groups belonging to this category into `registry`
- fn record_groups(registry: &mut V);
-}
-
-/// Trait implemented by all analysis rules: declares interest to a certain AstNode type,
-/// and a callback function to be executed on all nodes matching the query to possibly
-/// raise an analysis event
-pub trait Rule: RuleMeta + Sized {
- type Options: Default + Clone + Debug;
-
- fn run(ctx: &RuleContext) -> Vec;
-}
-
-/// Diagnostic object returned by a single analysis rule
-#[derive(Debug, Diagnostic, PartialEq)]
-pub struct RuleDiagnostic {
- #[category]
- pub(crate) category: &'static Category,
- #[location(span)]
- pub(crate) span: Option,
- #[message]
- #[description]
- pub(crate) message: MessageAndDescription,
- #[tags]
- pub(crate) tags: DiagnosticTags,
- #[advice]
- pub(crate) rule_advice: RuleAdvice,
-}
-
-#[derive(Debug, Default, PartialEq)]
-/// It contains possible advices to show when printing a diagnostic that belong to the rule
-pub struct RuleAdvice {
- pub(crate) details: Vec,
- pub(crate) notes: Vec<(LogCategory, MarkupBuf)>,
- pub(crate) suggestion_list: Option,
- pub(crate) code_suggestion_list: Vec>,
-}
-
-#[derive(Debug, Default, PartialEq)]
-pub struct SuggestionList {
- pub(crate) message: MarkupBuf,
- pub(crate) list: Vec,
-}
-
-impl Advices for RuleAdvice {
- fn record(&self, visitor: &mut dyn Visit) -> std::io::Result<()> {
- for detail in &self.details {
- visitor.record_log(
- detail.log_category,
- &markup! { {detail.message} }.to_owned(),
- )?;
- visitor.record_frame(Location::builder().span(&detail.range).build())?;
- }
- // we then print notes
- for (log_category, note) in &self.notes {
- visitor.record_log(*log_category, &markup! { {note} }.to_owned())?;
- }
-
- if let Some(suggestion_list) = &self.suggestion_list {
- visitor.record_log(
- LogCategory::Info,
- &markup! { {suggestion_list.message} }.to_owned(),
- )?;
- let list: Vec<_> = suggestion_list
- .list
- .iter()
- .map(|suggestion| suggestion as &dyn Display)
- .collect();
- visitor.record_list(&list)?;
- }
-
- // finally, we print possible code suggestions on how to fix the issue
- for suggestion in &self.code_suggestion_list {
- suggestion.record(visitor)?;
- }
-
- Ok(())
- }
-}
-
-#[derive(Debug, PartialEq)]
-pub struct Detail {
- pub log_category: LogCategory,
- pub message: MarkupBuf,
- pub range: Option,
-}
-
-impl RuleDiagnostic {
- /// Creates a new [`RuleDiagnostic`] with a severity and title that will be
- /// used in a builder-like way to modify labels.
- pub fn new(category: &'static Category, span: Option, title: impl Display) -> Self {
- let message = markup!({ title }).to_owned();
- Self {
- category,
- span,
- message: MessageAndDescription::from(message),
- tags: DiagnosticTags::empty(),
- rule_advice: RuleAdvice::default(),
- }
- }
-
- /// Set an explicit plain-text summary for this diagnostic.
- pub fn description(mut self, summary: impl Into) -> Self {
- self.message.set_description(summary.into());
- self
- }
-
- /// Marks this diagnostic as deprecated code, which will
- /// be displayed in the language server.
- ///
- /// This does not have any influence on the diagnostic rendering.
- pub fn deprecated(mut self) -> Self {
- self.tags |= DiagnosticTags::DEPRECATED_CODE;
- self
- }
-
- /// Marks this diagnostic as unnecessary code, which will
- /// be displayed in the language server.
- ///
- /// This does not have any influence on the diagnostic rendering.
- pub fn unnecessary(mut self) -> Self {
- self.tags |= DiagnosticTags::UNNECESSARY_CODE;
- self
- }
-
- /// Attaches a label to this [`RuleDiagnostic`].
- ///
- /// The given span has to be in the file that was provided while creating this [`RuleDiagnostic`].
- pub fn label(mut self, span: Option, msg: impl Display) -> Self {
- self.rule_advice.details.push(Detail {
- log_category: LogCategory::Info,
- message: markup!({ msg }).to_owned(),
- range: span,
- });
- self
- }
-
- /// Attaches a detailed message to this [`RuleDiagnostic`].
- pub fn detail(self, span: Option, msg: impl Display) -> Self {
- self.label(span, msg)
- }
-
- /// Adds a footer to this [`RuleDiagnostic`], which will be displayed under the actual error.
- fn footer(mut self, log_category: LogCategory, msg: impl Display) -> Self {
- self.rule_advice
- .notes
- .push((log_category, markup!({ msg }).to_owned()));
- self
- }
-
- /// Adds a footer to this [`RuleDiagnostic`], with the `Info` log category.
- pub fn note(self, msg: impl Display) -> Self {
- self.footer(LogCategory::Info, msg)
- }
-
- /// It creates a new footer note which contains a message and a list of possible suggestions.
- /// Useful when there's need to suggest a list of things inside a diagnostic.
- pub fn footer_list(mut self, message: impl Display, list: &[impl Display]) -> Self {
- if !list.is_empty() {
- self.rule_advice.suggestion_list = Some(SuggestionList {
- message: markup! { {message} }.to_owned(),
- list: list
- .iter()
- .map(|msg| markup! { {msg} }.to_owned())
- .collect(),
- });
- }
-
- self
- }
-
- /// Adds a footer to this [`RuleDiagnostic`], with the `Warn` severity.
- pub fn warning(self, msg: impl Display) -> Self {
- self.footer(LogCategory::Warn, msg)
- }
-
- pub fn advices(&self) -> &RuleAdvice {
- &self.rule_advice
- }
-
- /// Will return the rule's category name as defined via `define_categories! { .. }`.
- pub fn get_category_name(&self) -> &'static str {
- self.category.name()
- }
-}
-
-#[derive(Debug, Clone, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize))]
-#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
-pub enum RuleSource {
- /// Rules from [Squawk](https://squawkhq.com)
- Squawk(&'static str),
-}
-
-impl PartialEq for RuleSource {
- fn eq(&self, other: &Self) -> bool {
- std::mem::discriminant(self) == std::mem::discriminant(other)
- }
-}
-
-impl std::fmt::Display for RuleSource {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Squawk(_) => write!(f, "Squawk"),
- }
- }
-}
-
-impl PartialOrd for RuleSource {
- fn partial_cmp(&self, other: &Self) -> Option {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for RuleSource {
- fn cmp(&self, other: &Self) -> Ordering {
- let self_rule = self.as_rule_name();
- let other_rule = other.as_rule_name();
- self_rule.cmp(other_rule)
- }
-}
-
-impl RuleSource {
- pub fn as_rule_name(&self) -> &'static str {
- match self {
- Self::Squawk(rule_name) => rule_name,
- }
- }
-
- pub fn to_namespaced_rule_name(&self) -> String {
- match self {
- Self::Squawk(rule_name) => format!("squawk/{rule_name}"),
- }
- }
-
- pub fn to_rule_url(&self) -> String {
- match self {
- Self::Squawk(rule_name) => format!("https://squawkhq.com/docs/{rule_name}"),
- }
- }
-
- pub fn as_url_and_rule_name(&self) -> (String, &'static str) {
- (self.to_rule_url(), self.as_rule_name())
- }
-}
diff --git a/crates/pgt_analyser/CONTRIBUTING.md b/crates/pgt_analyser/CONTRIBUTING.md
deleted file mode 100644
index 50327d5e..00000000
--- a/crates/pgt_analyser/CONTRIBUTING.md
+++ /dev/null
@@ -1,358 +0,0 @@
-# Analyser
-
-## Creating a rule
-
-When creating or updating a lint rule, you need to be aware that there's a lot of generated code inside our toolchain.
-Our CI ensures that this code is not out of sync and fails otherwise.
-See the [code generation section](#code-generation) for more details.
-
-To create a new rule, you have to create and update several files.
-Because it is a bit tedious, we provide an easy way to create and test your rule using [Just](https://just.systems/man/en/).
-_Just_ is not part of the rust toolchain, you have to install it with [a package manager](https://just.systems/man/en/chapter_4.html).
-
-### Choose a name
-
-We follow a naming convention according to what the rule does:
-
-1. Forbid a concept
-
- ```block
- ban
- ```
-
- When a rule's sole intention is to **forbid a single concept** the rule should be named using the `ban` prefix.
-
- Example: "banDropColumn"
-
-2. Mandate a concept
-
- ```block
- use
- ```
-
- When a rule's sole intention is to **mandate a single concept** the rule should be named using the `use` prefix.
-
-### Explain a rule to the user
-
-A rule should be informative to the user, and give as much explanation as possible.
-
-When writing a rule, you must adhere to the following **pillars**:
-
-1. Explain to the user the error. Generally, this is the message of the diagnostic.
-2. Explain to the user **why** the error is triggered. Generally, this is implemented with an additional node.
-3. Tell the user what they should do. Generally, this is implemented using a code action. If a code action is not applicable a note should tell the user what they should do to fix the error.
-
-### Create and implement the rule
-
-> [!TIP]
-> As a developer, you aren't forced to make a rule perfect in one PR. Instead, you are encouraged to lay out a plan and to split the work into multiple PRs.
->
-> If you aren't familiar with the APIs, this is an option that you have. If you decide to use this option, you should make sure to describe your plan in an issue.
-
-Let's say we want to create a new **lint** rule called `useMyRuleName`, follow these steps:
-
-1. Run the command
-
- ```shell
- just new-lintrule safety useMyRuleName
- ```
-
- The script will generate a bunch of files inside the `pgt_analyser` crate.
- Among the other files, you'll find a file called `use_my_new_rule_name.rs` inside the `pgt_analyser/lib/src/lint/safety` folder. You'll implement your rule in this file.
-
-1. The `Options` type doesn't have to be used, so it can be considered optional. However, it has to be defined as `type Options = ()`.
-1. Implement the `run` function: The function is called for every statement, and should return zero or more diagnostics. Follow the [pillars](#explain-a-rule-to-the-user) when writing the message of a diagnostic
-
-Don't forget to format your code with `just f` and lint with `just l`.
-
-That's it! Now, let's test the rule.
-
-### Rule configuration
-
-Some rules may allow customization using options.
-We try to keep rule options to a minimum and only when needed.
-Before adding an option, it's worth a discussion.
-
-Let's assume that the rule we implement support the following options:
-
-- `behavior`: a string among `"A"`, `"B"`, and `"C"`;
-- `threshold`: an integer between 0 and 255;
-- `behaviorExceptions`: an array of strings.
-
-We would like to set the options in the `postgrestools.jsonc` configuration file:
-
-```json
-{
- "linter": {
- "rules": {
- "safety": {
- "myRule": {
- "level": "warn",
- "options": {
- "behavior": "A",
- "threshold": 20,
- "behaviorExceptions": ["one", "two"]
- }
- }
- }
- }
- }
-}
-```
-
-The first step is to create the Rust data representation of the rule's options.
-
-```rust
-#[derive(Clone, Debug, Default)]
-pub struct MyRuleOptions {
- behavior: Behavior,
- threshold: u8,
- behavior_exceptions: Box<[Box]>
-}
-
-#[derive(Clone, Debug, Defaul)]
-pub enum Behavior {
- #[default]
- A,
- B,
- C,
-}
-```
-
-Note that we use a boxed slice `Box<[Box]>` instead of `Vec`.
-This allows saving memory: [boxed slices and boxed str use two instead of three words](https://nnethercote.github.io/perf-book/type-sizes.html#boxed-slices).
-
-With these types in place, you can set the associated type `Options` of the rule:
-
-```rust
-impl Rule for MyRule {
- type Options = MyRuleOptions;
-}
-```
-
-A rule can retrieve its options with:
-
-```rust
-let options = ctx.options();
-```
-
-The compiler should warn you that `MyRuleOptions` does not implement some required types.
-We currently require implementing _serde_'s traits `Deserialize`/`Serialize`.
-
-Also, we use other `serde` macros to adjust the JSON configuration:
-
-- `rename_all = "camelCase"`: it renames all fields in camel-case, so they are in line with the naming style of the `postgrestools.jsonc`.
-- `deny_unknown_fields`: it raises an error if the configuration contains extraneous fields.
-- `default`: it uses the `Default` value when the field is missing from `postgrestools.jsonc`. This macro makes the field optional.
-
-You can simply use a derive macros:
-
-```rust
-#[derive(Debug, Default, Clone, Serialize, Deserialize)]
-#[cfg_attr(feature = "schemars", derive(JsonSchema))]
-#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
-pub struct MyRuleOptions {
- #[serde(default, skip_serializing_if = "is_default")]
- main_behavior: Behavior,
-
- #[serde(default, skip_serializing_if = "is_default")]
- extra_behaviors: Vec,
-}
-
-#[derive(Debug, Default, Clone)]
-#[cfg_attr(feature = "schemars", derive(JsonSchema))]
-pub enum Behavior {
- #[default]
- A,
- B,
- C,
-}
-```
-
-### Coding the rule
-
-Below, there are many tips and guidelines on how to create a lint rule using our infrastructure.
-
-#### `declare_lint_rule`
-
-This macro is used to declare an analyzer rule type, and implement the [RuleMeta] trait for it.
-
-The macro itself expects the following syntax:
-
-```rust
-use pgt_analyse::declare_lint_rule;
-
-declare_lint_rule! {
- /// Documentation
- pub(crate) ExampleRule {
- version: "next",
- name: "myRuleName",
- recommended: false,
- }
-}
-```
-
-##### Lint rules inspired by other lint rules
-
-If a **lint** rule is inspired by an existing rule from other ecosystems (Squawk etc.), you can add a new metadata to the macro called `source`. Its value is `&'static [RuleSource]`, which is a reference to a slice of `RuleSource` elements, each representing a different source.
-
-If you're implementing a lint rule that matches the behaviour of the Squawk rule `ban-drop-column`, you'll use the variant `::Squawk` and pass the name of the rule:
-
-```rust
-use pgt_analyse::{declare_lint_rule, RuleSource};
-
-declare_lint_rule! {
- /// Documentation
- pub(crate) ExampleRule {
- version: "next",
- name: "myRuleName",
- recommended: false,
- sources: &[RuleSource::Squawk("ban-drop-column")],
- }
-}
-```
-
-#### Category Macro
-
-Declaring a rule using `declare_lint_rule!` will cause a new `rule_category!`
-macro to be declared in the surrounding module. This macro can be used to
-refer to the corresponding diagnostic category for this lint rule, if it
-has one. Using this macro instead of getting the category for a diagnostic
-by dynamically parsing its string name has the advantage of statically
-injecting the category at compile time and checking that it is correctly
-registered to the `pgt_diagnostics` library.
-
-```rust
-declare_lint_rule! {
- /// Documentation
- pub(crate) ExampleRule {
- version: "next",
- name: "myRuleName",
- recommended: false,
- }
-}
-
-impl Rule for BanDropColumn {
- type Options = Options;
-
- fn run(ctx: &RuleContext) -> Vec {
- vec![RuleDiagnostic::new(
- rule_category!(),
- None,
- "message",
- )]
- }
-}
-```
-
-### Document the rule
-
-The documentation needs to adhere to the following rules:
-
-- The **first** paragraph of the documentation is used as brief description of the rule, and it **must** be written in one single line. Breaking the paragraph in multiple lines will break the table content of the rules page.
-- The next paragraphs can be used to further document the rule with as many details as you see fit.
-- The documentation must have a `## Examples` header, followed by two headers: `### Invalid` and `### Valid`. `### Invalid` must go first because we need to show when the rule is triggered.
-- Rule options if any, must be documented in the `## Options` section.
-- Each code block must have `sql` set as language defined.
-- When adding _invalid_ snippets in the `### Invalid` section, you must use the `expect_diagnostic` code block property. We use this property to generate a diagnostic and attach it to the snippet. A snippet **must emit only ONE diagnostic**.
-- When adding _valid_ snippets in the `### Valid` section, you can use one single snippet.
-- You can use the code block property `ignore` to tell the code generation script to **not generate a diagnostic for an invalid snippet**.
-
-Here's an example of how the documentation could look like:
-
-````rust
-declare_lint_rule! {
- /// Dropping a column may break existing clients.
- ///
- /// Update your application code to no longer read or write the column.
- ///
- /// You can leave the column as nullable or delete the column once queries no longer select or modify the column.
- ///
- /// ## Examples
- ///
- /// ### Invalid
- ///
- /// ```sql,expect_diagnostic
- /// alter table test drop column id;
- /// ```
- ///
- pub BanDropColumn {
- version: "next",
- name: "banDropColumn",
- recommended: true,
- sources: &[RuleSource::Squawk("ban-drop-column")],
- }
-}
-````
-
-This will cause the documentation generator to ensure the rule does emit
-exactly one diagnostic for this code, and to include a snapshot for the
-diagnostic in the resulting documentation page.
-
-### Testing the Rule
-
-#### Quick Test
-
-To quickly test your rule, head to the `pgt_analyser/src/lib.rs` file and modify the `debug_test` function.
-
-You should:
-
-- remove the `#[ignore]` macro if present
-- change the content of the `SQL` static `&str` to whatever you need
-- pass your group and rule to the `RuleFilter::Rule(..)`
-
-If you run the test, you'll see any diagnostics your rule created in your console.
-
-### Code generation
-
-For simplicity, use `just` to run all the commands with:
-
-```shell
-just gen-lint
-```
-
-### Commit your work
-
-Once the rule implemented, tested, and documented, you are ready to open a pull request!
-
-Stage and commit your changes:
-
-```shell
-> git add -A
-> git commit -m 'feat(pgt_analyser): myRuleName'
-```
-
-### Deprecate a rule
-
-There are occasions when a rule must be deprecated, to avoid breaking changes. The reason
-of deprecation can be multiple.
-
-In order to do, the macro allows adding additional field to add the reason for deprecation
-
-````rust
-use pgt_analyse::declare_lint_rule;
-
-declare_lint_rule! {
- /// Dropping a column may break existing clients.
- ///
- /// Update your application code to no longer read or write the column.
- ///
- /// You can leave the column as nullable or delete the column once queries no longer select or modify the column.
- ///
- /// ## Examples
- ///
- /// ### Invalid
- ///
- /// ```sql,expect_diagnostic
- /// alter table test drop column id;
- /// ```
- ///
- pub BanDropColumn {
- version: "next",
- name: "banDropColumn",
- recommended: true,
- deprecated: true,
- sources: &[RuleSource::Squawk("ban-drop-column")],
- }
-}
-````
diff --git a/crates/pgt_analyser/Cargo.toml b/crates/pgt_analyser/Cargo.toml
deleted file mode 100644
index bd51c36a..00000000
--- a/crates/pgt_analyser/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-[package]
-authors.workspace = true
-categories.workspace = true
-description = ""
-edition.workspace = true
-homepage.workspace = true
-keywords.workspace = true
-license.workspace = true
-name = "pgt_analyser"
-repository.workspace = true
-version = "0.0.0"
-
-[dependencies]
-pgt_analyse = { workspace = true }
-pgt_console = { workspace = true }
-pgt_query_ext = { workspace = true }
-serde = { workspace = true }
-
-[dev-dependencies]
-insta = { version = "1.42.1" }
-pgt_diagnostics = { workspace = true }
-pgt_test_macros = { workspace = true }
-termcolor = { workspace = true }
diff --git a/crates/pgt_analyser/src/lib.rs b/crates/pgt_analyser/src/lib.rs
deleted file mode 100644
index 248fe22b..00000000
--- a/crates/pgt_analyser/src/lib.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-use std::{ops::Deref, sync::LazyLock};
-
-use pgt_analyse::{
- AnalyserOptions, AnalysisFilter, MetadataRegistry, RegistryRuleParams, RuleDiagnostic,
- RuleRegistry,
-};
-pub use registry::visit_registry;
-
-mod lint;
-pub mod options;
-mod registry;
-
-pub static METADATA: LazyLock = LazyLock::new(|| {
- let mut metadata = MetadataRegistry::default();
- visit_registry(&mut metadata);
- metadata
-});
-
-/// Main entry point to the analyser.
-pub struct Analyser<'a> {
- /// Holds the metadata for all the rules statically known to the analyser
- /// we need this later when we add suppression support
- #[allow(dead_code)]
- metadata: &'a MetadataRegistry,
-
- /// Holds all rule options
- options: &'a AnalyserOptions,
-
- /// Holds all rules
- registry: RuleRegistry,
-}
-
-pub struct AnalyserContext<'a> {
- pub root: &'a pgt_query_ext::NodeEnum,
-}
-
-pub struct AnalyserConfig<'a> {
- pub options: &'a AnalyserOptions,
- pub filter: AnalysisFilter<'a>,
-}
-
-impl<'a> Analyser<'a> {
- pub fn new(conf: AnalyserConfig<'a>) -> Self {
- let mut builder = RuleRegistry::builder(&conf.filter);
- visit_registry(&mut builder);
- let registry = builder.build();
-
- Self {
- metadata: METADATA.deref(),
- registry,
- options: conf.options,
- }
- }
-
- pub fn run(&self, ctx: AnalyserContext) -> Vec {
- let params = RegistryRuleParams {
- root: ctx.root,
- options: self.options,
- };
-
- self.registry
- .rules
- .iter()
- .flat_map(|rule| (rule.run)(¶ms))
- .collect::>()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use core::slice;
-
- use pgt_analyse::{AnalyserOptions, AnalysisFilter, RuleFilter};
- use pgt_console::{
- Markup,
- fmt::{Formatter, Termcolor},
- markup,
- };
- use pgt_diagnostics::PrintDiagnostic;
- use termcolor::NoColor;
-
- use crate::Analyser;
-
- #[ignore]
- #[test]
- fn debug_test() {
- fn markup_to_string(markup: Markup) -> String {
- let mut buffer = Vec::new();
- let mut write = Termcolor(NoColor::new(&mut buffer));
- let mut fmt = Formatter::new(&mut write);
- fmt.write_markup(markup).unwrap();
-
- String::from_utf8(buffer).unwrap()
- }
-
- const SQL: &str = r#"alter table test drop column id;"#;
- let rule_filter = RuleFilter::Rule("safety", "banDropColumn");
-
- let filter = AnalysisFilter {
- enabled_rules: Some(slice::from_ref(&rule_filter)),
- ..Default::default()
- };
-
- let ast = pgt_query_ext::parse(SQL).expect("failed to parse SQL");
-
- let options = AnalyserOptions::default();
-
- let analyser = Analyser::new(crate::AnalyserConfig {
- options: &options,
- filter,
- });
-
- let results = analyser.run(crate::AnalyserContext { root: &ast });
-
- println!("*******************");
- for result in &results {
- let text = markup_to_string(markup! {
- {PrintDiagnostic::simple(result)}
- });
- eprintln!("{}", text);
- }
- println!("*******************");
-
- // assert_eq!(results, vec![]);
- }
-}
diff --git a/crates/pgt_analyser/src/lint.rs b/crates/pgt_analyser/src/lint.rs
deleted file mode 100644
index cbc13c9d..00000000
--- a/crates/pgt_analyser/src/lint.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! Generated file, do not edit by hand, see `xtask/codegen`
-
-pub mod safety;
-::pgt_analyse::declare_category! { pub Lint { kind : Lint , groups : [self :: safety :: Safety ,] } }
diff --git a/crates/pgt_analyser/src/lint/safety.rs b/crates/pgt_analyser/src/lint/safety.rs
deleted file mode 100644
index 920326c2..00000000
--- a/crates/pgt_analyser/src/lint/safety.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//! Generated file, do not edit by hand, see `xtask/codegen`
-
-use pgt_analyse::declare_lint_group;
-pub mod adding_required_field;
-pub mod ban_drop_column;
-pub mod ban_drop_not_null;
-pub mod ban_drop_table;
-declare_lint_group! { pub Safety { name : "safety" , rules : [self :: adding_required_field :: AddingRequiredField , self :: ban_drop_column :: BanDropColumn , self :: ban_drop_not_null :: BanDropNotNull , self :: ban_drop_table :: BanDropTable ,] } }
diff --git a/crates/pgt_analyser/src/lint/safety/adding_required_field.rs b/crates/pgt_analyser/src/lint/safety/adding_required_field.rs
deleted file mode 100644
index d4f72a7f..00000000
--- a/crates/pgt_analyser/src/lint/safety/adding_required_field.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use pgt_analyse::{Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule};
-use pgt_console::markup;
-
-declare_lint_rule! {
- /// Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required.
- ///
- /// This will fail immediately upon running for any populated table. Furthermore, old application code that is unaware of this column will fail to INSERT to this table.
- ///
- /// Make new columns optional initially by omitting the NOT NULL constraint until all existing data and application code has been updated. Once no NULL values are written to or persisted in the database, set it to NOT NULL.
- /// Alternatively, if using Postgres version 11 or later, add a DEFAULT value that is not volatile. This allows the column to keep its NOT NULL constraint.
- ///
- /// ## Invalid
- /// alter table test add column count int not null;
- ///
- /// ## Valid in Postgres >= 11
- /// alter table test add column count int not null default 0;
- pub AddingRequiredField {
- version: "next",
- name: "addingRequiredField",
- recommended: false,
- sources: &[RuleSource::Squawk("adding-required-field")],
- }
-}
-
-impl Rule for AddingRequiredField {
- type Options = ();
-
- fn run(ctx: &RuleContext) -> Vec {
- let mut diagnostics = vec![];
-
- if let pgt_query_ext::NodeEnum::AlterTableStmt(stmt) = ctx.stmt() {
- // We are currently lacking a way to check if a `AtAddColumn` subtype sets a
- // not null constraint – so we'll need to check the plain SQL.
- let plain_sql = ctx.stmt().to_ref().deparse().unwrap().to_ascii_lowercase();
- let is_nullable = !plain_sql.contains("not null");
- let has_set_default = plain_sql.contains("default");
- if is_nullable || has_set_default {
- return diagnostics;
- }
-
- for cmd in &stmt.cmds {
- if let Some(pgt_query_ext::NodeEnum::AlterTableCmd(alter_table_cmd)) = &cmd.node {
- if alter_table_cmd.subtype()
- == pgt_query_ext::protobuf::AlterTableType::AtAddColumn
- {
- diagnostics.push(
- RuleDiagnostic::new(
- rule_category!(),
- None,
- markup! {
- "Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required."
- },
- )
- .detail(
- None,
- "Make new columns optional initially by omitting the NOT NULL constraint until all existing data and application code has been updated. Once no NULL values are written to or persisted in the database, set it to NOT NULL. Alternatively, if using Postgres version 11 or later, add a DEFAULT value that is not volatile. This allows the column to keep its NOT NULL constraint.
- ",
- ),
- );
- }
- }
- }
- }
-
- diagnostics
- }
-}
diff --git a/crates/pgt_analyser/src/lint/safety/ban_drop_column.rs b/crates/pgt_analyser/src/lint/safety/ban_drop_column.rs
deleted file mode 100644
index aab5d515..00000000
--- a/crates/pgt_analyser/src/lint/safety/ban_drop_column.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use pgt_analyse::{Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule};
-use pgt_console::markup;
-
-declare_lint_rule! {
- /// Dropping a column may break existing clients.
- ///
- /// Update your application code to no longer read or write the column.
- ///
- /// You can leave the column as nullable or delete the column once queries no longer select or modify the column.
- ///
- /// ## Examples
- ///
- /// ### Invalid
- ///
- /// ```sql,expect_diagnostic
- /// alter table test drop column id;
- /// ```
- ///
- pub BanDropColumn {
- version: "next",
- name: "banDropColumn",
- recommended: true,
- sources: &[RuleSource::Squawk("ban-drop-column")],
- }
-}
-
-impl Rule for BanDropColumn {
- type Options = ();
-
- fn run(ctx: &RuleContext) -> Vec {
- let mut diagnostics = Vec::new();
-
- if let pgt_query_ext::NodeEnum::AlterTableStmt(stmt) = &ctx.stmt() {
- for cmd in &stmt.cmds {
- if let Some(pgt_query_ext::NodeEnum::AlterTableCmd(cmd)) = &cmd.node {
- if cmd.subtype() == pgt_query_ext::protobuf::AlterTableType::AtDropColumn {
- diagnostics.push(RuleDiagnostic::new(
- rule_category!(),
- None,
- markup! {
- "Dropping a column may break existing clients."
- },
- ).detail(None, "You can leave the column as nullable or delete the column once queries no longer select or modify the column."));
- }
- }
- }
- }
-
- diagnostics
- }
-}
diff --git a/crates/pgt_analyser/src/lint/safety/ban_drop_not_null.rs b/crates/pgt_analyser/src/lint/safety/ban_drop_not_null.rs
deleted file mode 100644
index eb17f694..00000000
--- a/crates/pgt_analyser/src/lint/safety/ban_drop_not_null.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use pgt_analyse::{Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule};
-use pgt_console::markup;
-
-declare_lint_rule! {
- /// Dropping a NOT NULL constraint may break existing clients.
- ///
- /// Application code or code written in procedural languages like PL/SQL or PL/pgSQL may not expect NULL values for the column that was previously guaranteed to be NOT NULL and therefore may fail to process them correctly.
- ///
- /// You can consider using a marker value that represents NULL. Alternatively, create a new table allowing NULL values, copy the data from the old table, and create a view that filters NULL values.
- ///
- /// ## Examples
- ///
- /// ### Invalid
- ///
- /// ```sql,expect_diagnostic
- /// alter table users alter column email drop not null;
- /// ```
- pub BanDropNotNull {
- version: "next",
- name: "banDropNotNull",
- recommended: true,
- sources: &[RuleSource::Squawk("ban-drop-not-null")],
-
- }
-}
-
-impl Rule for BanDropNotNull {
- type Options = ();
-
- fn run(ctx: &RuleContext) -> Vec {
- let mut diagnostics = Vec::new();
-
- if let pgt_query_ext::NodeEnum::AlterTableStmt(stmt) = &ctx.stmt() {
- for cmd in &stmt.cmds {
- if let Some(pgt_query_ext::NodeEnum::AlterTableCmd(cmd)) = &cmd.node {
- if cmd.subtype() == pgt_query_ext::protobuf::AlterTableType::AtDropNotNull {
- diagnostics.push(RuleDiagnostic::new(
- rule_category!(),
- None,
- markup! {
- "Dropping a NOT NULL constraint may break existing clients."
- },
- ).detail(None, "Consider using a marker value that represents NULL. Alternatively, create a new table allowing NULL values, copy the data from the old table, and create a view that filters NULL values."));
- }
- }
- }
- }
-
- diagnostics
- }
-}
diff --git a/crates/pgt_analyser/src/lint/safety/ban_drop_table.rs b/crates/pgt_analyser/src/lint/safety/ban_drop_table.rs
deleted file mode 100644
index 4ce00a60..00000000
--- a/crates/pgt_analyser/src/lint/safety/ban_drop_table.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use pgt_analyse::{Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule};
-use pgt_console::markup;
-
-declare_lint_rule! {
- /// Dropping a table may break existing clients.
- ///
- /// Update your application code to no longer read or write the table.
- ///
- /// Once the table is no longer needed, you can delete it by running the command "DROP TABLE mytable;".
- ///
- /// This command will permanently remove the table from the database and all its contents.
- /// Be sure to back up the table before deleting it, just in case you need to restore it in the future.
- ///
- /// ## Examples
- /// ```sql,expect_diagnostic
- /// drop table some_table;
- /// ```
- pub BanDropTable {
- version: "next",
- name: "banDropTable",
- recommended: true,
- sources: &[RuleSource::Squawk("ban-drop-table")],
- }
-}
-
-impl Rule for BanDropTable {
- type Options = ();
-
- fn run(ctx: &RuleContext) -> Vec {
- let mut diagnostics = vec![];
-
- if let pgt_query_ext::NodeEnum::DropStmt(stmt) = &ctx.stmt() {
- if stmt.remove_type() == pgt_query_ext::protobuf::ObjectType::ObjectTable {
- diagnostics.push(
- RuleDiagnostic::new(
- rule_category!(),
- None,
- markup! {
- "Dropping a table may break existing clients."
- },
- )
- .detail(
- None,
- "Update your application code to no longer read or write the table, and only then delete the table. Be sure to create a backup.",
- ),
- );
- }
- }
-
- diagnostics
- }
-}
diff --git a/crates/pgt_analyser/src/options.rs b/crates/pgt_analyser/src/options.rs
deleted file mode 100644
index d78020f8..00000000
--- a/crates/pgt_analyser/src/options.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//! Generated file, do not edit by hand, see `xtask/codegen`
-
-use crate::lint;
-pub type AddingRequiredField =
- ::Options;
-pub type BanDropColumn =
- ::Options;
-pub type BanDropNotNull =
- ::Options;
-pub type BanDropTable = ::Options;
diff --git a/crates/pgt_analyser/src/registry.rs b/crates/pgt_analyser/src/registry.rs
deleted file mode 100644
index fb549575..00000000
--- a/crates/pgt_analyser/src/registry.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//! Generated file, do not edit by hand, see `xtask/codegen`
-
-use pgt_analyse::RegistryVisitor;
-pub fn visit_registry(registry: &mut V) {
- registry.record_category::();
-}
diff --git a/crates/pgt_analyser/tests/rules_tests.rs b/crates/pgt_analyser/tests/rules_tests.rs
deleted file mode 100644
index 247c02b0..00000000
--- a/crates/pgt_analyser/tests/rules_tests.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-use core::slice;
-use std::{fmt::Write, fs::read_to_string, path::Path};
-
-use pgt_analyse::{AnalyserOptions, AnalysisFilter, RuleDiagnostic, RuleFilter};
-use pgt_analyser::{Analyser, AnalyserConfig, AnalyserContext};
-use pgt_console::StdDisplay;
-use pgt_diagnostics::PrintDiagnostic;
-
-pgt_test_macros::gen_tests! {
- "tests/specs/**/*.sql",
- crate::rule_test
-}
-
-fn rule_test(full_path: &'static str, _: &str, _: &str) {
- let input_file = Path::new(full_path);
-
- let (group, rule, fname) = parse_test_path(input_file);
-
- let rule_filter = RuleFilter::Rule(group.as_str(), rule.as_str());
- let filter = AnalysisFilter {
- enabled_rules: Some(slice::from_ref(&rule_filter)),
- ..Default::default()
- };
-
- let query =
- read_to_string(full_path).unwrap_or_else(|_| panic!("Failed to read file: {} ", full_path));
-
- let ast = pgt_query_ext::parse(&query).expect("failed to parse SQL");
- let options = AnalyserOptions::default();
- let analyser = Analyser::new(AnalyserConfig {
- options: &options,
- filter,
- });
-
- let results = analyser.run(AnalyserContext { root: &ast });
-
- let mut snapshot = String::new();
- write_snapshot(&mut snapshot, query.as_str(), results.as_slice());
-
- insta::with_settings!({
- prepend_module_to_snapshot => false,
- snapshot_path => input_file.parent().unwrap(),
- }, {
- insta::assert_snapshot!(fname, snapshot);
- });
-
- let expectation = Expectation::from_file(&query);
- expectation.assert(results.as_slice());
-}
-
-fn parse_test_path(path: &Path) -> (String, String, String) {
- let mut comps: Vec<&str> = path
- .components()
- .map(|c| c.as_os_str().to_str().unwrap())
- .collect();
-
- let fname = comps.pop().unwrap();
- let rule = comps.pop().unwrap();
- let group = comps.pop().unwrap();
-
- (group.into(), rule.into(), fname.into())
-}
-
-fn write_snapshot(snapshot: &mut String, query: &str, diagnostics: &[RuleDiagnostic]) {
- writeln!(snapshot, "# Input").unwrap();
- writeln!(snapshot, "```").unwrap();
- writeln!(snapshot, "{query}").unwrap();
- writeln!(snapshot, "```").unwrap();
- writeln!(snapshot).unwrap();
-
- if !diagnostics.is_empty() {
- writeln!(snapshot, "# Diagnostics").unwrap();
- for diagnostic in diagnostics {
- let printer = PrintDiagnostic::simple(diagnostic);
-
- writeln!(snapshot, "{}", StdDisplay(printer)).unwrap();
- writeln!(snapshot).unwrap();
- }
- }
-}
-
-enum Expectation {
- NoDiagnostics,
- AnyDiagnostics,
- OnlyOne(String),
-}
-
-impl Expectation {
- fn from_file(content: &str) -> Self {
- for line in content.lines() {
- if line.contains("expect_no_diagnostics") {
- return Self::NoDiagnostics;
- }
-
- if line.contains("expect_only_") {
- let kind = line
- .splitn(3, "_")
- .last()
- .expect("Use pattern: `-- expect_only_`")
- .trim();
-
- return Self::OnlyOne(kind.into());
- }
- }
-
- Self::AnyDiagnostics
- }
-
- fn assert(&self, diagnostics: &[RuleDiagnostic]) {
- match self {
- Self::NoDiagnostics => {
- if !diagnostics.is_empty() {
- panic!("This test should not have any diagnostics.");
- }
- }
- Self::OnlyOne(category) => {
- let found_kinds = diagnostics
- .iter()
- .map(|d| d.get_category_name())
- .collect::>()
- .join(", ");
-
- if diagnostics.len() != 1 || diagnostics[0].get_category_name() != category {
- panic!(
- "This test should only have one diagnostic of kind: {category}\nReceived: {found_kinds}"
- );
- }
- }
- Self::AnyDiagnostics => {}
- }
- }
-}
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql
deleted file mode 100644
index 836c295c..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql
+++ /dev/null
@@ -1,3 +0,0 @@
--- expect_only_lint/safety/addingRequiredField
-alter table test
-add column c int not null;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql.snap b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql.snap
deleted file mode 100644
index 559dbf53..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/basic.sql.snap
+++ /dev/null
@@ -1,17 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_only_lint/safety/addingRequiredField
-alter table test
-add column c int not null;
-```
-
-# Diagnostics
-lint/safety/addingRequiredField ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
- × Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required.
-
- i Make new columns optional initially by omitting the NOT NULL constraint until all existing data and application code has been updated. Once no NULL values are written to or persisted in the database, set it to NOT NULL. Alternatively, if using Postgres version 11 or later, add a DEFAULT value that is not volatile. This allows the column to keep its NOT NULL constraint.
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql
deleted file mode 100644
index 988f0a71..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql
+++ /dev/null
@@ -1,3 +0,0 @@
--- expect_no_diagnostics
-alter table test
-add column c int not null default 0;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql.snap b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql.snap
deleted file mode 100644
index 166ae7dc..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/with_default.sql.snap
+++ /dev/null
@@ -1,10 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_no_diagnostics
-alter table test
-add column c int not null default 0;
-```
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql
deleted file mode 100644
index 1990edc1..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql
+++ /dev/null
@@ -1,3 +0,0 @@
--- expect_no_diagnostics
-alter table test
-add column c int;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql.snap b/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql.snap
deleted file mode 100644
index f62cf4cd..00000000
--- a/crates/pgt_analyser/tests/specs/safety/addingRequiredField/without_required.sql.snap
+++ /dev/null
@@ -1,10 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_no_diagnostics
-alter table test
-add column c int;
-```
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql b/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql
deleted file mode 100644
index 16d3b476..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql
+++ /dev/null
@@ -1,3 +0,0 @@
--- expect_only_lint/safety/banDropColumn
-alter table test
-drop column id;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql.snap b/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql.snap
deleted file mode 100644
index 3fd80e19..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropColumn/basic.sql.snap
+++ /dev/null
@@ -1,17 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_only_lint/safety/banDropColumn
-alter table test
-drop column id;
-```
-
-# Diagnostics
-lint/safety/banDropColumn ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
- × Dropping a column may break existing clients.
-
- i You can leave the column as nullable or delete the column once queries no longer select or modify the column.
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql b/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql
deleted file mode 100644
index 1e1fc879..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql
+++ /dev/null
@@ -1,4 +0,0 @@
--- expect_only_lint/safety/banDropNotNull
-alter table users
-alter column id
-drop not null;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql.snap b/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql.snap
deleted file mode 100644
index e5d55267..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropNotNull/basic.sql.snap
+++ /dev/null
@@ -1,18 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_only_lint/safety/banDropNotNull
-alter table users
-alter column id
-drop not null;
-```
-
-# Diagnostics
-lint/safety/banDropNotNull ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
- × Dropping a NOT NULL constraint may break existing clients.
-
- i Consider using a marker value that represents NULL. Alternatively, create a new table allowing NULL values, copy the data from the old table, and create a view that filters NULL values.
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql b/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql
deleted file mode 100644
index 16f6fd62..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql
+++ /dev/null
@@ -1,2 +0,0 @@
--- expect_only_lint/safety/banDropTable
-drop table test;
\ No newline at end of file
diff --git a/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql.snap b/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql.snap
deleted file mode 100644
index 481b1223..00000000
--- a/crates/pgt_analyser/tests/specs/safety/banDropTable/basic.sql.snap
+++ /dev/null
@@ -1,16 +0,0 @@
----
-source: crates/pgt_analyser/tests/rules_tests.rs
-expression: snapshot
----
-# Input
-```
--- expect_only_lint/safety/banDropTable
-drop table test;
-```
-
-# Diagnostics
-lint/safety/banDropTable ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
- × Dropping a table may break existing clients.
-
- i Update your application code to no longer read or write the table, and only then delete the table. Be sure to create a backup.
diff --git a/crates/pgt_cli/Cargo.toml b/crates/pgt_cli/Cargo.toml
deleted file mode 100644
index f2a3fa18..00000000
--- a/crates/pgt_cli/Cargo.toml
+++ /dev/null
@@ -1,63 +0,0 @@
-[package]
-authors.workspace = true
-categories.workspace = true
-description = ""
-edition.workspace = true
-homepage.workspace = true
-keywords.workspace = true
-license.workspace = true
-name = "pgt_cli"
-repository.workspace = true
-version = "0.0.0"
-
-
-[dependencies]
-anyhow = { workspace = true }
-biome_deserialize = { workspace = true }
-biome_deserialize_macros = { workspace = true }
-bpaf = { workspace = true, features = ["bright-color"] }
-crossbeam = { workspace = true }
-dashmap = "5.5.3"
-hdrhistogram = { version = "7.5.4", default-features = false }
-path-absolutize = { version = "3.1.1", optional = false, features = ["use_unix_paths_on_wasm"] }
-pgt_analyse = { workspace = true }
-pgt_configuration = { workspace = true }
-pgt_console = { workspace = true }
-pgt_diagnostics = { workspace = true }
-pgt_flags = { workspace = true }
-pgt_fs = { workspace = true }
-pgt_lsp = { workspace = true }
-pgt_text_edit = { workspace = true }
-pgt_workspace = { workspace = true }
-quick-junit = "0.5.0"
-rayon = { workspace = true }
-rustc-hash = { workspace = true }
-serde = { workspace = true, features = ["derive"] }
-serde_json = { workspace = true }
-tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] }
-tracing = { workspace = true }
-tracing-appender = "0.2.3"
-tracing-bunyan-formatter = { workspace = true }
-tracing-subscriber = { workspace = true, features = ["env-filter", "json"] }
-tracing-tree = { version = "0.4.0", features = ["time"] }
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2.161"
-tokio = { workspace = true, features = ["process"] }
-
-[target.'cfg(windows)'.dependencies]
-mimalloc = "0.1.43"
-
-[target.'cfg(all(target_family="unix", not(all(target_arch = "aarch64", target_env = "musl"))))'.dependencies]
-tikv-jemallocator = "0.6.0"
-
-[dev-dependencies]
-assert_cmd = "2.0.16"
-predicates = "3.1.3"
-
-[lib]
-doctest = false
-
-[[bin]]
-name = "postgrestools"
-path = "src/main.rs"
diff --git a/crates/pgt_cli/src/changed.rs b/crates/pgt_cli/src/changed.rs
deleted file mode 100644
index a18502dd..00000000
--- a/crates/pgt_cli/src/changed.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use crate::CliDiagnostic;
-use pgt_configuration::PartialConfiguration;
-use pgt_fs::FileSystem;
-use pgt_workspace::DynRef;
-use std::ffi::OsString;
-
-pub(crate) fn get_changed_files(
- fs: &DynRef<'_, dyn FileSystem>,
- configuration: &PartialConfiguration,
- since: Option<&str>,
-) -> Result, CliDiagnostic> {
- let default_branch = configuration
- .vcs
- .as_ref()
- .and_then(|v| v.default_branch.as_ref());
-
- let base = match (since, default_branch) {
- (Some(since), Some(_)) => since,
- (Some(since), None) => since,
- (None, Some(branch)) => branch,
- (None, None) => {
- return Err(CliDiagnostic::incompatible_end_configuration(
- "The `--changed` flag was set, but couldn't determine the base to compare against. Either set configuration.vcs.default_branch or use the --since argument.",
- ));
- }
- };
-
- let changed_files = fs.get_changed_files(base)?;
-
- let filtered_changed_files = changed_files.iter().map(OsString::from).collect::>();
-
- Ok(filtered_changed_files)
-}
-
-pub(crate) fn get_staged_files(
- fs: &DynRef<'_, dyn FileSystem>,
-) -> Result, CliDiagnostic> {
- let staged_files = fs.get_staged_files()?;
-
- let filtered_staged_files = staged_files.iter().map(OsString::from).collect::>();
-
- Ok(filtered_staged_files)
-}
diff --git a/crates/pgt_cli/src/cli_options.rs b/crates/pgt_cli/src/cli_options.rs
deleted file mode 100644
index 5c41c7fc..00000000
--- a/crates/pgt_cli/src/cli_options.rs
+++ /dev/null
@@ -1,234 +0,0 @@
-use crate::LoggingLevel;
-use crate::logging::LoggingKind;
-use bpaf::Bpaf;
-use pgt_configuration::ConfigurationPathHint;
-use pgt_diagnostics::Severity;
-use std::fmt::{Display, Formatter};
-use std::path::PathBuf;
-use std::str::FromStr;
-
-/// Global options applied to all commands
-#[derive(Debug, Clone, Bpaf)]
-pub struct CliOptions {
- /// Set the formatting mode for markup: "off" prints everything as plain text, "force" forces the formatting of markup using ANSI even if the console output is determined to be incompatible
- #[bpaf(long("colors"), argument("off|force"))]
- pub colors: Option,
-
- /// Connect to a running instance of the daemon server.
- #[bpaf(long("use-server"), switch, fallback(false))]
- pub use_server: bool,
-
- /// Print additional diagnostics, and some diagnostics show more information. Also, print out what files were processed and which ones were modified.
- #[bpaf(long("verbose"), switch, fallback(false))]
- pub verbose: bool,
-
- /// Set the file path to the configuration file, or the directory path to find `postgrestools.jsonc`.
- /// If used, it disables the default configuration file resolution.
- #[bpaf(long("config-path"), argument("PATH"), optional)]
- pub config_path: Option,
-
- /// Cap the amount of diagnostics displayed. When `none` is provided, the limit is lifted.
- #[bpaf(
- long("max-diagnostics"),
- argument("none|"),
- fallback(MaxDiagnostics::default()),
- display_fallback
- )]
- pub max_diagnostics: MaxDiagnostics,
-
- /// Skip over files containing syntax errors instead of emitting an error diagnostic.
- #[bpaf(long("skip-errors"), switch)]
- pub skip_errors: bool,
-
- /// Silence errors that would be emitted in case no files were processed during the execution of the command.
- #[bpaf(long("no-errors-on-unmatched"), switch)]
- pub no_errors_on_unmatched: bool,
-
- /// Tell Postgres Tools to exit with an error code if some diagnostics emit warnings.
- #[bpaf(long("error-on-warnings"), switch)]
- pub error_on_warnings: bool,
-
- /// Allows to change how diagnostics and summary are reported.
- #[bpaf(
- long("reporter"),
- argument("json|json-pretty|github|junit|summary|gitlab"),
- fallback(CliReporter::default())
- )]
- pub reporter: CliReporter,
-
- #[bpaf(
- env("PGT_LOG_LEVEL"),
- long("log-level"),
- argument("none|debug|info|warn|error"),
- fallback(LoggingLevel::default()),
- display_fallback
- )]
- /// The level of logging. In order, from the most verbose to the least verbose: debug, info, warn, error.
- ///
- /// The value `none` won't show any logging.
- pub log_level: LoggingLevel,
-
- /// How the log should look like.
- #[bpaf(
- long("log-kind"),
- argument("pretty|compact|json"),
- fallback(LoggingKind::default()),
- display_fallback
- )]
- pub log_kind: LoggingKind,
-
- #[bpaf(
- long("diagnostic-level"),
- argument("info|warn|error"),
- fallback(Severity::default()),
- display_fallback
- )]
- /// The level of diagnostics to show. In order, from the lowest to the most important: info, warn, error. Passing `--diagnostic-level=error` will cause Postgres Tools to print only diagnostics that contain only errors.
- pub diagnostic_level: Severity,
-}
-
-impl CliOptions {
- /// Computes the [ConfigurationPathHint] based on the options passed by the user
- pub(crate) fn as_configuration_path_hint(&self) -> ConfigurationPathHint {
- match self.config_path.as_ref() {
- None => ConfigurationPathHint::default(),
- Some(path) => ConfigurationPathHint::FromUser(PathBuf::from(path)),
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum ColorsArg {
- Off,
- Force,
-}
-
-impl FromStr for ColorsArg {
- type Err = String;
-
- fn from_str(s: &str) -> Result {
- match s {
- "off" => Ok(Self::Off),
- "force" => Ok(Self::Force),
- _ => Err(format!(
- "value {s:?} is not valid for the --colors argument"
- )),
- }
- }
-}
-
-#[derive(Debug, Default, Clone)]
-pub enum CliReporter {
- /// The default reporter
- #[default]
- Default,
- /// Diagnostics are printed for GitHub workflow commands
- GitHub,
- /// Diagnostics and summary are printed in JUnit format
- Junit,
- /// Reports linter diagnostics using the [GitLab Code Quality report](https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool).
- GitLab,
-}
-
-impl CliReporter {
- pub(crate) const fn is_default(&self) -> bool {
- matches!(self, Self::Default)
- }
-}
-
-impl FromStr for CliReporter {
- type Err = String;
-
- fn from_str(s: &str) -> Result {
- match s {
- "github" => Ok(Self::GitHub),
- "junit" => Ok(Self::Junit),
- "gitlab" => Ok(Self::GitLab),
- _ => Err(format!(
- "value {s:?} is not valid for the --reporter argument"
- )),
- }
- }
-}
-
-impl Display for CliReporter {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- CliReporter::Default => f.write_str("default"),
- CliReporter::GitHub => f.write_str("github"),
- CliReporter::Junit => f.write_str("junit"),
- CliReporter::GitLab => f.write_str("gitlab"),
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, Bpaf)]
-pub enum MaxDiagnostics {
- None,
- Limit(u32),
-}
-
-impl MaxDiagnostics {
- pub fn ok(&self) -> Option {
- match self {
- MaxDiagnostics::None => None,
- MaxDiagnostics::Limit(value) => Some(*value),
- }
- }
-}
-
-impl Default for MaxDiagnostics {
- fn default() -> Self {
- Self::Limit(20)
- }
-}
-
-impl Display for MaxDiagnostics {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- MaxDiagnostics::None => {
- write!(f, "none")
- }
- MaxDiagnostics::Limit(value) => {
- write!(f, "{value}")
- }
- }
- }
-}
-
-impl FromStr for MaxDiagnostics {
- type Err = String;
- fn from_str(s: &str) -> Result {
- match s {
- "none" => Ok(MaxDiagnostics::None),
- _ => {
- if let Ok(value) = s.parse::() {
- Ok(MaxDiagnostics::Limit(value))
- } else {
- Err(format!(
- "Invalid value provided. Provide 'none' to lift the limit, or a number between 0 and {}.",
- u32::MAX
- ))
- }
- }
- }
- }
-}
-
-impl From for u64 {
- fn from(value: MaxDiagnostics) -> Self {
- match value {
- MaxDiagnostics::None => u64::MAX,
- MaxDiagnostics::Limit(value) => value as u64,
- }
- }
-}
-
-impl From for u32 {
- fn from(value: MaxDiagnostics) -> Self {
- match value {
- MaxDiagnostics::None => u32::MAX,
- MaxDiagnostics::Limit(value) => value,
- }
- }
-}
diff --git a/crates/pgt_cli/src/commands/check.rs b/crates/pgt_cli/src/commands/check.rs
deleted file mode 100644
index 46819624..00000000
--- a/crates/pgt_cli/src/commands/check.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use crate::cli_options::CliOptions;
-use crate::{CliDiagnostic, Execution, TraversalMode};
-use biome_deserialize::Merge;
-use pgt_configuration::PartialConfiguration;
-use pgt_console::Console;
-use pgt_fs::FileSystem;
-use pgt_workspace::{DynRef, Workspace, WorkspaceError, configuration::LoadedConfiguration};
-use std::ffi::OsString;
-
-use super::{CommandRunner, get_files_to_process_with_cli_options};
-
-pub(crate) struct CheckCommandPayload {
- pub(crate) configuration: Option,
- pub(crate) paths: Vec,
- pub(crate) stdin_file_path: Option,
- pub(crate) staged: bool,
- pub(crate) changed: bool,
- pub(crate) since: Option,
-}
-
-impl CommandRunner for CheckCommandPayload {
- const COMMAND_NAME: &'static str = "check";
-
- fn merge_configuration(
- &mut self,
- loaded_configuration: LoadedConfiguration,
- _fs: &DynRef<'_, dyn FileSystem>,
- _console: &mut dyn Console,
- ) -> Result {
- let LoadedConfiguration {
- configuration: mut fs_configuration,
- ..
- } = loaded_configuration;
-
- if let Some(configuration) = self.configuration.clone() {
- // overwrite fs config with cli args
- fs_configuration.merge_with(configuration);
- }
-
- Ok(fs_configuration)
- }
-
- fn get_files_to_process(
- &self,
- fs: &DynRef<'_, dyn FileSystem>,
- configuration: &PartialConfiguration,
- ) -> Result, CliDiagnostic> {
- let paths = get_files_to_process_with_cli_options(
- self.since.as_deref(),
- self.changed,
- self.staged,
- fs,
- configuration,
- )?
- .unwrap_or(self.paths.clone());
-
- Ok(paths)
- }
-
- fn get_stdin_file_path(&self) -> Option<&str> {
- self.stdin_file_path.as_deref()
- }
-
- fn get_execution(
- &self,
- cli_options: &CliOptions,
- console: &mut dyn Console,
- _workspace: &dyn Workspace,
- ) -> Result {
- Ok(Execution::new(TraversalMode::Check {
- stdin: self.get_stdin(console)?,
- vcs_targeted: (self.staged, self.changed).into(),
- })
- .set_report(cli_options))
- }
-}
diff --git a/crates/pgt_cli/src/commands/clean.rs b/crates/pgt_cli/src/commands/clean.rs
deleted file mode 100644
index e401f307..00000000
--- a/crates/pgt_cli/src/commands/clean.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::commands::daemon::default_pgt_log_path;
-use crate::{CliDiagnostic, CliSession};
-use pgt_flags::pgt_env;
-use std::fs::{create_dir, remove_dir_all};
-use std::path::PathBuf;
-
-/// Runs the clean command
-pub fn clean(_cli_session: CliSession) -> Result<(), CliDiagnostic> {
- let logs_path = pgt_env()
- .pgt_log_path
- .value()
- .map_or(default_pgt_log_path(), PathBuf::from);
- remove_dir_all(logs_path.clone()).and_then(|_| create_dir(logs_path))?;
- Ok(())
-}
diff --git a/crates/pgt_cli/src/commands/daemon.rs b/crates/pgt_cli/src/commands/daemon.rs
deleted file mode 100644
index 988286f4..00000000
--- a/crates/pgt_cli/src/commands/daemon.rs
+++ /dev/null
@@ -1,295 +0,0 @@
-use crate::{
- CliDiagnostic, CliSession, open_transport,
- service::{self, ensure_daemon, open_socket, run_daemon},
-};
-use pgt_console::{ConsoleExt, markup};
-use pgt_lsp::ServerFactory;
-use pgt_workspace::{TransportError, WorkspaceError, workspace::WorkspaceClient};
-use std::{env, path::PathBuf};
-use tokio::io;
-use tokio::runtime::Runtime;
-use tracing::subscriber::Interest;
-use tracing::{Instrument, Metadata, debug_span, metadata::LevelFilter};
-use tracing_appender::rolling::Rotation;
-use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
-use tracing_subscriber::{
- layer::{Context, Filter},
- prelude::*,
- registry,
-};
-use tracing_tree::{HierarchicalLayer, time::UtcDateTime};
-
-pub(crate) fn start(
- session: CliSession,
- config_path: Option,
- log_path: Option,
- log_file_name_prefix: Option,
-) -> Result<(), CliDiagnostic> {
- let rt = Runtime::new()?;
- let did_spawn = rt.block_on(ensure_daemon(
- false,
- config_path,
- log_path,
- log_file_name_prefix,
- ))?;
-
- if did_spawn {
- session.app.console.log(markup! {
- "The server was successfully started"
- });
- } else {
- session.app.console.log(markup! {
- "The server was already running"
- });
- }
-
- Ok(())
-}
-
-pub(crate) fn stop(session: CliSession) -> Result<(), CliDiagnostic> {
- let rt = Runtime::new()?;
-
- match open_transport(rt)? {
- Some(transport) => {
- let client = WorkspaceClient::new(transport)?;
- match client.shutdown() {
- // The `ChannelClosed` error is expected since the server can
- // shutdown before sending a response
- Ok(()) | Err(WorkspaceError::TransportError(TransportError::ChannelClosed)) => {}
- Err(err) => return Err(CliDiagnostic::from(err)),
- };
-
- session.app.console.log(markup! {
- "The server was successfully stopped"
- });
- }
- _ => {
- session.app.console.log(markup! {
- "The server was not running"
- });
- }
- }
-
- Ok(())
-}
-
-pub(crate) fn run_server(
- stop_on_disconnect: bool,
- config_path: Option,
- log_path: Option,
- log_file_name_prefix: Option,
- log_level: Option,
- log_kind: Option,
-) -> Result<(), CliDiagnostic> {
- setup_tracing_subscriber(log_path, log_file_name_prefix, log_level, log_kind);
-
- let rt = Runtime::new()?;
- let factory = ServerFactory::new(stop_on_disconnect);
- let cancellation = factory.cancellation();
- let span = debug_span!("Running Server", pid = std::process::id());
-
- rt.block_on(async move {
- tokio::select! {
- res = run_daemon(factory, config_path).instrument(span) => {
- match res {
- Ok(never) => match never {},
- Err(err) => Err(err.into()),
- }
- }
- _ = cancellation.notified() => {
- tracing::info!("Received shutdown signal");
- Ok(())
- }
- }
- })
-}
-
-pub(crate) fn print_socket() -> Result<(), CliDiagnostic> {
- let rt = Runtime::new()?;
- rt.block_on(service::print_socket())?;
- Ok(())
-}
-
-pub(crate) fn lsp_proxy(
- config_path: Option,
- log_path: Option,
- log_file_name_prefix: Option,
-) -> Result<(), CliDiagnostic> {
- let rt = Runtime::new()?;
- rt.block_on(start_lsp_proxy(
- &rt,
- config_path,
- log_path,
- log_file_name_prefix,
- ))?;
-
- Ok(())
-}
-
-/// Start a proxy process.
-/// Receives a process via `stdin` and then copy the content to the LSP socket.
-/// Copy to the process on `stdout` when the LSP responds to a message
-async fn start_lsp_proxy(
- rt: &Runtime,
- config_path: Option,
- log_path: Option,
- log_file_name_prefix: Option,
-) -> Result<(), CliDiagnostic> {
- ensure_daemon(true, config_path, log_path, log_file_name_prefix).await?;
-
- match open_socket().await? {
- Some((mut owned_read_half, mut owned_write_half)) => {
- // forward stdin to socket
- let mut stdin = io::stdin();
- let input_handle = rt.spawn(async move {
- loop {
- match io::copy(&mut stdin, &mut owned_write_half).await {
- Ok(b) => {
- if b == 0 {
- return Ok(());
- }
- }
- Err(err) => return Err(err),
- };
- }
- });
-
- // receive socket response to stdout
- let mut stdout = io::stdout();
- let out_put_handle = rt.spawn(async move {
- loop {
- match io::copy(&mut owned_read_half, &mut stdout).await {
- Ok(b) => {
- if b == 0 {
- return Ok(());
- }
- }
- Err(err) => return Err(err),
- };
- }
- });
-
- let _ = input_handle.await;
- let _ = out_put_handle.await;
- Ok(())
- }
- None => Ok(()),
- }
-}
-
-/// Set up the [tracing]-based logging system for the server
-/// The events received by the subscriber are filtered at the `info` level,
-/// then printed using the [HierarchicalLayer] layer, and the resulting text
-/// is written to log files rotated on a hourly basis (in
-/// `pgt-logs/server.log.yyyy-MM-dd-HH` files inside the system temporary
-/// directory)
-fn setup_tracing_subscriber(
- log_path: Option,
- log_file_name_prefix: Option,
- log_level: Option,
- log_kind: Option,
-) {
- let pgt_log_path = log_path.unwrap_or(pgt_fs::ensure_cache_dir().join("pgt-logs"));
-
- let appender_builder = tracing_appender::rolling::RollingFileAppender::builder();
-
- let file_appender = appender_builder
- .filename_prefix(log_file_name_prefix.unwrap_or(String::from("server.log")))
- .max_log_files(7)
- .rotation(Rotation::HOURLY)
- .build(pgt_log_path)
- .expect("Failed to start the logger for the daemon.");
-
- let filter = PgtLoggingFilter::from(log_level);
-
- let log_kind = log_kind.unwrap_or("hierarchical".into());
-
- match log_kind.as_str() {
- "bunyan" => {
- registry()
- .with(JsonStorageLayer)
- .with(
- BunyanFormattingLayer::new("pgt_logs".into(), file_appender)
- .with_filter(filter),
- )
- .init();
- }
-
- _ => registry()
- .with(
- HierarchicalLayer::default()
- .with_indent_lines(true)
- .with_indent_amount(2)
- .with_bracketed_fields(true)
- .with_targets(true)
- .with_ansi(false)
- .with_timer(UtcDateTime {
- higher_precision: false,
- })
- .with_writer(file_appender)
- .with_filter(filter),
- )
- .init(),
- }
-}
-
-pub fn default_pgt_log_path() -> PathBuf {
- match env::var_os("PGT_LOG_PATH") {
- Some(directory) => PathBuf::from(directory),
- None => pgt_fs::ensure_cache_dir().join("pgt-logs"),
- }
-}
-
-/// Tracing Filter with two rules:
-/// For all crates starting with pgt*, use `PGT_LOG_LEVEL` or CLI option or "info" as default
-/// For all other crates, use "info"
-struct PgtLoggingFilter(LevelFilter);
-
-impl From> for PgtLoggingFilter {
- fn from(value: Option) -> Self {
- Self(
- value
- .map(|lv_filter| match lv_filter.as_str() {
- "trace" => LevelFilter::TRACE,
- "debug" => LevelFilter::DEBUG,
- "info" => LevelFilter::INFO,
- "warn" => LevelFilter::WARN,
- "error" => LevelFilter::ERROR,
- "off" => LevelFilter::OFF,
-
- _ => LevelFilter::INFO,
- })
- .unwrap_or(LevelFilter::INFO),
- )
- }
-}
-
-impl PgtLoggingFilter {
- fn is_enabled(&self, meta: &Metadata<'_>) -> bool {
- let filter = if meta.target().starts_with("pgt") {
- self.0
- } else {
- LevelFilter::INFO
- };
-
- meta.level() <= &filter
- }
-}
-
-impl Filter for PgtLoggingFilter {
- fn enabled(&self, meta: &Metadata<'_>, _cx: &Context<'_, S>) -> bool {
- self.is_enabled(meta)
- }
-
- fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
- if self.is_enabled(meta) {
- Interest::always()
- } else {
- Interest::never()
- }
- }
-
- fn max_level_hint(&self) -> Option {
- Some(self.0)
- }
-}
diff --git a/crates/pgt_cli/src/commands/init.rs b/crates/pgt_cli/src/commands/init.rs
deleted file mode 100644
index 15b1b8a5..00000000
--- a/crates/pgt_cli/src/commands/init.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::{CliDiagnostic, CliSession};
-use pgt_configuration::PartialConfiguration;
-use pgt_console::{ConsoleExt, markup};
-use pgt_fs::ConfigName;
-use pgt_workspace::configuration::create_config;
-
-pub(crate) fn init(mut session: CliSession) -> Result<(), CliDiagnostic> {
- let fs = &mut session.app.fs;
- let config = &mut PartialConfiguration::init();
- create_config(fs, config)?;
- let file_created = ConfigName::pgt_jsonc();
- session.app.console.log(markup! {
-"
-Welcome to the Postgres Language Tools! Let's get you started...
-
-""Files created " "
-
- ""- " {file_created} "
- Your project configuration.
-"
- });
- Ok(())
-}
diff --git a/crates/pgt_cli/src/commands/mod.rs b/crates/pgt_cli/src/commands/mod.rs
deleted file mode 100644
index ebd16e3d..00000000
--- a/crates/pgt_cli/src/commands/mod.rs
+++ /dev/null
@@ -1,414 +0,0 @@
-use crate::changed::{get_changed_files, get_staged_files};
-use crate::cli_options::{CliOptions, CliReporter, ColorsArg, cli_options};
-use crate::execute::Stdin;
-use crate::logging::LoggingKind;
-use crate::{
- CliDiagnostic, CliSession, Execution, LoggingLevel, VERSION, execute_mode, setup_cli_subscriber,
-};
-use bpaf::Bpaf;
-use pgt_configuration::{PartialConfiguration, partial_configuration};
-use pgt_console::Console;
-use pgt_fs::FileSystem;
-use pgt_workspace::configuration::{LoadedConfiguration, load_configuration};
-use pgt_workspace::settings::PartialConfigurationExt;
-use pgt_workspace::workspace::UpdateSettingsParams;
-use pgt_workspace::{DynRef, Workspace, WorkspaceError};
-use std::ffi::OsString;
-use std::path::PathBuf;
-pub(crate) mod check;
-pub(crate) mod clean;
-pub(crate) mod daemon;
-pub(crate) mod init;
-pub(crate) mod version;
-
-#[derive(Debug, Clone, Bpaf)]
-#[bpaf(options, version(VERSION))]
-#[allow(clippy::large_enum_variant)]
-/// Postgres Tools official CLI. Use it to check the health of your project or run it to check single files.
-pub enum PgtCommand {
- /// Shows the version information and quit.
- #[bpaf(command)]
- Version(#[bpaf(external(cli_options), hide_usage)] CliOptions),
-
- /// Runs everything to the requested files.
- #[bpaf(command)]
- Check {
- #[bpaf(external(partial_configuration), hide_usage, optional)]
- configuration: Option,
-
- #[bpaf(external, hide_usage)]
- cli_options: CliOptions,
-
- /// Use this option when you want to format code piped from `stdin`, and print the output to `stdout`.
- ///
- /// The file doesn't need to exist on disk, what matters is the extension of the file. Based on the extension, we know how to check the code.
- ///
- /// Example: `echo 'let a;' | pgt_cli check --stdin-file-path=test.sql`
- #[bpaf(long("stdin-file-path"), argument("PATH"), hide_usage)]
- stdin_file_path: Option,
-
- /// When set to true, only the files that have been staged (the ones prepared to be committed)
- /// will be linted. This option should be used when working locally.
- #[bpaf(long("staged"), switch)]
- staged: bool,
-
- /// When set to true, only the files that have been changed compared to your `defaultBranch`
- /// configuration will be linted. This option should be used in CI environments.
- #[bpaf(long("changed"), switch)]
- changed: bool,
-
- /// Use this to specify the base branch to compare against when you're using the --changed
- /// flag and the `defaultBranch` is not set in your `postgrestools.jsonc`
- #[bpaf(long("since"), argument("REF"))]
- since: Option,
-
- /// Single file, single path or list of paths
- #[bpaf(positional("PATH"), many)]
- paths: Vec,
- },
-
- /// Starts the daemon server process.
- #[bpaf(command)]
- Start {
- /// Allows to change the prefix applied to the file name of the logs.
- #[bpaf(
- env("PGT_LOG_PREFIX_NAME"),
- long("log-prefix-name"),
- argument("STRING"),
- hide_usage,
- fallback(String::from("server.log")),
- display_fallback
- )]
- log_prefix_name: String,
-
- /// Allows to change the folder where logs are stored.
- #[bpaf(
- env("PGT_LOG_PATH"),
- long("log-path"),
- argument("PATH"),
- hide_usage,
- fallback(pgt_fs::ensure_cache_dir().join("pgt-logs")),
- )]
- log_path: PathBuf,
- /// Allows to set a custom file path to the configuration file,
- /// or a custom directory path to find `postgrestools.jsonc`
- #[bpaf(env("PGT_LOG_PREFIX_NAME"), long("config-path"), argument("PATH"))]
- config_path: Option,
- },
-
- /// Stops the daemon server process.
- #[bpaf(command)]
- Stop,
-
- /// Bootstraps a new project. Creates a configuration file with some defaults.
- #[bpaf(command)]
- Init,
-
- /// Acts as a server for the Language Server Protocol over stdin/stdout.
- #[bpaf(command("lsp-proxy"))]
- LspProxy {
- /// Allows to change the prefix applied to the file name of the logs.
- #[bpaf(
- env("PGT_LOG_PREFIX_NAME"),
- long("log-prefix-name"),
- argument("STRING"),
- hide_usage,
- fallback(String::from("server.log")),
- display_fallback
- )]
- log_prefix_name: String,
- /// Allows to change the folder where logs are stored.
- #[bpaf(
- env("PGT_LOG_PATH"),
- long("log-path"),
- argument("PATH"),
- hide_usage,
- fallback(pgt_fs::ensure_cache_dir().join("pgt-logs")),
- )]
- log_path: PathBuf,
- /// Allows to set a custom file path to the configuration file,
- /// or a custom directory path to find `postgrestools.jsonc`
- #[bpaf(env("PGT_CONFIG_PATH"), long("config-path"), argument("PATH"))]
- config_path: Option,
- /// Bogus argument to make the command work with vscode-languageclient
- #[bpaf(long("stdio"), hide, hide_usage, switch)]
- stdio: bool,
- },
-
- #[bpaf(command)]
- /// Cleans the logs emitted by the daemon.
- Clean,
-
- #[bpaf(command("__run_server"), hide)]
- RunServer {
- /// Allows to change the prefix applied to the file name of the logs.
- #[bpaf(
- env("PGT_LOG_PREFIX_NAME"),
- long("log-prefix-name"),
- argument("STRING"),
- hide_usage,
- fallback(String::from("server.log")),
- display_fallback
- )]
- log_prefix_name: String,
-
- /// Allows to change the folder where logs are stored.
- #[bpaf(
- env("PGT_LOG_PATH"),
- long("log-path"),
- argument("PATH"),
- hide_usage,
- fallback(pgt_fs::ensure_cache_dir().join("pgt-logs")),
- )]
- log_path: PathBuf,
-
- /// Allows to change the log level. Default is debug. This will only affect "pgt*" crates. All others are logged with info level.
- #[bpaf(
- env("PGT_LOG_LEVEL"),
- long("log-level"),
- argument("trace|debug|info|warn|error|none"),
- fallback(String::from("debug"))
- )]
- log_level: String,
-
- /// Allows to change the logging format kind. Default is hierarchical.
- #[bpaf(
- env("PGT_LOG_KIND"),
- long("log-kind"),
- argument("hierarchical|bunyan"),
- fallback(String::from("hierarchical"))
- )]
- log_kind: String,
-
- #[bpaf(long("stop-on-disconnect"), hide_usage)]
- stop_on_disconnect: bool,
- /// Allows to set a custom file path to the configuration file,
- /// or a custom directory path to find `postgrestools.jsonc`
- #[bpaf(env("PGT_CONFIG_PATH"), long("config-path"), argument("PATH"))]
- config_path: Option,
- },
- #[bpaf(command("__print_socket"), hide)]
- PrintSocket,
-}
-
-impl PgtCommand {
- const fn cli_options(&self) -> Option<&CliOptions> {
- match self {
- PgtCommand::Version(cli_options) | PgtCommand::Check { cli_options, .. } => {
- Some(cli_options)
- }
- PgtCommand::LspProxy { .. }
- | PgtCommand::Start { .. }
- | PgtCommand::Stop
- | PgtCommand::Init
- | PgtCommand::RunServer { .. }
- | PgtCommand::Clean
- | PgtCommand::PrintSocket => None,
- }
- }
-
- pub const fn get_color(&self) -> Option<&ColorsArg> {
- match self.cli_options() {
- Some(cli_options) => {
- // To properly display GitHub annotations we need to disable colors
- if matches!(cli_options.reporter, CliReporter::GitHub) {
- return Some(&ColorsArg::Off);
- }
- // We want force colors in CI, to give e better UX experience
- // Unless users explicitly set the colors flag
- // if matches!(self, Postgres ToolsCommand::Ci { .. }) && cli_options.colors.is_none() {
- // return Some(&ColorsArg::Force);
- // }
- // Normal behaviors
- cli_options.colors.as_ref()
- }
- None => None,
- }
- }
-
- pub const fn should_use_server(&self) -> bool {
- match self.cli_options() {
- Some(cli_options) => cli_options.use_server,
- None => false,
- }
- }
-
- pub const fn has_metrics(&self) -> bool {
- false
- }
-
- pub fn is_verbose(&self) -> bool {
- self.cli_options()
- .is_some_and(|cli_options| cli_options.verbose)
- }
-
- pub fn log_level(&self) -> LoggingLevel {
- self.cli_options()
- .map_or(LoggingLevel::default(), |cli_options| cli_options.log_level)
- }
-
- pub fn log_kind(&self) -> LoggingKind {
- self.cli_options()
- .map_or(LoggingKind::default(), |cli_options| cli_options.log_kind)
- }
-}
-
-/// Generic interface for executing commands.
-///
-/// Consumers must implement the following methods:
-///
-/// - [CommandRunner::merge_configuration]
-/// - [CommandRunner::get_files_to_process]
-/// - [CommandRunner::get_stdin_file_path]
-/// - [CommandRunner::should_write]
-/// - [CommandRunner::get_execution]
-///
-/// Optional methods:
-/// - [CommandRunner::check_incompatible_arguments]
-pub(crate) trait CommandRunner: Sized {
- const COMMAND_NAME: &'static str;
-
- /// The main command to use.
- fn run(&mut self, session: CliSession, cli_options: &CliOptions) -> Result<(), CliDiagnostic> {
- setup_cli_subscriber(cli_options.log_level, cli_options.log_kind);
- let fs = &session.app.fs;
- let console = &mut *session.app.console;
- let workspace = &*session.app.workspace;
- self.check_incompatible_arguments()?;
- let (execution, paths) = self.configure_workspace(fs, console, workspace, cli_options)?;
- execute_mode(execution, session, cli_options, paths)
- }
-
- /// This function prepares the workspace with the following:
- /// - Loading the configuration file.
- /// - Configure the VCS integration
- /// - Computes the paths to traverse/handle. This changes based on the VCS arguments that were passed.
- /// - Register a project folder using the working directory.
- /// - Updates the settings that belong to the project registered
- fn configure_workspace(
- &mut self,
- fs: &DynRef<'_, dyn FileSystem>,
- console: &mut dyn Console,
- workspace: &dyn Workspace,
- cli_options: &CliOptions,
- ) -> Result<(Execution, Vec), CliDiagnostic> {
- let loaded_configuration =
- load_configuration(fs, cli_options.as_configuration_path_hint())?;
-
- let configuration_path = loaded_configuration.directory_path.clone();
- let configuration = self.merge_configuration(loaded_configuration, fs, console)?;
- let vcs_base_path = configuration_path.or(fs.working_directory());
- let (vcs_base_path, gitignore_matches) =
- configuration.retrieve_gitignore_matches(fs, vcs_base_path.as_deref())?;
- let paths = self.get_files_to_process(fs, &configuration)?;
-
- workspace.update_settings(UpdateSettingsParams {
- workspace_directory: fs.working_directory(),
- configuration,
- vcs_base_path,
- gitignore_matches,
- })?;
-
- let execution = self.get_execution(cli_options, console, workspace)?;
- Ok((execution, paths))
- }
-
- /// Computes [Stdin] if the CLI has the necessary information.
- ///
- /// ## Errors
- /// - If the user didn't provide anything via `stdin` but the option `--stdin-file-path` is passed.
- fn get_stdin(&self, console: &mut dyn Console) -> Result, CliDiagnostic> {
- let stdin = if let Some(stdin_file_path) = self.get_stdin_file_path() {
- let input_code = console.read();
- if let Some(input_code) = input_code {
- let path = PathBuf::from(stdin_file_path);
- Some((path, input_code).into())
- } else {
- // we provided the argument without a piped stdin, we bail
- return Err(CliDiagnostic::missing_argument("stdin", Self::COMMAND_NAME));
- }
- } else {
- None
- };
-
- Ok(stdin)
- }
-
- // Below, the methods that consumers must implement.
-
- /// Implements this method if you need to merge CLI arguments to the loaded configuration.
- ///
- /// The CLI arguments take precedence over the option configured in the configuration file.
- fn merge_configuration(
- &mut self,
- loaded_configuration: LoadedConfiguration,
- fs: &DynRef<'_, dyn FileSystem>,
- console: &mut dyn Console,
- ) -> Result;
-
- /// It returns the paths that need to be handled/traversed.
- fn get_files_to_process(
- &self,
- fs: &DynRef<'_, dyn FileSystem>,
- configuration: &PartialConfiguration,
- ) -> Result, CliDiagnostic>;
-
- /// It returns the file path to use in `stdin` mode.
- fn get_stdin_file_path(&self) -> Option<&str>;
-
- /// Returns the [Execution] mode.
- fn get_execution(
- &self,
- cli_options: &CliOptions,
- console: &mut dyn Console,
- workspace: &dyn Workspace,
- ) -> Result;
-
- // Below, methods that consumers can implement
-
- /// Optional method that can be implemented to check if some CLI arguments aren't compatible.
- ///
- /// The method is called before loading the configuration from disk.
- fn check_incompatible_arguments(&self) -> Result<(), CliDiagnostic> {
- Ok(())
- }
-}
-
-fn get_files_to_process_with_cli_options(
- since: Option<&str>,
- changed: bool,
- staged: bool,
- fs: &DynRef<'_, dyn FileSystem>,
- configuration: &PartialConfiguration,
-) -> Result>, CliDiagnostic> {
- if since.is_some() {
- if !changed {
- return Err(CliDiagnostic::incompatible_arguments("since", "changed"));
- }
- if staged {
- return Err(CliDiagnostic::incompatible_arguments("since", "staged"));
- }
- }
-
- if changed {
- if staged {
- return Err(CliDiagnostic::incompatible_arguments("changed", "staged"));
- }
- Ok(Some(get_changed_files(fs, configuration, since)?))
- } else if staged {
- Ok(Some(get_staged_files(fs)?))
- } else {
- Ok(None)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- /// Tests that all CLI options adhere to the invariants expected by `bpaf`.
- #[test]
- fn check_options() {
- pgt_command().check_invariants(false);
- }
-}
diff --git a/crates/pgt_cli/src/commands/version.rs b/crates/pgt_cli/src/commands/version.rs
deleted file mode 100644
index 685684a3..00000000
--- a/crates/pgt_cli/src/commands/version.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use pgt_console::fmt::Formatter;
-use pgt_console::{ConsoleExt, fmt, markup};
-use pgt_workspace::workspace::ServerInfo;
-
-use crate::{CliDiagnostic, CliSession, VERSION};
-
-/// Handle of the `version` command. Prints a more in detail version.
-pub(crate) fn full_version(session: CliSession) -> Result<(), CliDiagnostic> {
- session.app.console.log(markup! {
- "CLI: "{VERSION}
- });
-
- match session.app.workspace.server_info() {
- None => {
- session.app.console.log(markup! {
- "Server: ""not connected"
- });
- }
- Some(info) => {
- session.app.console.log(markup! {
-"Server:
- Name: "{info.name}"
- Version: "{DisplayServerVersion(info)}
- });
- }
- };
-
- Ok(())
-}
-
-pub(super) struct DisplayServerVersion<'a>(pub &'a ServerInfo);
-
-impl fmt::Display for DisplayServerVersion<'_> {
- fn fmt(&self, fmt: &mut Formatter) -> std::io::Result<()> {
- match &self.0.version {
- None => markup!("-" ).fmt(fmt),
- Some(version) => {
- write!(fmt, "{version}")
- }
- }
- }
-}
diff --git a/crates/pgt_cli/src/diagnostics.rs b/crates/pgt_cli/src/diagnostics.rs
deleted file mode 100644
index d24d02e9..00000000
--- a/crates/pgt_cli/src/diagnostics.rs
+++ /dev/null
@@ -1,462 +0,0 @@
-use pgt_console::markup;
-use pgt_diagnostics::adapters::{BpafError, IoError, SerdeJsonError};
-use pgt_diagnostics::{
- Advices, Category, Diagnostic, Error, LogCategory, MessageAndDescription, Severity, Visit,
-};
-use pgt_workspace::WorkspaceError;
-use std::process::{ExitCode, Termination};
-use std::{env::current_exe, fmt::Debug};
-
-fn command_name() -> String {
- current_exe()
- .ok()
- .and_then(|path| Some(path.file_name()?.to_str()?.to_string()))
- .unwrap_or_else(|| String::from("postgrestools"))
-}
-
-/// A diagnostic that is emitted when running Postgres Tools via CLI.
-///
-/// When displaying the diagnostic,
-#[derive(Debug, Diagnostic)]
-pub enum CliDiagnostic {
- /// Returned when it is called with a subcommand it doesn't know
- UnknownCommand(UnknownCommand),
- /// Return by the help command when it is called with a subcommand it doesn't know
- UnknownCommandHelp(UnknownCommandHelp),
- /// Returned when the value of a command line argument could not be parsed
- ParseError(ParseDiagnostic),
- /// Returned when the CLI doesn't recognize a command line argument
- UnexpectedArgument(UnexpectedArgument),
- /// Returned when a required argument is not present in the command line
- MissingArgument(MissingArgument),
- /// Returned when a subcommand is called without any arguments
- EmptyArguments(EmptyArguments),
- /// Returned when a subcommand is called with an unsupported combination of arguments
- IncompatibleArguments(IncompatibleArguments),
- /// Returned by a traversal command when error diagnostics were emitted
- CheckError(CheckError),
- /// Emitted when a file is fixed, but it still contains diagnostics.
- ///
- /// This happens when these diagnostics come from rules that don't have a code action.
- FileCheck(FileCheck),
- /// When an argument is higher than the expected maximum
- OverflowNumberArgument(OverflowNumberArgument),
- /// Wrapper for an underlying pglt-service error
- WorkspaceError(WorkspaceError),
- /// Wrapper for an underlying `std::io` error
- IoError(IoDiagnostic),
- /// The daemon is not running
- ServerNotRunning(ServerNotRunning),
- /// The end configuration (`postgrestools.jsonc` + other options) is incompatible with the command
- IncompatibleEndConfiguration(IncompatibleEndConfiguration),
- /// No files processed during the file system traversal
- NoFilesWereProcessed(NoFilesWereProcessed),
- /// Emitted during the reporting phase
- Report(ReportDiagnostic),
- /// Emitted when there's an error emitted when using stdin mode
- Stdin(StdinDiagnostic),
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message(
- description = "Unknown command {command_name}",
- message("Unknown command "{self.command_name} )
- ),
-)]
-pub struct UnknownCommand {
- command_name: String,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
-category = "flags/invalid",
- severity = Error,
- message(
- description = "Cannot print help for unknown command {command_name}",
- message("Cannot print help for unknown command "{self.command_name} )
- ),
-)]
-pub struct UnknownCommandHelp {
- command_name: String,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
-)]
-pub struct ParseDiagnostic {
- #[message]
- #[description]
- message: MessageAndDescription,
- #[source]
- source: Option,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message(
- description = "Unrecognized option {argument}",
- message("Unrecognized option "{self.argument} ".")
- ),
-)]
-pub struct UnexpectedArgument {
- argument: String,
- #[advice]
- help: CliAdvice,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message(
- description = "Unrecognized option {argument}",
- message("Missing argument "{self.argument} )
- ),
-)]
-pub struct MissingArgument {
- argument: String,
- #[advice]
- advice: CliAdvice,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message = "Empty arguments"
-)]
-pub struct EmptyArguments;
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message(
- description = "Incompatible arguments {first_argument} and {second_argument}",
- message("Incompatible arguments "{self.first_argument} " and "{self.second_argument} )
- )
-)]
-pub struct IncompatibleArguments {
- first_argument: String,
- second_argument: String,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- severity = Error,
-)]
-pub struct CheckError {
- #[category]
- category: &'static Category,
-
- #[message]
- message: MessageAndDescription,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- severity = Error,
-)]
-pub struct FileCheck {
- #[message]
- #[description]
- pub message: MessageAndDescription,
-
- #[location(resource)]
- pub file_path: String,
-
- #[category]
- pub category: &'static Category,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "flags/invalid",
- severity = Error,
- message(
- description = "The value of the argument {argument} is too high, maximum accepted {maximum}",
- message("The value of the argument "{self.argument} " is too high, maximum accepted "{{self.maximum}})
- )
-)]
-pub struct OverflowNumberArgument {
- argument: String,
- maximum: u16,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "internalError/io",
- severity = Error,
- message = "Errors occurred while executing I/O operations."
-)]
-pub struct IoDiagnostic {
- #[source]
- source: Option,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "internalError/io",
- severity = Error,
- message = "No running instance of the daemon server was found."
-)]
-pub struct ServerNotRunning;
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "internalError/io",
- severity = Error,
- message(
- description = "The combination of configuration and arguments is invalid: \n{reason}",
- message("The combination of configuration and arguments is invalid: \n"{{&self.reason}})
- )
-)]
-pub struct IncompatibleEndConfiguration {
- reason: String,
-}
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(
- category = "internalError/io",
- severity = Error,
- message = "No files were processed in the specified paths."
-)]
-pub struct NoFilesWereProcessed;
-
-#[derive(Debug, Diagnostic)]
-pub enum ReportDiagnostic {
- /// Emitted when trying to serialise the report
- Serialization(SerdeJsonError),
-}
-
-/// Advices for the [CliDiagnostic]
-#[derive(Debug, Default)]
-struct CliAdvice {
- /// Used to print the help command
- sub_command: String,
-}
-
-impl CliAdvice {
- fn new_with_help(sub_command: impl Into) -> Self {
- Self {
- sub_command: sub_command.into(),
- }
- }
-}
-
-impl Advices for CliAdvice {
- fn record(&self, visitor: &mut dyn Visit) -> std::io::Result<()> {
- let command_name = command_name();
- let help_sub_command = format!("{} {} --help", command_name, &self.sub_command);
- visitor.record_log(
- LogCategory::Info,
- &markup! { "Type the following command for more information" },
- )?;
- visitor.record_command(&help_sub_command)?;
-
- Ok(())
- }
-}
-
-impl CliDiagnostic {
- /// Returned when a subcommand is called with an unsupported combination of arguments
- pub fn incompatible_arguments(
- first_argument: impl Into,
- second_argument: impl Into,
- ) -> Self {
- Self::IncompatibleArguments(IncompatibleArguments {
- first_argument: first_argument.into(),
- second_argument: second_argument.into(),
- })
- }
-
- /// To throw when there's been an error while parsing an argument
- pub fn parse_error_bpaf(source: bpaf::ParseFailure) -> Self {
- Self::ParseError(ParseDiagnostic {
- source: Some(Error::from(BpafError::from(source))),
- message: MessageAndDescription::from("Failed to parse CLI arguments.".to_string()),
- })
- }
-
- /// Returned when it is called with a subcommand it doesn't know
- pub fn unknown_command(command: impl Into) -> Self {
- Self::UnknownCommand(UnknownCommand {
- command_name: command.into(),
- })
- }
-
- /// Returned when a subcommand is called without any arguments
- pub fn empty_arguments() -> Self {
- Self::EmptyArguments(EmptyArguments)
- }
-
- /// Returned when a required argument is not present in the command line
- pub fn missing_argument(argument: impl Into, subcommand: impl Into) -> Self {
- Self::MissingArgument(MissingArgument {
- argument: argument.into(),
- advice: CliAdvice::new_with_help(subcommand),
- })
- }
-
- /// When no files were processed while traversing the file system
- pub fn no_files_processed() -> Self {
- Self::NoFilesWereProcessed(NoFilesWereProcessed)
- }
-
- /// Returned when the CLI doesn't recognize a command line argument
- pub fn unexpected_argument(argument: impl Into, subcommand: impl Into) -> Self {
- Self::UnexpectedArgument(UnexpectedArgument {
- argument: argument.into(),
- help: CliAdvice::new_with_help(subcommand),
- })
- }
-
- /// When there's been error inside the workspace
- pub fn workspace_error(error: WorkspaceError) -> Self {
- Self::WorkspaceError(error)
- }
-
- /// An I/O error
- pub fn io_error(error: std::io::Error) -> Self {
- Self::IoError(IoDiagnostic {
- source: Some(Error::from(IoError::from(error))),
- })
- }
-
- /// Emitted when errors were emitted while running `check` command
- pub fn check_error(category: &'static Category) -> Self {
- Self::CheckError(CheckError {
- category,
- message: MessageAndDescription::from(
- markup! {
- "Some ""errors" " were emitted while ""running checks" "."
- }
- .to_owned(),
- ),
- })
- }
-
- /// Emitted when warnings were emitted while running `check` command
- pub fn check_warnings(category: &'static Category) -> Self {
- Self::CheckError(CheckError {
- category,
- message: MessageAndDescription::from(
- markup! {
- "Some ""warnings" " were emitted while ""running checks" "."
- }
- .to_owned(),
- ),
- })
- }
-
- /// Emitted when errors were emitted while apply code fixes
- pub fn apply_error(category: &'static Category) -> Self {
- Self::CheckError(CheckError {
- category,
- message: MessageAndDescription::from(
- markup! {
- "Some ""errors" " were emitted while ""applying fixes" "."
- }
- .to_owned(),
- ),
- })
- }
- /// Emitted when warnings were emitted while apply code fixes
- pub fn apply_warnings(category: &'static Category) -> Self {
- Self::CheckError(CheckError {
- category,
- message: MessageAndDescription::from(
- markup! {
- "Some ""warnings" " were emitted while ""running checks" "."
- }
- .to_owned(),
- ),
- })
- }
-
- pub fn stdin() -> Self {
- Self::Stdin(StdinDiagnostic::default())
- }
-
- /// Emitted when the server is not running
- pub fn server_not_running() -> Self {
- Self::ServerNotRunning(ServerNotRunning)
- }
-
- /// Emitted when the end configuration (`postgrestools.jsonc` file + CLI arguments + LSP configuration)
- /// results in a combination of options that doesn't allow to run the command correctly.
- ///
- /// A reason needs to be provided
- pub fn incompatible_end_configuration(reason: impl Into) -> Self {
- Self::IncompatibleEndConfiguration(IncompatibleEndConfiguration {
- reason: reason.into(),
- })
- }
-
- /// Emitted when an argument value is greater than the allowed value
- pub fn overflown_argument(argument: impl Into, maximum: u16) -> Self {
- Self::OverflowNumberArgument(OverflowNumberArgument {
- argument: argument.into(),
- maximum,
- })
- }
-
- /// Return by the help command when it is called with a subcommand it doesn't know
- pub fn new_unknown_help(command: impl Into) -> Self {
- Self::UnknownCommandHelp(UnknownCommandHelp {
- command_name: command.into(),
- })
- }
-}
-
-impl From for CliDiagnostic {
- fn from(error: WorkspaceError) -> Self {
- CliDiagnostic::workspace_error(error)
- }
-}
-
-impl From for CliDiagnostic {
- fn from(error: std::io::Error) -> Self {
- CliDiagnostic::io_error(error)
- }
-}
-
-impl Termination for CliDiagnostic {
- fn report(self) -> ExitCode {
- let severity = self.severity();
- if severity >= Severity::Error {
- ExitCode::FAILURE
- } else {
- ExitCode::SUCCESS
- }
- }
-}
-
-#[derive(Debug, Default, Diagnostic)]
-#[diagnostic(
- severity = Error,
- category = "stdin",
- message = "The contents aren't fixed. Use the `--fix` flag to fix them."
-)]
-pub struct StdinDiagnostic {}
-
-#[cfg(test)]
-mod test {
- use crate::CliDiagnostic;
-
- #[test]
- fn termination_diagnostic_size() {
- assert_eq!(
- std::mem::size_of::(),
- 80,
- "you successfully decreased the size of the diagnostic!"
- )
- }
-}
diff --git a/crates/pgt_cli/src/execute/diagnostics.rs b/crates/pgt_cli/src/execute/diagnostics.rs
deleted file mode 100644
index a355abec..00000000
--- a/crates/pgt_cli/src/execute/diagnostics.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use pgt_diagnostics::adapters::{IoError, StdError};
-use pgt_diagnostics::{Category, Diagnostic, DiagnosticExt, DiagnosticTags, Error};
-use std::io;
-
-#[derive(Debug, Diagnostic)]
-#[diagnostic(category = "internalError/panic", tags(INTERNAL))]
-pub(crate) struct PanicDiagnostic {
- #[description]
- #[message]
- pub(crate) message: String,
-}
-
-/// Extension trait for turning [Display]-able error types into [TraversalError]
-pub(crate) trait ResultExt {
- type Result;
- fn with_file_path_and_code(
- self,
- file_path: String,
- code: &'static Category,
- ) -> Result;
-
- #[allow(unused)]
- fn with_file_path_and_code_and_tags(
- self,
- file_path: String,
- code: &'static Category,
- tags: DiagnosticTags,
- ) -> Result;
-}
-
-impl ResultExt for Result
-where
- E: std::error::Error + Send + Sync + 'static,
-{
- type Result = T;
-
- fn with_file_path_and_code_and_tags(
- self,
- file_path: String,
- code: &'static Category,
- diagnostic_tags: DiagnosticTags,
- ) -> Result {
- self.map_err(move |err| {
- StdError::from(err)
- .with_category(code)
- .with_file_path(file_path)
- .with_tags(diagnostic_tags)
- })
- }
-
- fn with_file_path_and_code(
- self,
- file_path: String,
- code: &'static Category,
- ) -> Result {
- self.map_err(move |err| {
- StdError::from(err)
- .with_category(code)
- .with_file_path(file_path)
- })
- }
-}
-
-/// Extension trait for turning [io::Error] into [Error]
-pub(crate) trait ResultIoExt: ResultExt {
- fn with_file_path(self, file_path: String) -> Result;
-}
-
-impl ResultIoExt for io::Result {
- fn with_file_path(self, file_path: String) -> Result {
- self.map_err(|error| IoError::from(error).with_file_path(file_path))
- }
-}
diff --git a/crates/pgt_cli/src/execute/mod.rs b/crates/pgt_cli/src/execute/mod.rs
deleted file mode 100644
index 6cb01ca7..00000000
--- a/crates/pgt_cli/src/execute/mod.rs
+++ /dev/null
@@ -1,308 +0,0 @@
-mod diagnostics;
-mod process_file;
-mod std_in;
-pub(crate) mod traverse;
-
-use crate::cli_options::{CliOptions, CliReporter};
-use crate::execute::traverse::{TraverseResult, traverse};
-use crate::reporter::github::{GithubReporter, GithubReporterVisitor};
-use crate::reporter::gitlab::{GitLabReporter, GitLabReporterVisitor};
-use crate::reporter::junit::{JunitReporter, JunitReporterVisitor};
-use crate::reporter::terminal::{ConsoleReporter, ConsoleReporterVisitor};
-use crate::{CliDiagnostic, CliSession, DiagnosticsPayload, Reporter};
-use pgt_diagnostics::{Category, category};
-use std::borrow::Borrow;
-use std::ffi::OsString;
-use std::fmt::{Display, Formatter};
-use std::path::PathBuf;
-use tracing::info;
-
-/// Useful information during the traversal of files and virtual content
-#[derive(Debug, Clone)]
-pub struct Execution {
- /// How the information should be collected and reported
- report_mode: ReportMode,
-
- /// The modality of execution of the traversal
- traversal_mode: TraversalMode,
-
- /// The maximum number of diagnostics that can be printed in console
- max_diagnostics: u32,
-}
-
-impl Execution {
- pub fn report_mode(&self) -> &ReportMode {
- &self.report_mode
- }
-}
-
-/// A type that holds the information to execute the CLI via `stdin
-#[derive(Debug, Clone)]
-pub struct Stdin(
- #[allow(unused)]
- /// The virtual path to the file
- PathBuf,
- /// The content of the file
- String,
-);
-
-impl Stdin {
- fn as_content(&self) -> &str {
- self.1.as_str()
- }
-}
-
-impl From<(PathBuf, String)> for Stdin {
- fn from((path, content): (PathBuf, String)) -> Self {
- Self(path, content)
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct VcsTargeted {
- pub staged: bool,
- pub changed: bool,
-}
-
-impl From<(bool, bool)> for VcsTargeted {
- fn from((staged, changed): (bool, bool)) -> Self {
- Self { staged, changed }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum TraversalMode {
- /// A dummy mode to be used when the CLI is not running any command
- Dummy,
- /// This mode is enabled when running the command `check`
- Check {
- // The type of fixes that should be applied when analyzing a file.
- //
- // It's [None] if the `check` command is called without `--apply` or `--apply-suggested`
- // arguments.
- // fix_file_mode: Option,
- /// An optional tuple.
- /// 1. The virtual path to the file
- /// 2. The content of the file
- stdin: Option,
- /// A flag to know vcs integrated options such as `--staged` or `--changed` are enabled
- vcs_targeted: VcsTargeted,
- },
-}
-
-impl Display for TraversalMode {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- TraversalMode::Dummy => write!(f, "dummy"),
- TraversalMode::Check { .. } => write!(f, "check"),
- }
- }
-}
-
-/// Tells to the execution of the traversal how the information should be reported
-#[derive(Copy, Clone, Debug)]
-pub enum ReportMode {
- /// Reports information straight to the console, it's the default mode
- Terminal,
- /// Reports information for GitHub
- GitHub,
- /// JUnit output
- /// Ref: https://github.com/testmoapp/junitxml?tab=readme-ov-file#basic-junit-xml-structure
- Junit,
- /// Reports information in the [GitLab Code Quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool) format.
- GitLab,
-}
-
-impl Default for ReportMode {
- fn default() -> Self {
- Self::Terminal {}
- }
-}
-
-impl From for ReportMode {
- fn from(value: CliReporter) -> Self {
- match value {
- CliReporter::Default => Self::Terminal,
- CliReporter::GitHub => Self::GitHub,
- CliReporter::Junit => Self::Junit,
- CliReporter::GitLab => Self::GitLab {},
- }
- }
-}
-
-impl Execution {
- pub(crate) fn new(mode: TraversalMode) -> Self {
- Self {
- report_mode: ReportMode::default(),
- traversal_mode: mode,
- max_diagnostics: 20,
- }
- }
-
- /// It sets the reporting mode by reading the [CliOptions]
- pub(crate) fn set_report(mut self, cli_options: &CliOptions) -> Self {
- self.report_mode = cli_options.reporter.clone().into();
- self
- }
-
- pub(crate) fn traversal_mode(&self) -> &TraversalMode {
- &self.traversal_mode
- }
-
- pub(crate) fn get_max_diagnostics(&self) -> u32 {
- self.max_diagnostics
- }
-
- pub(crate) fn as_diagnostic_category(&self) -> &'static Category {
- match self.traversal_mode {
- TraversalMode::Dummy => category!("dummy"),
- TraversalMode::Check { .. } => category!("check"),
- }
- }
-
- /// Whether the traversal mode requires write access to files
- pub(crate) const fn requires_write_access(&self) -> bool {
- match self.traversal_mode {
- TraversalMode::Dummy => false,
- TraversalMode::Check { .. } => false,
- }
- }
-
- pub(crate) fn as_stdin_file(&self) -> Option<&Stdin> {
- match &self.traversal_mode {
- TraversalMode::Dummy => None,
- TraversalMode::Check { stdin, .. } => stdin.as_ref(),
- }
- }
-
- pub(crate) fn is_vcs_targeted(&self) -> bool {
- match &self.traversal_mode {
- TraversalMode::Dummy => false,
- TraversalMode::Check { vcs_targeted, .. } => {
- vcs_targeted.staged || vcs_targeted.changed
- }
- }
- }
-
- pub(crate) const fn is_check_apply(&self) -> bool {
- false
- }
-
- #[allow(unused)]
- /// Returns [true] if the user used the `--write`/`--fix` option
- pub(crate) fn is_write(&self) -> bool {
- match self.traversal_mode {
- TraversalMode::Dummy => false,
- TraversalMode::Check { .. } => false,
- }
- }
-}
-
-/// Based on the [mode](TraversalMode), the function might launch a traversal of the file system
-/// or handles the stdin file.
-pub fn execute_mode(
- mut execution: Execution,
- mut session: CliSession,
- cli_options: &CliOptions,
- paths: Vec,
-) -> Result<(), CliDiagnostic> {
- // If a custom reporter was provided, let's lift the limit so users can see all of them
- execution.max_diagnostics = if cli_options.reporter.is_default() {
- cli_options.max_diagnostics.into()
- } else {
- info!(
- "Removing the limit of --max-diagnostics, because of a reporter different from the default one: {}",
- cli_options.reporter
- );
- u32::MAX
- };
-
- // don't do any traversal if there's some content coming from stdin
- if let Some(stdin) = execution.as_stdin_file() {
- std_in::run(session, stdin.as_content())
- } else {
- let TraverseResult {
- summary,
- evaluated_paths,
- diagnostics,
- } = traverse(&execution, &mut session, cli_options, paths)?;
- let console = session.app.console;
- let errors = summary.errors;
- let skipped = summary.skipped;
- let processed = summary.changed + summary.unchanged;
- let should_exit_on_warnings = summary.warnings > 0 && cli_options.error_on_warnings;
-
- match execution.report_mode {
- ReportMode::Terminal => {
- let reporter = ConsoleReporter {
- summary,
- diagnostics_payload: DiagnosticsPayload {
- verbose: cli_options.verbose,
- diagnostic_level: cli_options.diagnostic_level,
- diagnostics,
- },
- execution: execution.clone(),
- evaluated_paths,
- };
- reporter.write(&mut ConsoleReporterVisitor(console))?;
- }
- ReportMode::GitHub => {
- let reporter = GithubReporter {
- diagnostics_payload: DiagnosticsPayload {
- verbose: cli_options.verbose,
- diagnostic_level: cli_options.diagnostic_level,
- diagnostics,
- },
- execution: execution.clone(),
- };
- reporter.write(&mut GithubReporterVisitor(console))?;
- }
- ReportMode::GitLab => {
- let reporter = GitLabReporter {
- diagnostics: DiagnosticsPayload {
- verbose: cli_options.verbose,
- diagnostic_level: cli_options.diagnostic_level,
- diagnostics,
- },
- execution: execution.clone(),
- };
- reporter.write(&mut GitLabReporterVisitor::new(
- console,
- session.app.fs.borrow().working_directory(),
- ))?;
- }
- ReportMode::Junit => {
- let reporter = JunitReporter {
- summary,
- diagnostics_payload: DiagnosticsPayload {
- verbose: cli_options.verbose,
- diagnostic_level: cli_options.diagnostic_level,
- diagnostics,
- },
- execution: execution.clone(),
- };
- reporter.write(&mut JunitReporterVisitor::new(console))?;
- }
- }
-
- // Processing emitted error diagnostics, exit with a non-zero code
- if processed.saturating_sub(skipped) == 0 && !cli_options.no_errors_on_unmatched {
- Err(CliDiagnostic::no_files_processed())
- } else if errors > 0 || should_exit_on_warnings {
- let category = execution.as_diagnostic_category();
- if should_exit_on_warnings {
- if execution.is_check_apply() {
- Err(CliDiagnostic::apply_warnings(category))
- } else {
- Err(CliDiagnostic::check_warnings(category))
- }
- } else if execution.is_check_apply() {
- Err(CliDiagnostic::apply_error(category))
- } else {
- Err(CliDiagnostic::check_error(category))
- }
- } else {
- Ok(())
- }
- }
-}
diff --git a/crates/pgt_cli/src/execute/process_file.rs b/crates/pgt_cli/src/execute/process_file.rs
deleted file mode 100644
index 421f9bb3..00000000
--- a/crates/pgt_cli/src/execute/process_file.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-mod check;
-pub(crate) mod workspace_file;
-
-use crate::execute::TraversalMode;
-use crate::execute::traverse::TraversalOptions;
-use check::check_file;
-use pgt_diagnostics::Error;
-use pgt_fs::PgTPath;
-use std::marker::PhantomData;
-use std::ops::Deref;
-
-#[derive(Debug)]
-pub(crate) enum FileStatus {
- /// File changed and it was a success
- Changed,
- /// File unchanged, and it was a success
- Unchanged,
-
- /// While handling the file, something happened
- #[allow(unused)]
- Message(Message),
-
- /// A match was found while searching a file
- #[allow(unused)]
- SearchResult(usize, Message),
-
- /// File ignored, it should not be count as "handled"
- #[allow(unused)]
- Ignored,
-
- /// Files that belong to other tools and shouldn't be touched
- #[allow(unused)]
- Protected(String),
-}
-
-/// Wrapper type for messages that can be printed during the traversal process
-#[derive(Debug)]
-pub(crate) enum Message {
- #[allow(unused)]
- SkippedFixes {
- /// Suggested fixes skipped during the lint traversal
- skipped_suggested_fixes: u32,
- },
-
- #[allow(unused)]
- Failure,
- Error(Error),
- Diagnostics {
- name: String,
- content: String,
- diagnostics: Vec,
- skipped_diagnostics: u32,
- },
-}
-
-impl From for Message
-where
- Error: From,
- D: std::fmt::Debug,
-{
- fn from(err: D) -> Self {
- Self::Error(Error::from(err))
- }
-}
-
-/// The return type for [process_file], with the following semantics:
-/// - `Ok(Success)` means the operation was successful (the file is added to
-/// the `processed` counter)
-/// - `Ok(Message(_))` means the operation was successful but a message still
-/// needs to be printed (eg. the diff when not in CI or write mode)
-/// - `Ok(Ignored)` means the file was ignored (the file is not added to the
-/// `processed` or `skipped` counters)
-/// - `Err(_)` means the operation failed and the file should be added to the
-/// `skipped` counter
-pub(crate) type FileResult = Result;
-
-/// Data structure that allows to pass [TraversalOptions] to multiple consumers, bypassing the
-/// compiler constraints set by the lifetimes of the [TraversalOptions]
-pub(crate) struct SharedTraversalOptions<'ctx, 'app> {
- inner: &'app TraversalOptions<'ctx, 'app>,
- _p: PhantomData<&'app ()>,
-}
-
-impl<'ctx, 'app> SharedTraversalOptions<'ctx, 'app> {
- fn new(t: &'app TraversalOptions<'ctx, 'app>) -> Self {
- Self {
- _p: PhantomData,
- inner: t,
- }
- }
-}
-
-impl<'ctx, 'app> Deref for SharedTraversalOptions<'ctx, 'app> {
- type Target = TraversalOptions<'ctx, 'app>;
-
- fn deref(&self) -> &Self::Target {
- self.inner
- }
-}
-
-/// This function performs the actual processing: it reads the file from disk
-/// and parse it; analyze and / or format it; then it either fails if error
-/// diagnostics were emitted, or compare the formatted code with the original
-/// content of the file and emit a diff or write the new content to the disk if
-/// write mode is enabled
-pub(crate) fn process_file(ctx: &TraversalOptions, pgt_path: &PgTPath) -> FileResult {
- tracing::trace_span!("process_file", path = ?pgt_path).in_scope(move || {
- let shared_context = &SharedTraversalOptions::new(ctx);
-
- match ctx.execution.traversal_mode {
- TraversalMode::Dummy => {
- unreachable!("The dummy mode should not be called for this file")
- }
- TraversalMode::Check { .. } => check_file(shared_context, pgt_path),
- }
- })
-}
diff --git a/crates/pgt_cli/src/execute/process_file/check.rs b/crates/pgt_cli/src/execute/process_file/check.rs
deleted file mode 100644
index c48d0c4c..00000000
--- a/crates/pgt_cli/src/execute/process_file/check.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use pgt_analyse::RuleCategoriesBuilder;
-use pgt_diagnostics::{Error, category};
-
-use crate::execute::diagnostics::ResultExt;
-use crate::execute::process_file::workspace_file::WorkspaceFile;
-use crate::execute::process_file::{FileResult, FileStatus, Message, SharedTraversalOptions};
-use std::path::Path;
-use std::sync::atomic::Ordering;
-
-/// Lints a single file and returns a [FileResult]
-pub(crate) fn check_file<'ctx>(
- ctx: &'ctx SharedTraversalOptions<'ctx, '_>,
- path: &Path,
-) -> FileResult {
- let mut workspace_file = WorkspaceFile::new(ctx, path)?;
- check_with_guard(ctx, &mut workspace_file)
-}
-
-pub(crate) fn check_with_guard<'ctx>(
- ctx: &'ctx SharedTraversalOptions<'ctx, '_>,
- workspace_file: &mut WorkspaceFile,
-) -> FileResult {
- tracing::info_span!("Processes check", path =? workspace_file.path.display()).in_scope(
- move || {
- let input = workspace_file.input()?;
- let changed = false;
-
- let (only, skip) = (Vec::new(), Vec::new());
-
- let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed);
-
- let pull_diagnostics_result = workspace_file
- .guard()
- .pull_diagnostics(
- RuleCategoriesBuilder::default().all().build(),
- max_diagnostics,
- only,
- skip,
- )
- .with_file_path_and_code(
- workspace_file.path.display().to_string(),
- category!("check"),
- )?;
-
- let no_diagnostics = pull_diagnostics_result.diagnostics.is_empty()
- && pull_diagnostics_result.skipped_diagnostics == 0;
-
- if !no_diagnostics {
- ctx.push_message(Message::Diagnostics {
- name: workspace_file.path.display().to_string(),
- content: input,
- diagnostics: pull_diagnostics_result
- .diagnostics
- .into_iter()
- .map(Error::from)
- .collect(),
- skipped_diagnostics: pull_diagnostics_result.skipped_diagnostics as u32,
- });
- }
-
- if changed {
- Ok(FileStatus::Changed)
- } else {
- Ok(FileStatus::Unchanged)
- }
- },
- )
-}
diff --git a/crates/pgt_cli/src/execute/process_file/workspace_file.rs b/crates/pgt_cli/src/execute/process_file/workspace_file.rs
deleted file mode 100644
index 790176b9..00000000
--- a/crates/pgt_cli/src/execute/process_file/workspace_file.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use crate::execute::diagnostics::{ResultExt, ResultIoExt};
-use crate::execute::process_file::SharedTraversalOptions;
-use pgt_diagnostics::{Error, category};
-use pgt_fs::{File, OpenOptions, PgTPath};
-use pgt_workspace::workspace::{ChangeParams, FileGuard, OpenFileParams};
-use pgt_workspace::{Workspace, WorkspaceError};
-use std::path::{Path, PathBuf};
-
-/// Small wrapper that holds information and operations around the current processed file
-pub(crate) struct WorkspaceFile<'ctx, 'app> {
- guard: FileGuard<'app, dyn Workspace + 'ctx>,
- file: Box,
- pub(crate) path: PathBuf,
-}
-
-impl<'ctx, 'app> WorkspaceFile<'ctx, 'app> {
- /// It attempts to read the file from disk, creating a [FileGuard] and
- /// saving these information internally
- pub(crate) fn new(
- ctx: &SharedTraversalOptions<'ctx, 'app>,
- path: &Path,
- ) -> Result {
- let pgt_path = PgTPath::new(path);
- let open_options = OpenOptions::default()
- .read(true)
- .write(ctx.execution.requires_write_access());
- let mut file = ctx
- .fs
- .open_with_options(path, open_options)
- .with_file_path(path.display().to_string())?;
-
- let mut input = String::new();
- file.read_to_string(&mut input)
- .with_file_path(path.display().to_string())?;
-
- let guard = FileGuard::open(
- ctx.workspace,
- OpenFileParams {
- path: pgt_path,
- version: 0,
- content: input.clone(),
- },
- )
- .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?;
-
- Ok(Self {
- file,
- guard,
- path: PathBuf::from(path),
- })
- }
-
- pub(crate) fn guard(&self) -> &FileGuard<'app, dyn Workspace + 'ctx> {
- &self.guard
- }
-
- pub(crate) fn input(&self) -> Result {
- self.guard().get_file_content()
- }
-
- /// It updates the workspace file with `new_content`
- #[allow(dead_code)]
- pub(crate) fn update_file(&mut self, new_content: impl Into) -> Result<(), Error> {
- let new_content = new_content.into();
-
- self.file
- .set_content(new_content.as_bytes())
- .with_file_path(self.path.display().to_string())?;
- self.guard.change_file(
- self.file.file_version(),
- vec![ChangeParams::overwrite(new_content)],
- )?;
- Ok(())
- }
-}
diff --git a/crates/pgt_cli/src/execute/std_in.rs b/crates/pgt_cli/src/execute/std_in.rs
deleted file mode 100644
index f9346f6a..00000000
--- a/crates/pgt_cli/src/execute/std_in.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//! In here, there are the operations that run via standard input
-//!
-use crate::{CliDiagnostic, CliSession};
-use pgt_console::{ConsoleExt, markup};
-
-pub(crate) fn run(session: CliSession, content: &str) -> Result<(), CliDiagnostic> {
- let console = &mut *session.app.console;
-
- console.append(markup! {{content}});
- Ok(())
-}
diff --git a/crates/pgt_cli/src/execute/traverse.rs b/crates/pgt_cli/src/execute/traverse.rs
deleted file mode 100644
index 5673810c..00000000
--- a/crates/pgt_cli/src/execute/traverse.rs
+++ /dev/null
@@ -1,548 +0,0 @@
-use super::process_file::{FileStatus, Message, process_file};
-use super::{Execution, TraversalMode};
-use crate::cli_options::CliOptions;
-use crate::execute::diagnostics::PanicDiagnostic;
-use crate::reporter::TraversalSummary;
-use crate::{CliDiagnostic, CliSession};
-use crossbeam::channel::{Receiver, Sender, unbounded};
-use pgt_diagnostics::DiagnosticTags;
-use pgt_diagnostics::{DiagnosticExt, Error, Resource, Severity};
-use pgt_fs::{FileSystem, PathInterner, PgTPath};
-use pgt_fs::{TraversalContext, TraversalScope};
-use pgt_workspace::dome::Dome;
-use pgt_workspace::workspace::IsPathIgnoredParams;
-use pgt_workspace::{Workspace, WorkspaceError};
-use rustc_hash::FxHashSet;
-use std::collections::BTreeSet;
-use std::sync::RwLock;
-use std::sync::atomic::AtomicU32;
-use std::{
- env::current_dir,
- ffi::OsString,
- panic::catch_unwind,
- path::PathBuf,
- sync::{
- Once,
- atomic::{AtomicUsize, Ordering},
- },
- thread,
- time::{Duration, Instant},
-};
-
-pub(crate) struct TraverseResult {
- pub(crate) summary: TraversalSummary,
- pub(crate) evaluated_paths: BTreeSet,
- pub(crate) diagnostics: Vec,
-}
-
-pub(crate) fn traverse(
- execution: &Execution,
- session: &mut CliSession,
- cli_options: &CliOptions,
- mut inputs: Vec,
-) -> Result {
- init_thread_pool();
-
- if inputs.is_empty() {
- match &execution.traversal_mode {
- TraversalMode::Dummy => {
- // If `--staged` or `--changed` is specified, it's acceptable for them to be empty, so ignore it.
- if !execution.is_vcs_targeted() {
- match current_dir() {
- Ok(current_dir) => inputs.push(current_dir.into_os_string()),
- Err(err) => return Err(CliDiagnostic::io_error(err)),
- }
- }
- }
- _ => {
- if execution.as_stdin_file().is_none() && !cli_options.no_errors_on_unmatched {
- return Err(CliDiagnostic::missing_argument(
- " ",
- format!("{}", execution.traversal_mode),
- ));
- }
- }
- }
- }
-
- let (interner, recv_files) = PathInterner::new();
- let (sender, receiver) = unbounded();
-
- let changed = AtomicUsize::new(0);
- let unchanged = AtomicUsize::new(0);
- let matches = AtomicUsize::new(0);
- let skipped = AtomicUsize::new(0);
-
- let fs = &*session.app.fs;
- let workspace = &*session.app.workspace;
-
- let max_diagnostics = execution.get_max_diagnostics();
- let remaining_diagnostics = AtomicU32::new(max_diagnostics);
-
- let printer = DiagnosticsPrinter::new(execution)
- .with_verbose(cli_options.verbose)
- .with_diagnostic_level(cli_options.diagnostic_level)
- .with_max_diagnostics(max_diagnostics);
-
- let (duration, evaluated_paths, diagnostics) = thread::scope(|s| {
- let handler = thread::Builder::new()
- .name(String::from("pgt::console"))
- .spawn_scoped(s, || printer.run(receiver, recv_files))
- .expect("failed to spawn console thread");
-
- // The traversal context is scoped to ensure all the channels it
- // contains are properly closed once the traversal finishes
- let (elapsed, evaluated_paths) = traverse_inputs(
- fs,
- inputs,
- &TraversalOptions {
- fs,
- workspace,
- execution,
- interner,
- matches: &matches,
- changed: &changed,
- unchanged: &unchanged,
- skipped: &skipped,
- messages: sender,
- remaining_diagnostics: &remaining_diagnostics,
- evaluated_paths: RwLock::default(),
- },
- );
- // wait for the main thread to finish
- let diagnostics = handler.join().unwrap();
-
- (elapsed, evaluated_paths, diagnostics)
- });
-
- let errors = printer.errors();
- let warnings = printer.warnings();
- let changed = changed.load(Ordering::Relaxed);
- let unchanged = unchanged.load(Ordering::Relaxed);
- let matches = matches.load(Ordering::Relaxed);
- let skipped = skipped.load(Ordering::Relaxed);
- let suggested_fixes_skipped = printer.skipped_fixes();
- let diagnostics_not_printed = printer.not_printed_diagnostics();
-
- Ok(TraverseResult {
- summary: TraversalSummary {
- changed,
- unchanged,
- duration,
- errors,
- matches,
- warnings,
- skipped,
- suggested_fixes_skipped,
- diagnostics_not_printed,
- },
- evaluated_paths,
- diagnostics,
- })
-}
-
-/// This function will setup the global Rayon thread pool the first time it's called
-///
-/// This is currently only used to assign friendly debug names to the threads of the pool
-fn init_thread_pool() {
- static INIT_ONCE: Once = Once::new();
- INIT_ONCE.call_once(|| {
- rayon::ThreadPoolBuilder::new()
- .thread_name(|index| format!("pgt::worker_{index}"))
- .build_global()
- .expect("failed to initialize the global thread pool");
- });
-}
-
-/// Initiate the filesystem traversal tasks with the provided input paths and
-/// run it to completion, returning the duration of the process and the evaluated paths
-fn traverse_inputs(
- fs: &dyn FileSystem,
- inputs: Vec,
- ctx: &TraversalOptions,
-) -> (Duration, BTreeSet) {
- let start = Instant::now();
- fs.traversal(Box::new(move |scope: &dyn TraversalScope| {
- for input in inputs {
- scope.evaluate(ctx, PathBuf::from(input));
- }
- }));
-
- let paths = ctx.evaluated_paths();
- let dome = Dome::new(paths);
- let mut iter = dome.iter();
- fs.traversal(Box::new(|scope: &dyn TraversalScope| {
- while let Some(path) = iter.next_config() {
- scope.handle(ctx, path.to_path_buf());
- }
-
- for path in iter {
- scope.handle(ctx, path.to_path_buf());
- }
- }));
-
- (start.elapsed(), ctx.evaluated_paths())
-}
-
-// struct DiagnosticsReporter<'ctx> {}
-
-struct DiagnosticsPrinter<'ctx> {
- /// Execution of the traversal
- #[allow(dead_code)]
- execution: &'ctx Execution,
- /// The maximum number of diagnostics the console thread is allowed to print
- max_diagnostics: u32,
- /// The approximate number of diagnostics the console will print before
- /// folding the rest into the "skipped diagnostics" counter
- remaining_diagnostics: AtomicU32,
- /// Mutable reference to a boolean flag tracking whether the console thread
- /// printed any error-level message
- errors: AtomicU32,
- /// Mutable reference to a boolean flag tracking whether the console thread
- /// printed any warnings-level message
- warnings: AtomicU32,
- /// Whether the console thread should print diagnostics in verbose mode
- verbose: bool,
- /// The diagnostic level the console thread should print
- diagnostic_level: Severity,
-
- not_printed_diagnostics: AtomicU32,
- printed_diagnostics: AtomicU32,
- total_skipped_suggested_fixes: AtomicU32,
-}
-
-impl<'ctx> DiagnosticsPrinter<'ctx> {
- fn new(execution: &'ctx Execution) -> Self {
- Self {
- errors: AtomicU32::new(0),
- warnings: AtomicU32::new(0),
- remaining_diagnostics: AtomicU32::new(0),
- execution,
- diagnostic_level: Severity::Hint,
- verbose: false,
- max_diagnostics: 20,
- not_printed_diagnostics: AtomicU32::new(0),
- printed_diagnostics: AtomicU32::new(0),
- total_skipped_suggested_fixes: AtomicU32::new(0),
- }
- }
-
- fn with_verbose(mut self, verbose: bool) -> Self {
- self.verbose = verbose;
- self
- }
-
- fn with_max_diagnostics(mut self, value: u32) -> Self {
- self.max_diagnostics = value;
- self
- }
-
- fn with_diagnostic_level(mut self, value: Severity) -> Self {
- self.diagnostic_level = value;
- self
- }
-
- fn errors(&self) -> u32 {
- self.errors.load(Ordering::Relaxed)
- }
-
- fn warnings(&self) -> u32 {
- self.warnings.load(Ordering::Relaxed)
- }
-
- fn not_printed_diagnostics(&self) -> u32 {
- self.not_printed_diagnostics.load(Ordering::Relaxed)
- }
-
- fn skipped_fixes(&self) -> u32 {
- self.total_skipped_suggested_fixes.load(Ordering::Relaxed)
- }
-
- /// Checks if the diagnostic we received from the thread should be considered or not. Logic:
- /// - it should not be considered if its severity level is lower than the one provided via CLI;
- /// - it should not be considered if it's a verbose diagnostic and the CLI **didn't** request a `--verbose` option.
- fn should_skip_diagnostic(&self, severity: Severity, diagnostic_tags: DiagnosticTags) -> bool {
- if severity < self.diagnostic_level {
- return true;
- }
-
- if diagnostic_tags.is_verbose() && !self.verbose {
- return true;
- }
-
- false
- }
-
- /// Count the diagnostic, and then returns a boolean that tells if it should be printed
- fn should_print(&self) -> bool {
- let printed_diagnostics = self.printed_diagnostics.load(Ordering::Relaxed);
- let should_print = printed_diagnostics < self.max_diagnostics;
- if should_print {
- self.printed_diagnostics.fetch_add(1, Ordering::Relaxed);
- self.remaining_diagnostics.store(
- self.max_diagnostics.saturating_sub(printed_diagnostics),
- Ordering::Relaxed,
- );
- } else {
- self.not_printed_diagnostics.fetch_add(1, Ordering::Relaxed);
- }
-
- should_print
- }
-
- fn run(&self, receiver: Receiver, interner: Receiver) -> Vec {
- let mut paths: FxHashSet = FxHashSet::default();
-
- let mut diagnostics_to_print = vec![];
-
- while let Ok(msg) = receiver.recv() {
- match msg {
- Message::SkippedFixes {
- skipped_suggested_fixes,
- } => {
- self.total_skipped_suggested_fixes
- .fetch_add(skipped_suggested_fixes, Ordering::Relaxed);
- }
-
- Message::Failure => {
- self.errors.fetch_add(1, Ordering::Relaxed);
- }
-
- Message::Error(mut err) => {
- let location = err.location();
- if self.should_skip_diagnostic(err.severity(), err.tags()) {
- continue;
- }
- if err.severity() == Severity::Warning {
- // *warnings += 1;
- self.warnings.fetch_add(1, Ordering::Relaxed);
- // self.warnings.set(self.warnings.get() + 1)
- }
- if let Some(Resource::File(file_path)) = location.resource.as_ref() {
- // Retrieves the file name from the file ID cache, if it's a miss
- // flush entries from the interner channel until it's found
- let file_name = match paths.get(*file_path) {
- Some(path) => Some(path),
- None => loop {
- match interner.recv() {
- Ok(path) => {
- paths.insert(path.display().to_string());
- if path.display().to_string() == *file_path {
- break paths.get(&path.display().to_string());
- }
- }
- // In case the channel disconnected without sending
- // the path we need, print the error without a file
- // name (normally this should never happen)
- Err(_) => break None,
- }
- },
- };
-
- if let Some(path) = file_name {
- err = err.with_file_path(path.as_str());
- }
- }
-
- let should_print = self.should_print();
-
- if should_print {
- diagnostics_to_print.push(err);
- }
- }
-
- Message::Diagnostics {
- name,
- content,
- diagnostics,
- skipped_diagnostics,
- } => {
- self.not_printed_diagnostics
- .fetch_add(skipped_diagnostics, Ordering::Relaxed);
-
- // is CI mode we want to print all the diagnostics
- for diag in diagnostics {
- let severity = diag.severity();
- if self.should_skip_diagnostic(severity, diag.tags()) {
- continue;
- }
- if severity == Severity::Error {
- self.errors.fetch_add(1, Ordering::Relaxed);
- }
- if severity == Severity::Warning {
- self.warnings.fetch_add(1, Ordering::Relaxed);
- }
-
- let should_print = self.should_print();
-
- if should_print {
- let diag = diag.with_file_path(&name).with_file_source_code(&content);
- diagnostics_to_print.push(diag)
- }
- }
- }
- }
- }
-
- diagnostics_to_print
- }
-}
-
-/// Context object shared between directory traversal tasks
-pub(crate) struct TraversalOptions<'ctx, 'app> {
- /// Shared instance of [FileSystem]
- pub(crate) fs: &'app dyn FileSystem,
- /// Instance of [Workspace] used by this instance of the CLI
- pub(crate) workspace: &'ctx dyn Workspace,
- /// Determines how the files should be processed
- pub(crate) execution: &'ctx Execution,
- /// File paths interner cache used by the filesystem traversal
- interner: PathInterner,
- /// Shared atomic counter storing the number of changed files
- changed: &'ctx AtomicUsize,
- /// Shared atomic counter storing the number of unchanged files
- unchanged: &'ctx AtomicUsize,
- /// Shared atomic counter storing the number of unchanged files
- matches: &'ctx AtomicUsize,
- /// Shared atomic counter storing the number of skipped files
- skipped: &'ctx AtomicUsize,
- /// Channel sending messages to the display thread
- pub(crate) messages: Sender,
- /// The approximate number of diagnostics the console will print before
- /// folding the rest into the "skipped diagnostics" counter
- pub(crate) remaining_diagnostics: &'ctx AtomicU32,
-
- /// List of paths that should be processed
- pub(crate) evaluated_paths: RwLock>,
-}
-
-impl TraversalOptions<'_, '_> {
- pub(crate) fn increment_changed(&self, path: &PgTPath) {
- self.changed.fetch_add(1, Ordering::Relaxed);
- self.evaluated_paths
- .write()
- .unwrap()
- .replace(path.to_written());
- }
- pub(crate) fn increment_unchanged(&self) {
- self.unchanged.fetch_add(1, Ordering::Relaxed);
- }
-
- pub(crate) fn increment_matches(&self, num_matches: usize) {
- self.matches.fetch_add(num_matches, Ordering::Relaxed);
- }
-
- /// Send a message to the display thread
- pub(crate) fn push_message(&self, msg: impl Into) {
- self.messages.send(msg.into()).ok();
- }
-}
-
-impl TraversalContext for TraversalOptions<'_, '_> {
- fn interner(&self) -> &PathInterner {
- &self.interner
- }
-
- fn evaluated_paths(&self) -> BTreeSet {
- self.evaluated_paths.read().unwrap().clone()
- }
-
- fn push_diagnostic(&self, error: Error) {
- self.push_message(error);
- }
-
- fn can_handle(&self, pgt_path: &PgTPath) -> bool {
- let path = pgt_path.as_path();
-
- let is_valid_file = self.fs.path_is_file(path)
- && path
- .extension()
- .is_some_and(|ext| ext == "sql" || ext == "pg");
-
- if self.fs.path_is_dir(path) || self.fs.path_is_symlink(path) || is_valid_file {
- // handle:
- // - directories
- // - symlinks
- // - unresolved symlinks
- // e.g `symlink/subdir` where symlink points to a directory that includes `subdir`.
- // Note that `symlink/subdir` is not an existing file.
- let can_handle = !self
- .workspace
- .is_path_ignored(IsPathIgnoredParams {
- pgt_path: pgt_path.clone(),
- })
- .unwrap_or_else(|err| {
- self.push_diagnostic(err.into());
- false
- });
- return can_handle;
- }
-
- // bail on fifo and socket files
- if !is_valid_file {
- return false;
- }
-
- match self.execution.traversal_mode() {
- TraversalMode::Dummy => true,
- TraversalMode::Check { .. } => true,
- }
- }
-
- fn handle_path(&self, path: PgTPath) {
- handle_file(self, &path)
- }
-
- fn store_path(&self, path: PgTPath) {
- self.evaluated_paths
- .write()
- .unwrap()
- .insert(PgTPath::new(path.as_path()));
- }
-}
-
-/// This function wraps the [process_file] function implementing the traversal
-/// in a [catch_unwind] block and emit diagnostics in case of error (either the
-/// traversal function returns Err or panics)
-fn handle_file(ctx: &TraversalOptions, path: &PgTPath) {
- match catch_unwind(move || process_file(ctx, path)) {
- Ok(Ok(FileStatus::Changed)) => {
- ctx.increment_changed(path);
- }
- Ok(Ok(FileStatus::Unchanged)) => {
- ctx.increment_unchanged();
- }
- Ok(Ok(FileStatus::SearchResult(num_matches, msg))) => {
- ctx.increment_unchanged();
- ctx.increment_matches(num_matches);
- ctx.push_message(msg);
- }
- Ok(Ok(FileStatus::Message(msg))) => {
- ctx.increment_unchanged();
- ctx.push_message(msg);
- }
- Ok(Ok(FileStatus::Protected(file_path))) => {
- ctx.increment_unchanged();
- ctx.push_diagnostic(WorkspaceError::protected_file(file_path).into());
- }
- Ok(Ok(FileStatus::Ignored)) => {}
- Ok(Err(err)) => {
- ctx.increment_unchanged();
- ctx.skipped.fetch_add(1, Ordering::Relaxed);
- ctx.push_message(err);
- }
- Err(err) => {
- let message = match err.downcast::() {
- Ok(msg) => format!("processing panicked: {msg}"),
- Err(err) => match err.downcast::<&'static str>() {
- Ok(msg) => format!("processing panicked: {msg}"),
- Err(_) => String::from("processing panicked"),
- },
- };
-
- ctx.push_message(
- PanicDiagnostic { message }.with_file_path(path.display().to_string()),
- );
- }
- }
-}
diff --git a/crates/pgt_cli/src/lib.rs b/crates/pgt_cli/src/lib.rs
deleted file mode 100644
index f8a04244..00000000
--- a/crates/pgt_cli/src/lib.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-//! # Module
-//!
-//! This is where the main CLI session starts. The module is responsible
-//! to parse commands and arguments, redirect the execution of the commands and
-//! execute the traversal of directory and files, based on the command that was passed.
-
-use cli_options::CliOptions;
-use commands::CommandRunner;
-use commands::check::CheckCommandPayload;
-use pgt_console::{ColorMode, Console};
-use pgt_fs::OsFileSystem;
-use pgt_workspace::{App, DynRef, Workspace, WorkspaceRef};
-use std::env;
-
-mod changed;
-mod cli_options;
-mod commands;
-mod diagnostics;
-mod execute;
-mod logging;
-mod metrics;
-mod panic;
-mod reporter;
-mod service;
-
-use crate::cli_options::ColorsArg;
-pub use crate::commands::{PgtCommand, pgt_command};
-pub use crate::logging::{LoggingLevel, setup_cli_subscriber};
-pub use diagnostics::CliDiagnostic;
-pub use execute::{Execution, TraversalMode, VcsTargeted, execute_mode};
-pub use panic::setup_panic_handler;
-pub use reporter::{DiagnosticsPayload, Reporter, ReporterVisitor, TraversalSummary};
-pub use service::{SocketTransport, open_transport};
-
-pub(crate) const VERSION: &str = match option_env!("PGT_VERSION") {
- Some(version) => version,
- None => env!("CARGO_PKG_VERSION"),
-};
-
-/// Global context for an execution of the CLI
-pub struct CliSession<'app> {
- /// Instance of [App] used by this run of the CLI
- pub app: App<'app>,
-}
-
-impl<'app> CliSession<'app> {
- pub fn new(
- workspace: &'app dyn Workspace,
- console: &'app mut dyn Console,
- ) -> Result {
- Ok(Self {
- app: App::new(
- DynRef::Owned(Box::::default()),
- console,
- WorkspaceRef::Borrowed(workspace),
- ),
- })
- }
-
- /// Main function to run the CLI
- pub fn run(self, command: PgtCommand) -> Result<(), CliDiagnostic> {
- let has_metrics = command.has_metrics();
- if has_metrics {
- crate::metrics::init_metrics();
- }
-
- let result = match command {
- PgtCommand::Version(_) => commands::version::full_version(self),
- PgtCommand::Check {
- cli_options,
- configuration,
- paths,
- stdin_file_path,
- staged,
- changed,
- since,
- } => run_command(
- self,
- &cli_options,
- CheckCommandPayload {
- configuration,
- paths,
- stdin_file_path,
- staged,
- changed,
- since,
- },
- ),
- PgtCommand::Clean => commands::clean::clean(self),
- PgtCommand::Start {
- config_path,
- log_path,
- log_prefix_name,
- } => commands::daemon::start(self, config_path, Some(log_path), Some(log_prefix_name)),
- PgtCommand::Stop => commands::daemon::stop(self),
- PgtCommand::Init => commands::init::init(self),
- PgtCommand::LspProxy {
- config_path,
- log_path,
- log_prefix_name,
- ..
- } => commands::daemon::lsp_proxy(config_path, Some(log_path), Some(log_prefix_name)),
- PgtCommand::RunServer {
- stop_on_disconnect,
- config_path,
- log_path,
- log_prefix_name,
- log_level,
- log_kind,
- } => commands::daemon::run_server(
- stop_on_disconnect,
- config_path,
- Some(log_path),
- Some(log_prefix_name),
- Some(log_level),
- Some(log_kind),
- ),
- PgtCommand::PrintSocket => commands::daemon::print_socket(),
- };
-
- if has_metrics {
- metrics::print_metrics();
- }
-
- result
- }
-}
-
-pub fn to_color_mode(color: Option<&ColorsArg>) -> ColorMode {
- match color {
- Some(ColorsArg::Off) => ColorMode::Disabled,
- Some(ColorsArg::Force) => ColorMode::Enabled,
- None => ColorMode::Auto,
- }
-}
-
-pub(crate) fn run_command(
- session: CliSession,
- cli_options: &CliOptions,
- mut command: impl CommandRunner,
-) -> Result<(), CliDiagnostic> {
- let command = &mut command;
- command.run(session, cli_options)
-}
diff --git a/crates/pgt_cli/src/logging.rs b/crates/pgt_cli/src/logging.rs
deleted file mode 100644
index 35911927..00000000
--- a/crates/pgt_cli/src/logging.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-use std::fmt::{Display, Formatter};
-use std::str::FromStr;
-use tracing::Metadata;
-use tracing::subscriber::Interest;
-use tracing_subscriber::filter::LevelFilter;
-use tracing_subscriber::layer::{Context, Filter, SubscriberExt};
-use tracing_subscriber::util::SubscriberInitExt;
-use tracing_subscriber::{Layer, registry};
-
-pub fn setup_cli_subscriber(level: LoggingLevel, kind: LoggingKind) {
- if level == LoggingLevel::None {
- return;
- }
-
- let format = tracing_subscriber::fmt::layer()
- .with_level(true)
- .with_target(false)
- .with_thread_names(true)
- .with_file(true)
- .with_ansi(true);
- match kind {
- LoggingKind::Pretty => {
- let format = format.pretty();
- registry()
- .with(format.with_filter(LoggingFilter { level }))
- .init()
- }
- LoggingKind::Compact => {
- let format = format.compact();
- registry()
- .with(format.with_filter(LoggingFilter { level }))
- .init()
- }
- LoggingKind::Json => {
- let format = format.json().flatten_event(true);
-
- registry()
- .with(format.with_filter(LoggingFilter { level }))
- .init()
- }
- };
-}
-
-#[derive(Copy, Debug, Default, Clone, Ord, PartialOrd, Eq, PartialEq)]
-pub enum LoggingLevel {
- /// No logs should be shown
- #[default]
- None,
- Debug,
- Info,
- Warn,
- Error,
-}
-
-impl LoggingLevel {
- fn to_filter_level(self) -> Option {
- match self {
- LoggingLevel::None => None,
- LoggingLevel::Info => Some(LevelFilter::INFO),
- LoggingLevel::Warn => Some(LevelFilter::WARN),
- LoggingLevel::Error => Some(LevelFilter::ERROR),
- LoggingLevel::Debug => Some(LevelFilter::DEBUG),
- }
- }
-}
-
-impl FromStr for LoggingLevel {
- type Err = String;
- fn from_str(s: &str) -> Result {
- match s {
- "none" => Ok(Self::None),
- "info" => Ok(Self::Info),
- "warn" => Ok(Self::Warn),
- "error" => Ok(Self::Error),
- "debug" => Ok(Self::Debug),
- _ => Err("Unexpected value".to_string()),
- }
- }
-}
-
-impl Display for LoggingLevel {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- LoggingLevel::None => write!(f, "none"),
- LoggingLevel::Debug => write!(f, "debug"),
- LoggingLevel::Info => write!(f, "info"),
- LoggingLevel::Warn => write!(f, "warn"),
- LoggingLevel::Error => write!(f, "error"),
- }
- }
-}
-
-/// Tracing filter enabling:
-/// - All spans and events at level info or higher
-/// - All spans and events at level debug in crates whose name starts with `pgt`
-struct LoggingFilter {
- level: LoggingLevel,
-}
-
-/// Tracing filter used for spans emitted by `pgt*` crates
-const SELF_FILTER: LevelFilter = if cfg!(debug_assertions) {
- LevelFilter::TRACE
-} else {
- LevelFilter::DEBUG
-};
-
-impl LoggingFilter {
- fn is_enabled(&self, meta: &Metadata<'_>) -> bool {
- let filter = if meta.target().starts_with("pgt") {
- if let Some(level) = self.level.to_filter_level() {
- level
- } else {
- return false;
- }
- } else {
- LevelFilter::INFO
- };
-
- meta.level() <= &filter
- }
-}
-
-impl