Skip to content

Implement Shorter Attribute Syntax #5796

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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ PHP 8.0 UPGRADE NOTES
Additionally, care should be taken that error messages are not displayed in
production environments, which can result in information leaks. Please
ensure that display_errors=Off is used in conjunction with error logging.
. Adding more than one @ operator to an expression is no longer supported,
since this syntax is now used for attributes (previously extra @ operators
had no effect).
RFC: https://wiki.php.net/rfc/shorter_attribute_syntax
. Inheritance errors due to incompatible method signatures (LSP violations)
will now always generate a fatal error. Previously a warning was generated
in some cases.
Expand Down Expand Up @@ -605,6 +609,7 @@ PHP 8.0 UPGRADE NOTES
. Added support for Attributes
RFC: https://wiki.php.net/rfc/attributes_v2
RFC: https://wiki.php.net/rfc/attribute_amendments
RFC: https://wiki.php.net/rfc/shorter_attribute_syntax
. Added support for constructor property promotion (declaring properties in
the constructor signature).
RFC: https://wiki.php.net/rfc/constructor_promotion
Expand Down
18 changes: 9 additions & 9 deletions Zend/tests/attributes/001_placement.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ Attributes can be placed on all supported elements.
--FILE--
<?php

<<A1(1)>>
@@A1(1)
class Foo
{
<<A1(2)>>
@@A1(2)
public const FOO = 'foo';

<<A1(3)>>
@@A1(3)
public $x;

<<A1(4)>>
public function foo(<<A1(5)>> $a, <<A1(6)>> $b) { }
@@A1(4)
public function foo(@@A1(5) $a, @@A1(6) $b) { }
}

$object = new <<A1(7)>> class () { };
$object = new @@A1(7) class () { };

<<A1(8)>>
@@A1(8)
function f1() { }

$f2 = <<A1(9)>> function () { };
$f2 = @@A1(9) function () { };

$f3 = <<A1(10)>> fn () => 1;
$f3 = @@A1(10) fn () => 1;

$ref = new \ReflectionClass(Foo::class);

Expand Down
4 changes: 2 additions & 2 deletions Zend/tests/attributes/002_rfcexample.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Attributes: Example from Attributes RFC
namespace My\Attributes {
use Attribute;

<<Attribute>>
@@Attribute
class SingleArgument {
public $argumentValue;

Expand All @@ -19,7 +19,7 @@ namespace My\Attributes {
namespace {
use My\Attributes\SingleArgument;

<<SingleArgument("Hello World")>>
@@SingleArgument("Hello World")
class Foo {
}

Expand Down
12 changes: 6 additions & 6 deletions Zend/tests/attributes/003_ast_nodes.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Attributes can deal with AST nodes.

define('V1', strtoupper(php_sapi_name()));

<<A1([V1 => V1])>>
@@A1([V1 => V1])
class C1
{
public const BAR = 'bar';
Expand All @@ -20,7 +20,7 @@ var_dump(count($args), $args[0][V1] === V1);

echo "\n";

<<A1(V1, 1 + 2, C1::class)>>
@@A1(V1, 1 + 2, C1::class)
class C2 { }

$ref = new \ReflectionClass(C2::class);
Expand All @@ -35,7 +35,7 @@ var_dump($args[2] === C1::class);

echo "\n";

<<A1(self::FOO, C1::BAR)>>
@@A1(self::FOO, C1::BAR)
class C3
{
private const FOO = 'foo';
Expand All @@ -52,20 +52,20 @@ var_dump($args[1] === C1::BAR);

echo "\n";

<<ExampleWithShift(4 >> 1)>>
@@ExampleWithShift(4 >> 1)
class C4 {}
$ref = new \ReflectionClass(C4::class);
var_dump($ref->getAttributes()[0]->getArguments());

echo "\n";

<<Attribute>>
@@Attribute
class C5
{
public function __construct() { }
}

$ref = new \ReflectionFunction(<<C5(MissingClass::SOME_CONST)>> function () { });
$ref = new \ReflectionFunction(@@C5(MissingClass::SOME_CONST) function () { });
$attr = $ref->getAttributes();
var_dump(count($attr));

Expand Down
10 changes: 5 additions & 5 deletions Zend/tests/attributes/004_name_resolution.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ namespace Foo {
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Attributes;

<<Entity("imported class")>>
<<ORM\Entity("imported namespace")>>
<<\Doctrine\ORM\Mapping\Entity("absolute from namespace")>>
<<\Entity("import absolute from global")>>
<<Attributes\Table()>>
@@Entity("imported class")
@@ORM\Entity("imported namespace")
@@\Doctrine\ORM\Mapping\Entity("absolute from namespace")
@@\Entity("import absolute from global")
@@Attributes\Table()
function foo() {
}
}
Expand Down
20 changes: 10 additions & 10 deletions Zend/tests/attributes/005_objects.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Attributes can be converted into objects.
--FILE--
<?php

<<Attribute(Attribute::TARGET_FUNCTION)>>
@@Attribute(Attribute::TARGET_FUNCTION)
class A1
{
public string $name;
Expand All @@ -16,7 +16,7 @@ class A1
}
}

$ref = new \ReflectionFunction(<<A1('test')>> function () { });
$ref = new \ReflectionFunction(@@A1('test') function () { });

foreach ($ref->getAttributes() as $attr) {
$obj = $attr->newInstance();
Expand All @@ -26,7 +26,7 @@ foreach ($ref->getAttributes() as $attr) {

echo "\n";

$ref = new \ReflectionFunction(<<A1>> function () { });
$ref = new \ReflectionFunction(@@A1 function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand All @@ -36,7 +36,7 @@ try {

echo "\n";

$ref = new \ReflectionFunction(<<A1([])>> function () { });
$ref = new \ReflectionFunction(@@A1([]) function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand All @@ -46,7 +46,7 @@ try {

echo "\n";

$ref = new \ReflectionFunction(<<A2>> function () { });
$ref = new \ReflectionFunction(@@A2 function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand All @@ -56,13 +56,13 @@ try {

echo "\n";

<<Attribute>>
@@Attribute
class A3
{
private function __construct() { }
}

$ref = new \ReflectionFunction(<<A3>> function () { });
$ref = new \ReflectionFunction(@@A3 function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand All @@ -72,10 +72,10 @@ try {

echo "\n";

<<Attribute>>
@@Attribute
class A4 { }

$ref = new \ReflectionFunction(<<A4(1)>> function () { });
$ref = new \ReflectionFunction(@@A4(1) function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand All @@ -87,7 +87,7 @@ echo "\n";

class A5 { }

$ref = new \ReflectionFunction(<<A5>> function () { });
$ref = new \ReflectionFunction(@@A5 function () { });

try {
$ref->getAttributes()[0]->newInstance();
Expand Down
16 changes: 8 additions & 8 deletions Zend/tests/attributes/006_filter.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ Attributes can be filtered by name and base type.
--FILE--
<?php

$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 function () { });
$attr = $ref->getAttributes(A3::class);

var_dump(count($attr));

$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 function () { });
$attr = $ref->getAttributes(A2::class);

var_dump(count($attr), $attr[0]->getName());

$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A2>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 @@A2 function () { });
$attr = $ref->getAttributes(A2::class);

var_dump(count($attr), $attr[0]->getName(), $attr[1]->getName());
Expand All @@ -25,27 +25,27 @@ class A1 implements Base { }
class A2 implements Base { }
class A3 extends A2 { }

$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A5>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 @@A5 function () { });
$attr = $ref->getAttributes(\stdClass::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump(count($attr));
print_r(array_map(fn ($a) => $a->getName(), $attr));

$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 function () { });
$attr = $ref->getAttributes(A1::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump(count($attr));
print_r(array_map(fn ($a) => $a->getName(), $attr));

$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 function () { });
$attr = $ref->getAttributes(Base::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump(count($attr));
print_r(array_map(fn ($a) => $a->getName(), $attr));

$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A3>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 @@A3 function () { });
$attr = $ref->getAttributes(A2::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump(count($attr));
print_r(array_map(fn ($a) => $a->getName(), $attr));

$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A3>> function () { });
$ref = new \ReflectionFunction(@@A1 @@A2 @@A3 function () { });
$attr = $ref->getAttributes(Base::class, \ReflectionAttribute::IS_INSTANCEOF);
var_dump(count($attr));
print_r(array_map(fn ($a) => $a->getName(), $attr));
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/attributes/008_wrong_attribution.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Attributes: Prevent Attribute on non classes
--FILE--
<?php

<<Attribute>>
@@Attribute
function foo() {}
--EXPECTF--
Fatal error: Attribute "Attribute" cannot target function (allowed targets: class) in %s
22 changes: 12 additions & 10 deletions Zend/tests/attributes/009_doctrine_annotations_example.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,22 @@ namespace {
use Doctrine\ORM\Attributes as ORM;
use Symfony\Component\Validator\Constraints as Assert;

<<ORM\Entity>>
@@ORM\Entity
/** @ORM\Entity */
class User
{
/** @ORM\Id @ORM\Column(type="integer"*) @ORM\GeneratedValue */
<<ORM\Id>><<ORM\Column("integer")>><<ORM\GeneratedValue>>
@@ORM\Id
@@ORM\Column("integer")
@@ORM\GeneratedValue
private $id;

/**
* @ORM\Column(type="string", unique=true)
* @Assert\Email(message="The email '{{ value }}' is not a valid email.")
*/
<<ORM\Column("string", ORM\Column::UNIQUE)>>
<<Assert\Email(array("message" => "The email '{{ value }}' is not a valid email."))>>
@@ORM\Column("string", ORM\Column::UNIQUE)
@@Assert\Email(array("message" => "The email '{{ value }}' is not a valid email."))
private $email;

/**
Expand All @@ -50,8 +52,8 @@ class User
* maxMessage = "You cannot be taller than {{ limit }}cm to enter"
* )
*/
<<Assert\Range(["min" => 120, "max" => 180, "minMessage" => "You must be at least {{ limit }}cm tall to enter"])>>
<<ORM\Column(ORM\Column::T_INTEGER)>>
@@Assert\Range(["min" => 120, "max" => 180, "minMessage" => "You must be at least {{ limit }}cm tall to enter"])
@@ORM\Column(ORM\Column::T_INTEGER)
protected $height;

/**
Expand All @@ -61,10 +63,10 @@ class User
* inverseJoinColumns={@ORM\JoinColumn(name="phonenumber_id", referencedColumnName="id", unique=true)}
* )
*/
<<ORM\ManyToMany(Phonenumber::class)>>
<<ORM\JoinTable("users_phonenumbers")>>
<<ORM\JoinColumn("user_id", "id")>>
<<ORM\InverseJoinColumn("phonenumber_id", "id", ORM\JoinColumn::UNIQUE)>>
@@ORM\ManyToMany(Phonenumber::class)
@@ORM\JoinTable("users_phonenumbers")
@@ORM\JoinColumn("user_id", "id")
@@ORM\InverseJoinColumn("phonenumber_id", "id", ORM\JoinColumn::UNIQUE)
private $phonenumbers;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Attribute arguments support only const expressions.
--FILE--
<?php

<<A1(foo())>>
@@A1(foo())
class C1 { }

?>
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/attributes/011_inheritance.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ Attributes comply with inheritance rules.
--FILE--
<?php

<<A2>>
@@A2
class C1
{
<<A1>>
@@A1
public function foo() { }
}

Expand All @@ -17,7 +17,7 @@ class C2 extends C1

class C3 extends C1
{
<<A1>>
@@A1
public function bar() { }
}

Expand All @@ -37,7 +37,7 @@ echo "\n";

trait T1
{
<<A2>>
@@A2
public $a;
}

Expand Down
Loading