Skip to content

Commit 448734e

Browse files
Add Rust-based LQL Language Server and VSCode extension overhaul (#26)
## TLDR - New Rust LSP server for LQL with ANTLR-generated parser, completions, hover, diagnostics, schema awareness, and AI integration - VSCode extension rewritten to use the Rust LSP as backend, with comprehensive test suites - Repo standardisation: Makefile, CI/CD, devcontainer, LQL website (Eleventy), csproj/editorconfig cleanups ## What Was Added? - **`Lql/lql-lsp-rust/`** — Full Rust LSP implementation in a Cargo workspace: - `lql-parser`: ANTLR-generated Rust parser with span tracking, token mapping, and error recovery - `lql-analyzer`: Completions, hover, diagnostics, symbol resolution, scope analysis, schema-aware intelligence - `lql-lsp`: LSP server (`tower-lsp`), database schema introspection, AI-powered features (explain query, suggest optimisations) - **`Lql/LqlExtension/src/test/`** — Three test suites: LSP protocol (3584 lines), VSCode E2E (526 lines), VSIX packaging (153 lines), plus LQL fixture files - **`Lql/LqlWebsite-Eleventy/`** — Full documentation site with docs for syntax, pipelines, lambdas, joins, aggregation, SQL dialects, VSCode, and AI integration - **`Makefile`** — Centralised build/test/lint/fmt/coverage commands across C#, Rust, and TypeScript - **`.devcontainer/`** — Dev container config for codespace development - **Claude skills** — `ci-prep`, `fmt`, `lint` skills; removed old `format` skill ## What Was Changed or Deleted? - **`Lql/LqlExtension/`** — Extension rewritten: now launches the Rust LSP binary, removed bundled `out/` build artifacts from repo - **`.github/workflows/ci.yml`** — Expanded CI to build/test Rust crates, run TypeScript tests, build VSIX - **`.github/workflows/release.yml`** — Updated for Rust binary cross-compilation and VSIX publishing - **`.editorconfig`** — Major expansion for multi-language consistency - **`Lql/Lql/Parsing/Lql.g4`** — Grammar updates (arithmetic functions, syntax refinements) - **csproj files** — Removed explicit `<Nullable>` / `<ImplicitUsings>` (centralised in `Directory.Build.props`) - **`Sync/`** — Minor fixes in `MappingConfigParser`, `MappingEngine`, `SyncSchemaDefinition` - **Website** — Added sitemap, about page, samples docs, layout improvements ## How Do The Automated Tests Prove It Works? **Rust unit tests** (`Lql/lql-lsp-rust/crates/lql-analyzer/src/tests.rs` — 1258 lines): - `test_completion_*`: Verifies completions for keywords, table names, columns, functions, aliases in various contexts (SELECT, WHERE, JOIN, GROUP BY, HAVING, window functions) - `test_hover_*`: Validates hover info for tables, columns, functions, keywords, aliases, aggregate/window functions - `test_diagnostics_*`: Checks error detection for syntax errors, unknown tables/columns, type mismatches, ambiguous columns - `test_scope_*`: Tests scope resolution across subqueries, CTEs, let bindings, pipeline stages - `test_schema_*`: Tests schema loading, introspection, and table/column resolution **Rust integration tests** (`Lql/lql-lsp-rust/crates/lql-lsp/tests/lsp_protocol.rs` — 879 lines): - Full LSP lifecycle: initialize → open document → request completions/hover/diagnostics → shutdown - Tests actual JSON-RPC message serialization and protocol compliance **TypeScript LSP protocol tests** (`Lql/LqlExtension/src/test/suite/lsp-protocol.test.ts` — 3584 lines): - Tests LSP message construction, response parsing, capability negotiation, error handling - Validates completion item kinds, hover content format, diagnostic severity mapping **TypeScript E2E tests** (`Lql/LqlExtension/src/test/suite/vscode-e2e.test.ts` — 526 lines): - Extension activation, document opening, language ID registration, command registration - Tests against LQL fixture files (simple select, filter lambda, case expression, window functions, subqueries, complex pipelines) **VSIX packaging tests** (`Lql/LqlExtension/src/test/suite/vsix-packaging.test.ts` — 153 lines): - Validates package.json structure, language contribution points, activation events, grammar scopes ## Spec / Doc Changes - `CLAUDE.md` updated with LQL platform-independence rule, CSS rules, web/SEO rules - `Lql/LqlWebsite-Eleventy/` — Full documentation site added - `Lql/LqlExtension/README.md` — Rewritten for Rust LSP architecture ## Breaking Changes - [ ] None 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a126320 commit 448734e

File tree

201 files changed

+32568
-2594
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

201 files changed

+32568
-2594
lines changed

.claude/skills/build/SKILL.md

Lines changed: 0 additions & 41 deletions
This file was deleted.

.claude/skills/ci-prep/SKILL.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
name: ci-prep
3+
description: Prepares the current branch for CI by running the exact same steps locally and fixing issues. If CI is already failing, fetches the GH Actions logs first to diagnose. Use before pushing, when CI is red, or when the user says "fix ci".
4+
argument-hint: "[--failing] [optional job name to focus on]"
5+
---
6+
7+
# CI Prep
8+
9+
Prepare the current state for CI. If CI is already failing, fetch and analyze the logs first.
10+
11+
## Arguments
12+
13+
- `--failing` — Indicates a GitHub Actions run is already failing. When present, you MUST execute **Step 1** before doing anything else.
14+
- Any other argument is treated as a job name to focus on (but all failures are still reported).
15+
16+
If `--failing` is NOT passed, skip directly to **Step 2**.
17+
18+
## Step 1 �� Fetch failed CI logs (only when `--failing`)
19+
20+
You MUST do this before any other work.
21+
22+
```bash
23+
BRANCH=$(git branch --show-current)
24+
PR_JSON=$(gh pr list --head "$BRANCH" --state open --json number,title,url --limit 1)
25+
```
26+
27+
If the JSON array is empty, **stop immediately**:
28+
> No open PR found for branch `$BRANCH`. Create a PR first.
29+
30+
Otherwise fetch the logs:
31+
32+
```bash
33+
PR_NUMBER=$(echo "$PR_JSON" | jq -r '.[0].number')
34+
gh pr checks "$PR_NUMBER"
35+
RUN_ID=$(gh run list --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId')
36+
gh run view "$RUN_ID"
37+
gh run view "$RUN_ID" --log-failed
38+
```
39+
40+
Read **every line** of `--log-failed` output. For each failure note the exact file, line, and error message. If a job name argument was provided, prioritize that job but still report all failures.
41+
42+
## Step 2 — Analyze the CI workflow
43+
44+
1. Read `.github/workflows/ci.yml` completely. Parse every job and every step.
45+
2. Extract the ordered list of commands the CI actually runs.
46+
3. Note environment variables, matrix strategies, conditional steps, and service containers.
47+
48+
**Do NOT assume the steps are `make lint`, `make test`, `make build`.** Extract what the CI *actually does*.
49+
50+
## Step 3 — Run each CI step locally, in order
51+
52+
Work through failures in this priority order:
53+
54+
1. **Formatting** — run auto-formatters first to clear noise
55+
2. **Compilation errors** — must compile before lint/test
56+
3. **Lint violations** — fix the code pattern
57+
4. **Runtime / test failures** — fix source code to satisfy the test
58+
59+
For each command extracted from the CI workflow:
60+
61+
1. Run the command exactly as CI would run it.
62+
2. If the step fails, **stop and fix the issues** before continuing to the next step.
63+
3. After fixing, re-run the same step to confirm it passes.
64+
4. Move to the next step only after the current one succeeds.
65+
66+
### Hard constraints
67+
68+
- **NEVER modify test files** — fix the source code, not the tests
69+
- **NEVER add suppressions** (`#pragma warning disable`, `#[allow(...)]`, `// eslint-disable`)
70+
- **NEVER delete or ignore failing tests**
71+
- **NEVER remove assertions**
72+
73+
If stuck on the same failure after 5 attempts, ask the user for help.
74+
75+
## Step 4 — Loop
76+
77+
- Go back to the first step and repeat until all steps pass locally. If `--failing`, you should see the exact same errors in your terminal that CI shows in the logs. Fix those errors until they are resolved.
78+
79+
## Step 5 — Commit/Push (only when `--failing`)
80+
81+
Once all CI steps pass locally:
82+
83+
1. Commit, but DO NOT MARK THE COMMIT WITH YOU AS AN AUTHOR!!! Only the user authors the commit!
84+
2. Push
85+
3. Monitor until completion or failure
86+
4. Upon failure, go back to Step 1
87+
88+
## Rules
89+
90+
- *You are not allowed to commi/push until all tests pass*. Do not waste GitHub action minutes! The local CI must prove that everything is working.
91+
- **Always read the CI workflow first.** Never assume what commands CI runs.
92+
- Do not push if any step fails (unless `--failing` and all steps now pass)
93+
- Fix issues found in each step before moving to the next
94+
- Never skip steps or suppress errors
95+
- If the CI workflow has multiple jobs, run all of them (respecting dependency order)
96+
- Skip steps that are CI-infrastructure-only (checkout, setup actions, cache steps, artifact uploads) — focus on the actual build/test/lint commands
97+
98+
## Success criteria
99+
100+
- Every command that CI runs has been executed locally and passed
101+
- All fixes are applied to the working tree
102+
- The CI passes successfully (if you are correcting an existing failure)

.claude/skills/code-dedup/SKILL.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
name: code-dedup
3+
description: Searches for duplicate code, duplicate tests, and dead code, then safely merges or removes them. Use when the user says "deduplicate", "find duplicates", "remove dead code", "DRY up", or "code dedup". Requires test coverage — refuses to touch untested code.
4+
---
5+
6+
# Code Dedup
7+
8+
Carefully search for duplicate code, duplicate tests, and dead code across the repo. Merge duplicates and delete dead code — but only when test coverage proves the change is safe.
9+
10+
## Prerequisites — hard gate
11+
12+
Before touching ANY code, verify these conditions. If any fail, stop and report why.
13+
14+
1. Run `make test` — all tests must pass. If tests fail, stop. Do not dedup a broken codebase.
15+
2. Run `make coverage-check` — coverage must meet the repo's threshold. If it doesn't, stop.
16+
3. This repo uses **C#, F#, Rust, and TypeScript** — all statically typed. Proceed.
17+
18+
## Steps
19+
20+
Copy this checklist and track progress:
21+
22+
```
23+
Dedup Progress:
24+
- [ ] Step 1: Prerequisites passed (tests green, coverage met, typed)
25+
- [ ] Step 2: Dead code scan complete
26+
- [ ] Step 3: Duplicate code scan complete
27+
- [ ] Step 4: Duplicate test scan complete
28+
- [ ] Step 5: Changes applied
29+
- [ ] Step 6: Verification passed (tests green, coverage stable)
30+
```
31+
32+
### Step 1 — Inventory test coverage
33+
34+
Before deciding what to touch, understand what is tested.
35+
36+
1. Run `make test` and `make coverage-check` to confirm green baseline
37+
2. Note the current coverage percentage — this is the floor. It must not drop.
38+
3. Identify which files/modules have coverage and which do not. Only files WITH coverage are candidates for dedup.
39+
40+
### Step 2 — Scan for dead code
41+
42+
Search for code that is never called, never imported, never referenced.
43+
44+
1. Look for unused exports, unused functions, unused records, unused variables
45+
2. Use language-appropriate tools:
46+
- **C#/F#:** Analyzer warnings for unused members (build with `-warnaserror` catches these)
47+
- **Rust:** The compiler already warns on dead code — check `make lint` output
48+
- **TypeScript:** Check for unexported functions with zero references in `Lql/LqlExtension/`
49+
3. For each candidate: **grep the entire codebase** for references (including tests, scripts, configs). Only mark as dead if truly zero references.
50+
4. List all dead code found with file paths and line numbers. Do NOT delete yet.
51+
52+
### Step 3 — Scan for duplicate code
53+
54+
Search for code blocks that do the same thing in multiple places.
55+
56+
1. Look for functions/methods with identical or near-identical logic
57+
2. Look for copy-pasted blocks (same structure, maybe different variable names)
58+
3. Look for multiple implementations of the same algorithm or pattern
59+
4. Check across module boundaries — duplicates often hide in different projects (DataProvider, Lql, Sync, Gatekeeper, Samples)
60+
5. For each duplicate pair: note both locations, what they do, and how they differ (if at all)
61+
6. List all duplicates found. Do NOT merge yet.
62+
63+
### Step 4 — Scan for duplicate tests
64+
65+
Search for tests that verify the same behavior.
66+
67+
1. Look for test functions with identical assertions against the same code paths
68+
2. Look for test fixtures/helpers that are duplicated across test files
69+
3. Look for integration tests that fully cover what a unit test also covers (keep the integration test, mark the unit test as redundant per CLAUDE.md rules)
70+
4. List all duplicate tests found. Do NOT delete yet.
71+
72+
### Step 5 — Apply changes (one at a time)
73+
74+
For each change, follow this cycle: **change -> test -> verify coverage -> continue or revert**.
75+
76+
#### 5a. Remove dead code
77+
- Delete dead code identified in Step 2
78+
- After each deletion: run `make test` and `make coverage-check`
79+
- If tests fail or coverage drops: **revert immediately** and investigate
80+
81+
#### 5b. Merge duplicate code
82+
- For each duplicate pair: extract the shared logic into a single function/module
83+
- Update all call sites to use the shared version
84+
- After each merge: run `make test` and `make coverage-check`
85+
- If tests fail: **revert immediately**. The duplicates may have subtle differences you missed.
86+
87+
#### 5c. Remove duplicate tests
88+
- Delete the redundant test (keep the more thorough one)
89+
- After each deletion: run `make coverage-check`
90+
- If coverage drops: **revert immediately**. The "duplicate" test was covering something the other wasn't.
91+
92+
### Step 6 — Final verification
93+
94+
1. Run `make test` — all tests must still pass
95+
2. Run `make coverage-check` — coverage must be >= the baseline from Step 1
96+
3. Run `make lint` and `make fmt-check` — code must be clean
97+
4. Report: what was removed, what was merged, final coverage vs baseline
98+
99+
## Rules
100+
101+
- **No test coverage = do not touch.** If a file has no tests covering it, leave it alone entirely.
102+
- **Coverage must not drop.** The coverage floor from Step 1 is sacred.
103+
- **One change at a time.** Make one dedup change, run tests, verify coverage. Never batch multiple dedup changes before testing.
104+
- **When in doubt, leave it.** If two code blocks look similar but you're not 100% sure they're functionally identical, leave both.
105+
- **Preserve public API surface.** Do not change function signatures, record names, or module exports that external code depends on. Internal refactoring only.
106+
- **Three similar lines is fine.** Only dedup when the shared logic is substantial (>10 lines) or when there are 3+ copies.

.claude/skills/format/SKILL.md

Lines changed: 0 additions & 20 deletions
This file was deleted.

.claude/skills/spec-check/SKILL.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
name: spec-check
3+
description: Audits spec/plan documents against the codebase to ensure every spec section has implementing code and tests. Use when the user says "check specs", "audit specs", "spec coverage", or "validate specs".
4+
---
5+
<!-- agent-pmo:d75d5c8 -->
6+
7+
# Spec Check
8+
9+
Audit spec and plan documents against the codebase.
10+
11+
## Steps
12+
13+
### Step 1 — Validate spec ID structure
14+
15+
For every markdown file in `docs/specs/`:
16+
1. Find all headings that contain a spec ID (pattern: `[GROUP-TOPIC-DETAIL]`)
17+
2. Validate each ID:
18+
- MUST be uppercase, hyphen-separated
19+
- MUST NOT contain sequential numbers (e.g., `[SPEC-001]` is ILLEGAL)
20+
- First word is the **group** — all sections sharing the same group MUST be adjacent
21+
3. Check for duplicate IDs across all spec files
22+
4. Report any violations
23+
24+
### Step 2 — Find spec documents
25+
26+
Scan `docs/specs/` and `docs/plans/` for all markdown files. For each file:
27+
1. Extract all spec section IDs
28+
2. Build a map: `spec ID → file path + heading`
29+
30+
### Step 3 — Check code references
31+
32+
For each spec ID found in Step 2:
33+
1. Search the entire codebase (C#, Rust, TypeScript, F# files) for references to the ID
34+
2. A reference is any comment containing the spec ID (e.g., `// Implements [AUTH-TOKEN-VERIFY]`)
35+
3. Record which files reference each spec ID
36+
37+
### Step 4 — Check test references
38+
39+
For each spec ID:
40+
1. Search test files for references to the ID
41+
2. A test reference is a comment like `// Tests [AUTH-TOKEN-VERIFY]` in a test file
42+
43+
### Step 5 — Verify code logic matches spec
44+
45+
For spec IDs that DO have code references:
46+
1. Read the spec section
47+
2. Read the implementing code
48+
3. Check that the code actually does what the spec describes
49+
4. Flag any discrepancies
50+
51+
### Step 6 — Report
52+
53+
Output a table:
54+
55+
| Spec ID | Spec File | Code References | Test References | Status |
56+
|---------|-----------|-----------------|-----------------|--------|
57+
58+
Status values:
59+
- **COVERED** — has both code and test references
60+
- **UNTESTED** — has code references but no test references
61+
- **UNIMPLEMENTED** — has no code references at all
62+
- **ORPHANED** — spec ID found in code but not in any spec document
63+
64+
## Rules
65+
66+
- Never modify spec documents — only report findings
67+
- Never modify code — only report findings
68+
- Every spec section MUST have at least one code reference and one test reference
69+
- Orphaned references (code mentioning a spec ID that doesn't exist) are errors

0 commit comments

Comments
 (0)