Skip to content

Attributes v2 #2

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 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5b5e895
Adopt dstogov Attributes PR #1878 to php8 without Ast Nodes but no va…
beberlei Feb 20, 2020
ed76308
Tinkering around to evaluate constant AST when accessing attributes.
beberlei Feb 20, 2020
b737879
Adjust tests, fix node conversion, still leaking and not resolving na…
beberlei Feb 21, 2020
44340c4
Move AST attribute functions to zend_ast.c
beberlei Mar 2, 2020
32df5b7
Resolve attribute names according to imports (still requiring attribu…
beberlei Mar 3, 2020
9a2b506
Basics of ReflectionAttribute support.
beberlei Mar 3, 2020
6d49c93
Prepare for returning ReflectionAttribute not array.
beberlei Mar 3, 2020
2875a23
Convert getAttributes() to return list of ReflectionAttribute and adj…
beberlei Mar 3, 2020
781ca23
Some cleanup
beberlei Mar 3, 2020
cd4d759
Reduce variability in attribute declarations
beberlei Mar 4, 2020
756a083
Go back to unique attribute names
beberlei Mar 4, 2020
03e2ece
Test redeclaration of attributes throws error.
beberlei Mar 4, 2020
356538f
Test redeclaration of attributes throws error.
beberlei Mar 4, 2020
048bfa4
Cleanup
beberlei Mar 4, 2020
dcae6bd
Cleanup
beberlei Mar 4, 2020
e367e00
Reworked grammar and compiler. Fixed all memory leaks.
kooldev Apr 4, 2020
13db356
Implemented access to multi & param attributes.
kooldev Apr 4, 2020
97bcede
Adjusted Opcache to PHP 8.
kooldev Apr 5, 2020
214c435
Added support for empty arg list. Added AST evaluation test case.
kooldev Apr 5, 2020
34a8904
Fixed property attributes. Added attribute placement a test case.
kooldev Apr 5, 2020
00c8d29
Merge remote-tracking branch 'koolkode/Attributes' into AttributesPatch
beberlei Apr 5, 2020
e9962a5
Merge master
beberlei Apr 5, 2020
09be412
merge conflict
beberlei Apr 5, 2020
6efec1b
Fix tests and rename variable
beberlei Apr 5, 2020
603a4ac
Merge pull request #4 from koolkode/Opcache
beberlei Apr 5, 2020
53371a5
Add tests for attributes on all elements.
beberlei Apr 5, 2020
ffaacd3
Move tests from ext/reflection to Zend/tests/attributes* because its …
beberlei Apr 5, 2020
ed99062
Implemented ReflectionAttribute::getAsObject(). Moved tests to dir.
kooldev Apr 5, 2020
a376173
Implemented attribute filtering (name and instanceof).
kooldev Apr 5, 2020
79eb355
Fixed failing reflection test case.
kooldev Apr 5, 2020
47adcc3
Extracted duplicated code into a function. Fixed annotation type.
kooldev Apr 6, 2020
551c7d5
Changed boolean argument of getAttributes() into a flags type.
kooldev Apr 6, 2020
b6d392d
Renamed const to IS_INSTANCE to be consistent with getMethods() filter.
kooldev Apr 6, 2020
5d06c35
Merge pull request #5 from koolkode/Attributes
beberlei Apr 6, 2020
205bd8e
Add PhpCompilerAttribute and PhpAttribute classes.
beberlei Apr 13, 2020
13e53ad
Add very simple compiler attribute validation for now (no constant as…
beberlei Apr 13, 2020
db7f5fc
Validate that class attributes are PhpAttribute or PhpCompilerAttribute.
beberlei Apr 13, 2020
0bb4d66
Move code from zend_default_classes.c to zend_attributes.c
beberlei Apr 13, 2020
72aea5a
Allow internal compiler attribute validators to check for attributed …
beberlei Apr 13, 2020
27b4453
Merge pull request #6 from beberlei/AttributesValidator
beberlei Apr 13, 2020
2ef898a
Rename tests for ordering of features from basic to complex
beberlei Apr 14, 2020
a5fc69f
Simplify validator function pointer wiggling.
beberlei Apr 15, 2020
716acb6
Merge master
beberlei Apr 15, 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
112 changes: 112 additions & 0 deletions Zend/tests/attributes/001_placement.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
--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) {
foreach ($r->getAttributes() as $attr) {
var_dump($attr->getName(), $attr->getArguments());
}
}

?>
--EXPECT--
string(2) "A1"
array(1) {
[0]=>
int(1)
}
string(2) "A1"
array(1) {
[0]=>
int(2)
}
string(2) "A1"
array(1) {
[0]=>
int(2)
}
string(2) "A1"
array(1) {
[0]=>
int(3)
}
string(2) "A1"
array(1) {
[0]=>
int(3)
}
string(2) "A1"
array(1) {
[0]=>
int(4)
}
string(2) "A1"
array(1) {
[0]=>
int(5)
}
string(2) "A1"
array(1) {
[0]=>
int(6)
}
string(2) "A1"
array(1) {
[0]=>
int(7)
}
string(2) "A1"
array(1) {
[0]=>
int(8)
}
string(2) "A1"
array(1) {
[0]=>
int(9)
}
string(2) "A1"
array(1) {
[0]=>
int(10)
}
41 changes: 41 additions & 0 deletions Zend/tests/attributes/002_rfcexample.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--TEST--
Attributes: RFC Example
--FILE--
<?php
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]->getAsObject());
}
--EXPECTF--
string(28) "My\Attributes\SingleArgument"
array(1) {
[0]=>
string(11) "Hello World"
}
object(My\Attributes\SingleArgument)#3 (1) {
["argumentValue"]=>
string(11) "Hello World"
}
68 changes: 68 additions & 0 deletions Zend/tests/attributes/003_ast_nodes.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
--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);

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

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

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

<<Entity(["foo" => "bar"])>>
function foo() {
}
}

namespace {
dump_attributes((new ReflectionFunction('Foo\foo'))->getAttributes());
}
--EXPECTF--
array(1) {
["Doctrine\ORM\Mapping\Entity"]=>
array(1) {
[0]=>
array(1) {
["foo"]=>
string(3) "bar"
}
}
}
102 changes: 102 additions & 0 deletions Zend/tests/attributes/005_objects.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
--TEST--
Attributes can be converted into objects.
--FILE--
<?php

class A1
{
public string $name;
public int $ttl;

public function __construct(string $name, int $ttl = 50)
{
$this->name = $name;
$this->ttl = $ttl;
}
}

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

foreach ($ref->getAttributes() as $attr) {
$obj = $attr->getAsObject();

var_dump(get_class($obj), $obj->name, $obj->ttl);
}

echo "\n";

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

try {
$ref->getAttributes()[0]->getAsObject();
} catch (\ArgumentCountError $e) {
var_dump('ERROR 1', $e->getMessage());
}

echo "\n";

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

try {
$ref->getAttributes()[0]->getAsObject();
} catch (\TypeError $e) {
var_dump('ERROR 2', $e->getMessage());
}

echo "\n";

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

try {
$ref->getAttributes()[0]->getAsObject();
} catch (\Error $e) {
var_dump('ERROR 3', $e->getMessage());
}

echo "\n";

class A3
{
private function __construct() { }
}

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

try {
$ref->getAttributes()[0]->getAsObject();
} catch (\Error $e) {
var_dump('ERROR 4', $e->getMessage());
}

echo "\n";

class A4 { }

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

try {
$ref->getAttributes()[0]->getAsObject();
} catch (\Error $e) {
var_dump('ERROR 5', $e->getMessage());
}

?>
--EXPECT--
string(2) "A1"
string(4) "test"
int(50)

string(7) "ERROR 1"
string(81) "Too few arguments to function A1::__construct(), 0 passed and at least 1 expected"

string(7) "ERROR 2"
string(74) "A1::__construct(): Argument #1 ($name) must be of type string, array given"

string(7) "ERROR 3"
string(30) "Attribute class 'A2' not found"

string(7) "ERROR 4"
string(50) "Attribute constructor of class 'A3' must be public"

string(7) "ERROR 5"
string(71) "Attribute class 'A4' does not have a constructor, cannot pass arguments"
Loading