Swift semantic adapter, and name the test holding a human wait - #792
Merged
Conversation
added 2 commits
August 15, 2026 12:30
The Swift adapter (GH #778 follow-up). tree-sitter-swift folds struct, class, enum, actor AND extension into one `class_declaration` kind, so the shapes are read from a parser dump rather than guessed: an extension declares no type and is not emitted as one, but its members attribute to the type it extends, which is where someone looking for them expects to find them. Swift's default access level is internal, so only public/open/package count as exported. Registering it in the syntax gate is a HARD write block, so the grammar was measured first against async/await, actors, generics with where-clauses, property wrappers, result builders, @main, multi-line strings, custom operators and enums with associated values — no false errors. That evidence is a test, so a grammar regression says so before a user finds their valid Swift refused. The gate keeps its own extension table, separate from the adapter registry, with nothing to notice a language in one and not the other — the fourth such table this week. Adapter extensions must now be gated or listed in GATE_EXCLUSIONS with a reason; the check derives from the registry, which is itself now one list (default_adapters) rather than a copy in the manager. It immediately found `.h`: claimed by the C adapter, ungated, and correctly so — C++ in a header is ordinary and tree-sitter-c would refuse it on a hard block. Now that is written down instead of being an accident. For dirge-lfux, the human-wait flake: no fix, because nine full-suite runs with instrumentation would not reproduce it, and the relative-assertion fix I tried first was unsound — a baseline over a shared global is no better than a level over one. What ships is HOLDERS, a test-only record of which thread holds each wait, named in every assertion failure. Cargo names test threads after the test, so the next occurrence prints the culprit rather than an unattributable flake.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The two follow-ups filed from #791.
Swift semantic adapter (dirge-3cfq)
find_definition,list_symbolsandget_symbol_bodyare tree-sitter backed, not LSP backed, so a model asked to find a Swift symbol got nothing while thelsptool answered the same question correctly. And the pre-write syntax gate did not cover.swiftat all.tree-sitter-swiftfoldsstruct,class,enum,actorandextensioninto oneclass_declarationkind, so the node shapes here were dumped from the parser rather than guessed. Two calls worth stating:Greeterdefined" returns two answers, one of them wrong. Its members do attribute to the type it extends.internal, so onlypublic/open/packagecount as exported. Treating unmarked declarations as exported would makeexportsmeaningless, since most Swift carries no modifier.Registering
.swiftin the syntax gate is a hard write block, so the grammar was measured before wiring it in — async/await, actors, generics withwhere, property wrappers, result builders,@main, multi-line strings, custom operators, subscripts, enums with associated values: no false errors. That measurement is now a test, so a grammar regression reports itself instead of silently refusing valid Swift.The fourth table
The gate keeps its own extension→grammar map, separate from the adapter registry, with nothing to notice a language present in one and absent from the other. That is the same shape as the three-table LSP bug in #791, and it is why
.swiftcould have an adapter and no gate coverage.Adapter extensions must now be either gated or listed in
GATE_EXCLUSIONSwith a reason, checked against the registry — which is itself now a singledefault_adapters()list rather than a copy inside the manager. The check immediately found.h: claimed by the C adapter, ungated, and correctly so — C++ in a header is ordinary andtree-sitter-cwould refuse it on a hard block. Now that is a written decision rather than an accident..sql,.ex/.exs/.heexand.dfyare likewise recorded, the last three honestly marked "not assessed" rather than pretending they were considered.The human-wait flake (dirge-lfux) — diagnostic only
No fix, deliberately. Nine full-suite runs (six default, three at
--test-threads=32) with instrumentation would not reproduce it; both original occurrences were under heavy machine load.The first fix I tried was unsound and is worth recording: making the assertions relative (baseline, act, compare) fails just as hard, because the baseline is read at T0 and a concurrent guard lands at T1. It turned an occasional flake into a deterministic failure. A delta over a shared mutable global is no more sound than a level over one.
What ships is
HOLDERS, a test-build-only record of which thread holds each wait, named in every assertion failure. Cargo names test threads after the test, so the next occurrence prints the culprit instead of an unattributable flake. The remaining decision — sweep every test that can raise the counter intoTEST_GATE, or make the watchdog's input injectable so tests stop sharing one counter — is written up on the bead.Verification
Against the real SwiftPM package from #791:
find_definition greet→Greeter.swift:3 [method] public func greet(_ name: String) -> Stringlist_symbols→ the type and its members, with export flagsSyntax check failed … 1 error(s) detected by tree-sitter, and no file writtenFull suite 5621 pass, four clippy configs and fmt clean.