Commit b55fcdf
ArgParser: reject leaf-only attributes on structural fields (#606)
* ArgParser: reject leaf-only attributes on structural fields
A field whose type is another argument record, or a union of alternative
argument sets, contributes that type's whole set of arguments rather than
one. [<PositionalArgs>], [<ParseExact>], [<InvariantCulture>] and
[<ArgumentNegateWithPrefix>] each describe how a single argument is
collected, spelled or read, so there is nothing here for them to act on --
and the structural branches take over before the leaf machinery which
reads them ever runs, so each was computed and then dropped on the floor.
[<ArgumentHelpText>] is deliberately not in the list: on a structural
field it introduces the group of arguments the field contributes.
Breaking; lands under the 11.0 bump carried by the previous commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ArgParser: reject [<ArgumentNegateWithPrefix>] on positional fields (#607)
* ArgParser: reject [<ArgumentNegateWithPrefix>] on positional fields
`hasNegateAttr` was computed inside the non-positional leaf branch only.
The positional branch never looked at it and hardcoded
`AcceptsNegation = false`, so the attribute was silently ignored.
A positional field is not spelled at all -- it collects whatever carries
no name -- so there is no name from which a --no- variant could be formed,
whatever the field's type. That is a different complaint from the existing
boolean-shape check, and gets its own message.
The extraction moves above the positional split so both sides read one
definition.
Breaking; lands under the 11.0 bump carried earlier in this stack.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Correct the rejection message: a positional sink does have keyed forms
A [<PositionalArgs>] field is addressable -- `--rest value` and
`--rest=value` route to the sink, and an explicit [<ArgumentLongForm>]
can add further spellings -- so claiming it "has no spelling to negate"
contradicted the parser's own behaviour.
The rejection stands; the reason is that those keyed forms are
value-taking routing keys, so a sink which accumulates values has no
boolean for a `--no-` form to invert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* ArgParser: reject [<ParseExact>] and [<InvariantCulture>] where they are not read (#608)
* ArgParser: reject [<ParseExact>] and [<InvariantCulture>] where unread
Both are read in exactly one place: the TimeSpan arm of
createParseFunction. On any other type they were dropped -- and for
[<ParseExact>] that is worse than silence, because `helpText` advertises
the format unconditionally, so the generated --help promised a format the
generated parser did not honour.
Checked against the type actually handed to the parser rather than the
declared field type, exactly as checkSeparatorAttributesPlacement is, so
`TimeSpan option` and `TimeSpan list` keep working.
Departure from the planned scope: the plan called for rejecting maps
outright, on the belief that only the value type sees the attribute. It
does not -- the map branch hands the field's attributes to its key parser
as well -- so `Map<string, TimeSpan>` and `Map<TimeSpan, string>` both
genuinely honour the attribute today, and rejecting them would have
removed working behaviour. A map is therefore rejected only when neither
component is a TimeSpan.
Also noted while testing: System.DateTime, the type an author would most
likely want a parse format for, is not supported by the generator at all
and fails earlier with its own message. There is no lying help to fix
there; the lie is on `string`, `int` and friends.
Breaking; lands under the 11.0 bump carried earlier in this stack.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Document ArgParser attribute placement, and the 11.0 breaking changes (#609)
Attribute doc comments now state where each attribute is read and where
it is rejected. Two were actively misleading:
- ArgumentFlagAttribute said it went on "a field of a two-case no-data
discriminated union". It goes on the union's *cases*; the loose wording
invited precisely the mistake now rejected.
- ParseExactAttribute and InvariantCultureAttribute both wrote the
attribute as [<ArgumentParseExact>], which does not exist, and neither
said it is honoured on TimeSpan alone.
README gains an "attribute placement at a structural boundary" section,
and no longer claims [<ParseExact>] works on "TimeSpan and friends".
CHANGELOG records 11.0 as one entry covering the whole rejection stack,
plus the backtick fix which landed after 10.7.2 and was never published.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent 235763f commit b55fcdf
5 files changed
Lines changed: 597 additions & 18 deletions
File tree
- WoofWare.Myriad.Plugins.Attributes
- WoofWare.Myriad.Plugins
- Test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
3 | 12 | | |
4 | 13 | | |
5 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
243 | 243 | | |
244 | 244 | | |
245 | 245 | | |
246 | | - | |
| 246 | + | |
| 247 | + | |
247 | 248 | | |
248 | 249 | | |
249 | 250 | | |
| |||
379 | 380 | | |
380 | 381 | | |
381 | 382 | | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
382 | 395 | | |
383 | 396 | | |
384 | 397 | | |
| |||
Lines changed: 47 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
34 | 46 | | |
35 | 47 | | |
36 | 48 | | |
| |||
102 | 114 | | |
103 | 115 | | |
104 | 116 | | |
105 | | - | |
106 | | - | |
107 | | - | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
108 | 129 | | |
109 | 130 | | |
110 | 131 | | |
111 | 132 | | |
112 | 133 | | |
113 | | - | |
114 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
115 | 140 | | |
116 | 141 | | |
117 | 142 | | |
118 | | - | |
| 143 | + | |
| 144 | + | |
119 | 145 | | |
120 | 146 | | |
121 | 147 | | |
122 | 148 | | |
123 | 149 | | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
124 | 153 | | |
125 | 154 | | |
126 | 155 | | |
| |||
132 | 161 | | |
133 | 162 | | |
134 | 163 | | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
135 | 170 | | |
136 | 171 | | |
137 | 172 | | |
| |||
215 | 250 | | |
216 | 251 | | |
217 | 252 | | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
218 | 259 | | |
219 | 260 | | |
220 | 261 | | |
0 commit comments