chore(linter): traverse "runArgs" as the "docker run" argv it is - #92
Merged
Conversation
Seven rules read a devcontainer.json's "runArgs", and each opened with the
same preamble: cast the node to an array, check the file type, pull out one
flag's values and loop. Any one of them could get that wrong on its own.
The engine now walks a devcontainer.json's "runArgs" as the argv it becomes.
A rule names the flag it wants in its path ("/runArgs/--cap-add") and is
handed each occurrence, with the value in Node.Arg and the node pointing at
the element the value is written in — the value's element, not the flag's, so
a finding lands where the rule read. Flags are identified by their normalized
long name, so "/runArgs/--volume" also matches "-v", and the traversal runs
only for devcontainer.json, which is the only file type the property belongs
to, so rules no longer check it themselves.
The ordinary walk stops descending at the document's own "runArgs" while
still visiting the array itself. Descending both ways would give each element
an index path and a flag path, and "/runArgs/*" would hand the same element
over twice.
The two rules that report a flag's *absence* cannot be driven by
per-occurrence dispatch, since a flag that is not there is never matched;
they keep reading the document root, now through a single helper.
Reporting is unchanged except that a flag written more than once is now
reported once per occurrence rather than only at the first, matching what
no-docker-socket-mount already did; suppressing one line no longer hides the
others.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sq1U3yDE8B3YYw8M5rqvi9
cmd/dockerflagsgen is a module of its own, and it consumes dockerargs for the flag table and for the differential test against pflag. Putting the array to argv step in dockerargs pulled hujson into that module: its go.sum has no entry for it, so "make dockerflags-test" failed to build, and satisfying it would have made a generator that never touches a syntax tree depend on a JSON parser. The step moves to the traversal that needs it, exported as linter.RunArgs for the two rules that report a flag's absence and so cannot be driven by the per-occurrence dispatch. dockerargs goes back to reading strings only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sq1U3yDE8B3YYw8M5rqvi9
…visited as "A rule is visited at most once per value" was written for the ordinary traversal, where a value is reached by one path however many patterns match it. It does not hold for a "runArgs" element: a run of shorthands names several flags, and the element is visited once for each, so a rule subscribing to "/runArgs/*" or to more than one of those flags is called twice on it. That is the behavior the addressing wants — collapsing the occurrences would drop a flag silently, which is what naming flags by their long form exists to prevent — so the three statements of the contract are what change, along with a test comment that repeated the wrong one. The wildcard case is pinned by a test: deduplicating per element now fails it rather than quietly narrowing what rules see. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sq1U3yDE8B3YYw8M5rqvi9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Seven rules read a devcontainer.json's "runArgs", and each opened with the
same preamble: cast the node to an array, check the file type, pull out one
flag's values and loop. Any one of them could get that wrong on its own.
The engine now walks a devcontainer.json's "runArgs" as the argv it becomes.
A rule names the flag it wants in its path ("/runArgs/--cap-add") and is
handed each occurrence, with the value in Node.Arg and the node pointing at
the element the value is written in — the value's element, not the flag's, so
a finding lands where the rule read. Flags are identified by their normalized
long name, so "/runArgs/--volume" also matches "-v", and the traversal runs
only for devcontainer.json, which is the only file type the property belongs
to, so rules no longer check it themselves.
The ordinary walk stops descending at the document's own "runArgs" while
still visiting the array itself. Descending both ways would give each element
an index path and a flag path, and "/runArgs/*" would hand the same element
over twice.
The two rules that report a flag's absence cannot be driven by
per-occurrence dispatch, since a flag that is not there is never matched;
they keep reading the document root, now through a single helper.
Reporting is unchanged except that a flag written more than once is now
reported once per occurrence rather than only at the first, matching what
no-docker-socket-mount already did; suppressing one line no longer hides the
others.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Sq1U3yDE8B3YYw8M5rqvi9