Drupal version

10.0.x

Drupal Rector version

TBD

Problem / Motivation

Part of #3252386: Use PHP attributes instead of doctrine annotations

While there's MVP patch to replace annotations with attributes as Drupal 10.0 require PHP 8.1

ATM parent issue work is about to define replacements to doctrine annotation which gonna be deprecated

Comments

andypost created an issue. See original summary.

mstrelan’s picture

See https://getrector.org/blog/how-to-upgrade-annotations-to-attributes for reference. Is there anything Drupal-specific that is needed?

berdir’s picture

Status: Postponed » Active

Drupal uses different classes for Annotation and Attribute discovery, so it will require a mapping/logic to derive the Attribute class from the Annotation. We also don't use namespaces in Annotations, so that's an extra hurdle for rector to understand.

The core issue is getting close and having this could be extremely beneficial in getting all the remaining core plugin types converted, doing that by hand especially for big ones like entity types is *painful*. So setting this to active in the hope that someone who knows rector gives this a try :)

andypost’s picture

https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview...

there's existing rector which just needs configuration

berdir’s picture

Early findings:

https://getrector.com/blog/how-to-upgrade-annotations-to-attributes mentions DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES, that is vendor/rector/rector-doctrine/config/sets/doctrine-annotations-to-attributes.php, which is a hardcoded list of annotation => attribute classes.

That seems like a good start to work on core plugin types, but any contrib and plugin type annotation discovery will need to be converted as well. The optimal case would be that we somehow find those dynamically, with a few patterns for nested stuff like the translation. No idea if that's possible, as that would imply dynamic configuration OR complex, dynamic conversions with state?

Generic rule to find the Attribute class from the Annotation class would be something like: Drupal\foo\Annotation\Bar => Drupal\foo\Attribute\Bar. See https://www.drupal.org/node/3395575. Action is a special early case that was in a different namespace, those should be limited and specific to Drupal\Core annotations.

Another aspect is to convert plugin types, while less common, they are still very common. http://grep.xnddx.ru/search?text=extends%20DefaultPluginManager finds 67 pages of DefaultPluginManager subclasses. Not all of them use annotation discovery, but many do. That will involve creating entire new attribute classes, I've now idea how feasible that is.

@mglaman had this to say on this whole topic:
> Lol this looks like a nightmare waiting to happen

andypost’s picture

WIP PR https://github.com/palantirnet/drupal-rector/pull/257

Looks like it will need specific parser per annotation with mapping of each key, also will need some formatting to split one argument per line

amber himes matz’s picture

Title: Provide automatic conversion from annotions to native attributes » Provide automatic conversion from annotations to native attributes

Updated title to fix typo in "annotations" to ensure issue is discoverable in searches for "annotations".

bbrala’s picture

bbrala’s picture

Status: Active » Fixed

The rector is available now, with some docs, it wont cover everything, but it seems to function quite well with out structure. Now we just need to see how many edge cases we run into.

Guess we should create new issues when they arrive.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

klausi’s picture

Is the rector code supposed to work with contrib plugin annotations and attributes supposed to work? Tried to convert graphql dataproducer plugins, but I get no output.

Rector config:

<?php

declare(strict_types=1);

use Drupal\graphql\Attribute\DataProducer;
use DrupalRector\Drupal10\Rector\Deprecation\AnnotationToAttributeRector;
use DrupalRector\Drupal10\Rector\ValueObject\AnnotationToAttributeConfiguration;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [
      new AnnotationToAttributeConfiguration('10.0.0', '10.0.0', 'DataProducer', DataProducer::class),
    ]);

    if (class_exists('DrupalFinder\DrupalFinderComposerRuntime')) {
        $drupalFinder = new DrupalFinder\DrupalFinderComposerRuntime();
    } else {
        $drupalFinder = new DrupalFinder\DrupalFinder();
        $drupalFinder->locateRoot(__DIR__);
    }
    $drupalRoot = $drupalFinder->getDrupalRoot();
    $rectorConfig->autoloadPaths([
        $drupalRoot . '/core',
        $drupalRoot . '/modules',
        $drupalRoot . '/profiles',
        $drupalRoot . '/themes'
    ]);

    $rectorConfig->skip(['*/upgrade_status/tests/modules/*']);
    $rectorConfig->fileExtensions(['php', 'module', 'theme', 'install', 'profile', 'inc', 'engine']);
    $rectorConfig->importNames(true, false);
    $rectorConfig->importShortClasses(false);
};

Invocation:
vendor/bin/rector process modules/graphql --dry-run

output:

klausi@drupal-11-web:/var/www/html$ vendor/bin/rector process modules/graphql
 36/68 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░]  52%
In ProcessPool.php line 30:
                                   
  Process "qabrfesumt" not found.  

Looks like rector is crashing here?

Did anyone convert contrib annotation successfully with an automated tool?

penyaskito’s picture

@klausi I just did with SectionStorage (from core, but weird enough no-one probably used it before)
I was using HEAD and did some manual amends for handling ContextDefinitions, even if I had to do some manual changes anyway.
See #3543910: AnnotationToAttributeRector not working OOTB with SectionStorage plugins where I describe my "hacks" + #3543079: Convert phpdoc doctrine plugin annotation to modern attributes for the actual issue (I will post my rector.php there)