2017-11-02 18:56:01 +01:00
|
|
|
<?php declare(strict_types=1);
|
2014-02-06 14:44:16 +01:00
|
|
|
|
|
|
|
namespace PhpParser;
|
|
|
|
|
2017-04-28 18:13:06 +02:00
|
|
|
use PhpParser\Node\Arg;
|
2014-12-19 18:35:19 +01:00
|
|
|
use PhpParser\Node\Expr;
|
2017-04-24 21:42:59 +02:00
|
|
|
use PhpParser\Node\Expr\BinaryOp\Concat;
|
2018-03-03 15:40:51 +01:00
|
|
|
use PhpParser\Node\Identifier;
|
|
|
|
use PhpParser\Node\Name;
|
|
|
|
use PhpParser\Node\Scalar\LNumber;
|
2017-04-24 21:28:03 +02:00
|
|
|
use PhpParser\Node\Scalar\String_;
|
2014-12-19 18:35:19 +01:00
|
|
|
|
2019-01-19 11:18:00 +01:00
|
|
|
class BuilderFactoryTest extends \PHPUnit\Framework\TestCase
|
2014-02-06 14:44:16 +01:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @dataProvider provideTestFactory
|
|
|
|
*/
|
|
|
|
public function testFactory($methodName, $className) {
|
|
|
|
$factory = new BuilderFactory;
|
|
|
|
$this->assertInstanceOf($className, $factory->$methodName('test'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function provideTestFactory() {
|
2017-08-13 14:35:03 +02:00
|
|
|
return [
|
2018-07-20 21:43:43 +02:00
|
|
|
['namespace', Builder\Namespace_::class],
|
|
|
|
['class', Builder\Class_::class],
|
|
|
|
['interface', Builder\Interface_::class],
|
|
|
|
['trait', Builder\Trait_::class],
|
|
|
|
['method', Builder\Method::class],
|
|
|
|
['function', Builder\Function_::class],
|
|
|
|
['property', Builder\Property::class],
|
|
|
|
['param', Builder\Param::class],
|
|
|
|
['use', Builder\Use_::class],
|
|
|
|
['useFunction', Builder\Use_::class],
|
|
|
|
['useConst', Builder\Use_::class],
|
2017-08-13 14:35:03 +02:00
|
|
|
];
|
2014-02-06 14:44:16 +01:00
|
|
|
}
|
2014-12-19 18:35:19 +01:00
|
|
|
|
2017-04-24 21:28:03 +02:00
|
|
|
public function testVal() {
|
|
|
|
// This method is a wrapper around BuilderHelpers::normalizeValue(),
|
|
|
|
// which is already tested elsewhere
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
$this->assertEquals(
|
|
|
|
new String_("foo"),
|
|
|
|
$factory->val("foo")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-04-24 21:42:59 +02:00
|
|
|
public function testConcat() {
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
$varA = new Expr\Variable('a');
|
|
|
|
$varB = new Expr\Variable('b');
|
|
|
|
$varC = new Expr\Variable('c');
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
new Concat($varA, $varB),
|
|
|
|
$factory->concat($varA, $varB)
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Concat(new Concat($varA, $varB), $varC),
|
|
|
|
$factory->concat($varA, $varB, $varC)
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Concat(new Concat(new String_("a"), $varB), new String_("c")),
|
|
|
|
$factory->concat("a", $varB, "c")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testConcatOneError() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Expected at least two expressions');
|
2017-04-24 21:42:59 +02:00
|
|
|
(new BuilderFactory())->concat("a");
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testConcatInvalidExpr() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Expected string or Expr');
|
2017-04-24 21:42:59 +02:00
|
|
|
(new BuilderFactory())->concat("a", 42);
|
|
|
|
}
|
|
|
|
|
2017-04-28 18:13:06 +02:00
|
|
|
public function testArgs() {
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
$unpack = new Arg(new Expr\Variable('c'), false, true);
|
|
|
|
$this->assertEquals(
|
|
|
|
[
|
|
|
|
new Arg(new Expr\Variable('a')),
|
|
|
|
new Arg(new String_('b')),
|
|
|
|
$unpack
|
|
|
|
],
|
|
|
|
$factory->args([new Expr\Variable('a'), 'b', $unpack])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-03-03 15:40:51 +01:00
|
|
|
public function testCalls() {
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
|
|
|
|
// Simple function call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\FuncCall(
|
|
|
|
new Name('var_dump'),
|
|
|
|
[new Arg(new String_('str'))]
|
|
|
|
),
|
|
|
|
$factory->funcCall('var_dump', ['str'])
|
|
|
|
);
|
|
|
|
// Dynamic function call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\FuncCall(new Expr\Variable('fn')),
|
|
|
|
$factory->funcCall(new Expr\Variable('fn'))
|
|
|
|
);
|
|
|
|
|
|
|
|
// Simple method call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\MethodCall(
|
|
|
|
new Expr\Variable('obj'),
|
|
|
|
new Identifier('method'),
|
|
|
|
[new Arg(new LNumber(42))]
|
|
|
|
),
|
|
|
|
$factory->methodCall(new Expr\Variable('obj'), 'method', [42])
|
|
|
|
);
|
|
|
|
// Explicitly pass Identifier node
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\MethodCall(
|
|
|
|
new Expr\Variable('obj'),
|
|
|
|
new Identifier('method')
|
|
|
|
),
|
|
|
|
$factory->methodCall(new Expr\Variable('obj'), new Identifier('method'))
|
|
|
|
);
|
|
|
|
// Dynamic method call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\MethodCall(
|
|
|
|
new Expr\Variable('obj'),
|
|
|
|
new Expr\Variable('method')
|
|
|
|
),
|
|
|
|
$factory->methodCall(new Expr\Variable('obj'), new Expr\Variable('method'))
|
|
|
|
);
|
|
|
|
|
|
|
|
// Simple static method call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\StaticCall(
|
|
|
|
new Name\FullyQualified('Foo'),
|
|
|
|
new Identifier('bar'),
|
|
|
|
[new Arg(new Expr\Variable('baz'))]
|
|
|
|
),
|
|
|
|
$factory->staticCall('\Foo', 'bar', [new Expr\Variable('baz')])
|
|
|
|
);
|
|
|
|
// Dynamic static method call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\StaticCall(
|
|
|
|
new Expr\Variable('foo'),
|
|
|
|
new Expr\Variable('bar')
|
|
|
|
),
|
|
|
|
$factory->staticCall(new Expr\Variable('foo'), new Expr\Variable('bar'))
|
|
|
|
);
|
2018-03-03 22:25:58 +01:00
|
|
|
|
|
|
|
// Simple new call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\New_(new Name\FullyQualified('stdClass')),
|
|
|
|
$factory->new('\stdClass')
|
|
|
|
);
|
|
|
|
// Dynamic new call
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\New_(
|
|
|
|
new Expr\Variable('foo'),
|
|
|
|
[new Arg(new String_('bar'))]
|
|
|
|
),
|
|
|
|
$factory->new(new Expr\Variable('foo'), ['bar'])
|
|
|
|
);
|
2018-03-03 15:40:51 +01:00
|
|
|
}
|
|
|
|
|
2018-03-03 22:14:42 +01:00
|
|
|
public function testConstFetches() {
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\ConstFetch(new Name('FOO')),
|
|
|
|
$factory->constFetch('FOO')
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\ClassConstFetch(new Name('Foo'), new Identifier('BAR')),
|
|
|
|
$factory->classConstFetch('Foo', 'BAR')
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\ClassConstFetch(new Expr\Variable('foo'), new Identifier('BAR')),
|
|
|
|
$factory->classConstFetch(new Expr\Variable('foo'), 'BAR')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-07-20 21:59:42 +02:00
|
|
|
public function testVar() {
|
|
|
|
$factory = new BuilderFactory();
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\Variable("foo"),
|
|
|
|
$factory->var("foo")
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\Variable(new Expr\Variable("foo")),
|
|
|
|
$factory->var($factory->var("foo"))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testPropertyFetch() {
|
|
|
|
$f = new BuilderFactory();
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\PropertyFetch(new Expr\Variable('foo'), 'bar'),
|
|
|
|
$f->propertyFetch($f->var('foo'), 'bar')
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\PropertyFetch(new Expr\Variable('foo'), 'bar'),
|
|
|
|
$f->propertyFetch($f->var('foo'), new Identifier('bar'))
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
new Expr\PropertyFetch(new Expr\Variable('foo'), new Expr\Variable('bar')),
|
|
|
|
$f->propertyFetch($f->var('foo'), $f->var('bar'))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-03-03 15:40:51 +01:00
|
|
|
public function testInvalidIdentifier() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Expected string or instance of Node\Identifier');
|
2018-03-03 22:14:42 +01:00
|
|
|
(new BuilderFactory())->classConstFetch('Foo', new Expr\Variable('foo'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testInvalidIdentifierOrExpr() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Expected string or instance of Node\Identifier or Node\Expr');
|
2018-03-03 15:40:51 +01:00
|
|
|
(new BuilderFactory())->staticCall('Foo', new Name('bar'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testInvalidNameOrExpr() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Name must be a string or an instance of Node\Name or Node\Expr');
|
2018-03-03 15:40:51 +01:00
|
|
|
(new BuilderFactory())->funcCall(new Node\Stmt\Return_());
|
|
|
|
}
|
|
|
|
|
2018-07-20 21:59:42 +02:00
|
|
|
public function testInvalidVar() {
|
2018-09-22 10:43:54 +02:00
|
|
|
$this->expectException(\LogicException::class);
|
|
|
|
$this->expectExceptionMessage('Variable name must be string or Expr');
|
2018-07-20 21:59:42 +02:00
|
|
|
(new BuilderFactory())->var(new Node\Stmt\Return_());
|
|
|
|
}
|
|
|
|
|
2014-12-19 18:35:19 +01:00
|
|
|
public function testIntegration() {
|
|
|
|
$factory = new BuilderFactory;
|
|
|
|
$node = $factory->namespace('Name\Space')
|
2015-03-10 16:05:55 +01:00
|
|
|
->addStmt($factory->use('Foo\Bar\SomeOtherClass'))
|
|
|
|
->addStmt($factory->use('Foo\Bar')->as('A'))
|
2018-07-20 21:43:43 +02:00
|
|
|
->addStmt($factory->useFunction('strlen'))
|
|
|
|
->addStmt($factory->useConst('PHP_VERSION'))
|
2014-12-19 18:35:19 +01:00
|
|
|
->addStmt($factory
|
|
|
|
->class('SomeClass')
|
|
|
|
->extend('SomeOtherClass')
|
2014-12-19 18:48:21 +01:00
|
|
|
->implement('A\Few', '\Interfaces')
|
2014-12-19 18:35:19 +01:00
|
|
|
->makeAbstract()
|
|
|
|
|
2018-07-22 15:30:39 +02:00
|
|
|
->addStmt($factory->useTrait('FirstTrait'))
|
|
|
|
|
|
|
|
->addStmt($factory->useTrait('SecondTrait', 'ThirdTrait')
|
|
|
|
->and('AnotherTrait')
|
|
|
|
->with($factory->traitUseAdaptation('foo')->as('bar'))
|
|
|
|
->with($factory->traitUseAdaptation('AnotherTrait', 'baz')->as('test'))
|
|
|
|
->with($factory->traitUseAdaptation('AnotherTrait', 'func')->insteadof('SecondTrait')))
|
|
|
|
|
2015-03-02 11:33:41 +01:00
|
|
|
->addStmt($factory->method('firstMethod'))
|
|
|
|
|
2014-12-19 18:35:19 +01:00
|
|
|
->addStmt($factory->method('someMethod')
|
2015-03-02 11:33:41 +01:00
|
|
|
->makePublic()
|
2014-12-19 18:35:19 +01:00
|
|
|
->makeAbstract()
|
2018-07-22 21:41:21 +02:00
|
|
|
->addParam($factory->param('someParam')->setType('SomeClass'))
|
2014-12-19 18:35:19 +01:00
|
|
|
->setDocComment('/**
|
|
|
|
* This method does something.
|
|
|
|
*
|
|
|
|
* @param SomeClass And takes a parameter
|
|
|
|
*/'))
|
|
|
|
|
|
|
|
->addStmt($factory->method('anotherMethod')
|
|
|
|
->makeProtected()
|
|
|
|
->addParam($factory->param('someParam')->setDefault('test'))
|
|
|
|
->addStmt(new Expr\Print_(new Expr\Variable('someParam'))))
|
|
|
|
|
|
|
|
->addStmt($factory->property('someProperty')->makeProtected())
|
|
|
|
->addStmt($factory->property('anotherProperty')
|
|
|
|
->makePrivate()
|
2017-08-13 14:35:03 +02:00
|
|
|
->setDefault([1, 2, 3])))
|
2014-12-19 18:35:19 +01:00
|
|
|
->getNode()
|
|
|
|
;
|
|
|
|
|
|
|
|
$expected = <<<'EOC'
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Name\Space;
|
|
|
|
|
2015-03-10 16:05:55 +01:00
|
|
|
use Foo\Bar\SomeOtherClass;
|
|
|
|
use Foo\Bar as A;
|
2018-07-20 21:43:43 +02:00
|
|
|
use function strlen;
|
|
|
|
use const PHP_VERSION;
|
2014-12-19 18:48:21 +01:00
|
|
|
abstract class SomeClass extends SomeOtherClass implements A\Few, \Interfaces
|
2014-12-19 18:35:19 +01:00
|
|
|
{
|
2018-07-22 15:30:39 +02:00
|
|
|
use FirstTrait;
|
|
|
|
use SecondTrait, ThirdTrait, AnotherTrait {
|
|
|
|
foo as bar;
|
|
|
|
AnotherTrait::baz as test;
|
|
|
|
AnotherTrait::func insteadof SecondTrait;
|
|
|
|
}
|
2014-12-19 18:35:19 +01:00
|
|
|
protected $someProperty;
|
|
|
|
private $anotherProperty = array(1, 2, 3);
|
2015-03-02 11:33:41 +01:00
|
|
|
function firstMethod()
|
|
|
|
{
|
|
|
|
}
|
2014-12-19 18:35:19 +01:00
|
|
|
/**
|
|
|
|
* This method does something.
|
|
|
|
*
|
|
|
|
* @param SomeClass And takes a parameter
|
|
|
|
*/
|
|
|
|
public abstract function someMethod(SomeClass $someParam);
|
|
|
|
protected function anotherMethod($someParam = 'test')
|
|
|
|
{
|
|
|
|
print $someParam;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EOC;
|
|
|
|
|
2017-08-13 14:35:03 +02:00
|
|
|
$stmts = [$node];
|
2014-12-19 18:35:19 +01:00
|
|
|
$prettyPrinter = new PrettyPrinter\Standard();
|
|
|
|
$generated = $prettyPrinter->prettyPrintFile($stmts);
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
str_replace("\r\n", "\n", $expected),
|
|
|
|
str_replace("\r\n", "\n", $generated)
|
|
|
|
);
|
|
|
|
}
|
2014-12-19 17:58:47 +01:00
|
|
|
}
|