feat: ADR-0035 4i(e) — colour DSL vs SQL completions when mixed
Building on the 4i(d) merge: tag each completion Candidate with a ModeClass (Both/Advanced/Simple) and, in the hint UI, colour the continuations by mode ONLY when a candidate list actually mixes modes (a shared entry word offering both SQL and DSL forms) — Advanced → theme.mode_advanced, Simple → theme.mode_simple, Both → the token-kind colour. A single-mode list (the common case, e.g. deep inside a SQL statement) keeps the token-kind colours, so the tint appears only where it distinguishes DSL from SQL. With (d)'s Both → Advanced → Simple block-ordering, each colour reads as one contiguous block. Candidate gains a `mode` field (typing_surface snapshots regenerated — uniformly `mode: Both`, no semantic change). Tests: render_candidate_line mixed-mode colours + the single-mode-keeps-kind-colour rule. Full suite 1913 passing / 0 failing / 1 ignored; clippy clean.
This commit is contained in:
+23
-3
@@ -146,6 +146,11 @@ fn expected_at(leading: &str, mode: Mode) -> Vec<Expectation> {
|
||||
pub struct Candidate {
|
||||
pub text: String,
|
||||
pub kind: CandidateKind,
|
||||
/// Source-mode classification (ADR-0035 §4i e). `Both` (neutral)
|
||||
/// except for the merged continuations of a shared entry word, where
|
||||
/// the hint UI colours `Advanced`/`Simple` differently — but only
|
||||
/// when the candidate list actually mixes modes.
|
||||
pub mode: ModeClass,
|
||||
}
|
||||
|
||||
/// Re-ranker for a freshly-computed candidate list (ADR-0024
|
||||
@@ -712,26 +717,37 @@ pub fn candidates_at_cursor_with_in_mode(
|
||||
candidates.extend(identifiers.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Identifier,
|
||||
mode: ModeClass::Both,
|
||||
}));
|
||||
candidates.extend(keywords.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Keyword,
|
||||
// Keywords carry their merged mode-class (Both unless a shared entry
|
||||
// word mixed simple + advanced continuations — ADR-0035 §4i e).
|
||||
candidates.extend(keywords.into_iter().map(|text| {
|
||||
let mode = kw_mode(text.as_str());
|
||||
Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Keyword,
|
||||
mode,
|
||||
}
|
||||
}));
|
||||
candidates.extend(type_names.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Keyword,
|
||||
mode: ModeClass::Both,
|
||||
}));
|
||||
candidates.extend(composites.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Keyword,
|
||||
mode: ModeClass::Both,
|
||||
}));
|
||||
candidates.extend(punct_candidates.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Punct,
|
||||
mode: ModeClass::Both,
|
||||
}));
|
||||
candidates.extend(flags.into_iter().map(|text| Candidate {
|
||||
text,
|
||||
kind: CandidateKind::Flag,
|
||||
mode: ModeClass::Both,
|
||||
}));
|
||||
|
||||
if candidates.is_empty() {
|
||||
@@ -2219,6 +2235,7 @@ mod tests {
|
||||
Candidate {
|
||||
text: text.to_string(),
|
||||
kind: CandidateKind::Keyword,
|
||||
mode: ModeClass::Both,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2260,14 +2277,17 @@ mod tests {
|
||||
Candidate {
|
||||
text: "b".to_string(),
|
||||
kind: CandidateKind::Keyword,
|
||||
mode: ModeClass::Both,
|
||||
},
|
||||
Candidate {
|
||||
text: "a".to_string(),
|
||||
kind: CandidateKind::Keyword,
|
||||
mode: ModeClass::Both,
|
||||
},
|
||||
Candidate {
|
||||
text: "c".to_string(),
|
||||
kind: CandidateKind::Identifier,
|
||||
mode: ModeClass::Both,
|
||||
},
|
||||
];
|
||||
let out = identity_ranker(input.clone());
|
||||
|
||||
Reference in New Issue
Block a user