From c8bded2b4f8bec75e0069fa0028812d451b09be3 Mon Sep 17 00:00:00 2001 From: LionTree Date: Wed, 6 Apr 2022 20:43:29 +0800 Subject: [PATCH 1/3] support trait use --- lib/PHPCfg/Alias.php | 43 +++++++++++ lib/PHPCfg/Op/Stmt/TraitUse.php | 35 +++++++++ lib/PHPCfg/Parser.php | 29 +++++++- lib/PHPCfg/Precedence.php | 23 ++++++ lib/PHPCfg/Printer.php | 35 +++++++++ lib/PHPCfg/TraitUseAdaptation.php | 26 +++++++ test/code/traitUse.test | 115 ++++++++++++++++++++++++++++++ 7 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 lib/PHPCfg/Alias.php create mode 100644 lib/PHPCfg/Op/Stmt/TraitUse.php create mode 100644 lib/PHPCfg/Precedence.php create mode 100644 lib/PHPCfg/TraitUseAdaptation.php create mode 100644 test/code/traitUse.test diff --git a/lib/PHPCfg/Alias.php b/lib/PHPCfg/Alias.php new file mode 100644 index 0000000..d06f75c --- /dev/null +++ b/lib/PHPCfg/Alias.php @@ -0,0 +1,43 @@ +newName = $newName; + $this->newModifier = $newModifier; + } + + public function isPublic() : bool + { + return (bool) ($this->newModifier & Node\Stmt\Class_::MODIFIER_PUBLIC); + } + + public function isProtected() : bool + { + return (bool) ($this->newModifier & Node\Stmt\Class_::MODIFIER_PROTECTED); + } + + public function isPrivate() : bool + { + return (bool) ($this->newModifier & Node\Stmt\Class_::MODIFIER_PRIVATE); + } +} \ No newline at end of file diff --git a/lib/PHPCfg/Op/Stmt/TraitUse.php b/lib/PHPCfg/Op/Stmt/TraitUse.php new file mode 100644 index 0000000..7e60ca1 --- /dev/null +++ b/lib/PHPCfg/Op/Stmt/TraitUse.php @@ -0,0 +1,35 @@ +traits = $traits; + $this->adaptations = $adaptations; + } +} \ No newline at end of file diff --git a/lib/PHPCfg/Parser.php b/lib/PHPCfg/Parser.php index 8a27a78..eee4efd 100755 --- a/lib/PHPCfg/Parser.php +++ b/lib/PHPCfg/Parser.php @@ -13,6 +13,7 @@ use PHPCfg\Op\Stmt\Jump; use PHPCfg\Op\Stmt\JumpIf; +use PHPCfg\Op\Stmt\TraitUse; use PHPCfg\Op\Terminal\Return_; use PHPCfg\Operand\Literal; use PHPCfg\Operand\Temporary; @@ -684,7 +685,33 @@ protected function parseStmt_Trait(Stmt\Trait_ $node) protected function parseStmt_TraitUse(Stmt\TraitUse $node) { - // TODO + $traits = []; + $adaptations = []; + foreach($node->traits as $trait_) { + $traits[] = new Literal($trait_->toCodeString()); + } + foreach($node->adaptations as $adaptation) { + if($adaptation instanceof Stmt\TraitUseAdaptation\Alias) { + $adaptations[] = new Alias( + new Literal($adaptation->trait != null ? $adaptation->trait->toCodeString() : null), + new Literal($adaptation->method->name), + new Literal($adaptation->newName != null ? $adaptation->newName->name : null), + $adaptation->newModifier + ); + } + else if($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { + $insteadofs = []; + foreach($adaptation->insteadof as $insteadof) { + $insteadofs[] = new Literal($insteadof->toCodeString()); + } + $adaptations[] = new Precedence( + new Literal($adaptation->trait != null ? $adaptation->trait->toCodeString() : null), + new Literal($adaptation->method->name), + $insteadofs + ); + } + } + $this->block->children[] = new TraitUse($traits,$adaptations); } protected function parseStmt_TryCatch(Stmt\TryCatch $node) diff --git a/lib/PHPCfg/Precedence.php b/lib/PHPCfg/Precedence.php new file mode 100644 index 0000000..c3b18a8 --- /dev/null +++ b/lib/PHPCfg/Precedence.php @@ -0,0 +1,23 @@ +insteadof = $insteadof; + } +} \ No newline at end of file diff --git a/lib/PHPCfg/Printer.php b/lib/PHPCfg/Printer.php index fcd4fe7..d38f13f 100755 --- a/lib/PHPCfg/Printer.php +++ b/lib/PHPCfg/Printer.php @@ -123,6 +123,41 @@ protected function renderOp(Op $op) $result .= "\n flags: " . $this->indent($this->renderFlags($op)); $result .= "\n declaredType: " . $this->indent($this->renderType($op->declaredType)); } + if($op instanceof Op\Stmt\TraitUse) { + foreach($op->traits as $index => $trait_) { + $result .= "\n use[$index]: " . $this->indent($this->renderOperand($trait_)); + } + foreach($op->adaptations as $index => $adaptation) { + if($adaptation instanceof Alias) { + $result .= "\n adaptation[$index]: Alias"; + $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + $result .= "\n method:".$this->indent($this->renderOperand($adaptation->method)); + if($adaptation->newName->value != null) { + $result .= "\n newName:".$this->indent($this->renderOperand($adaptation->newName)); + } + if($adaptation->newModifier != null) { + $result .= "\n newModifier:"; + if($adaptation->isPublic()) { + $result .= "public"; + } + if($adaptation->isPrivate()) { + $result .= "private"; + } + if($adaptation->isProtected()) { + $result .= "protected"; + } + } + } + else if($adaptation instanceof Precedence) { + $result .= "\n adaptation[$index]: Insteadof"; + $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + $result .= "\n method:".$this->indent($this->renderOperand($adaptation->method)); + foreach($adaptation->insteadof as $index2 => $insteadof) { + $result .= "\n insteadof[$index2]: " . $this->indent($this->renderOperand($insteadof)); + } + } + } + } if ($op instanceof Op\Stmt\ClassMethod) { $result .= "\n flags: " . $this->indent($this->renderFlags($op)); } diff --git a/lib/PHPCfg/TraitUseAdaptation.php b/lib/PHPCfg/TraitUseAdaptation.php new file mode 100644 index 0000000..dc0dc3b --- /dev/null +++ b/lib/PHPCfg/TraitUseAdaptation.php @@ -0,0 +1,26 @@ +trait = $trait; + $this->method = $method; + } +} \ No newline at end of file diff --git a/test/code/traitUse.test b/test/code/traitUse.test new file mode 100644 index 0000000..c52e98d --- /dev/null +++ b/test/code/traitUse.test @@ -0,0 +1,115 @@ + + flags: public + Stmt_ClassMethod<'bigTalk'> + flags: public + +Block#3 + Stmt_ClassMethod<'smallTalk'> + flags: public + Stmt_ClassMethod<'bigTalk'> + flags: public + +Block#4 + Stmt_TraitUse + use[0]: LITERAL('\\A') + use[1]: LITERAL('\\B') + adaptation[0]: Insteadof + trait:LITERAL('\\B') + method:LITERAL('smallTalk') + insteadof[0]: LITERAL('\\A') + adaptation[1]: Insteadof + trait:LITERAL('\\A') + method:LITERAL('bigTalk') + insteadof[0]: LITERAL('\\B') + +Block#5 + Stmt_TraitUse + use[0]: LITERAL('\\A') + use[1]: LITERAL('\\B') + adaptation[0]: Insteadof + trait:LITERAL('\\B') + method:LITERAL('smallTalk') + insteadof[0]: LITERAL('\\A') + adaptation[1]: Insteadof + trait:LITERAL('\\A') + method:LITERAL('bigTalk') + insteadof[0]: LITERAL('\\B') + adaptation[2]: Alias + trait:LITERAL('\\B') + method:LITERAL('bigTalk') + newName:LITERAL('talk') + newModifier:private + +Function 'A::smallTalk': mixed +Block#1 + Terminal_Echo + expr: LITERAL('a') + Terminal_Return + +Function 'A::bigTalk': mixed +Block#1 + Terminal_Echo + expr: LITERAL('A') + Terminal_Return + +Function 'B::smallTalk': mixed +Block#1 + Terminal_Echo + expr: LITERAL('b') + Terminal_Return + +Function 'B::bigTalk': mixed +Block#1 + Terminal_Echo + expr: LITERAL('B') + Terminal_Return From b91854f1b64b68fbb091e909e715b7f9a1c5e534 Mon Sep 17 00:00:00 2001 From: LioTree Date: Mon, 2 May 2022 23:53:51 +0800 Subject: [PATCH 2/3] modify useTrait --- lib/PHPCfg/Op/Stmt/TraitUse.php | 3 +- lib/PHPCfg/{ => Op/TraitUse}/Alias.php | 8 ++-- lib/PHPCfg/{ => Op/TraitUse}/Precedence.php | 9 ++-- lib/PHPCfg/{ => Op}/TraitUseAdaptation.php | 10 ++-- lib/PHPCfg/Parser.php | 16 ++++--- lib/PHPCfg/Printer.php | 14 ++++-- test/code/traitUse.test | 2 +- test/code/traitUse2.test | 51 +++++++++++++++++++++ 8 files changed, 91 insertions(+), 22 deletions(-) rename lib/PHPCfg/{ => Op/TraitUse}/Alias.php (81%) rename lib/PHPCfg/{ => Op/TraitUse}/Precedence.php (60%) rename lib/PHPCfg/{ => Op}/TraitUseAdaptation.php (62%) create mode 100644 test/code/traitUse2.test diff --git a/lib/PHPCfg/Op/Stmt/TraitUse.php b/lib/PHPCfg/Op/Stmt/TraitUse.php index 7e60ca1..266bd91 100644 --- a/lib/PHPCfg/Op/Stmt/TraitUse.php +++ b/lib/PHPCfg/Op/Stmt/TraitUse.php @@ -27,8 +27,9 @@ class TraitUse extends Stmt */ public array $adaptations; - public function __construct(array $traits,array $adaptations) + public function __construct(array $traits,array $adaptations, array $attributes = []) { + parent::__construct($attributes); $this->traits = $traits; $this->adaptations = $adaptations; } diff --git a/lib/PHPCfg/Alias.php b/lib/PHPCfg/Op/TraitUse/Alias.php similarity index 81% rename from lib/PHPCfg/Alias.php rename to lib/PHPCfg/Op/TraitUse/Alias.php index d06f75c..2c96e45 100644 --- a/lib/PHPCfg/Alias.php +++ b/lib/PHPCfg/Op/TraitUse/Alias.php @@ -9,9 +9,11 @@ * @license MIT See LICENSE at the root of the project for more info */ -namespace PHPCfg; +namespace PHPCfg\Op\TraitUse; use PhpParser\Node; +use PHPCfg\Operand; +use PHPCfg\Op\TraitUseAdaptation; class Alias extends TraitUseAdaptation { @@ -19,9 +21,9 @@ class Alias extends TraitUseAdaptation public ?int $newModifier; - public function __construct(?Operand $trait,Operand $method,?Operand $newName,?int $newModifier) + public function __construct(?Operand $trait,Operand $method,?Operand $newName,?int $newModifier,array $attributes = []) { - parent::__construct($trait,$method); + parent::__construct($trait,$method,$attributes); $this->newName = $newName; $this->newModifier = $newModifier; } diff --git a/lib/PHPCfg/Precedence.php b/lib/PHPCfg/Op/TraitUse/Precedence.php similarity index 60% rename from lib/PHPCfg/Precedence.php rename to lib/PHPCfg/Op/TraitUse/Precedence.php index c3b18a8..ea1eca2 100644 --- a/lib/PHPCfg/Precedence.php +++ b/lib/PHPCfg/Op/TraitUse/Precedence.php @@ -9,15 +9,18 @@ * @license MIT See LICENSE at the root of the project for more info */ -namespace PHPCfg; +namespace PHPCfg\Op\TraitUse; + +use PHPCfg\Operand; +use PHPCfg\Op\TraitUseAdaptation; class Precedence extends TraitUseAdaptation { public array $insteadof; - public function __construct(Operand $trait,Operand $method,array $insteadof) + public function __construct(?Operand $trait,Operand $method,array $insteadof,array $attributes = []) { - parent::__construct($trait,$method); + parent::__construct($trait,$method,$attributes); $this->insteadof = $insteadof; } } \ No newline at end of file diff --git a/lib/PHPCfg/TraitUseAdaptation.php b/lib/PHPCfg/Op/TraitUseAdaptation.php similarity index 62% rename from lib/PHPCfg/TraitUseAdaptation.php rename to lib/PHPCfg/Op/TraitUseAdaptation.php index dc0dc3b..3886e31 100644 --- a/lib/PHPCfg/TraitUseAdaptation.php +++ b/lib/PHPCfg/Op/TraitUseAdaptation.php @@ -10,16 +10,20 @@ * @license MIT See LICENSE at the root of the project for more info */ -namespace PHPCfg; +namespace PHPCfg\Op; -class TraitUseAdaptation +use PHPCfg\Op; +use PHPCfg\Operand; + +abstract class TraitUseAdaptation extends Op { public ?Operand $trait; public Operand $method; - public function __construct(?Operand $trait,Operand $method) + public function __construct(?Operand $trait,Operand $method,array $attributes = []) { + parent::__construct($attributes); $this->trait = $trait; $this->method = $method; } diff --git a/lib/PHPCfg/Parser.php b/lib/PHPCfg/Parser.php index eee4efd..7642261 100755 --- a/lib/PHPCfg/Parser.php +++ b/lib/PHPCfg/Parser.php @@ -15,6 +15,8 @@ use PHPCfg\Op\Stmt\JumpIf; use PHPCfg\Op\Stmt\TraitUse; use PHPCfg\Op\Terminal\Return_; +use PHPCfg\Op\TraitUse\Alias; +use PHPCfg\Op\TraitUse\Precedence; use PHPCfg\Operand\Literal; use PHPCfg\Operand\Temporary; use PHPCfg\Operand\Variable; @@ -693,10 +695,11 @@ protected function parseStmt_TraitUse(Stmt\TraitUse $node) foreach($node->adaptations as $adaptation) { if($adaptation instanceof Stmt\TraitUseAdaptation\Alias) { $adaptations[] = new Alias( - new Literal($adaptation->trait != null ? $adaptation->trait->toCodeString() : null), + $adaptation->trait != null ? new Literal($adaptation->trait->toCodeString()) : null, new Literal($adaptation->method->name), - new Literal($adaptation->newName != null ? $adaptation->newName->name : null), - $adaptation->newModifier + $adaptation->newName != null ? new Literal($adaptation->newName->name) : null, + $adaptation->newModifier, + $this->mapAttributes($adaptation) ); } else if($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { @@ -705,13 +708,14 @@ protected function parseStmt_TraitUse(Stmt\TraitUse $node) $insteadofs[] = new Literal($insteadof->toCodeString()); } $adaptations[] = new Precedence( - new Literal($adaptation->trait != null ? $adaptation->trait->toCodeString() : null), + $adaptation->trait != null ? new Literal($adaptation->trait->toCodeString()) : null, new Literal($adaptation->method->name), - $insteadofs + $insteadofs, + $this->mapAttributes($adaptation) ); } } - $this->block->children[] = new TraitUse($traits,$adaptations); + $this->block->children[] = new TraitUse($traits,$adaptations,$this->mapAttributes($node)); } protected function parseStmt_TryCatch(Stmt\TryCatch $node) diff --git a/lib/PHPCfg/Printer.php b/lib/PHPCfg/Printer.php index d38f13f..a587e09 100755 --- a/lib/PHPCfg/Printer.php +++ b/lib/PHPCfg/Printer.php @@ -128,11 +128,13 @@ protected function renderOp(Op $op) $result .= "\n use[$index]: " . $this->indent($this->renderOperand($trait_)); } foreach($op->adaptations as $index => $adaptation) { - if($adaptation instanceof Alias) { + if($adaptation instanceof Op\TraitUse\Alias) { $result .= "\n adaptation[$index]: Alias"; - $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + if($adaptation->trait != null) { + $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + } $result .= "\n method:".$this->indent($this->renderOperand($adaptation->method)); - if($adaptation->newName->value != null) { + if($adaptation->newName != null) { $result .= "\n newName:".$this->indent($this->renderOperand($adaptation->newName)); } if($adaptation->newModifier != null) { @@ -148,9 +150,11 @@ protected function renderOp(Op $op) } } } - else if($adaptation instanceof Precedence) { + else if($adaptation instanceof Op\TraitUse\Precedence) { $result .= "\n adaptation[$index]: Insteadof"; - $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + if($adaptation->trait != null) { + $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); + } $result .= "\n method:".$this->indent($this->renderOperand($adaptation->method)); foreach($adaptation->insteadof as $index2 => $insteadof) { $result .= "\n insteadof[$index2]: " . $this->indent($this->renderOperand($insteadof)); diff --git a/test/code/traitUse.test b/test/code/traitUse.test index c52e98d..fe9ae62 100644 --- a/test/code/traitUse.test +++ b/test/code/traitUse.test @@ -112,4 +112,4 @@ Function 'B::bigTalk': mixed Block#1 Terminal_Echo expr: LITERAL('B') - Terminal_Return + Terminal_Return \ No newline at end of file diff --git a/test/code/traitUse2.test b/test/code/traitUse2.test new file mode 100644 index 0000000..cc0146c --- /dev/null +++ b/test/code/traitUse2.test @@ -0,0 +1,51 @@ + + flags: public + +Block#3 + Stmt_TraitUse + use[0]: LITERAL('\\HelloWorld') + adaptation[0]: Alias + method:LITERAL('sayHello') + newModifier:protected + +Block#4 + Stmt_TraitUse + use[0]: LITERAL('\\HelloWorld') + adaptation[0]: Alias + method:LITERAL('sayHello') + newName:LITERAL('myPrivateHello') + newModifier:private + +Function 'HelloWorld::sayHello': mixed +Block#1 + Terminal_Echo + expr: LITERAL('Hello World!') + Terminal_Return \ No newline at end of file From c5d758335cb495b29ecd020e483bcf9cdb150e74 Mon Sep 17 00:00:00 2001 From: LioTree Date: Tue, 3 May 2022 00:10:57 +0800 Subject: [PATCH 3/3] change TraitUse to TraitUseAdaptation --- lib/PHPCfg/Op/{TraitUse => TraitUseAdaptation}/Alias.php | 2 +- lib/PHPCfg/Op/{TraitUse => TraitUseAdaptation}/Precedence.php | 2 +- lib/PHPCfg/Parser.php | 4 ++-- lib/PHPCfg/Printer.php | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename lib/PHPCfg/Op/{TraitUse => TraitUseAdaptation}/Alias.php (96%) rename lib/PHPCfg/Op/{TraitUse => TraitUseAdaptation}/Precedence.php (93%) diff --git a/lib/PHPCfg/Op/TraitUse/Alias.php b/lib/PHPCfg/Op/TraitUseAdaptation/Alias.php similarity index 96% rename from lib/PHPCfg/Op/TraitUse/Alias.php rename to lib/PHPCfg/Op/TraitUseAdaptation/Alias.php index 2c96e45..2bd617d 100644 --- a/lib/PHPCfg/Op/TraitUse/Alias.php +++ b/lib/PHPCfg/Op/TraitUseAdaptation/Alias.php @@ -9,7 +9,7 @@ * @license MIT See LICENSE at the root of the project for more info */ -namespace PHPCfg\Op\TraitUse; +namespace PHPCfg\Op\TraitUseAdaptation; use PhpParser\Node; use PHPCfg\Operand; diff --git a/lib/PHPCfg/Op/TraitUse/Precedence.php b/lib/PHPCfg/Op/TraitUseAdaptation/Precedence.php similarity index 93% rename from lib/PHPCfg/Op/TraitUse/Precedence.php rename to lib/PHPCfg/Op/TraitUseAdaptation/Precedence.php index ea1eca2..a0acb8c 100644 --- a/lib/PHPCfg/Op/TraitUse/Precedence.php +++ b/lib/PHPCfg/Op/TraitUseAdaptation/Precedence.php @@ -9,7 +9,7 @@ * @license MIT See LICENSE at the root of the project for more info */ -namespace PHPCfg\Op\TraitUse; +namespace PHPCfg\Op\TraitUseAdaptation; use PHPCfg\Operand; use PHPCfg\Op\TraitUseAdaptation; diff --git a/lib/PHPCfg/Parser.php b/lib/PHPCfg/Parser.php index 7642261..5c5c02d 100755 --- a/lib/PHPCfg/Parser.php +++ b/lib/PHPCfg/Parser.php @@ -15,8 +15,8 @@ use PHPCfg\Op\Stmt\JumpIf; use PHPCfg\Op\Stmt\TraitUse; use PHPCfg\Op\Terminal\Return_; -use PHPCfg\Op\TraitUse\Alias; -use PHPCfg\Op\TraitUse\Precedence; +use PHPCfg\Op\TraitUseAdaptation\Alias; +use PHPCfg\Op\TraitUseAdaptation\Precedence; use PHPCfg\Operand\Literal; use PHPCfg\Operand\Temporary; use PHPCfg\Operand\Variable; diff --git a/lib/PHPCfg/Printer.php b/lib/PHPCfg/Printer.php index a587e09..f09a2fe 100755 --- a/lib/PHPCfg/Printer.php +++ b/lib/PHPCfg/Printer.php @@ -128,7 +128,7 @@ protected function renderOp(Op $op) $result .= "\n use[$index]: " . $this->indent($this->renderOperand($trait_)); } foreach($op->adaptations as $index => $adaptation) { - if($adaptation instanceof Op\TraitUse\Alias) { + if($adaptation instanceof Op\TraitUseAdaptation\Alias) { $result .= "\n adaptation[$index]: Alias"; if($adaptation->trait != null) { $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait)); @@ -150,7 +150,7 @@ protected function renderOp(Op $op) } } } - else if($adaptation instanceof Op\TraitUse\Precedence) { + else if($adaptation instanceof Op\TraitUseAdaptation\Precedence) { $result .= "\n adaptation[$index]: Insteadof"; if($adaptation->trait != null) { $result .= "\n trait:".$this->indent($this->renderOperand($adaptation->trait));