• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

valkyrjaio / sindri-php / 30415490388
100%

Build:
DEFAULT BRANCH: 26.x
Ran 29 Jul 2026 01:58AM UTC
Jobs 1
Files 79
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

29 Jul 2026 01:56AM UTC coverage: 100.0%. Remained the same
30415490388

push

github

web-flow
[Ast] Stop reading a named attribute argument by its position (#177)

# Description

An attribute that names only some of its arguments generated a broken
data cache — one
that fatals the moment it is loaded.

`getAttrArg()` resolves an argument by name and, when no name matches,
falls back to
`$args[$position]`. That fallback did not check whether the argument
sitting at that
position was itself written with a *different* name. Because PHP
requires positional
arguments to precede named ones, a positional lookup is only ever valid
for a genuinely
positional argument; once an attribute uses named arguments, position
tells you nothing.

So a command declaring

```php
#[OptionParameter(name: 'flag', description: '…', mode: OptionMode::OPTIONAL, valueMode: OptionValueMode::NONE)]
```

generated

```php
new OptionParameter(
    name: 'flag',
    description: '…',
    valueDisplayName: 'Valkyrja\Cli\Routing\Enum\OptionMode::OPTIONAL', // the mode, as a string
    cast: OptionValueMode::NONE,                                        // the value mode
    …
)
```

— the third and fourth declared arguments read into `valueDisplayName`
and `cast` purely
because they shared those positions. Loading that cache throws
`ArgumentParameter::__construct(): Argument #3 ($cast) must be of type
?Cast, ArgumentMode
given`. The same applies to `ArgumentParameter`.

This went unnoticed because the framework's own commands happen to
declare their attribute
arguments in exact constructor order, so positional fallback coincided
with the right
slots, and the example application's only command declares no arguments
or options at all —
so this generation path had never run. The HTTP readers escaped visible
damage only by
luck: the values they mis-picked were type-incompatible and were
silently dropped by the
`is_string()` / `is_bool()` guards in `extractStringArg()` /
`extractBoolArg()`, quietly
falling back to defaults.

Found while adding one command per argument and option permu... (continued)

1554 of 1554 relevant lines covered (100.0%)

17.53 hits per line

Jobs
ID Job ID Ran Files Coverage
1 30415490388.1 29 Jul 2026 01:58AM UTC 79
100.0
GitHub Action Run
Source Files on build 30415490388
  • Tree
  • List 79
  • Changed 1
  • Source Changed 1
  • Coverage Changed 1
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #30415490388
  • 2b9ca15e on github
  • Prev Build on 26.x (#30330881856)
  • Next Build on 26.x (#30415762065)
  • Delete
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc