feat(hint): clause-concept hints layered on F1 (issue #37)
Add a hint.concept.* tier-3 layer surfaced when the cursor sits inside a recognized clause (referential actions, 1:n/m:n cardinality, primary key, unique, check, foreign key), layered beneath the per-form block. New Node::Concept grammar wrapper records clause byte-spans; concept_topic_at_cursor resolves the innermost containing span. Examples are mode-keyed so they stay syntax-correct in both simple and advanced mode. Draft ADR (number at merge).
This commit is contained in:
@@ -134,6 +134,18 @@ pub struct WalkContext<'a> {
|
||||
/// resolver reads this directly instead of inferring the
|
||||
/// slot kind from the shape of the expected set.
|
||||
pub pending_hint_mode: Option<crate::dsl::grammar::HintMode>,
|
||||
/// Byte spans of the clause-concept regions the walk passed
|
||||
/// through (issue #37 / ADR clause-concept-hints, D1).
|
||||
///
|
||||
/// A `Node::Concept { topic, inner }` wrapper pushes one entry
|
||||
/// per *committed* inner walk (Matched / Incomplete / Failed —
|
||||
/// never on NoMatch). Unlike `pending_hint_mode`, this is
|
||||
/// **append-only and never cleared on match**, so a fully-typed
|
||||
/// clause keeps its span — that is what lets the F1
|
||||
/// clause-concept resolver report a concept for a cursor parked
|
||||
/// *inside* already-typed clause text, not only at the slot
|
||||
/// boundary.
|
||||
pub concept_spans: Vec<ConceptSpan>,
|
||||
/// An `IntroProse` hint captured from an *optional* slot that
|
||||
/// the walk skipped (issue #26). Unlike `pending_hint_mode`
|
||||
/// (cleared on the very next match — including the empty match
|
||||
@@ -227,6 +239,19 @@ pub struct PendingCteHarvest {
|
||||
pub cte_name_span: (usize, usize),
|
||||
}
|
||||
|
||||
/// A clause-concept region recorded during a walk (issue #37).
|
||||
///
|
||||
/// `topic` is the `hint.concept.<topic>` catalogue key; `[start,
|
||||
/// end]` is the inclusive byte range the clause covered as typed so
|
||||
/// far (`end` is the matched end on a full match, or the stop
|
||||
/// position on an incomplete / failed inner).
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ConceptSpan {
|
||||
pub topic: &'static str,
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
impl<'a> WalkContext<'a> {
|
||||
/// Schemaless walk context — the legacy default used by
|
||||
/// pre-Phase-D callers and tests that don't care about
|
||||
@@ -243,6 +268,7 @@ impl<'a> WalkContext<'a> {
|
||||
pending_value_type: None,
|
||||
pending_value_column: None,
|
||||
pending_hint_mode: None,
|
||||
concept_spans: Vec::new(),
|
||||
surviving_intro_hint: None,
|
||||
user_listed_columns: None,
|
||||
subgrammar_depth: 0,
|
||||
@@ -266,6 +292,7 @@ impl<'a> WalkContext<'a> {
|
||||
pending_value_type: None,
|
||||
pending_value_column: None,
|
||||
pending_hint_mode: None,
|
||||
concept_spans: Vec::new(),
|
||||
surviving_intro_hint: None,
|
||||
user_listed_columns: None,
|
||||
subgrammar_depth: 0,
|
||||
|
||||
Reference in New Issue
Block a user