completion+hint: F1/F2 advanced-mode completion fixes
F1: the hint panel is the completion UI, so a premature "no such table/
column" ERROR on the token the user is still typing must not shadow its
completion. ambient_hint now suppresses an under-cursor error diagnostic
when a completion exists for the (non-empty) partial it overlaps, and
falls through to the candidates. Genuinely-unknown names (no prefix match)
still show the error; WARNINGs are unaffected. Both modes.
F2: projection-before-FROM ("select <cursor> from T" after deleting *)
offered the global column list instead of T's columns, because the §10.6
look-ahead's full-input walk can't reach FROM through an empty projection.
When the look-ahead finds no scope, retry with a neutral placeholder
inserted at the cursor so the trailing FROM/CTE scope is recovered for
narrowing. Only the repaired walk's from_scope/cte_bindings are used.
Test-first: 3 F1 tests (mid-typed completes, unknown still errors, simple-
mode DSL) + 1 F2 multi-table narrowing test. 1469 baseline green.
This commit is contained in:
+27
-1
@@ -279,7 +279,33 @@ pub fn candidates_at_cursor_with_in_mode(
|
||||
&& probe.cte_bindings.is_empty()
|
||||
&& input.len() > leading.len()
|
||||
{
|
||||
Some(crate::dsl::walker::completion_probe_in_mode(input, cache, mode))
|
||||
let direct = crate::dsl::walker::completion_probe_in_mode(input, cache, mode);
|
||||
if direct.from_scope.is_empty() && direct.cte_bindings.is_empty() {
|
||||
// The slot at the cursor is empty/incomplete — e.g. the
|
||||
// projection list of `select <cursor> from T` after the
|
||||
// user deleted `*` — so the full-input walk never
|
||||
// reached FROM and recovered no scope. Repair by
|
||||
// inserting a neutral expression placeholder at the
|
||||
// cursor and re-walking, so the trailing FROM/CTE scope
|
||||
// is recovered for column narrowing (ADR-0032 §10.6).
|
||||
// Only the repaired walk's `from_scope` / `cte_bindings`
|
||||
// are consumed (table + columns), so the inserted token
|
||||
// doesn't perturb the expected set, which comes from the
|
||||
// leading probe.
|
||||
let mut repaired = String::with_capacity(input.len() + 2);
|
||||
repaired.push_str(&input[..start]);
|
||||
repaired.push_str("1 ");
|
||||
repaired.push_str(&input[start..]);
|
||||
let repaired_probe =
|
||||
crate::dsl::walker::completion_probe_in_mode(&repaired, cache, mode);
|
||||
if repaired_probe.from_scope.is_empty() && repaired_probe.cte_bindings.is_empty() {
|
||||
Some(direct)
|
||||
} else {
|
||||
Some(repaired_probe)
|
||||
}
|
||||
} else {
|
||||
Some(direct)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user