Skip to content

Introduce <<Deprecated>> attribute #11

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

Open
wants to merge 19 commits into
base: attributes_v2_rfc
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6bf867a
Add Attributes based on attributes_v2 RFC.
beberlei Apr 15, 2020
efbf7d0
Update tests with more complex examples and edge cases.
beberlei Apr 17, 2020
ea9277b
Rename ReflectionAttribute::getAsObject to ReflectionAttribute::newIn…
beberlei Apr 20, 2020
4263b3b
Fixed attribute class validation bug.
kooldev Apr 28, 2020
bc2f4f7
Implemented many of the smaller changes suggested by Nikita Popov.
kooldev Apr 30, 2020
08eca9c
Introduced struct zend_attribute. Defer ASt evaluation to access time.
kooldev Apr 30, 2020
08b2528
Added additional tests.
kooldev Apr 30, 2020
141409e
Implemented Opcache (memory-only) for new attribute structs.
kooldev Apr 30, 2020
e870452
Merge pull request #8 from koolkode/FixAttributeValidation
beberlei May 1, 2020
4e8bba9
Implemented attribute storage in file-based Opcache.
kooldev May 1, 2020
2468119
Fixed parameter offset bug. Refined test case to detect this.
kooldev May 1, 2020
c2cbe30
Merge pull request #9 from koolkode/AttributeOpcache
beberlei May 1, 2020
55e6e75
Improve name resolution test to show all potential cases.
beberlei May 1, 2020
6ce5c27
Enable external linkage. Fixed comments.
kooldev May 2, 2020
bd4eed0
Implemented AST export of attribute nodes.
kooldev May 2, 2020
a9d94bb
Removed ZEND_API from register ce function.
kooldev May 2, 2020
bd1e66b
Merge pull request #10 from koolkode/PrintAst
beberlei May 2, 2020
4155391
Introduce <<Deprecated>> attribute compiled into a method/function.
beberlei May 2, 2020
b7bc91e
Address review comments.
beberlei May 6, 2020
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
127 changes: 127 additions & 0 deletions Zend/tests/attributes/001_placement.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
--TEST--
Attributes can be placed on all supported elements.
--FILE--
<?php

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

<<A1(3)>>
public $x, $y;

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

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

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

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

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

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

$sources = [
$ref,
$ref->getReflectionConstant('FOO'),
$ref->getReflectionConstant('BAR'),
$ref->getProperty('x'),
$ref->getProperty('y'),
$ref->getMethod('foo'),
$ref->getMethod('foo')->getParameters()[0],
$ref->getMethod('foo')->getParameters()[1],
new \ReflectionObject($object),
new \ReflectionFunction('f1'),
new \ReflectionFunction($f2),
new \ReflectionFunction($f3)
];

foreach ($sources as $r) {
$attr = $r->getAttributes();
var_dump(count($attr));

foreach ($attr as $a) {
var_dump($a->getName(), $a->getArguments());
}
}

?>
--EXPECT--
int(1)
string(2) "A1"
array(1) {
[0]=>
int(1)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(2)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(2)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(3)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(3)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(4)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(5)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(6)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(7)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(8)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(9)
}
int(1)
string(2) "A1"
array(1) {
[0]=>
int(10)
}
43 changes: 43 additions & 0 deletions Zend/tests/attributes/002_rfcexample.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--TEST--
Attributes: Example from Attributes RFC
--FILE--
<?php
// https://wiki.php.net/rfc/attributes_v2#attribute_syntax
namespace My\Attributes {
use PhpAttribute;

<<PhpAttribute>>
class SingleArgument {
public $argumentValue;

public function __construct($argumentValue) {
$this->argumentValue = $argumentValue;
}
}
}

namespace {
use My\Attributes\SingleArgument;

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

$reflectionClass = new \ReflectionClass(Foo::class);
$attributes = $reflectionClass->getAttributes();

var_dump($attributes[0]->getName());
var_dump($attributes[0]->getArguments());
var_dump($attributes[0]->newInstance());
}
?>
--EXPECTF--
string(28) "My\Attributes\SingleArgument"
array(1) {
[0]=>
string(11) "Hello World"
}
object(My\Attributes\SingleArgument)#3 (1) {
["argumentValue"]=>
string(11) "Hello World"
}
109 changes: 109 additions & 0 deletions Zend/tests/attributes/003_ast_nodes.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
--TEST--
Attributes can deal with AST nodes.
--FILE--
<?php

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

<<A1([V1 => V1])>>
class C1
{
public const BAR = 'bar';
}

$ref = new \ReflectionClass(C1::class);
$attr = $ref->getAttributes();
var_dump(count($attr));

$args = $attr[0]->getArguments();
var_dump(count($args), $args[0][V1] === V1);

echo "\n";

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

$ref = new \ReflectionClass(C2::class);
$attr = $ref->getAttributes();
var_dump(count($attr));

$args = $attr[0]->getArguments();
var_dump(count($args));
var_dump($args[0] === V1);
var_dump($args[1] === 3);
var_dump($args[2] === C1::class);

echo "\n";

<<A1(self::FOO, C1::BAR)>>
class C3
{
private const FOO = 'foo';
}

$ref = new \ReflectionClass(C3::class);
$attr = $ref->getAttributes();
var_dump(count($attr));

$args = $attr[0]->getArguments();
var_dump(count($args));
var_dump($args[0] === 'foo');
var_dump($args[1] === C1::BAR);

echo "\n";

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

echo "\n";

<<PhpAttribute>>
class C5
{
public function __construct() { }
}

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

try {
$attr[0]->getArguments();
} catch (\Error $e) {
var_dump($e->getMessage());
}

try {
$attr[0]->newInstance();
} catch (\Error $e) {
var_dump($e->getMessage());
}

?>
--EXPECT--
int(1)
int(1)
bool(true)

int(1)
int(3)
bool(true)
bool(true)
bool(true)

int(1)
int(2)
bool(true)
bool(true)

array(1) {
[0]=>
int(2)
}

int(1)
string(30) "Class 'MissingClass' not found"
string(30) "Class 'MissingClass' not found"

78 changes: 78 additions & 0 deletions Zend/tests/attributes/004_name_resolution.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
--TEST--
Resolve attribute names
--FILE--
<?php
function dump_attributes($attributes) {
$arr = [];
foreach ($attributes as $attribute) {
$arr[] = ['name' => $attribute->getName(), 'args' => $attribute->getArguments()];
}
var_dump($arr);
}

namespace Doctrine\ORM\Mapping {
class Entity {
}
}

namespace Foo {
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping as ORM;

<<Entity("imported class")>>
<<ORM\Entity("imported namespace")>>
<<\Doctrine\ORM\Mapping\Entity("absolute from namespace")>>
<<\Entity("import absolute from global")>>
function foo() {
}
}

namespace {
class Entity {}

dump_attributes((new ReflectionFunction('Foo\foo'))->getAttributes());
}
?>
--EXPECTF--
array(4) {
[0]=>
array(2) {
["name"]=>
string(27) "Doctrine\ORM\Mapping\Entity"
["args"]=>
array(1) {
[0]=>
string(14) "imported class"
}
}
[1]=>
array(2) {
["name"]=>
string(27) "Doctrine\ORM\Mapping\Entity"
["args"]=>
array(1) {
[0]=>
string(18) "imported namespace"
}
}
[2]=>
array(2) {
["name"]=>
string(27) "Doctrine\ORM\Mapping\Entity"
["args"]=>
array(1) {
[0]=>
string(23) "absolute from namespace"
}
}
[3]=>
array(2) {
["name"]=>
string(6) "Entity"
["args"]=>
array(1) {
[0]=>
string(27) "import absolute from global"
}
}
}
Loading