Skip to content
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

Return type deprecations for library tests #33235

Closed
derrabus opened this issue Aug 19, 2019 · 5 comments · Fixed by #33708
Closed

Return type deprecations for library tests #33235

derrabus opened this issue Aug 19, 2019 · 5 comments · Fixed by #33708

Comments

@derrabus
Copy link
Member

derrabus commented Aug 19, 2019

Symfony version(s) affected: 4.4-dev

One of my open source projects starts to produce failing travis builds because of the deprecation notices triggered by DebugClassLoader since #30323. In order to make DebugClassLoader helpful for libraries, I think we need to fine tune it a bit:

  • Almost all of the notices triggered here affect vendor code (here: Pimple and Silex). Four deprecation notices are flagged as "direct deprecation notices" by PHPUnit Bridge, but only two of the notices are actually triggered by my own classes.
  • I'm pretty sure that Silex and Pimple won't be patched, so I need a way to silence deprecation triggered by vendor code.
  • The branch that is tested here maintains php 5 compatibility. Because of that, I'd probably want to deactivate return type checks completely?

For reference, the errors from my travis log:

Remaining direct deprecation notices (4)

  1x: Method "Symfony\Component\HttpKernel\HttpKernelInterface::handle()" will return "Response" as of its next major version. Doing the same in child class "Silex\Application" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Psr\Container\ContainerInterface::has()" will return "bool" as of its next major version. Doing the same in child class "Pimple\Psr11\Container" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface::supports()" will return "bool" as of its next major version. Doing the same in child class "Rabus\Psr11ServiceProvider\ArgumentResolver" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface::resolve()" will return "iterable" as of its next major version. Doing the same in child class "Rabus\Psr11ServiceProvider\ArgumentResolver" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

Remaining indirect deprecation notices (8)

  1x: Method "Symfony\Component\EventDispatcher\EventSubscriberInterface::getSubscribedEvents()" will return "array" as of its next major version. Doing the same in child class "Silex\EventListener\MiddlewareListener" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\EventDispatcher\EventSubscriberInterface::getSubscribedEvents()" will return "array" as of its next major version. Doing the same in child class "Silex\EventListener\ConverterListener" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\EventDispatcher\EventSubscriberInterface::getSubscribedEvents()" will return "array" as of its next major version. Doing the same in child class "Silex\EventListener\StringToResponseListener" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\Routing\Matcher\RequestMatcherInterface::matchRequest()" will return "array" as of its next major version. Doing the same in child class "Silex\Provider\Routing\LazyRequestMatcher" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\EventDispatcher\EventSubscriberInterface::getSubscribedEvents()" will return "array" as of its next major version. Doing the same in child class "Silex\ExceptionHandler" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface::supports()" will return "bool" as of its next major version. Doing the same in child class "Silex\AppArgumentValueResolver" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface::resolve()" will return "iterable" as of its next major version. Doing the same in child class "Silex\AppArgumentValueResolver" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testServiceRegistration from Rabus\Psr11ServiceProvider

  1x: Method "Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface::redirect()" will return "array" as of its next major version. Doing the same in child class "Silex\Provider\Routing\RedirectableUrlMatcher" will be required when upgrading.

    1x in Psr11ServiceProviderTest::testControllerArgument from Rabus\Psr11ServiceProvider
@nicolas-grekas
Copy link
Member

Almost all of the notices triggered here affect vendor code (here: Pimple and Silex). Four deprecation notices are flagged as "direct deprecation notices" by PHPUnit Bridge, but only two of the notices are actually triggered by my own classes.

Someone would need to have a look for a way to improve this, if possible

I'm pretty sure that Silex and Pimple won't be patched, so I need a way to silence deprecation triggered by vendor code.

see #33236

The branch that is tested here maintains php 5 compatibility. Because of that, I'd probably want to deactivate return type checks completely?

That's the use case why adding @return annotations in your codebase silences the deprecations. That's how you should do it.

@derrabus
Copy link
Member Author

The branch that is tested here maintains php 5 compatibility. Because of that, I'd probably want to deactivate return type checks completely?

That's the use case why adding @return annotations in your codebase silences the deprecations. That's how you should do it.

I was merely thinking about some sort of global switch for PHPUnit bridge.

I mean, in this particular case we're talking about a tiny codebase, where I certainly could add those annotations. But in practice, we would tell library vendors to add those @return annotations everywhere. And as soon as they bump to php 7.2 they would need to remove all those annotations again so that they get proper deprecations. That sounds like a pretty complex workflow for something that have been an env var setting.

@mdlutz24
Copy link
Contributor

Just as a talking point this shows a run of the Drupal Test suite with the new classloader. There's a couple unrelated fails there as well, but the bulk of the failures are the new deprecations from the merge. In general, I think this is fine. We are able to suppress specific deprecations in our test suite and address them in follow ups. A couple of interesting ones here..

1x: Method "Symfony\Component\DependencyInjection\ContainerInterface::get()" will return "?object" as of its next major version. Doing the same in child class "Drupal\Component\DependencyInjection\Container" will be required when upgrading.
1x in FieldConfigAccessControlHandlerTest::setUp from Drupal\Tests\field\Unit

This test is running against php 7.1, so I can't return typehint ?object yet, but when we open the D9 branch, we will be on php 7.2 or 7.3, so I don't think it bothers us necessarily. It's tempting to consider not throwing that deprecation on php 7.1, but at the end of the day, SF5 will require php 7.2 and a object typehint, so the deprecation is valid regardless.

1x: Method "SebastianBergmann\Comparator\Comparator::accepts()" will return "bool" as of its next major version. Doing the same in child class "Prophecy\Comparator\ClosureComparator" will be required when upgrading.
1x in ManyPlaceholderTest::testManyNoJsPlaceHolders from Drupal\Tests\big_pipe\Unit\Render

1x: Method "SebastianBergmann\Comparator\ObjectComparator::accepts()" will return "bool" as of its next major version. Doing the same in child class "Prophecy\Comparator\ProphecyComparator" will be required when upgrading.
1x in ManyPlaceholderTest::testManyNoJsPlaceHolders from Drupal\Tests\big_pipe\Unit\Render

Definitely some issues in vendor libraries that we will have to figure out when we open our Drupal 9 branch too.

I think at the end of the day we will end up needing to drop the {@inheritdoc} and copy the full docblock to eliminate the deprecation notice for Drupal 9 core but pass it through to our contrib projects if any of them happen to be extending or implementing any Symfony classes or interfaces, then we can add the actual php return typehints in Drupal 10 which would likely release on Symfony 5.4 in a couple years.

@mdlutz24
Copy link
Contributor

Now what I would really be interested in (and this might either be a separate Symfony issue, or maybe something we do in Drupal core in a extended Debug classloader) is a way to use this ourselves, trigger deprecations notices on Drupal interfaces that aren't return typehinted downstream. We've been trying to find a way to introduce return type hints in a backwards compatible way, and I really think the work here (and other work in the Debug ClassLoader in SF4) has been really great work, and solves a lot of problems we've been having trying to trigger deprecation errors in situations where we can't easily do it in code.

@nicolas-grekas
Copy link
Member

Follow up in #33283

nicolas-grekas added a commit that referenced this issue Aug 26, 2019
…CI (nicolas-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

Add return-types with help from DebugClassLoader in the CI

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

I've spent a great deal of time on this PR, experimenting with adding return types to the codebase.

TL;DR: my conclusion is that we cannot make it for 5.0.

There are two reasons for this:
1. The burden this will put on the community is immense, especially when considering that third party libs must also be updated for any apps to work at all on a return-typed 5.0. Symfony must add them last, not first.
2. We need return type covariance, yet this won't be available before PHP 7.4, while 5.0 supports 7.2.

What's attached?
- ~a draft patching logic in `DebugClassLoader` to add return-type where it discovers this should be done~
- return types added automatically thanks to #33283
- ~manual fixes for situations not handled (yet, if possible at all) by that logic in `DebugClassLoader`~ #33332

What's achieved? Tests are green \o/

At this stage, I think we have to acknowledge we won't add return-types in 5.0 but prepare a serious plan to add them in 6.0.

This plan could be:
- [x] make DebugClassLoader able to automate adding return types.
- [x] in 4.4: add all possible return types that don't break BC, e.g. in `Tests` and in generated code
- [x] spot and fix places where annotations aren't accurate, add more annotations where possible.
- [x] ensure `DebugClassLoader` triggers the best possible deprecations that encourage ppl to add return-types in their libs/apps. This means we could decide to disable the current ones (see #33235) and to re-enable them in 5.1. This will also give us the time to fine-tune the tooling (item 1. on this list)

Ideally, we could reach a point where we could test branch 4.4 *with* return-types: we'd use the tooling to add them automatically in the CI job, then we'd run tests and they should be green. Let's do this?

Help Wanted, here is how:

*With PHP 7.4*, run `php .github/patch-types.php`. This will add return types everywhere possible.

Then run tests, e.g. `./phpunit src/Symfony/Component/HttpFoundation --exclude-group legacy,issue-32995`

Here are the components that fail with return types added, please help me check them all with a PR on [my fork](https://github.com/nicolas-grekas/symfony/tree/eh-return-types):
 - [x] src/Symfony/Bridge/Doctrine
 - [x] src/Symfony/Bridge/Monolog
 - [x] src/Symfony/Bridge/PhpUnit
 - [x] src/Symfony/Bridge/ProxyManager
 - [x] src/Symfony/Bridge/Twig
 - [x] src/Symfony/Bundle/DebugBundle
 - [x] src/Symfony/Bundle/FrameworkBundle
 - [x] src/Symfony/Bundle/SecurityBundle
 - [x] src/Symfony/Bundle/TwigBundle
 - [x] src/Symfony/Bundle/WebProfilerBundle
 - [x] src/Symfony/Bundle/WebServerBundle
 - [x] src/Symfony/Component/Asset
 - [x] src/Symfony/Component/BrowserKit
 - [x] src/Symfony/Component/Cache
 - [x] nicolas-grekas#28 src/Symfony/Component/Config
 - [x] src/Symfony/Component/Console
 - [x] src/Symfony/Component/CssSelector
 - [x] src/Symfony/Component/Debug
 - [x] nicolas-grekas#28 src/Symfony/Component/DependencyInjection
 - [x] src/Symfony/Component/DomCrawler
 - [x] src/Symfony/Component/Dotenv
 - [x] src/Symfony/Component/ErrorHandler
 - [x] src/Symfony/Component/ErrorRenderer
 - [x] nicolas-grekas#24 src/Symfony/Component/EventDispatcher
 - [x] src/Symfony/Component/ExpressionLanguage
 - [x] src/Symfony/Component/Filesystem
 - [x] src/Symfony/Component/Finder
 - [x] src/Symfony/Component/Form
 - [x] src/Symfony/Component/HttpClient
 - [x] src/Symfony/Component/HttpFoundation
 - [x] src/Symfony/Component/HttpKernel
 - [x] src/Symfony/Component/Inflector
 - [x] src/Symfony/Component/Intl
 - [x] src/Symfony/Component/Ldap
 - [x] src/Symfony/Component/Lock
 - [x] src/Symfony/Component/Mailer
 - [x] src/Symfony/Component/Messenger
 - [x] src/Symfony/Component/Mime
 - [x] src/Symfony/Component/OptionsResolver
 - [x] src/Symfony/Component/Process
 - [x] src/Symfony/Component/PropertyAccess
 - [x] src/Symfony/Component/PropertyInfo
 - [x] nicolas-grekas#25 src/Symfony/Component/Routing
 - [x] nicolas-grekas#26 src/Symfony/Component/Security
 - [x] src/Symfony/Component/Security/Core
 - [x] src/Symfony/Component/Security/Guard
 - [x] src/Symfony/Component/Security/Http
 - [x] nicolas-grekas#29 src/Symfony/Component/Serializer
 - [x] src/Symfony/Component/Security/Csrf
 - [x] src/Symfony/Component/Stopwatch
 - [x] src/Symfony/Component/Templating
 - [x] nicolas-grekas#27 src/Symfony/Component/Translation
 - [x] src/Symfony/Component/Validator
 - [x] src/Symfony/Component/VarDumper
 - [x] src/Symfony/Component/VarExporter
 - [x] src/Symfony/Component/WebLink
 - [x] src/Symfony/Component/Workflow
 - [x] src/Symfony/Component/Yaml
 - [x] src/Symfony/Contracts

Commits
-------

11149a1 Add return-types with help from DebugClassLoader in the CI
@fabpot fabpot closed this as completed in 745248f Sep 25, 2019
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 a pull request may close this issue.

3 participants