Reuse the declaration validation path across siblings
This commit is contained in:
70
command.go
70
command.go
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user