aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/match.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 00:55:01 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 00:55:01 +0200
commit86e55e31f6905ae997619aa095706674e2ffe623 (patch)
tree35397d5b33b453b87473fac849d2fdb21ece36fa /internal/engine/match.go
parent9a77de31dc9759708ce9c2d14ea7c0876c214e71 (diff)
downloadkrino-86e55e31f6905ae997619aa095706674e2ffe623.tar.gz
krino-86e55e31f6905ae997619aa095706674e2ffe623.zip
explain reports captures and the chain a file would get
Diffstat (limited to 'internal/engine/match.go')
-rw-r--r--internal/engine/match.go32
1 files changed, 25 insertions, 7 deletions
diff --git a/internal/engine/match.go b/internal/engine/match.go
index 67f0c06..591f686 100644
--- a/internal/engine/match.go
+++ b/internal/engine/match.go
@@ -228,10 +228,11 @@ func noDelete(f *facts, scopes [][]string) string {
// RuleTrace is one rule's outcome in an Explain call.
type RuleTrace struct {
- Rule *Rule
- Match bool
- Trace *cond.Trace // nil when not evaluated
- Stopped string // "stopped by rule acme" when an earlier (stop) ended the search
+ Rule *Rule
+ Match bool
+ Captures []string // of a matching rule, as its actions' {N} see them
+ Trace *cond.Trace // nil when not evaluated
+ Stopped string // "stopped by rule acme" when an earlier (stop) ended the search
}
// ExcludeTrace is one (exclude ...) form's outcome in an Explain call.
@@ -250,6 +251,10 @@ type Explanation struct {
Excluded string // the first exclude that matches, which sets the file aside; "" when none does
Rules []RuleTrace
NoDelete string // why a delete from the matching rules would be skipped (spec §5.5); "" when it would not
+ // Chain is what the matching rules would do to the file: the same steps
+ // the directory's plan builds for it, placeholders expanded and
+ // conflicts resolved (GUI design §1.3).
+ Chain []plan.Step
}
// Explain reports, for one file, whether krino's ordinary scan would ever
@@ -333,11 +338,16 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error)
continue
}
}
+ var caps []string
if match {
+ // Eval, on the same memoised facts and before matched becomes
+ // true, is what gives the captures its actions would use.
+ res := r.Cond.Eval(f)
+ caps = res.Captures
f.matched = true
- matched = append(matched, RuleMatch{Rule: r})
+ matched = append(matched, RuleMatch{Rule: r, Captures: caps, Reasons: res.Reasons})
}
- rules = append(rules, RuleTrace{Rule: r, Match: match, Trace: trace})
+ rules = append(rules, RuleTrace{Rule: r, Match: match, Captures: caps, Trace: trace})
if match && r.Conf.Stop {
stoppedBy = r.Name
}
@@ -347,7 +357,15 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error)
noDel = noDelete(f, d.DupScopes)
}
- return &Explanation{Dir: d, File: sf, Skip: skip, Excludes: excludes, Excluded: excluded, Rules: rules, NoDelete: noDel}, nil
+ var chain []plan.Step
+ if len(matched) > 0 {
+ in := []plan.Input{{File: sf, Rules: planRules(matched), NoDelete: noDel}}
+ if built := plan.Build(d.Root, in, now, plan.OS{}, plan.NewClaims()); len(built) == 1 {
+ chain = built[0].Steps
+ }
+ }
+
+ return &Explanation{Dir: d, File: sf, Skip: skip, Excludes: excludes, Excluded: excluded, Rules: rules, NoDelete: noDel, Chain: chain}, nil
}
// excludesUseDuplicate reports whether any of d's excludes has a