Each is marked as confirmed by running the code against the test project or a small script, or as read from the code without running. Line numbers refer to 0.3.8 (commit 37c78b6), where the review was done. Thirteen of the fifteen findings are fixed, fully or in part: twelve in 0.4.0 and F13 in 0.4.1.
{{ config() }} header disabled column and CTE completionA file containing a config call never parsed, in any dialect, so it had no tree to complete from. Config and other standalone macro calls, block set and call bodies, and else branches are now blanked out before parsing, with all positions kept.
Merged, released in 0.4.0, with tests. Still a parse error: a for loop ending each item with a comma, and jinja glued to an identifier.
Commit 9f5490b gave _get_database_schema a third required argument and updated only the Postgres caller. The other four raised a swallowed TypeError.
Fixed in b3989db. A DuckDB load test now guards it; the other three were not run.
Missing fields, a half-written file and unparseable SQL are now skipped, and the project's dialect is used. Merged, released in 0.4.0, with tests.
Still open: the refresh replaces typed warehouse columns with a weaker list.
A missing backend package, no profiles.yml, or an unset env_var used to remove model and source completion too. The load now raises only when there is no project; everything else is recorded in a load report and shown as a warning.
Merged, released in 0.4.0, with tests and an end-to-end run of the server.
A. for ... }} A offered nothing, because declarations were found in lowercased text. Merged, released in 0.4.0, with tests.
ref spelling bound an aliasInner spaces and {{- whitespace control now work for ref and source. Merged, released in 0.4.0, with tests.
Still open: the two-argument ref('package', 'x'), a ref used without an alias, and subquery aliases.
It now inserts the quote that was typed, and the second argument offers the tables of the named source. Merged, released in 0.4.0, with tests.
select * from a CTE completed as a literal *CTEs are now resolved in order, so a star and its column types follow through earlier CTEs. A star that cannot be expanded is not offered. Merged, released in 0.4.0, with tests.
A cursor after the final newline gave IndexError. Merged, released in 0.4.0, with tests.
Both now page through every database and table, with two-page tests. Merged, released in 0.4.0. Checked against stubbed clients, not a real account.
Still open: the region and access keys in the profile are ignored; only the named AWS profile is used.
Every documented source is now kept; the warehouse only adds columns to the ones it has. Merged, released in 0.4.0, with tests.
Tables are now identified by schema, and by database where the reader reports one. A model matches the target schema first; a source matches the schema it declares. Ambiguous names match nothing. Merged, released in 0.4.0, with tests.
Models with a literal alias, custom schema or database are matched by it. Merged, released in 0.4.0. Still open: sources in a database the reader does not scan, and locations set in dbt_project.yml or by macros.
Confirmed on a generated project with 2,000 models and 6,000 warehouse tables: 35.6 seconds to the first completion. Now 2.4 seconds, with live columns in after 5.4. The warehouse is read in one statement per database, on a background thread.
Merged, released in 0.4.1, with tests. The scan still covers every schema on purpose, so undocumented tables can complete. Still open: Spark reads table by table, and YAML files are parsed twice.
Fixed on main, not released: --profiles-dir and DBT_PROFILES_DIR are honoured in dbt's order. Still open: there is no way to choose a target other than the profile's default, and the VS Code client watches project files but the server reloads on nothing except run results.
A model entry with only a description raised KeyError, which failed the whole config source for the project. Confirmed by running it. Merged, released in 0.4.0, with tests.
Smaller items, such as the extras in pyproject.toml, are in the task list. The MySQL target requires a user key; I believe dbt-mysql calls it username, which is worth checking against a real profile.
Before 0.4.0 the tests covered text handling only. Finding F2 would have been caught by a single test that opens the DuckDB file already in the repo; that test now exists. The idea is to test each layer at the cheapest level that can catch its bugs, and to stop needing an editor to check anything.
Most reader code is turning an API response into columns. The Databricks, Athena, Glue and Redshift readers now run against stand-in clients in test/test_cloud_readers.py. No account needed, runs in CI. Next step: replace the hand-written responses with ones recorded from a real workspace.
Runs the full load against testdata/project and asserts on the columns. In-process, no setup, covers the shared ibis path and the merge rules.
Postgres, MySQL, SQL Server and Spark Connect from test/compose.yml, on ports of their own. test/test_containers.py seeds each one and runs the real reader, a full project load and dbt-ls check. just test-all starts them, runs everything and stops them again; about 15 seconds to start, 4 seconds to run. On its first run it found two bugs: the Spark extra could not connect at all, and SQL Server types lost their precision. A CI job runs the same file; it has not run on GitHub yet.
scripts/generate_bench_project.py writes a dbt project and an empty DuckDB warehouse of any size. The numbers under F13 come from it.
dbt-ls check loads a project and prints what each source returned, how long it took, and any error. A cloud check is now one command and a pasted result. Not yet done: running it against a real Databricks or AWS account and recording the result with date and version.
# one command per tier
uv run pytest # tier 0+1: unit, fakes, DuckDB (seconds, CI)
docker compose -f test/compose.yml up -d --wait && \
uv run pytest -m containers # tier 2: Postgres, MySQL, SQL Server, Spark
uv run dbt-ls check path/to/proj # tier 3: cloud smoke test, by hand
Fabric and Synapse speak the same protocol and dialect as SQL Server. If the Fabric reader is the SQL Server reader plus a different sign-in, the query logic is covered by the SQL Server container and only the sign-in stays unverified. Label that honestly in the README as untested, and ask a Fabric user to run dbt-ls check. Until then Fabric users already get everything except live columns by using config,catalog.
serve_completions in server.py. It is one function with a branch per kind of completion, and every other module is reached from it or from _load_project just above it.
Set DBT_LS_LOG_LEVEL=DEBUG. Everything goes to stderr, which the editor shows in its LSP log. Each completion logs which branch matched and what it served.
Use the complete helper in test/conftest.py. Write the SQL with a | where the cursor is and pass models and sources built with the model and source helpers.
The parser gives query block boundaries and CTE select lists, but fails on text being typed. The regexes find alias declarations in any text. Scope comes from the last good tree, declarations from the live buffer.
CTE columns come from the file's own select list. Model columns come only from YAML, the catalog, the warehouse or a dbt run. A model that is undocumented, never built and not in the catalog has none.
Nothing that changes behaviour. Main is pushed and CI is green, container tests included. Not released since 0.4.1: --profiles-dir / DBT_PROFILES_DIR, the devcontainer, hover, and keeping undocumented tables as WarehouseTable with one state.tables list. Still outside git: testdata/project/.user.yml and todo.md. The untracked seed.py draft is no longer in the working tree; it was never committed.
Run uv run docs/build.py. It writes docs/index.html from the fragments in docs/src, from README.md (the Use it tab) and from todo.md (the Tasks tab). Edit those, never index.html.