Remove unused parser resource plumbing
This commit is contained in:
@@ -76,6 +76,8 @@ rendering. A session owns the mutable backend tree for one invocation; parsing
|
||||
and presentation reuse that session. The adapter returns raw values and neutral
|
||||
syntax failures to core. It does not own the registry, typed input preparation,
|
||||
integration declarations, provider acquisition, or native report rendering.
|
||||
Parser options carry flag-alias selection; invocation context and streams stay
|
||||
with core, while backend output destinations discard and help uses a local buffer.
|
||||
Cobra and pflag imports remain inside this package.
|
||||
|
||||
## Optional modules
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Consolidated audit catalog
|
||||
|
||||
Status: **14 distinct open findings: 14 P3**, consolidated from 30
|
||||
Status: **13 distinct open findings: 13 P3**, consolidated from 30
|
||||
numbered entries in seven audit documents. Reviewed audit state:
|
||||
`db732e3a1de55c844f77870e1c6db683c2685d5d`.
|
||||
|
||||
@@ -257,6 +257,10 @@ consumer compatibility or migration work is needed.
|
||||
|
||||
## F12 — P3: Parser sessions carry unused execution resources
|
||||
|
||||
**Complete.** Unused execution and parser resource plumbing was removed; the
|
||||
backend retains discard destinations and buffered help. Focused routing, help,
|
||||
context-forwarding and session-isolation tests passed.
|
||||
|
||||
Core and the Cobra adapter duplicate stream normalization and retain context and
|
||||
streams through parser options and backend nodes, although the adapter parses
|
||||
and renders buffered help rather than executing callbacks or reading application
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Audit remediation implementation plan
|
||||
|
||||
Status: in progress; Stages 1–12 complete.
|
||||
Status: in progress; Stages 1–13 complete.
|
||||
|
||||
Baseline: `d492c7747175c01a53261206c2b4356e53453621`. Before this sprint,
|
||||
intervening changes recorded decisions and retired the completed older
|
||||
@@ -442,6 +442,12 @@ Complete F21 when both callers share one adapter and preserve their context.
|
||||
|
||||
## Stage 13 — Remove unused parser resource plumbing
|
||||
|
||||
**Complete.** Parser options carry only alias selection, backend output and
|
||||
error destinations explicitly discard, and core retains invocation resources.
|
||||
The test-only App.parse wrapper was removed. Focused routed parsing, help,
|
||||
context, backend parsing and session-isolation tests passed in the offline aligned
|
||||
Go 1.27.0 workspace with `-mod=readonly`. F24 remains open for binding wrappers.
|
||||
|
||||
Findings: F12 and parsing portion of F24. Sources: `execute.go`, `parser.go`,
|
||||
`internal/commandmeta/metadata.go`, and `internal/cobra/parse.go`.
|
||||
|
||||
|
||||
11
execute.go
11
execute.go
@@ -80,10 +80,8 @@ func (a *App) Execute(ctx context.Context, args []string, streams Streams) Outco
|
||||
type execution struct {
|
||||
app *App
|
||||
ctx context.Context
|
||||
streams Streams
|
||||
reporter *Reporter
|
||||
debugEvents []string
|
||||
options commandmeta.ParseOptions
|
||||
snapshot *routingSnapshot
|
||||
session *internalcobra.Session
|
||||
route routeResult
|
||||
@@ -116,13 +114,10 @@ func (current commandExecution) renderHelpTargets(targets []string) Outcome {
|
||||
}
|
||||
|
||||
func newExecution(app *App, ctx context.Context, streams Streams) *execution {
|
||||
streams = normalizeStreams(streams)
|
||||
current := &execution{
|
||||
app: app,
|
||||
ctx: ctx,
|
||||
streams: streams,
|
||||
reporter: newReporter(streams),
|
||||
options: commandmeta.ParseOptions{Context: ctx, Out: streams.Out, Err: streams.Err},
|
||||
}
|
||||
if app != nil {
|
||||
current.snapshot = app.routeSnapshot()
|
||||
@@ -147,7 +142,7 @@ func (current *execution) prepareSession() {
|
||||
if current.snapshot == nil {
|
||||
current.snapshot = current.app.routeSnapshot()
|
||||
}
|
||||
options := current.options
|
||||
options := commandmeta.ParseOptions{}
|
||||
if current.snapshot != nil {
|
||||
switch current.route.kind {
|
||||
case routeCanonical:
|
||||
@@ -201,11 +196,11 @@ func (current *execution) renderHelpTargets(targets []string) Outcome {
|
||||
// Explicit help targets are paths, not command invocations with operands.
|
||||
// Discovery routes have no canonical path and retain only trailing options.
|
||||
if route.kind == routeUnknown || len(route.args) != len(route.canonicalPath) {
|
||||
session := internalcobra.Prepare(snapshot.metadata, current.options)
|
||||
session := internalcobra.Prepare(snapshot.metadata, commandmeta.ParseOptions{})
|
||||
view := commandmeta.HelpView{EnteredPath: targets, CanonicalPath: targets}
|
||||
return current.app.renderHelpViewOutcomeWithSession(view, current.reporter, session)
|
||||
}
|
||||
options := current.options
|
||||
options := commandmeta.ParseOptions{}
|
||||
switch route.kind {
|
||||
case routeCanonical:
|
||||
options.FlagAliases = snapshot.flagAliases[route.canonicalPath.Key()].neutralRecords()
|
||||
|
||||
@@ -4,7 +4,6 @@ package cobra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
@@ -35,8 +34,7 @@ func Prepare(root *commandmeta.Command, options commandmeta.ParseOptions) *Sessi
|
||||
session.metadata = root
|
||||
session.flagAliases = append([]commandmeta.FlagAlias(nil), options.FlagAliases...)
|
||||
session.flagAliasesForPath = options.FlagAliasesForPath
|
||||
options = normalizeOptions(options)
|
||||
session.root, session.declarations = buildTree(root, options)
|
||||
session.root, session.declarations = buildTree(root)
|
||||
return session
|
||||
}
|
||||
|
||||
@@ -289,23 +287,7 @@ func Parse(root *commandmeta.Command, argv []string, options commandmeta.ParseOp
|
||||
return Prepare(root, options).Parse(argv)
|
||||
}
|
||||
|
||||
func normalizeOptions(options commandmeta.ParseOptions) commandmeta.ParseOptions {
|
||||
if options.Context == nil {
|
||||
options.Context = context.Background()
|
||||
}
|
||||
if options.In == nil {
|
||||
options.In = strings.NewReader("")
|
||||
}
|
||||
if options.Out == nil {
|
||||
options.Out = io.Discard
|
||||
}
|
||||
if options.Err == nil {
|
||||
options.Err = io.Discard
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func buildTree(root *commandmeta.Command, options commandmeta.ParseOptions) (*spfcobra.Command, map[*spfcobra.Command]*commandmeta.Command) {
|
||||
func buildTree(root *commandmeta.Command) (*spfcobra.Command, map[*spfcobra.Command]*commandmeta.Command) {
|
||||
nodes := make(map[*spfcobra.Command]*commandmeta.Command)
|
||||
var build func(*commandmeta.Command) *spfcobra.Command
|
||||
build = func(declaration *commandmeta.Command) *spfcobra.Command {
|
||||
@@ -321,10 +303,8 @@ func buildTree(root *commandmeta.Command, options commandmeta.ParseOptions) (*sp
|
||||
if declaration.Runnable {
|
||||
backend.Run = func(*spfcobra.Command, []string) {}
|
||||
}
|
||||
backend.SetContext(options.Context)
|
||||
backend.SetIn(options.In)
|
||||
backend.SetOut(options.Out)
|
||||
backend.SetErr(options.Err)
|
||||
backend.SetOut(io.Discard)
|
||||
backend.SetErr(io.Discard)
|
||||
backend.SetHelpFunc(func(*spfcobra.Command, []string) {})
|
||||
backend.SetFlagErrorFunc(func(_ *spfcobra.Command, err error) error { return err })
|
||||
backend.SetUsageTemplate(usageTemplate)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package cobra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
@@ -182,7 +180,7 @@ func TestParseReturnsNeutralFailuresAndFreshState(t *testing.T) {
|
||||
tree := &Command{Name: "app", Children: []*Command{
|
||||
{Name: "run", Runnable: true, Flags: []Flag{{Name: "value"}}},
|
||||
}}
|
||||
options := ParseOptions{Context: context.Background(), In: strings.NewReader("unused"), Out: io.Discard, Err: io.Discard}
|
||||
options := ParseOptions{}
|
||||
first := Parse(tree, []string{"run", "--value=old"}, options)
|
||||
second := Parse(tree, []string{"run"}, options)
|
||||
if first.Failure != nil || second.Failure != nil {
|
||||
@@ -247,8 +245,7 @@ func TestSelectedPathsResolveThroughBackendParents(t *testing.T) {
|
||||
|
||||
func TestSessionReusesTreeForParseHelpAndUsageWithFreshState(t *testing.T) {
|
||||
tree := &Command{Name: "app", Children: []*Command{{Name: "run", Runnable: true, Flags: []Flag{{Name: "value"}}}}}
|
||||
var output, errors bytes.Buffer
|
||||
session := Prepare(tree, ParseOptions{Context: context.Background(), Out: &output, Err: &errors})
|
||||
session := Prepare(tree, ParseOptions{})
|
||||
first := session.Parse([]string{"run", "--value=old"})
|
||||
if first.Failure != nil || !reflect.DeepEqual(first.FlagValues, [][]string{{"old"}}) {
|
||||
t.Fatalf("first session parse = %#v", first)
|
||||
@@ -261,19 +258,15 @@ func TestSessionReusesTreeForParseHelpAndUsageWithFreshState(t *testing.T) {
|
||||
if failure != nil || !strings.Contains(line, "run") {
|
||||
t.Fatalf("session usage = %q, %v", line, failure)
|
||||
}
|
||||
if output.Len() != 0 || errors.Len() != 0 {
|
||||
t.Fatalf("help escaped session delivery control: out=%q err=%q", output.String(), errors.String())
|
||||
if session.root.OutOrStdout() != io.Discard || session.root.ErrOrStderr() != io.Discard {
|
||||
t.Fatal("backend destinations are not discarded")
|
||||
}
|
||||
|
||||
var secondOutput, secondErrors bytes.Buffer
|
||||
second := Prepare(tree, ParseOptions{Context: context.Background(), Out: &secondOutput, Err: &secondErrors})
|
||||
second := Prepare(tree, ParseOptions{})
|
||||
secondResult := second.Parse([]string{"run"})
|
||||
if secondResult.Failure != nil || !reflect.DeepEqual(secondResult.FlagValues, [][]string{nil}) {
|
||||
t.Fatalf("fresh session state = %#v", secondResult)
|
||||
}
|
||||
if output.Len() != 0 || errors.Len() != 0 || secondOutput.Len() != 0 || secondErrors.Len() != 0 {
|
||||
t.Fatal("prepared session streams were unexpectedly used")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingSessionTreeReturnsNeutralFailures(t *testing.T) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package cobra
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -11,7 +9,7 @@ func BenchmarkPerformanceParse(b *testing.B) {
|
||||
wide := performanceFlatTree(128)
|
||||
wideArgs := []string{"wide127"}
|
||||
deep, deepArgs := performanceNestedTree(24)
|
||||
options := ParseOptions{Context: context.Background(), Out: io.Discard, Err: io.Discard}
|
||||
options := ParseOptions{}
|
||||
|
||||
for _, benchmark := range []struct {
|
||||
name string
|
||||
@@ -41,7 +39,7 @@ func BenchmarkPerformanceParse(b *testing.B) {
|
||||
func BenchmarkPerformanceSessionParseAndHelp(b *testing.B) {
|
||||
root := performanceFlatTree(8)
|
||||
args := []string{"wide007"}
|
||||
session := Prepare(root, ParseOptions{Context: context.Background(), Out: io.Discard, Err: io.Discard})
|
||||
session := Prepare(root, ParseOptions{})
|
||||
result := session.Parse(args)
|
||||
if result.Failure != nil {
|
||||
b.Fatalf("fixture parse failed: %s", result.Failure.Message)
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// its command-line backend.
|
||||
package commandmeta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Key identifies one command inside one routing snapshot.
|
||||
type Key uint64
|
||||
|
||||
@@ -181,14 +176,10 @@ type Result struct {
|
||||
Failure *Failure
|
||||
}
|
||||
|
||||
// ParseOptions makes parser context and streams explicit.
|
||||
// ParseOptions selects flag aliases for parser contexts.
|
||||
type ParseOptions struct {
|
||||
// FlagAliasesForPath selects aliases for the actual parser context when
|
||||
// routing has not already selected one. It overrides FlagAliases when set.
|
||||
FlagAliasesForPath func([]string) []FlagAlias
|
||||
Context context.Context
|
||||
In io.Reader
|
||||
Out io.Writer
|
||||
Err io.Writer
|
||||
FlagAliases []FlagAlias
|
||||
}
|
||||
|
||||
@@ -5,19 +5,10 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
internalcobra "go.maximumdirect.net/commandkit/internal/cobra"
|
||||
commandmeta "go.maximumdirect.net/commandkit/internal/commandmeta"
|
||||
"go.maximumdirect.net/commandkit/internal/commandpath"
|
||||
)
|
||||
|
||||
func (a *App) parse(args []string, options commandmeta.ParseOptions) commandmeta.Result {
|
||||
if a == nil {
|
||||
return commandmeta.Result{Failure: &commandmeta.Failure{Message: "cannot parse commands on a nil app"}}
|
||||
}
|
||||
result := internalcobra.Parse(a.routeSnapshot().metadata, args, options)
|
||||
return reduceReportingOccurrences(result)
|
||||
}
|
||||
|
||||
func reduceReportingOccurrences(result commandmeta.Result) commandmeta.Result {
|
||||
selection := commandmeta.ReportingSelection{}
|
||||
for index, occurrence := range result.FlagOccurrences {
|
||||
|
||||
@@ -34,15 +34,14 @@ func TestAppParseUsesRegisteredBindingsWithTheAdapter(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
options := commandmeta.ParseOptions{Context: context.Background()}
|
||||
result := app.parse([]string{"config", "show", "one", "--scope", "app"}, options)
|
||||
result := parseReportingArgs(app, []string{"config", "show", "one", "--scope", "app"})
|
||||
if result.Failure != nil {
|
||||
t.Fatalf("parse failed: %s", result.Failure.Message)
|
||||
}
|
||||
if !reflect.DeepEqual(result.Path, []string{"config", "show"}) || !reflect.DeepEqual(result.FlagValues, [][]string{{"app"}}) || !reflect.DeepEqual(result.Operands, []string{"one"}) {
|
||||
t.Fatalf("parse result = %#v", result)
|
||||
}
|
||||
result = app.parse([]string{"config", "--scope", "app", "show"}, options)
|
||||
result = parseReportingArgs(app, []string{"config", "--scope", "app", "show"})
|
||||
if result.Failure == nil {
|
||||
t.Fatal("accepted a child flag before the complete command path")
|
||||
}
|
||||
@@ -55,7 +54,7 @@ func TestRoutingSnapshotPairsParsedKeyWithItsRunner(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
snapshot := app.routeSnapshot()
|
||||
session := internalcobra.Prepare(snapshot.metadata, commandmeta.ParseOptions{Context: context.Background()})
|
||||
session := internalcobra.Prepare(snapshot.metadata, commandmeta.ParseOptions{})
|
||||
parsed := session.Parse([]string{"run"})
|
||||
if parsed.Failure != nil {
|
||||
t.Fatalf("parse failed: %s", parsed.Failure.Message)
|
||||
|
||||
Reference in New Issue
Block a user