refactor(semantic): shared helpers, ImportKind, UTF-8 trace, populated exports - #117
Merged
Merged
Conversation
…d exports Four cross-cutting cleanups identified in the adapter review, applied across all 9 language adapters (bash + clojure + go + ruby + rust + java + c + cpp + python + typescript). ## 1. Shared helpers — `semantic/common.rs` Three helpers previously duplicated 7+ times across adapters now live in one place: - `node_text(node, source)` — UTF-8 decode with structured-log fallback (see #3). - `find_node_at_range(root, start, end)` — depth-first range match used by every `find_callees_in_range` impl. - `signature_first_line(node, source)` and `signature_up_to_body(node, source)` — the two signature builders. Per-adapter rules choose between them based on the language's body-field convention. `ByteRange::from(tree_sitter::Node)` (in `types.rs`) replaces the 7 hand-written constructors. Each adapter's local `text()` / `range()` shim is preserved as a one-liner that delegates, keeping the call-site shape (`self.text(n, s)`) so the bulk of each adapter reads unchanged. Net effect: ~150 lines of duplication removed; any future fix to range arithmetic / signature truncation lands in one place. ## 2. `ImportKind` normalization `Import` gained a `kind: ImportKind` field with three variants: - `Header` — C / C++ `#include` - `Module` — single-token namespaces (Go `"fmt"`, Python `os.path`, Ruby `'json'`, Clojure `clojure.string`) - `Qualified` — fully-qualified names with explicit scoping (Java `java.util.List`, Rust `std::sync::Arc`, TypeScript module specifiers) Lets cross-language queries ("what files import this module?") normalize without re-parsing the source string. Each adapter sets `kind` on every `Import` it constructs. ## 3. UTF-8 fallback → `tracing::debug!` `node.utf8_text(s).unwrap_or("")` (the pattern every adapter used) was silent. The fallback is now logged at `debug` level via `common::node_text` — visible under `--verbose` (which enables `dirge=debug`), quiet by default. Chose `debug` over `warn` deliberately: UTF-8 failures aren't load-bearing (the resulting empty symbol name is filtered out downstream) and the log line exists for diagnostic purposes only. Default-mode users running on a single oddball file shouldn't see a noisy warning. ## 4. `exports` field populated The field on `ExtractedFile` was `Vec::new()` in every adapter; now backfilled from `is_exported=true` symbols at the end of each `extract()`. TypeScript + Python preserve their existing explicit-exports list (TS index re-exports are load-bearing); other adapters fall through to the is_exported-derived backfill when their per-language exports vec is empty. Consumers asking "what does this file export?" can now read `extracted.exports` directly instead of iterating the symbol vec. ## Tests 3 new regression tests: - `byte_range_from_node_uses_1_based_lines` — pins the new `From<Node>` impl's line-number contract (the 7 hand-written copies all used `row + 1`; the shared converter has to match). - `imports_are_tagged_module_kind` (Clojure) — verifies the kind classification. - `exports_mirror_is_exported_symbols` (Clojure) — verifies the backfill picks up `defn` while filtering `defn-`. 812 all-features / 729 plugin / 603 default pass (was 809 / 729 / 603). All build profiles + `cargo fmt --check` clean. ## Files touched - `src/semantic/common.rs` (new) - `src/semantic/types.rs` — `ImportKind` enum, `Import.kind` field, `ByteRange::From<Node>` impl, `exports` docstring. - `src/semantic/mod.rs` — wire `common` module. - `src/semantic/adapters/{bash,clojure,go,ruby,rust,java,c,cpp,python,typescript}.rs` — refactored to use shared helpers + new Import shape + populate exports.
allen-munsch
pushed a commit
to allen-munsch/dirge
that referenced
this pull request
Jun 3, 2026
…d exports (dirge-code#117) Four cross-cutting cleanups identified in the adapter review, applied across all 9 language adapters (bash + clojure + go + ruby + rust + java + c + cpp + python + typescript). ## 1. Shared helpers — `semantic/common.rs` Three helpers previously duplicated 7+ times across adapters now live in one place: - `node_text(node, source)` — UTF-8 decode with structured-log fallback (see #3). - `find_node_at_range(root, start, end)` — depth-first range match used by every `find_callees_in_range` impl. - `signature_first_line(node, source)` and `signature_up_to_body(node, source)` — the two signature builders. Per-adapter rules choose between them based on the language's body-field convention. `ByteRange::from(tree_sitter::Node)` (in `types.rs`) replaces the 7 hand-written constructors. Each adapter's local `text()` / `range()` shim is preserved as a one-liner that delegates, keeping the call-site shape (`self.text(n, s)`) so the bulk of each adapter reads unchanged. Net effect: ~150 lines of duplication removed; any future fix to range arithmetic / signature truncation lands in one place. ## 2. `ImportKind` normalization `Import` gained a `kind: ImportKind` field with three variants: - `Header` — C / C++ `#include` - `Module` — single-token namespaces (Go `"fmt"`, Python `os.path`, Ruby `'json'`, Clojure `clojure.string`) - `Qualified` — fully-qualified names with explicit scoping (Java `java.util.List`, Rust `std::sync::Arc`, TypeScript module specifiers) Lets cross-language queries ("what files import this module?") normalize without re-parsing the source string. Each adapter sets `kind` on every `Import` it constructs. ## 3. UTF-8 fallback → `tracing::debug!` `node.utf8_text(s).unwrap_or("")` (the pattern every adapter used) was silent. The fallback is now logged at `debug` level via `common::node_text` — visible under `--verbose` (which enables `dirge=debug`), quiet by default. Chose `debug` over `warn` deliberately: UTF-8 failures aren't load-bearing (the resulting empty symbol name is filtered out downstream) and the log line exists for diagnostic purposes only. Default-mode users running on a single oddball file shouldn't see a noisy warning. ## 4. `exports` field populated The field on `ExtractedFile` was `Vec::new()` in every adapter; now backfilled from `is_exported=true` symbols at the end of each `extract()`. TypeScript + Python preserve their existing explicit-exports list (TS index re-exports are load-bearing); other adapters fall through to the is_exported-derived backfill when their per-language exports vec is empty. Consumers asking "what does this file export?" can now read `extracted.exports` directly instead of iterating the symbol vec. ## Tests 3 new regression tests: - `byte_range_from_node_uses_1_based_lines` — pins the new `From<Node>` impl's line-number contract (the 7 hand-written copies all used `row + 1`; the shared converter has to match). - `imports_are_tagged_module_kind` (Clojure) — verifies the kind classification. - `exports_mirror_is_exported_symbols` (Clojure) — verifies the backfill picks up `defn` while filtering `defn-`. 812 all-features / 729 plugin / 603 default pass (was 809 / 729 / 603). All build profiles + `cargo fmt --check` clean. ## Files touched - `src/semantic/common.rs` (new) - `src/semantic/types.rs` — `ImportKind` enum, `Import.kind` field, `ByteRange::From<Node>` impl, `exports` docstring. - `src/semantic/mod.rs` — wire `common` module. - `src/semantic/adapters/{bash,clojure,go,ruby,rust,java,c,cpp,python,typescript}.rs` — refactored to use shared helpers + new Import shape + populate exports. Co-authored-by: Yogthos <yogthos@gmail.com>
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.
Four cross-cutting cleanups across all 9 semantic adapters. (1) Shared
common.rsfornode_text/find_node_at_range/ signature builders — ~150 lines of duplication gone;ByteRange::from(Node)replaces 7 hand-written constructors. (2)ImportKindenum (Header/Module/Qualified) so cross-language import queries can normalize. (3) UTF-8 fallback now logs atdebug(visible under--verbose). (4)exportsfield populated fromis_exportedsymbols. 3 new regression tests. 812 all-features pass (was 809).