ADR-0022 stage 8c: IdentSlot propagation + SchemaCache API
`IdentSlot` gains `expected_label()` and the round-trip
`from_expected_label()`. The four slot kinds map to the
user-facing labels "identifier" (NewName), "table name",
"column name", "relationship name".
`ident_ctx(slot)` now actually applies `slot.expected_label()`
as the chumsky label (was documentation-only after stage 6).
Parser errors and the hint panel's "expected: …" prose now
read with the slot-specific name: "expected table name"
instead of the generic "expected identifier". One parser
test updated accordingly; the four catalog `parse.token.*`
keys are unaffected (the slot labels are a parallel surface).
New `completion::SchemaCache { tables, columns,
relationships }` struct + `for_slot(slot) -> &[String]`
accessor. Empty by default; runtime wiring lands in a
follow-on substage. NewName slots return `&[]`
unconditionally.
`candidates_at_cursor` extended to accept `&SchemaCache`:
when the parser's expected-set includes a slot label,
schema candidates from the cache are added alongside the
keyword candidates. Both sources are then prefix-filtered,
combined, sorted, deduplicated. App::schema_cache field
threaded into both the App-side completion paths and the
ambient_hint computation in ui.
Tests: 738 passing, 0 failing, 1 ignored (730 baseline →
+8: 2 IdentSlot label round-trip tests, 6 completion-with-cache
cases covering table/column/relationship slots, prefix
filtering, empty cache, and NewName-no-candidates).
Clippy clean.
User-visible: identifier completion infrastructure is in
place but the cache is always empty — runtime wiring (the
next substage) will populate it on project load and after
successful DDL, at which point Tab on identifier slots
starts offering schema names.
This commit is contained in:
+16
-2
@@ -135,6 +135,11 @@ pub struct App {
|
||||
/// keystroke — no completion mode, just a transient
|
||||
/// memory of "the last thing Tab did."
|
||||
pub last_completion: Option<crate::completion::LastCompletion>,
|
||||
/// Per-project schema lookup cache feeding Tab completion
|
||||
/// for identifier slots (ADR-0022 §9 + stage 8c). Empty
|
||||
/// by default; refreshed by the runtime on project load
|
||||
/// and after successful DDL.
|
||||
pub schema_cache: crate::completion::SchemaCache,
|
||||
}
|
||||
|
||||
/// Dialogs that take over keyboard input when active.
|
||||
@@ -245,6 +250,7 @@ impl App {
|
||||
fatal_message: None,
|
||||
modal: None,
|
||||
last_completion: None,
|
||||
schema_cache: crate::completion::SchemaCache::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,7 +689,11 @@ impl App {
|
||||
/// candidates to insert.
|
||||
fn start_completion(&mut self, start_idx: usize) -> Option<crate::completion::LastCompletion> {
|
||||
let cursor = self.input_cursor.min(self.input.len());
|
||||
let comp = crate::completion::candidates_at_cursor(&self.input, cursor)?;
|
||||
let comp = crate::completion::candidates_at_cursor(
|
||||
&self.input,
|
||||
cursor,
|
||||
&self.schema_cache,
|
||||
)?;
|
||||
let idx = start_idx % comp.candidates.len();
|
||||
let inserted = format!("{} ", comp.candidates[idx]);
|
||||
let original_text =
|
||||
@@ -708,7 +718,11 @@ impl App {
|
||||
// before we can pick "last". Compute the completion
|
||||
// first, then call start_completion with that index.
|
||||
let cursor = self.input_cursor.min(self.input.len());
|
||||
let comp = crate::completion::candidates_at_cursor(&self.input, cursor)?;
|
||||
let comp = crate::completion::candidates_at_cursor(
|
||||
&self.input,
|
||||
cursor,
|
||||
&self.schema_cache,
|
||||
)?;
|
||||
let last = comp.candidates.len() - 1;
|
||||
// Fall through to the same path so the inserted text
|
||||
// and memo construction stay in one place.
|
||||
|
||||
Reference in New Issue
Block a user