Skip to content

Latest commit

 

History

History
134 lines (120 loc) · 12.9 KB

language-coverage.md

File metadata and controls

134 lines (120 loc) · 12.9 KB

Language Coverage

pi-lens supports 37+ languages through dispatch runners and LSP integration.

Formatting uses a single selected formatter per file: explicit project config wins, otherwise pi-lens uses a smart default where supported, and config-first ecosystems do not autoformat without config.

Dispatch is diagnostics-oriented: automatic formatting and safe autofix happen in the post-write pipeline rather than through dispatch format-check runners.

Language LSP Dispatch Runners Formatter
JavaScript/TypeScript ✓ lsp, ts-lsp, biome-check-json, tree-sitter, ast-grep-napi, type-safety, similarity, fact-rules, eslint, oxlint biome, prettier
Python ✓ lsp, pyright, mypy (config-first), ruff-lint, tree-sitter ruff, black
Go ✓ lsp, go-vet, golangci-lint, tree-sitter gofmt
Rust ✓ lsp, rust-clippy, tree-sitter rustfmt
Ruby ✓ lsp, rubocop, tree-sitter rubocop, standardrb
C/C++ ✓ lsp, cpp-check, tree-sitter clang-format
Shell ✓ lsp, shellcheck shfmt
Fish ✓ (fish-lsp) lsp, fish-indent fish_indent
CSS/SCSS/Less ✓ lsp, stylelint biome, prettier
HTML ✓ lsp, htmlhint prettier (with project config)
YAML ✓ lsp, yamllint, actionlint (GitHub workflows), trivy-config (opt-in; Kubernetes manifests, CloudFormation) prettier (with project config)
JSON ✓ lsp, trivy-config (opt-in; CloudFormation templates only) biome, prettier
Svelte ✓ lsp oxfmt (needs svelte pkg installed + config svelte: true)
Vue ✓ lsp prettier, oxfmt
SQL — sqlfluff sqlfluff
Markdown — spellcheck, markdownlint, vale prettier
Docker ✓ lsp, hadolint, trivy-config (opt-in) —
PHP ✓ lsp, php-lint, phpstan php-cs-fixer
PowerShell ✓ lsp, psscriptanalyzer psscriptanalyzer-format
Prisma ✓ lsp, prisma-validate —
C# ✓ lsp, dotnet-build csharpier
F# ✓ lsp fantomas
Java ✓ lsp, javac google-java-format
Java + Lombok ✓ JDT LS launched with -javaagent:<lombok.jar> when Lombok is detected and a jar is found (PI_LENS_LOMBOK_JAR / LOMBOK_JAR, project .lombok/lombok.jar, or Maven/Gradle cache) google-java-format
Kotlin ✓ lsp, ktlint, detekt ktlint
Lean 4 ✓ (Lake serve) lsp; uses each project's Lake toolchain and environment —
Swift ✓ lsp, swiftlint swiftformat
Dart ✓ lsp, dart-analyze dart format
Lua ✓ lsp stylua
Zig ✓ lsp, zig-check zig fmt
Haskell ✓ lsp ormolu
Elixir ✓ (ElixirLS default, Expert alternate) lsp, elixir-check, credo mix format
Gleam ✓ lsp, gleam-check gleam format
Typst ✓ (tinymist) — typstyle (.typ, .typc)
OCaml ✓ lsp ocamlformat
Clojure ✓ lsp cljfmt
Terraform ✓ lsp, tflint, trivy-config (opt-in) terraform fmt
Terragrunt — terragrunt terragrunt hcl fmt
Nix ✓ lsp nixfmt
TOML ✓ lsp, taplo taplo
CMake ✓ (cmake-language-server) lsp cmake-format
CUE ✓ (syntax via cue lsp, evaluation via cue vet) lsp, cue-vet cue fmt

CUE tree-sitter grammar

cue lsp reports load and parse errors as you type but leaves conflicting values and failed constraints to cue vet — the cue-vet auxiliary runner (#1522) covers that gap, so together they give full coverage: syntax/parse diagnostics, hover, definition, completion, code actions, and formatting from the language server, plus evaluation-error validation from cue vet on every edit (vetted at the PACKAGE level — the touched file's directory — with the result filtered back to that file, since CUE packages are directory-scoped). .cue files parse under tree-sitter with symbol (#Definitions, fields, let bindings) and import queries (#1522), giving CUE the same structural symbol search and import extraction as any other language, with two known rough edges inherited from the young tree-sitter-cue grammar itself (not this repo's queries):

  • Multi-hash raw strings (##"..."##, two or more # delimiters) mis-parse regardless of content — the field's value becomes a bare identifier node instead of a string, and the parser emits stray top-level nodes outside the field entirely. Because the broken value node can carry #-prefixed text, this can surface as a spurious symbol reference in the extracted refs. Single-hash raw strings (#"..."#) are unaffected.
  • Aliased field labels (X=name: value) emit the alias identifier (X) as its own spurious property symbol alongside the real field's correct symbol, because the grammar exposes both identifiers as untagged siblings under the same label node with no way to tell them apart structurally.

Both are upstream grammar limitations (tracked among eonpatapon/tree-sitter-cue's open issues), not something a query change here can fix.

Non-core grammars

The tree-sitter runner and symbol_search/module_report structural extraction ship a fixed set of core grammars; grammars for the other languages in the table above (CUE included) are fetched lazily on first use into web-tree-sitter's resolved package directory, verified against scripts/grammars.lock.json. This resolution works on a runtime that cannot resolve a bare package specifier — pi shipped as a bun build --compile binary — via one shared subpath-based ladder (scripts/lib/web-tree-sitter-dir.mjs, #3409); before that fix, non-core languages could never be analysed on those hosts. A grammar that never loads (fetch failure, unwritable target, an unsupported runtime) is recorded as a grammar_unavailable skip, never a clean pass (clients/dispatch/runners/tree-sitter.ts).

Considered and skipped (2026-08-20 survey, closed out by #1757)

Recorded so these are not re-litigated. The 2026-08-20 survey's first pass rejected bandit and checkov as duplicates of existing lanes; #1752's review disproved both "already covered" claims against the actual code, and #1757 closed the resulting gaps:

  • bandit (Python SAST) — RESOLVED. ruff's S ruleset implements Bandit's checks; config/ruff/core.toml now selects S, with S101 (assert), S311 (non-cryptographic random), S603/S607 (subprocess without shell=True / partial executable path) excluded as over-firing on real code (measured against the requests and pip packages — see the config file's comments for the exclusion reasoning and hit counts). C90 (mccabe complexity) was evaluated and NOT enabled: it is a maintainability metric, not a Bandit-equivalent security check, and its hit volume on a large pre-existing codebase (379 in pandas) would drown the security signal S adds. As always, a project-local ruff config overrides the bundled one outright.
  • checkov (IaC security) — the trivy config lane pi-lens's own dispatch registry already carries (clients/dispatch/runners/trivy-config.ts, opt-in via trivy.enabled) makes checkov a duplicate, not a gap: no second full-scan tool is needed. That lane covers Kubernetes manifests, Dockerfiles, and Terraform; #1757 added CloudFormation (yaml and json templates, detected via AWSTemplateFormatVersion / SAM Transform / Type: AWS::* heuristics) and fixed a real bug found while verifying against the installed binary: the runner passed --no-progress to trivy config, a flag that subcommand rejects (only trivy fs accepts it) — every real invocation exited 1 and, because trivy prints its usage text to stdout on a rejected flag, was misreported as a clean succeeded scan rather than an errored one. Dropping the flag was the fix.
  • radon / lizard (complexity) — still not enabled; see the C90 note above. Unchanged conclusion, now backed by measurement rather than assumption.

Known coverage holes with no tool currently clearing the adoption bar: Rust and Java dead-code detection, Ruby type checking (sorbet judged too heavy and idiosyncratic for a default lane).