diff -u b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php --- b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php +++ b/core/lib/Drupal/Component/Annotation/AnnotationInterface.php @@ -16,6 +16,7 @@ * Gets the name(s) of the provider(s) of the annotated class. * * @return string|array + * Can be str4ing or array because of backwards compatibility reasons. */ public function getProvider(); @@ -23,6 +24,7 @@ * Sets the name(s) of the provider(s) of the annotated class. * * @param string|array $provider + * Can be str4ing or array because of backwards compatibility reasons. */ public function setProvider($provider); diff -u b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php --- b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -21,7 +21,7 @@ /** * Whether the parser should return only wants class annotations. */ - const CLASSANNOTATIONOPTIMIZE = TRUE; + const CLASS_ANNOTATION_OPTIMIZE = TRUE; /** * The namespaces within which to find plugin classes. @@ -143,7 +143,7 @@ // file. However, StaticReflectionParser needs a finder, so use a // mock version. $finder = MockFileFinder::create($fileinfo->getPathName()); - $parser = new StaticReflectionParser($class, $finder, static::CLASSANNOTATIONOPTIMIZE); + $parser = new StaticReflectionParser($class, $finder, static::CLASS_ANNOTATION_OPTIMIZE); /** @var $annotation \Drupal\Component\Annotation\AnnotationInterface */ if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), $this->pluginDefinitionAnnotationName)) { diff -u b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php --- b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscoveryAutomatedProviders.php @@ -13,7 +13,7 @@ /** * {@inheritdoc} */ - const CLASSANNOTATIONOPTIMIZE = FALSE; + const CLASS_ANNOTATION_OPTIMIZE = FALSE; /** * {@inheritdoc} @@ -21,11 +21,12 @@ protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class, BaseStaticReflectionParser $parser) { parent::prepareAnnotationDefinition($annotation, $class, $parser); $finder = \Drupal::service('class_loader'); - $providers = array_flip((array) $annotation->getProvider()); + $providers = (array) $annotation->getProvider(); do { - $providers += array_flip(array_filter(array_map([$this, 'getProviderFromNamespace'], $parser->getUseStatements()))); + $new_providers = array_map([$this, 'getProviderFromNamespace'], $parser->getUseStatements()); + $providers = array_merge($providers, $new_providers); } while ($parser = StaticReflectionParser::getParentParser($parser, $finder)); - $annotation->setProvider(array_keys($providers)); + $annotation->setProvider(array_unique(array_filter($providers))); } } diff -u b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php --- b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/ProviderFilterDecorator.php @@ -30,8 +30,9 @@ * * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $decorated * The object implementing DiscoveryInterface that is being decorated. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. + * @param callable $provider_exists + * A callable, gets passed a provider name, should return TRUE if the + * provider exists and FALSE if not. */ public function __construct(DiscoveryInterface $decorated, callable $provider_exists) { $this->decorated = $decorated; @@ -39,7 +40,7 @@ } /** - * Remove plugin definitions with non-existing providers. + * Removes plugin definitions with non-existing providers. * * @param mixed[] $definitions * An array of plugin definitions (empty array if no definitions were diff -u b/core/lib/Drupal/Core/Plugin/Discovery/StaticReflectionParser.php b/core/lib/Drupal/Core/Plugin/Discovery/StaticReflectionParser.php --- b/core/lib/Drupal/Core/Plugin/Discovery/StaticReflectionParser.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/StaticReflectionParser.php @@ -10,6 +10,8 @@ class StaticReflectionParser extends BaseStaticReflectionParser { /** + * If the current class extends another, get the parser for the latter. + * * @param \Doctrine\Common\Reflection\StaticReflectionParser $parser * The current static parser. *