-
Notifications
You must be signed in to change notification settings - Fork 7.8k
[RFC] Add support for attributes on compile-time constants #16952
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--TEST-- | ||
Attribute flags are all different, TARGET_ALL includes all targets | ||
--FILE-- | ||
<?php | ||
|
||
function showFlag(string $name, int $value) { | ||
$all = Attribute::TARGET_ALL; | ||
$and = $all & $value; | ||
echo "Attribute::$name = $value ($all & $value === $and)\n"; | ||
} | ||
|
||
showFlag("TARGET_CLASS", Attribute::TARGET_CLASS); | ||
showFlag("TARGET_FUNCTION", Attribute::TARGET_FUNCTION); | ||
showFlag("TARGET_METHOD", Attribute::TARGET_METHOD); | ||
showFlag("TARGET_PROPERTY", Attribute::TARGET_PROPERTY); | ||
showFlag("TARGET_CLASS_CONSTANT", Attribute::TARGET_CLASS_CONSTANT); | ||
showFlag("TARGET_PARAMETER", Attribute::TARGET_PARAMETER); | ||
showFlag("TARGET_CONSTANT", Attribute::TARGET_CONSTANT); | ||
showFlag("IS_REPEATABLE", Attribute::IS_REPEATABLE); | ||
|
||
$all = Attribute::TARGET_CLASS | Attribute::TARGET_FUNCTION | ||
| Attribute::TARGET_METHOD | Attribute::TARGET_PROPERTY | ||
| Attribute::TARGET_CLASS_CONSTANT | Attribute::TARGET_PARAMETER | ||
| Attribute::TARGET_CONSTANT; | ||
var_dump($all, Attribute::TARGET_ALL, $all === Attribute::TARGET_ALL); | ||
|
||
?> | ||
--EXPECT-- | ||
Attribute::TARGET_CLASS = 1 (127 & 1 === 1) | ||
Attribute::TARGET_FUNCTION = 2 (127 & 2 === 2) | ||
Attribute::TARGET_METHOD = 4 (127 & 4 === 4) | ||
Attribute::TARGET_PROPERTY = 8 (127 & 8 === 8) | ||
Attribute::TARGET_CLASS_CONSTANT = 16 (127 & 16 === 16) | ||
Attribute::TARGET_PARAMETER = 32 (127 & 32 === 32) | ||
Attribute::TARGET_CONSTANT = 64 (127 & 64 === 64) | ||
Attribute::IS_REPEATABLE = 128 (127 & 128 === 0) | ||
int(127) | ||
int(127) | ||
bool(true) |
39 changes: 39 additions & 0 deletions
39
Zend/tests/attributes/constants/allow_named_parameters.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--TEST-- | ||
Verify that named parameters can be passed to attributes on constants | ||
iluuu1994 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--FILE-- | ||
<?php | ||
|
||
#[Attribute] | ||
class MyAttribute { | ||
public function __construct($first, $second) { | ||
echo "first: $first\n"; | ||
echo "second: $second\n"; | ||
} | ||
} | ||
|
||
#[MyAttribute(second: "bar", first: "foo")] | ||
const EXAMPLE = 'ignored'; | ||
|
||
$ref = new ReflectionConstant('EXAMPLE'); | ||
$attribs = $ref->getAttributes(); | ||
var_dump($attribs); | ||
var_dump($attribs[0]->getArguments()); | ||
$attribs[0]->newInstance(); | ||
|
||
?> | ||
--EXPECTF-- | ||
array(1) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(11) "MyAttribute" | ||
} | ||
} | ||
array(2) { | ||
["second"]=> | ||
string(3) "bar" | ||
["first"]=> | ||
string(3) "foo" | ||
} | ||
first: foo | ||
second: bar |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--TEST-- | ||
AST can be recreated when constants have attributes | ||
--EXTENSIONS-- | ||
zend_test | ||
--FILE-- | ||
<?php | ||
|
||
#[MyAttrib] | ||
const WITH_ATTRIBUTE = true; | ||
|
||
#[First] | ||
#[Second] | ||
const WITH_UNGROUPED = true; | ||
|
||
#[First, Second] | ||
const WITH_GROUPED = true; | ||
|
||
#[MyAttrib(5, param: "example")] | ||
const WITH_PARAMETERS = true; | ||
|
||
echo zend_test_compile_to_ast(file_get_contents(__FILE__)); | ||
|
||
?> | ||
--EXPECT-- | ||
#[MyAttrib] | ||
const WITH_ATTRIBUTE = true; | ||
#[First] | ||
#[Second] | ||
const WITH_UNGROUPED = true; | ||
#[First, Second] | ||
const WITH_GROUPED = true; | ||
#[MyAttrib(5, param: 'example')] | ||
const WITH_PARAMETERS = true; | ||
echo zend_test_compile_to_ast(file_get_contents(__FILE__)); |
11 changes: 11 additions & 0 deletions
11
Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Constants listed in valid targets when used wrong (internal attribute) | ||
--FILE-- | ||
<?php | ||
|
||
#[Deprecated] | ||
class Example {} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Attribute "Deprecated" cannot target class (allowed targets: function, method, class constant, constant) in %s on line %d |
31 changes: 31 additions & 0 deletions
31
Zend/tests/attributes/constants/constant_listed_as_target-userland.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
--TEST-- | ||
Constants listed in valid targets when used wrong (userland attribute) | ||
--FILE-- | ||
<?php | ||
|
||
#[Attribute(Attribute::TARGET_CONSTANT)] | ||
class MyConstantAttribute {} | ||
|
||
#[MyConstantAttribute] | ||
class Example {} | ||
|
||
$ref = new ReflectionClass(Example::class); | ||
$attribs = $ref->getAttributes(); | ||
var_dump($attribs); | ||
$attribs[0]->newInstance(); | ||
|
||
?> | ||
--EXPECTF-- | ||
array(1) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(19) "MyConstantAttribute" | ||
} | ||
} | ||
|
||
Fatal error: Uncaught Error: Attribute "MyConstantAttribute" cannot target class (allowed targets: constant) in %s:%d | ||
Stack trace: | ||
#0 %s(%d): ReflectionAttribute->newInstance() | ||
#1 {main} | ||
thrown in %s on line %d |
21 changes: 21 additions & 0 deletions
21
Zend/tests/attributes/constants/constant_redefined_addition.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
If a constant is redefined, attributes remain unchanged (no attributes) | ||
--FILE-- | ||
<?php | ||
|
||
const MY_CONST = "No attributes"; | ||
|
||
#[\MyAttribute] | ||
const MY_CONST = "Has attributes"; | ||
|
||
echo MY_CONST . "\n"; | ||
|
||
$reflection = new ReflectionConstant('MY_CONST'); | ||
var_dump($reflection->getAttributes()) | ||
|
||
?> | ||
--EXPECTF-- | ||
Warning: Constant MY_CONST already defined in %s on line %d | ||
No attributes | ||
array(0) { | ||
} |
27 changes: 27 additions & 0 deletions
27
Zend/tests/attributes/constants/constant_redefined_change.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--TEST-- | ||
If a constant is redefined, attributes remain unchanged (different attributes) | ||
--FILE-- | ||
<?php | ||
|
||
#[\MyAttribute] | ||
const MY_CONST = "Has attributes (1)"; | ||
|
||
#[\MyOtherAttribute] | ||
const MY_CONST = "Has attributes (2)"; | ||
|
||
echo MY_CONST . "\n"; | ||
|
||
$reflection = new ReflectionConstant('MY_CONST'); | ||
var_dump($reflection->getAttributes()) | ||
|
||
?> | ||
--EXPECTF-- | ||
Warning: Constant MY_CONST already defined in %s on line %d | ||
Has attributes (1) | ||
array(1) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(11) "MyAttribute" | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
Zend/tests/attributes/constants/constant_redefined_removal.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
If a constant is redefined, attributes remain unchanged (had attributes) | ||
--FILE-- | ||
<?php | ||
|
||
#[\MyAttribute] | ||
const MY_CONST = "Has attributes"; | ||
|
||
const MY_CONST = "No attributes"; | ||
|
||
echo MY_CONST . "\n"; | ||
|
||
$reflection = new ReflectionConstant('MY_CONST'); | ||
var_dump($reflection->getAttributes()) | ||
|
||
?> | ||
--EXPECTF-- | ||
Warning: Constant MY_CONST already defined in %s on line %d | ||
Has attributes | ||
array(1) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(11) "MyAttribute" | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Zend/tests/attributes/constants/multiple_attributes_grouped.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--TEST-- | ||
Multiple attributes in a group are allowed | ||
--FILE-- | ||
<?php | ||
|
||
#[\Foo, \Bar] | ||
const CONSTANT = 1; | ||
|
||
$ref = new ReflectionConstant('CONSTANT'); | ||
var_dump($ref->getAttributes()); | ||
|
||
?> | ||
--EXPECTF-- | ||
array(2) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(3) "Foo" | ||
} | ||
[1]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(3) "Bar" | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
Zend/tests/attributes/constants/multiple_attributes_ungrouped.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
Multiple attributes in separate groups are allowed | ||
--FILE-- | ||
<?php | ||
|
||
#[\Foo] | ||
#[\Bar] | ||
const CONSTANT = 1; | ||
|
||
$ref = new ReflectionConstant('CONSTANT'); | ||
var_dump($ref->getAttributes()); | ||
|
||
?> | ||
--EXPECTF-- | ||
array(2) { | ||
[0]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(3) "Foo" | ||
} | ||
[1]=> | ||
object(ReflectionAttribute)#%d (1) { | ||
["name"]=> | ||
string(3) "Bar" | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Zend/tests/attributes/constants/multiple_constants_error.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Error trying to add attributes to multiple constants at once | ||
--FILE-- | ||
<?php | ||
|
||
#[\Foo] | ||
const First = 1, | ||
Second = 2; | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot apply attributes to multiple constants at once in %s on line %d |
11 changes: 11 additions & 0 deletions
11
Zend/tests/attributes/constants/must_target_const-internal.phpt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Error when attribute does not target constants (internal attribute) | ||
--FILE-- | ||
<?php | ||
|
||
#[Attribute] | ||
const EXAMPLE = 'Foo'; | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Attribute "Attribute" cannot target constant (allowed targets: class) in %s on line %d |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global constants are not actually compile time in PHP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They aren't created at compile time, but they are declared at compile time, unlike those with
define()
. https://www.php.net/manual/en/language.constants.syntax.phpThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the
UPGRADING
file keeps causing merge conflicts, I've removed my changes to that file for now, but the language I'm planning to include is: