walker: F5 — drop preceding-clause keywords from committed-child Incomplete sets
walk_seq's Incomplete arm unconditionally merged the accumulated skipped-Optional expectations (pending_skipped) into the child's expected set. When a child committed terminals before going Incomplete (e.g. `order by` consumed, now awaiting a sort item), this leaked ~13 clause keywords from clauses positioned *before* the committed child — WHERE/GROUP BY/HAVING, the FROM's JOIN options, set-ops — into the ORDER BY completion list, shoving the actual columns off-screen. Merge pending_skipped only when the Incomplete-producing child consumed nothing (path length unchanged): the cursor still sits at the optional boundary, so those optionals are genuine alternatives. A committed child means the cursor is past them. Tests: walker expected-set guard (+ over-correction guard) and a full-stack completion-layer regression test.
This commit is contained in:
@@ -1474,6 +1474,38 @@ mod tests {
|
||||
assert!(!cs.contains(&"Stock".to_string()), "got {cs:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn order_by_completion_omits_preceding_clause_keywords() {
|
||||
use crate::dsl::types::Type;
|
||||
// F5 (handoff 30 §3.3): at `… order by ` the candidate
|
||||
// list is the start of a sort item — the table's columns
|
||||
// plus expression-start keywords. It must NOT be padded
|
||||
// with clause keywords belonging to clauses positioned
|
||||
// *before* ORDER BY (the FROM's JOIN options, WHERE /
|
||||
// GROUP BY / HAVING, set-ops). Those used to shove the
|
||||
// columns off-screen.
|
||||
let cache = schema_with_table(
|
||||
"Things",
|
||||
&[("Name", Type::Text), ("Qty", Type::Int)],
|
||||
);
|
||||
let input = "select Name from Things order by ";
|
||||
let cs = cands_with(input, input.len(), &cache);
|
||||
// The columns the user wants are offered:
|
||||
assert!(cs.contains(&"Name".to_string()), "got {cs:?}");
|
||||
assert!(cs.contains(&"Qty".to_string()), "got {cs:?}");
|
||||
// Preceding-clause keywords must not leak in:
|
||||
for kw in [
|
||||
"where", "group", "having", "join", "union", "intersect",
|
||||
"except", "left", "right", "full", "cross", "inner", "as",
|
||||
] {
|
||||
assert!(
|
||||
!cs.contains(&kw.to_string()),
|
||||
"preceding-clause keyword `{kw}` leaked into ORDER BY \
|
||||
completion; got {cs:?}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_where_offers_only_current_table_columns() {
|
||||
use crate::dsl::types::Type;
|
||||
|
||||
Reference in New Issue
Block a user