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:
@@ -290,6 +290,33 @@ fn walk_node_inner(
|
||||
ctx.pending_hint_mode = Some(*mode);
|
||||
walk_node(source, pos, inner, ctx, path, per_byte)
|
||||
}
|
||||
Node::Concept { topic, inner } => {
|
||||
// Issue #37 / ADR clause-concept-hints D1. Walk the
|
||||
// inner clause, then record its covered byte span in
|
||||
// `ctx.concept_spans` iff the inner *committed* — i.e.
|
||||
// matched, ran out mid-clause (Incomplete), or hit a
|
||||
// hard failure after engaging (Failed). On `NoMatch`
|
||||
// the node never engaged (e.g. a `Choice` tried this
|
||||
// branch and it didn't apply), so record nothing — no
|
||||
// stale span. `start` is the post-whitespace position
|
||||
// the walk wrapper already resolved.
|
||||
let result = walk_node(source, pos, inner, ctx, path, per_byte);
|
||||
let end = match &result {
|
||||
NodeWalkResult::Matched { end, .. } => Some(*end),
|
||||
NodeWalkResult::Incomplete { position, .. }
|
||||
| NodeWalkResult::Failed { position, .. } => Some(*position),
|
||||
NodeWalkResult::NoMatch { .. } => None,
|
||||
};
|
||||
if let Some(end) = end {
|
||||
ctx.concept_spans
|
||||
.push(crate::dsl::walker::context::ConceptSpan {
|
||||
topic,
|
||||
start: pos,
|
||||
end,
|
||||
});
|
||||
}
|
||||
result
|
||||
}
|
||||
Node::Flag(name) => walk_flag(source, pos, name, path, per_byte),
|
||||
Node::Repeated {
|
||||
inner,
|
||||
|
||||
Reference in New Issue
Block a user