Skip to content

PHP 8 attributes #243

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

Closed
wants to merge 18 commits into from
Closed

Conversation

thekid
Copy link
Member

@thekid thekid commented May 24, 2020

See https://wiki.php.net/rfc/attributes_v2 - another step forward to full PHP 8 support (see #211). Non-scalar values (which are not supported by PHP) can be written in an inline comment form.

use unittest\{Test, Values, Assert};

class DemoTest {

  <<Test>>
  public function can_create() {
    new Demo();
  }

  <<Test>>
  <<Values(
    #[
    #  Demo::$DEFAULT,
    #  new Demo('Live'),
    #]
  )>>
  public function valid($demo) {
    Assert::true($demo->valid());
  }
}

$t= XPClass::forName(DemoTest::class);

$c= $t->getMethod('can_create');
$c->getAnnotations();              // ["unittest\Test" => null]
$c->hasAnnotation(Test::class);    // true

$c= $t->getMethod('valid');
$c->getAnnotation(Values::class);  // [Demo<"default">, Demo<"live">]

For BC reasons, lowercased annotations are not resolved

<<author('Timm')>>
class Test { }

XPClass::forName(Test::class)->getAnnotations(); // ["author" => "Timm"]

@thekid
Copy link
Member Author

thekid commented May 24, 2020

Unfortunately, PHP 8 attributes do not support all values which are supported in XP annotations, e.g. instantations, closures, static member references:

use unittest\Assert;
use unittest\actions\VerifyThat;

#[@action(new VerifyThat(function() {
#  return PHP_VERSION_ID >= 70000;
#}))]
class NameTest {

  #[@test, @values([
  #  [Name::$EMPTY],
  #  [new Name('Test')],
  #  [new Name('Test J. West')],
  #])]
  public function is_valid($name) {
    Assert::true($name->valid());
  }
}

PHP will yield a parse error - Constant expression contains invalid operations.

@thekid
Copy link
Member Author

thekid commented May 24, 2020

PHP will yield a parse error - Constant expression contains invalid operations.

A possible workaround would be to use a special kind of array argument like this:

use unittest\Action;
use unittest\actions\VerifyThat;

// Inline as code. Downside: Escaping, manual import resolution necessary
<<Action([this => 'new VerifyThat(function() { return PHP_VERSION_ID >= 70000; })'])>>
class NameTest {

}

// Via magic method. Downside: Far away from method declarations
<<Action([this => 'function'])>>
class NameTest {
  static function __attributes() {
    return [self::class => new VerifyThat(function() { return PHP_VERSION_ID >= 70000; })];
  }
}

this is a global constant and evaluates to NULL. We could use anything else, really (except keywords...), or other values - it will always be ambiguous! However NULL is an unlikely use for an array key, so by this we reduce the likelihood of a "false positive" //cc @mikey179

@thekid thekid closed this May 31, 2020
@thekid thekid reopened this May 31, 2020
@thekid
Copy link
Member Author

thekid commented May 31, 2020

A possible workaround would be to use a special kind of array argument like this:

Another possibility is to mix syntaxes:

use net\xp_framework\unittest\annotations\Name;

class NameTest {

  <<Test>>
  #[@Values([
  #  new Name('Test'),
  #  new Name('Test T. West'),
  #  Name::$EMPTY,
  #])]
  public function is_valid($name) {
    // TBI
  }
}

(which even already works!)

...or maybe even with a special "inline" notation:

use net\xp_framework\unittest\annotations\Name;

class NameTest {

  <<Test>>
  <<Values(
    #[
    #  new Name('Test'),
    #  new Name('Test T. West'),
    #  Name::$EMPTY,
    #]
  )>>
  public function is_valid($name) {
    // TBI
  }
}

@thekid
Copy link
Member Author

thekid commented May 31, 2020

...or maybe even with a special "inline" notation:

Implemented as noted above ✅

@thekid
Copy link
Member Author

thekid commented May 31, 2020

Waiting to see if koolkode/php-src#1 (Attribute Grouping) is merged - see https://wiki.php.net/rfc/attribute_amendments. This PR would then need some additional tweaks.

@thekid
Copy link
Member Author

thekid commented Jul 5, 2020

Will need adjustments when php/php-src#5796 is merged, see https://wiki.php.net/rfc/shorter_attribute_syntax

@thekid thekid closed this Sep 20, 2020
@thekid thekid deleted the refactor/php8-attributes branch September 20, 2020 23:42
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.

1 participant