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

Learning PHP with PHP Parser

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/

inouehi

March 24, 2023
Tweet

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) {}