Reuse the declaration validation path across siblings

This commit is contained in:
2026-11-07 17:00:12 +00:00
parent e46d28a924
commit aac0e11ae6
4 changed files with 91 additions and 53 deletions

View File

@@ -443,42 +443,46 @@ func validateCommandDeclaration(command Command) error {
func validateCommandPlacement(command Command) error {
var issues []error
collectDeclarationIssues(command, nil, true, &issues)
// Keep the grown slice header across recursive calls so siblings reuse capacity.
var path []string
var collectDeclarationIssues func(Command, bool)
collectDeclarationIssues = func(command Command, root bool) {
if command.record == nil {
issues = append(issues, errors.New("invalid zero command declaration"))
return
}
record := command.record
length := len(path)
path = append(path, record.name)
defer func() { path = path[:length] }()
var label string
if len(record.issues) > 0 || (record.rootOnly && !root) {
label = commandpath.Path(path).String()
}
for _, issue := range record.issues {
if label != "" {
issues = append(issues, fmt.Errorf("command %q: %w", label, issue))
} else {
issues = append(issues, issue)
}
}
if record.rootOnly && !root {
issues = append(issues, fmt.Errorf("root-only command %q is nested beneath another command", label))
}
if record.invalid || record.absent {
return
}
for _, child := range record.children {
if child.record == nil {
continue
}
collectDeclarationIssues(child, false)
}
}
collectDeclarationIssues(command, true)
return errors.Join(issues...)
}
func collectDeclarationIssues(command Command, parents []string, root bool, issues *[]error) {
if command.record == nil {
*issues = append(*issues, errors.New("invalid zero command declaration"))
return
}
record := command.record
path := append(parents, record.name)
var label string
if len(record.issues) > 0 || (record.rootOnly && !root) {
label = commandpath.Path(path).String()
}
for _, issue := range record.issues {
if label != "" {
*issues = append(*issues, fmt.Errorf("command %q: %w", label, issue))
} else {
*issues = append(*issues, issue)
}
}
if record.rootOnly && !root {
*issues = append(*issues, fmt.Errorf("root-only command %q is nested beneath another command", label))
}
if record.invalid || record.absent {
return
}
for _, child := range record.children {
if child.record == nil {
continue
}
collectDeclarationIssues(child, path, false, issues)
}
}
func validateCommandName(name string) error {
return commandpath.ValidateComponent(name)
}