Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Automatically process extensions when they implement CompilerPassInterface #13761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 15, 2015

Conversation

wouterj
Copy link
Member

@wouterj wouterj commented Feb 22, 2015

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets -
License MIT
Doc PR todo (if people are in favor of this PR)

Compiler passes are very powerfull, but also quite strange to work with. Especially when you just need a very simple compiler pass (like https://github.com/symfony-cmf/RoutingBundle/blob/master/DependencyInjection/Compiler/SetRouterPass.php). For 3 lines of code, you need to tweak your bundle class and create a new class.

When using the DI component standalone, compiler passes are even harder to work with, as DI extensions can't register them. I believe that's why libraries like Behat make their extensions compiler passes by default.

I think it would be very easy to just implement an interface and have a compile method for the simple compiler pass stuff. If a bundle needs multiple compiler passes or need compiler passes to be executed at other times in the compile process, a bundle can use the normal compiler passes. But if it's just one simple thing, like replacing a definition or getting services with a specific tag, I think this method will be very usefull.

@linaori
Copy link
Contributor

linaori commented Feb 23, 2015

You get a 👍 from me for this idea. I've actually ran into this "issue" a few times myself. What about allowing callables to be passed to container itself? I know it would be a BC break for the current container, but it does allow you to flexibly add the passes at the right moment. Though the current PR makes it easier to add it to the most use cases, it will not allow you to register anything but the default.

public function process(ContainerBuilder $container)
{
foreach ($container->getExtensions() as $extension) {
if (!$extension instanceof CompilerExtensionInterface) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about checking whether the extension implements CompilerPassInterface instead of introducing a different interface ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is that the CompilerPassInterface requires a method called process(), which I don't think is very describing in the Extension context.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj actually, compile() is misleading as the container builder is not compiled here. It is still being processed, so I'll vote for process() and using the existing interface.

Wouldn't it be better to call this class InlineCompilerPass or ExtensionCompilerPass?

@wouterj wouterj force-pushed the inline_compilers branch from 8d0edd0 to 6c50013 Compare April 3, 2015 14:27
@wouterj wouterj changed the title [RFC] Add interface for Extension#compile() to allow simple compiler passes Automatically process extensions when they implement CompilerPassInterface Apr 3, 2015
@wouterj
Copy link
Member Author

wouterj commented Apr 3, 2015

I've updated the PR with the suggestions (removed new interface, reuse CompilerPassInterface and rename pass class name).

ping @symfony/deciders

@aitboudad
Copy link
Contributor

@wouterj but we can't register extension as instance of CompilerPassInterface ? https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/DependencyInjection/ContainerBuilder.php#L133

@wouterj
Copy link
Member Author

wouterj commented Apr 3, 2015

@aitboudad a class can implement multiple interfaces:

class AppExtension implements ExtensionInterface, CompilerPassInterface
{

@aitboudad
Copy link
Contributor

@wouterj then how to avoid the duplicate call of process if someone already addCompilerPass for an extension ?

@fabpot
Copy link
Member

fabpot commented Sep 14, 2015

👍

@nicolas-grekas
Copy link
Member

Maybe dumb question, but is it possible/desirable to create a compiler tag for this instead of using the interface check? I'm not a big fan of "configuration by interface".

@jakzal
Copy link
Contributor

jakzal commented Sep 14, 2015

@nicolas-grekas not sure how this would work. You'd need to register an extension as a service, right? This PR is all about decreasing amount of work the end user needs to do to get his compiler pass registered. DI Extension would also act as a compiler pass.

@nicolas-grekas
Copy link
Member

@jakzal ok, understood, extensions classes are not meant for wide range reuse
👍 then!

@jakzal
Copy link
Contributor

jakzal commented Sep 15, 2015

I'm 👍 btw :)

@fabpot
Copy link
Member

fabpot commented Sep 15, 2015

Thank you @wouterj.

@fabpot fabpot merged commit 6c50013 into symfony:2.7 Sep 15, 2015
fabpot added a commit that referenced this pull request Sep 15, 2015
…ompilerPassInterface (WouterJ)

This PR was merged into the 2.7 branch.

Discussion
----------

Automatically process extensions when they implement CompilerPassInterface

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | todo (if people are in favor of this PR)

Compiler passes are very powerfull, but also quite strange to work with. Especially when you just need a very simple compiler pass (like https://github.com/symfony-cmf/RoutingBundle/blob/master/DependencyInjection/Compiler/SetRouterPass.php). For 3 lines of code, you need to tweak your bundle class and create a new class.

When using the DI component standalone, compiler passes are even harder to work with, as DI extensions can't register them. I believe that's why libraries like Behat make their extensions compiler passes by default.

I think it would be very easy to just implement an interface and have a `compile` method for the simple compiler pass stuff. If a bundle needs multiple compiler passes or need compiler passes to be executed at other times in the compile process, a bundle can use the normal compiler passes. But if it's just one simple thing, like replacing a definition or getting services with a specific tag, I think this method will be very usefull.

Commits
-------

6c50013 Allowed extensions to inline compiler passes
@wouterj wouterj deleted the inline_compilers branch September 15, 2015 10:32
@fabpot
Copy link
Member

fabpot commented Sep 25, 2015

This one has been inadvertently merged into the 2.7 version. Not a big deal, just for reference.

@fabpot fabpot mentioned this pull request Nov 16, 2015
wouterj added a commit to symfony/symfony-docs that referenced this pull request Feb 6, 2016
…asses (WouterJ)

This PR was squashed before being merged into the 2.8 branch (closes #5920).

Discussion
----------

Document automatic registration of extension compiler passes

| Q | A
| --- | ---
| Doc fix? | no
| New docs? | yes (symfony/symfony#13761)
| Applies to | 2.8+
| Fixed tickets | -

Commits
-------

353df25 Document automatic registration of extension compiler passes
nicolas-grekas added a commit that referenced this pull request Sep 20, 2017
…ssInterface (nicolas-grekas)

This PR was squashed before being merged into the 3.4 branch (closes #24257).

Discussion
----------

[HttpKernel][DI] Enable Kernel to implement CompilerPassInterface

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

In the same spirit as #13761 that allowed DI exts to be also compiler passes, and as #23812 that allowed the kernel to listen to events, in our new bundle-less world, should we allow the kernel to register itself as a compiler pass? That would make some scenario possible (like having a `TestKernel` that turns some services public.)

Commits
-------

6973a1a [HttpKernel][DI] Enable Kernel to implement CompilerPassInterface
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants