Skip to content

Add migrate:neon2attributes command and extend attribute services - #6920

Merged
ondrejmirtes merged 14 commits into
2.3.xfrom
neon2attributes
Nov 3, 2026
Merged

ondrejmirtes merged 14 commits into
2.3.xfrom
neon2attributes

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Adds the migrate:neon2attributes command, which converts services, rules, conditionalTags and extensionInterfaces entries in a project's NEON config files to the DI attributes, and extends the attributes so they cover more NEON cases.

Attribute changes:

  • #[Conditional] with a parameter holding a list is evaluated like conditionalTags.
  • Attribute services are discovered through the autoloader (class_exists()), not Composer autoload rules.
  • #[AutowiredParameter] values go through Nette's filterArguments() like NEON arguments (Class::CONST, @service).
  • factory: in #[AutowiredService] and #[NonAutowiredService] accepts a static method Foo::create.
  • A single type in #[AutowiredService(as:)] becomes the service type, like class: Interface, factory: Implementation in NEON. The service is no longer also autowired as the implementation class.
  • Third-party extension interfaces can map to their own tags through #[ExtensionInterface(tag:)] (now @api) or the new extensionInterfaces: section. Auto-tagging, conditionalTags and tag validation use the merged mapping.

The command:

  • Reads the config the same way as analyse, plus extra.phpstan.includes from composer.json.
  • Fails when the project supports PHP < 8.0.
  • Lists the entries it keeps in NEON, with the reason for each.

Parity testing: each project was migrated, then its compiled DI container was compared before and after, with the default config and with every conditionalTags boolean flipped. Extensions were also compared on a level-8 analysis. All 10 1st-party extensions, 78 Packagist packages and 2 private apps came out identical. The remaining differences:

  • Attribute services are ordered by class name, so tagged() lists can change order. This is documented.
  • Projects with several PHPStan entry points, such as TwigStan, are not handled yet. The command only sees the configs included by -c.

A single `if` string that expands to a list of conditions, like
strictRules.booleansInLoopConditions, now requires all of them to be met.
It was wrapped in another list and the non-empty array counted as met.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
…r autoload rules

Classes declared in the attributeServicesDirectories are loaded with
class_exists(), so any autoloader works, including --autoload-file.
Each class is autoloaded once, which avoids redeclaring classes whose
file does not match its PSR-4 path.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
Replaces the rules, services and conditionalTags entries of the project's
non-vendor NEON config files with attributes on the service classes in
attributeServicesDirectories. Entries the attributes cannot express stay
in the config files and are reported with the reason.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
Class::CONST, ::CONST, Enum::Case and @service strings become constants
and references, also inside the value of a referenced parameter.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
… class

class: FooInterface with factory: Foo becomes #[AutowiredService(as: FooInterface::class)] on Foo.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
…face] and the extensionInterfaces section

Attribute services implementing these interfaces get the tag automatically,
and conditionalTags and the tag validation accept the configured tags.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
Like class: Interface, factory: Implementation in NEON, the service is no longer
autowired as the implementation class too.

Amp-Thread-ID: https://ampcode.com/threads/T-01a19cd4-be31-75b4-bd15-67786eff5983
@ondrejmirtes
ondrejmirtes merged commit 6c1ebc9 into 2.3.x Nov 3, 2026
598 of 599 checks passed
@ondrejmirtes
ondrejmirtes deleted the neon2attributes branch November 3, 2026 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant