Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learning PHP with PHP Parser

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for inouehi inouehi
March 24, 2023

Learning PHP with PHP Parser

『PHP Parserで学ぶPHP』

PHPerKaigi 2023
2023-03-24 14:05~ Track B
https://phperkaigi.jp/2023/

Avatar for inouehi

inouehi

March 24, 2023

More Decks by inouehi

Other Decks in Programming

Transcript

  1. AST(抽象構文木) 13 x = (1 + 2) * 3 =

    * x + 3 1 2 ノード ノード ノード
  2. AST(抽象構文木) 14 x = (1 + 2) * 3 =

    * x + 3 1 2 親 子 子 親 子 子
  3. <?php echo 'あしたっていまさ'; PHP ParserにおけるAST 16 array(1) { [0]=> object(PhpParser\Node\Stmt\Echo_)#1180

    (2) { ["exprs"]=> array(1) { [0]=> object(PhpParser\Node\Scalar\String_)#1179 (2) { ["value"]=> string(9) "あしたっていまさ" ["attributes":protected]=> array(4) { ["startLine"]=> int(2) ["endLine"]=> int(2) ["kind"]=> int(1) ["rawValue"]=> string(11) "'あしたっていまさ'" } } } (略) } }
  4. <?php echo 'あしたっていまさ'; PHP ParserにおけるAST 17 array(1) { [0]=> object(PhpParser\Node\Stmt\Echo_)#1180

    (2) { ["exprs"]=> array(1) { [0]=> object(PhpParser\Node\Scalar\String_)#1179 (2) { ["value"]=> string(9) "あしたっていまさ" ["attributes":protected]=> array(4) { ["startLine"]=> int(2) ["endLine"]=> int(2) ["kind"]=> int(1) ["rawValue"]=> string(11) "'あしたっていまさ'" } } } (略) } }
  5. <?php echo 'あしたっていまさ'; PHP ParserにおけるAST 18 array(1) { [0]=> object(PhpParser\Node\Stmt\Echo_)#1180

    (2) { ["exprs"]=> array(1) { [0]=> object(PhpParser\Node\Scalar\String_)#1179 (2) { ["value"]=> string(9) "あしたっていまさ" ["attributes":protected]=> array(4) { ["startLine"]=> int(2) ["endLine"]=> int(2) ["kind"]=> int(1) ["rawValue"]=> string(11) "'あしたっていまさ'" } } } (略) } }
  6. PHP ParserにおけるAST Node(親)がSub Node(子)を持つという階層構造になっている。 19 class Echo_ extends Node\Stmt {

    /** @var Node\Expr[] Expressions */ public $exprs; (略) public function getSubNodeNames() : array { return ['exprs']; } public function getType() : string { return 'Stmt_Echo'; } }
  7. abstract class Stmt extends NodeAbstract PHP ParserにおけるAST 20 abstract class

    NodeAbstract implements Node, \JsonSerializable interface Node { public function getType() : string; public function getSubNodeNames() : array; public function getLine() : int; public function getStartLine() : int; public function getEndLine() : int; public function getStartTokenPos() : int; public function getEndTokenPos() : int; public function getStartFilePos() : int; public function getEndFilePos() : int; public function getComments() : array; public function getDocComment(); public function setDocComment(Comment\Doc $docComment); public function setAttribute(string $key, $value); public function hasAttribute(string $key) : bool; public function getAttribute(string $key, $default = null); public function getAttributes() : array; public function setAttributes(array $attributes); }
  8. array(1) { [0]=> object(PhpParser\Node\Stmt\Expression)#1184 (2) { ["expr"]=> object(PhpParser\Node\Expr\Assign)#1183 (3) {

    ["var"]=> object(PhpParser\Node\Expr\Variable)#1179 (2) { ["name"]=> string(3) "x" (略) } ["expr"]=> object(PhpParser\Node\Expr\BinaryOp\Plus)#1182 (3) { ["left"]=> object(PhpParser\Node\Scalar\LNumber)#1180 (2) { ["value"]=> int(1) (略) } ["right"]=> object(PhpParser\Node\Scalar\LNumber)#1181 (2) { ["value"]=> int(2) PHP ParserにおけるAST <?php $x = 1 + 2; 23 = + $x 1 2 Assign Variable Plus LNumber LNumber Expression
  9. 4種類のノード[1] • 文に相当するノード • 式に相当するノード • スカラ値に相当するノード • その他のノード 26

    1. https://github.com/nikic/PHP-Parser/blob/4.x/doc/2_Usage_of_basic_components.markdown#node-tree-structure
  10. 文と式 27 PHPのコードは文(と式)から成る。 • 文[1] • ;で区切られた塊 • {}で囲まれた制御構造(if文等) など

    • 式[2] • 値があるもの全て 1. https://www.php.net/manual/ja/control-structures.intro.php 2. https://www.php.net/manual/ja/language.expressions.php
  11. 文(PhpParser\Node\Stmt) “PhpParser\Node\Stmts are statement nodes, i.e. language constructs that do

    not return a value and can not occur in an expression. For example a class definition is a statement. It doesn't return a value and you can't write something like func(class A {});.”[1] PhpParser\Node\Stmtsは文のノードです。つまり値を返さず式の中に含めら れない言語構造です。例えばクラスの定義は文です。それは値を返さず func(class A {});のように書くことができません。 29 1. https://github.com/nikic/PHP-Parser/blob/4.x/doc/2_Usage_of_basic_components.markdown#node-tree-structure
  12. 文(PhpParser\Node\Stmt) 30 Break_ DeclareDeclare Foreach_ Namespace_ TraitUse Case_ Do_ Function_

    Nop TraitUseAdaptation Catch_ Echo_ Global_ Property TryCatch ClassConst Else_ Goto_ PropertyProperty Unset_ ClassLike ElseIf_ GroupUse Return_ Use_ ClassMethod Enum_ HaltCompiler Static_ UseUse Class_ EnumCase If_ StaticVar While_ Const_ Expression InlineHTML Switch_ Alias Continue_ Finally_ Interface_ Throw_ Precedence Declare_ For_ Label Trait_
  13. 文(PhpParser\Node\Stmt) 31 break; declare(strict_types=1); foreach ($foos as $foo) {} namespace

    Foo; class Bar { use Foo; } switch ($foo) { case 'bar'; } do {} while(true); function foo() {} // 空行 traitの衝突回避機構 try {} catch (Exception $e) {} echo 'foo'; global $foo, $bar; class Foo { private string $bar; } try {} catch (Exception $e) {} class Foo { private const BAR = 'bar'; } if ($foo) {} elseif ($bar) {} else {}; goto foo; foo: class Foo { private string $bar; } unset($foo); クラスの定義等 if ($foo) {} elseif ($bar) {} else {}; use Foo\{ Bar, Baz as Qux }; return; use Foo; class Foo { private function foo() {} } enum Foo {} __halt_compiler(); function foo() { static $bar; } use function foo as f; class Foo {} enum Foo{ case Foo; } if ($foo) {} elseif ($bar) {} else {}; function foo() { static $bar; } while (true) {}; const FOO = 'foo'; foo(); foo switch ($foo) { case 'bar'; } class Qux { use Foo, Bar { Bar::baz insteadof Foo; Bar::baz as bazz; }} continue; try {} catch (Exception $e) {} filnaly {} interface Foo{} throw new Exception(''); class Qux { use Foo, Bar { Bar::baz insteadof Foo; Bar::baz as bazz; }} declare(strict_types=1); for ($i = 0; $i < 21; $i++) {} goto foo; foo: trait Foo {}
  14. 式(PhpParser\Node\Expr) "PhpParser\Node\Exprs are expression nodes, i.e. language constructs that return

    a value and thus can occur in other expressions. Examples of expressions are $var (PhpParser\Node\Expr\Variable) and func() (PhpParser\Node\Expr\FuncCall)."[1] PhpParser\Node\Exprsは式のノードです。つまり値を返すため式の中に含 められる言語構造です。例えば$varやfunc()は式です。 32 1. https://github.com/nikic/PHP-Parser/blob/4.x/doc/2_Usage_of_basic_components.markdown#node-tree-structure
  15. 式(PhpParser\Node\Expr) 33 Array_ ClassConstFetch Instanceof_ Print_ BitwiseAnd ShiftRight Identical ShiftRight

    ArrayDimFetch Clone_ Isset_ PropertyFetch BitwiseOr BitwiseAnd LogicalAnd Smaller ArrayItem Closure List_ ShellExec BitwiseXor BitwiseOr LogicalOr SmallerOrEqual ArrowFunction ClosureUse Match_ StaticCall Coalesce BitwiseXor LogicalXor Spaceship Assign ConstFetch MethodCall StaticPropertyFetch Concat BooleanAnd Minus Array_ AssignOp Empty_ New_ Ternary Div BooleanOr Mod Bool_ AssignRef Error NullsafeMethodCall Throw_ Minus Coalesce Mul Double BinaryOp ErrorSuppress NullsafePropertyFetch UnaryMinus Mod Concat NotEqual Int_ BitwiseNot Eval_ PostDec UnaryPlus Mul Div NotIdentical Object_ BooleanNot Exit_ PostInc Variable Plus Equal Plus String_ CallLike FuncCall PreDec Yield_ Pow Greater Pow Unset_ Cast Include_ PreInc YieldFrom ShiftLeft GreaterOrEqual ShiftLeft
  16. 式(PhpParser\Node\Expr) 34 array(); Foo::BAR; $foo instanceof Foo; print 'foo'; $foo

    &= $bar; $foo >>= $bar; $foo === $bar; $foo >> $bar; $foo[0]; $foo = clone $bar; isset($foo); $foo->bar; $foo |= $bar; $foo & $bar; $foo and $bar; $foo < $bar; $foo(['bar']); function () {}; list($foo) = []; `ls -al`; $foo ^= $bar; $foo | $bar; $foo or $bar; $foo <= $bar; fn() => 'foo'; function () use ($foo) {}; match ($foo) { 'bar' => 'baz' }; Foo::bar(); $foo ??= $bar; $foo ^ $bar; $foo xor $bar; $foo <=> $bar; $foo = 'bar'; FOO; $foo->bar(); Foo::bar; $foo .= $bar; $foo && $bar; $foo - $bar; (array)$foo; 代入演算子 empty($foo); new Foo(); ($foo) ? 'bar' : 'baz'; $foo /= $bar; $foo || $bar; $foo % $bar; (bool)$foo; $foo =& $bar; $foo->; $foo?->bar(); throw new Exception(''); $foo -= $bar; $foo ?? $bar; $foo * $bar; (float)$foo; ビット演算子 @$foo->; $foo?->bar; -77; $foo %= $bar; $bar . $baz; $foo != $bar; (int)$foo; ~ $foo; eval('foo'); $foo--; +77; $foo *= $bar; $foo / $bar; $foo !== $bar; (object)$foo; !$foo; exit(); $foo++; $foo; $foo += $bar; $foo == $bar; $foo + $bar; (string)$foo; 関数コール等 foo(); --$foo; yield $foo; $foo **= $bar; $foo > $bar; $foo ** $bar; (unset)$foo; キャスト include 'foo'; ++$foo; yield from $foo; $foo <<= $bar; $foo >= $bar; $foo << $bar;
  17. スカラ値(PhpParser\Node\Scalar) "PhpParser\Node\Scalars are nodes representing scalar values, like 'string' (PhpParser\Node\Scalar\String_),

    0 (PhpParser\Node\Scalar\LNumber) or magic constants like __FILE__ (PhpParser\Node\Scalar\MagicConst\File). All PhpParser\Node\Scalars extend PhpParser\Node\Expr, as scalars are expressions, too."[1] PhpParser\Node\Scalarsはスカラ値を表すノードです。例えば’string’, 0や __FILE__のようなマジック定数です。全てのスカラ値は式でもあるため PhpParser\Node\Exprを拡張します。 35 1. https://github.com/nikic/PHP-Parser/blob/4.x/doc/2_Usage_of_basic_components.markdown#node-tree-structure
  18. スカラ値(PhpParser\Node\Scalar) 37 77.0; 77; __CLASS__; __FUNCTION__; __NAMESPACE__; "$foo is not

    bar"; マジック定数 __DIR__; __LINE__; __TRAIT__; `ls -al`; 'foo'; __FILE__; __METHOD__;
  19. その他 "There are some nodes not in either of these

    groups, for example names (PhpParser\Node\Name) and call arguments (PhpParser\Node\Arg)."[1] 以上の3つのどれにも属さないノードがあります。例えばnamesやarguments です。 38 1. https://github.com/nikic/PHP-Parser/blob/4.x/doc/2_Usage_of_basic_components.markdown#node-tree-structure
  20. その他 39 Arg Const_ IntersectionType Param VariadicPlaceholder Attribute Expr MatchArm

    Scalar VarLikeIdentifier AttributeGroup FunctionLike Name Stmt FullyQualified ComplexType Identifier NullableType UnionType Relative
  21. その他 40 foo($bar); const FOO = 'foo'; function foo(Bar&Baz $qux)

    {} function foo(string $bar) {} foo(...); #[foo] class Bar{} foo(); match ($foo) { 'bar' => 'baz', }; $foo = 'bar'; class Foo { public string $bar; } #[foo(0), foo(1)] class Bar{} 関数の定義等 namespace foo; $foo = 'bar'; new \foo\Bar(); Nullable型等 class Foo {} function foo(?string $bar) {} function foo(Bar|Baz $qux) {} new namespace\Bar();
  22. class Isset_ extends Expr { /** @var Expr[] Variables */

    public $vars; /** * Constructs an array node. * * @param Expr[] $vars Variables * @param array $attributes Additional attributes */ public function __construct(array $vars, array $attributes = []) { $this->attributes = $attributes; $this->vars = $vars; } ②issetの引数として正しいのはどちら? 【正解】 両方正しい。 48 複数の式を受け取ることを想定し ている。 isset( $foo, $bar ); 親ノード 子ノード
  23. 関数と言語構造 PHPには言語構造という関数とぱっとみ見分けがつかない代物がある。 https://www.php.net/manual/ja/language.types.callable.phpによると “ array(), echo, empty(), eval(), exit(), isset(),

    list(), print あるいは unset()” https://www.php.net/manual/ja/functions.variable-functions.phpによると "echo, print, isset(), empty(), include, require" ここに記載されていない言語構造が他にもありますが… 49
  24. ③die()関数(言語構造)とは何か? 【正解】 exit()と同等。 54 class Exit_ extends Expr { /*

    For use in "kind" attribute */ const KIND_EXIT = 1; const KIND_DIE = 2; /** @var null|Expr Expression */ public $expr; エイリアスをconstで見分けてい る。
  25. エイリアスやバリエーション 他にも例えば… 55 class Array_ extends Expr { // For

    use in "kind" attribute const KIND_LONG = 1; // array() syntax const KIND_SHORT = 2; // [] syntax class String_ extends Scalar { /* For use in "kind" attribute */ const KIND_SINGLE_QUOTED = 1; const KIND_DOUBLE_QUOTED = 2; const KIND_HEREDOC = 3; const KIND_NOWDOC = 4;
  26. ④foo(...)とは何か? 【正解】 第一級callableを生成する記法。 58 class VariadicPlaceholder extends NodeAbstract { /**

    * Create a variadic argument placeholder (first-class callable syntax). * * @param array $attributes Additional attributes */ public function __construct(array $attributes = []) { $this->attributes = $attributes; }
  27. ⑤定数の宣言として正しいのはどちら? 【正解】 両方正しい。 61 class Const_ extends Node\Stmt { /**

    @var Node\Const_[] Constant declarations */ public $consts; /** * Constructs a const list node. * * @param Node\Const_[] $consts Constant declarations * @param array $attributes Additional attributes */ public function __construct(array $consts, array $attributes = []) { $this->attributes = $attributes; $this->consts = $consts; } 複数の定数宣言を受け取ること を想定している。
  28. 1 FunctionLike interface アロー関数、クロージャ、メソッド、関数の定義が実装するインタフェース 2 ComplexType abstract IntersectionType, NullableType, UnionTypeが拡張する抽象クラス

    3 Expr abstract 式が拡張する抽象クラス 4 Scalar abstract スカラ値が拡張する抽象クラス 5 Stmt abstract 文が拡張する抽象クラス 6 AssignOp abstract 代入演算子が拡張する抽象クラス 7 BinaryOp abstract ビット演算子が拡張する抽象クラス 8 CallLike abstract オブジェクト生成、メソッド、関数の呼び出しが拡張する抽象クラス 9 Cast abstract キャストが拡張する抽象クラス 10 MagicConst abstract マジック定数が拡張する抽象クラス 11 ClassLike abstract trait, interface, enum, classが拡張する抽象クラス 12 TraitUseAdaptation abstract Alias, Precedenceが拡張する抽象クラス 便宜的なノード 66
  29. ケーススタディ(while) 71 class While_ extends Node\Stmt { /** @var Node\Expr

    Condition */ public $cond; /** @var Node\Stmt[] Statements */ public $stmts; /** * Constructs a while node. * * @param Node\Expr $cond Condition * @param Node\Stmt[] $stmts Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; }
  30. ケーススタディ(while) 72 class While_ extends Node\Stmt { /** @var Node\Expr

    Condition */ public $cond; /** @var Node\Stmt[] Statements */ public $stmts; /** * Constructs a while node. * * @param Node\Expr $cond Condition * @param Node\Stmt[] $stmts Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; }
  31. ケーススタディ(while) 73 class While_ extends Node\Stmt { /** @var Node\Expr

    Condition */ public $cond; /** @var Node\Stmt[] Statements */ public $stmts; /** * Constructs a while node. * * @param Node\Expr $cond Condition * @param Node\Stmt[] $stmts Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; }
  32. ケーススタディ(while) 74 class While_ extends Node\Stmt { /** @var Node\Expr

    Condition */ public $cond; /** @var Node\Stmt[] Statements */ public $stmts; /** * Constructs a while node. * * @param Node\Expr $cond Condition * @param Node\Stmt[] $stmts Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } while (true) { echo “無”; echo “駄”; }
  33. ケーススタディ(関数) 75 interface FunctionLike extends Node { /** * Whether

    to return by reference * * @return bool */ public function returnsByRef() : bool; /** * List of parameters * * @return Param[] */ public function getParams() : array; /** * Get the declared return type or null * * @return null|Identifier|Name|ComplexType */ public function getReturnType(); /** * The function body * * @return Stmt[]|null */ public function getStmts(); /** * Get PHP attribute groups. * * @return AttributeGroup[] */ public function getAttrGroups() : array; }
  34. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 76
  35. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 77
  36. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 78 function &f($param) {} function f($param) {}
  37. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 79 function f($param) {}
  38. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 80 function f($param) {}
  39. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 81 function f(): bool {} function f(): SomeType {} function f(): bool|int {}
  40. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 82 function f() { $awesomeValue = awesome(); return $awesomeValue; }
  41. class Function_ extends Node\Stmt implements FunctionLike { /** @var bool

    Whether function returns by reference */ public $byRef; /** @var Node\Identifier Name */ public $name; /** @var Node\Param[] Parameters */ public $params; /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } ケーススタディ(関数) 83 #[Attribute] function f() {}
  42. ケーススタディ(関数) getSubNodeNames()を比較することで、相違点も分かる。 84 ArrowFunction 'attrGroups', 'byRef', 'params', 'returnType', 'static', 'expr'

    ClassMethod 'attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts', 'flags' Closure 'attrGroups', 'byRef', 'params', 'returnType', 'stmts', 'static', 'uses' Function_ 'attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts'
  43. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 85
  44. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 86
  45. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 87 function f(bool $param){} function f(SomeType $param) {} function f(bool|int $param) {}
  46. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 88 function f(&$param) {} function f($param) {}
  47. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 89 function f(...$param) {}
  48. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 90 function f($param) {} function f(param) {}
  49. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 91 function f($param = “di molto”) {}
  50. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 92 ???
  51. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 93 コンストラクタの@paramによると Optional visibility flags
  52. class Param extends NodeAbstract { /** @var null|Identifier|Name|ComplexType Type declaration

    */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; /** @var int */ public $flags; /** @var AttributeGroup[] PHP attribute groups */ public $attrGroups; (略) public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } ケーススタディ(Param) 94 function f(#[Attribute]$param) {}