annotate vendor/nikic/php-parser/test/PhpParser/BuilderFactoryTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@13 1 <?php declare(strict_types=1);
Chris@0 2
Chris@0 3 namespace PhpParser;
Chris@0 4
Chris@13 5 use PhpParser\Node\Arg;
Chris@0 6 use PhpParser\Node\Expr;
Chris@13 7 use PhpParser\Node\Expr\BinaryOp\Concat;
Chris@13 8 use PhpParser\Node\Identifier;
Chris@13 9 use PhpParser\Node\Name;
Chris@13 10 use PhpParser\Node\Scalar\LNumber;
Chris@13 11 use PhpParser\Node\Scalar\String_;
Chris@0 12
Chris@17 13 class BuilderFactoryTest extends \PHPUnit\Framework\TestCase
Chris@0 14 {
Chris@0 15 /**
Chris@0 16 * @dataProvider provideTestFactory
Chris@0 17 */
Chris@0 18 public function testFactory($methodName, $className) {
Chris@0 19 $factory = new BuilderFactory;
Chris@0 20 $this->assertInstanceOf($className, $factory->$methodName('test'));
Chris@0 21 }
Chris@0 22
Chris@0 23 public function provideTestFactory() {
Chris@13 24 return [
Chris@17 25 ['namespace', Builder\Namespace_::class],
Chris@17 26 ['class', Builder\Class_::class],
Chris@17 27 ['interface', Builder\Interface_::class],
Chris@17 28 ['trait', Builder\Trait_::class],
Chris@17 29 ['method', Builder\Method::class],
Chris@17 30 ['function', Builder\Function_::class],
Chris@17 31 ['property', Builder\Property::class],
Chris@17 32 ['param', Builder\Param::class],
Chris@17 33 ['use', Builder\Use_::class],
Chris@17 34 ['useFunction', Builder\Use_::class],
Chris@17 35 ['useConst', Builder\Use_::class],
Chris@13 36 ];
Chris@13 37 }
Chris@13 38
Chris@13 39 public function testVal() {
Chris@13 40 // This method is a wrapper around BuilderHelpers::normalizeValue(),
Chris@13 41 // which is already tested elsewhere
Chris@13 42 $factory = new BuilderFactory();
Chris@13 43 $this->assertEquals(
Chris@13 44 new String_("foo"),
Chris@13 45 $factory->val("foo")
Chris@0 46 );
Chris@0 47 }
Chris@0 48
Chris@13 49 public function testConcat() {
Chris@0 50 $factory = new BuilderFactory();
Chris@13 51 $varA = new Expr\Variable('a');
Chris@13 52 $varB = new Expr\Variable('b');
Chris@13 53 $varC = new Expr\Variable('c');
Chris@13 54
Chris@13 55 $this->assertEquals(
Chris@13 56 new Concat($varA, $varB),
Chris@13 57 $factory->concat($varA, $varB)
Chris@13 58 );
Chris@13 59 $this->assertEquals(
Chris@13 60 new Concat(new Concat($varA, $varB), $varC),
Chris@13 61 $factory->concat($varA, $varB, $varC)
Chris@13 62 );
Chris@13 63 $this->assertEquals(
Chris@13 64 new Concat(new Concat(new String_("a"), $varB), new String_("c")),
Chris@13 65 $factory->concat("a", $varB, "c")
Chris@13 66 );
Chris@13 67 }
Chris@13 68
Chris@13 69 public function testConcatOneError() {
Chris@17 70 $this->expectException(\LogicException::class);
Chris@17 71 $this->expectExceptionMessage('Expected at least two expressions');
Chris@13 72 (new BuilderFactory())->concat("a");
Chris@13 73 }
Chris@13 74
Chris@13 75 public function testConcatInvalidExpr() {
Chris@17 76 $this->expectException(\LogicException::class);
Chris@17 77 $this->expectExceptionMessage('Expected string or Expr');
Chris@13 78 (new BuilderFactory())->concat("a", 42);
Chris@13 79 }
Chris@13 80
Chris@13 81 public function testArgs() {
Chris@13 82 $factory = new BuilderFactory();
Chris@13 83 $unpack = new Arg(new Expr\Variable('c'), false, true);
Chris@13 84 $this->assertEquals(
Chris@13 85 [
Chris@13 86 new Arg(new Expr\Variable('a')),
Chris@13 87 new Arg(new String_('b')),
Chris@13 88 $unpack
Chris@13 89 ],
Chris@13 90 $factory->args([new Expr\Variable('a'), 'b', $unpack])
Chris@13 91 );
Chris@13 92 }
Chris@13 93
Chris@13 94 public function testCalls() {
Chris@13 95 $factory = new BuilderFactory();
Chris@13 96
Chris@13 97 // Simple function call
Chris@13 98 $this->assertEquals(
Chris@13 99 new Expr\FuncCall(
Chris@13 100 new Name('var_dump'),
Chris@13 101 [new Arg(new String_('str'))]
Chris@13 102 ),
Chris@13 103 $factory->funcCall('var_dump', ['str'])
Chris@13 104 );
Chris@13 105 // Dynamic function call
Chris@13 106 $this->assertEquals(
Chris@13 107 new Expr\FuncCall(new Expr\Variable('fn')),
Chris@13 108 $factory->funcCall(new Expr\Variable('fn'))
Chris@13 109 );
Chris@13 110
Chris@13 111 // Simple method call
Chris@13 112 $this->assertEquals(
Chris@13 113 new Expr\MethodCall(
Chris@13 114 new Expr\Variable('obj'),
Chris@13 115 new Identifier('method'),
Chris@13 116 [new Arg(new LNumber(42))]
Chris@13 117 ),
Chris@13 118 $factory->methodCall(new Expr\Variable('obj'), 'method', [42])
Chris@13 119 );
Chris@13 120 // Explicitly pass Identifier node
Chris@13 121 $this->assertEquals(
Chris@13 122 new Expr\MethodCall(
Chris@13 123 new Expr\Variable('obj'),
Chris@13 124 new Identifier('method')
Chris@13 125 ),
Chris@13 126 $factory->methodCall(new Expr\Variable('obj'), new Identifier('method'))
Chris@13 127 );
Chris@13 128 // Dynamic method call
Chris@13 129 $this->assertEquals(
Chris@13 130 new Expr\MethodCall(
Chris@13 131 new Expr\Variable('obj'),
Chris@13 132 new Expr\Variable('method')
Chris@13 133 ),
Chris@13 134 $factory->methodCall(new Expr\Variable('obj'), new Expr\Variable('method'))
Chris@13 135 );
Chris@13 136
Chris@13 137 // Simple static method call
Chris@13 138 $this->assertEquals(
Chris@13 139 new Expr\StaticCall(
Chris@13 140 new Name\FullyQualified('Foo'),
Chris@13 141 new Identifier('bar'),
Chris@13 142 [new Arg(new Expr\Variable('baz'))]
Chris@13 143 ),
Chris@13 144 $factory->staticCall('\Foo', 'bar', [new Expr\Variable('baz')])
Chris@13 145 );
Chris@13 146 // Dynamic static method call
Chris@13 147 $this->assertEquals(
Chris@13 148 new Expr\StaticCall(
Chris@13 149 new Expr\Variable('foo'),
Chris@13 150 new Expr\Variable('bar')
Chris@13 151 ),
Chris@13 152 $factory->staticCall(new Expr\Variable('foo'), new Expr\Variable('bar'))
Chris@13 153 );
Chris@13 154
Chris@13 155 // Simple new call
Chris@13 156 $this->assertEquals(
Chris@13 157 new Expr\New_(new Name\FullyQualified('stdClass')),
Chris@13 158 $factory->new('\stdClass')
Chris@13 159 );
Chris@13 160 // Dynamic new call
Chris@13 161 $this->assertEquals(
Chris@13 162 new Expr\New_(
Chris@13 163 new Expr\Variable('foo'),
Chris@13 164 [new Arg(new String_('bar'))]
Chris@13 165 ),
Chris@13 166 $factory->new(new Expr\Variable('foo'), ['bar'])
Chris@13 167 );
Chris@13 168 }
Chris@13 169
Chris@13 170 public function testConstFetches() {
Chris@13 171 $factory = new BuilderFactory();
Chris@13 172 $this->assertEquals(
Chris@13 173 new Expr\ConstFetch(new Name('FOO')),
Chris@13 174 $factory->constFetch('FOO')
Chris@13 175 );
Chris@13 176 $this->assertEquals(
Chris@13 177 new Expr\ClassConstFetch(new Name('Foo'), new Identifier('BAR')),
Chris@13 178 $factory->classConstFetch('Foo', 'BAR')
Chris@13 179 );
Chris@13 180 $this->assertEquals(
Chris@13 181 new Expr\ClassConstFetch(new Expr\Variable('foo'), new Identifier('BAR')),
Chris@13 182 $factory->classConstFetch(new Expr\Variable('foo'), 'BAR')
Chris@13 183 );
Chris@13 184 }
Chris@13 185
Chris@17 186 public function testVar() {
Chris@17 187 $factory = new BuilderFactory();
Chris@17 188 $this->assertEquals(
Chris@17 189 new Expr\Variable("foo"),
Chris@17 190 $factory->var("foo")
Chris@17 191 );
Chris@17 192 $this->assertEquals(
Chris@17 193 new Expr\Variable(new Expr\Variable("foo")),
Chris@17 194 $factory->var($factory->var("foo"))
Chris@17 195 );
Chris@17 196 }
Chris@17 197
Chris@17 198 public function testPropertyFetch() {
Chris@17 199 $f = new BuilderFactory();
Chris@17 200 $this->assertEquals(
Chris@17 201 new Expr\PropertyFetch(new Expr\Variable('foo'), 'bar'),
Chris@17 202 $f->propertyFetch($f->var('foo'), 'bar')
Chris@17 203 );
Chris@17 204 $this->assertEquals(
Chris@17 205 new Expr\PropertyFetch(new Expr\Variable('foo'), 'bar'),
Chris@17 206 $f->propertyFetch($f->var('foo'), new Identifier('bar'))
Chris@17 207 );
Chris@17 208 $this->assertEquals(
Chris@17 209 new Expr\PropertyFetch(new Expr\Variable('foo'), new Expr\Variable('bar')),
Chris@17 210 $f->propertyFetch($f->var('foo'), $f->var('bar'))
Chris@17 211 );
Chris@17 212 }
Chris@17 213
Chris@13 214 public function testInvalidIdentifier() {
Chris@17 215 $this->expectException(\LogicException::class);
Chris@17 216 $this->expectExceptionMessage('Expected string or instance of Node\Identifier');
Chris@13 217 (new BuilderFactory())->classConstFetch('Foo', new Expr\Variable('foo'));
Chris@13 218 }
Chris@13 219
Chris@13 220 public function testInvalidIdentifierOrExpr() {
Chris@17 221 $this->expectException(\LogicException::class);
Chris@17 222 $this->expectExceptionMessage('Expected string or instance of Node\Identifier or Node\Expr');
Chris@13 223 (new BuilderFactory())->staticCall('Foo', new Name('bar'));
Chris@13 224 }
Chris@13 225
Chris@13 226 public function testInvalidNameOrExpr() {
Chris@17 227 $this->expectException(\LogicException::class);
Chris@17 228 $this->expectExceptionMessage('Name must be a string or an instance of Node\Name or Node\Expr');
Chris@13 229 (new BuilderFactory())->funcCall(new Node\Stmt\Return_());
Chris@0 230 }
Chris@0 231
Chris@17 232 public function testInvalidVar() {
Chris@17 233 $this->expectException(\LogicException::class);
Chris@17 234 $this->expectExceptionMessage('Variable name must be string or Expr');
Chris@17 235 (new BuilderFactory())->var(new Node\Stmt\Return_());
Chris@17 236 }
Chris@17 237
Chris@0 238 public function testIntegration() {
Chris@0 239 $factory = new BuilderFactory;
Chris@0 240 $node = $factory->namespace('Name\Space')
Chris@0 241 ->addStmt($factory->use('Foo\Bar\SomeOtherClass'))
Chris@0 242 ->addStmt($factory->use('Foo\Bar')->as('A'))
Chris@17 243 ->addStmt($factory->useFunction('strlen'))
Chris@17 244 ->addStmt($factory->useConst('PHP_VERSION'))
Chris@0 245 ->addStmt($factory
Chris@0 246 ->class('SomeClass')
Chris@0 247 ->extend('SomeOtherClass')
Chris@0 248 ->implement('A\Few', '\Interfaces')
Chris@0 249 ->makeAbstract()
Chris@0 250
Chris@17 251 ->addStmt($factory->useTrait('FirstTrait'))
Chris@17 252
Chris@17 253 ->addStmt($factory->useTrait('SecondTrait', 'ThirdTrait')
Chris@17 254 ->and('AnotherTrait')
Chris@17 255 ->with($factory->traitUseAdaptation('foo')->as('bar'))
Chris@17 256 ->with($factory->traitUseAdaptation('AnotherTrait', 'baz')->as('test'))
Chris@17 257 ->with($factory->traitUseAdaptation('AnotherTrait', 'func')->insteadof('SecondTrait')))
Chris@17 258
Chris@0 259 ->addStmt($factory->method('firstMethod'))
Chris@0 260
Chris@0 261 ->addStmt($factory->method('someMethod')
Chris@0 262 ->makePublic()
Chris@0 263 ->makeAbstract()
Chris@17 264 ->addParam($factory->param('someParam')->setType('SomeClass'))
Chris@0 265 ->setDocComment('/**
Chris@0 266 * This method does something.
Chris@0 267 *
Chris@0 268 * @param SomeClass And takes a parameter
Chris@0 269 */'))
Chris@0 270
Chris@0 271 ->addStmt($factory->method('anotherMethod')
Chris@0 272 ->makeProtected()
Chris@0 273 ->addParam($factory->param('someParam')->setDefault('test'))
Chris@0 274 ->addStmt(new Expr\Print_(new Expr\Variable('someParam'))))
Chris@0 275
Chris@0 276 ->addStmt($factory->property('someProperty')->makeProtected())
Chris@0 277 ->addStmt($factory->property('anotherProperty')
Chris@0 278 ->makePrivate()
Chris@13 279 ->setDefault([1, 2, 3])))
Chris@0 280 ->getNode()
Chris@0 281 ;
Chris@0 282
Chris@0 283 $expected = <<<'EOC'
Chris@0 284 <?php
Chris@0 285
Chris@0 286 namespace Name\Space;
Chris@0 287
Chris@0 288 use Foo\Bar\SomeOtherClass;
Chris@0 289 use Foo\Bar as A;
Chris@17 290 use function strlen;
Chris@17 291 use const PHP_VERSION;
Chris@0 292 abstract class SomeClass extends SomeOtherClass implements A\Few, \Interfaces
Chris@0 293 {
Chris@17 294 use FirstTrait;
Chris@17 295 use SecondTrait, ThirdTrait, AnotherTrait {
Chris@17 296 foo as bar;
Chris@17 297 AnotherTrait::baz as test;
Chris@17 298 AnotherTrait::func insteadof SecondTrait;
Chris@17 299 }
Chris@0 300 protected $someProperty;
Chris@0 301 private $anotherProperty = array(1, 2, 3);
Chris@0 302 function firstMethod()
Chris@0 303 {
Chris@0 304 }
Chris@0 305 /**
Chris@0 306 * This method does something.
Chris@0 307 *
Chris@0 308 * @param SomeClass And takes a parameter
Chris@0 309 */
Chris@0 310 public abstract function someMethod(SomeClass $someParam);
Chris@0 311 protected function anotherMethod($someParam = 'test')
Chris@0 312 {
Chris@0 313 print $someParam;
Chris@0 314 }
Chris@0 315 }
Chris@0 316 EOC;
Chris@0 317
Chris@13 318 $stmts = [$node];
Chris@0 319 $prettyPrinter = new PrettyPrinter\Standard();
Chris@0 320 $generated = $prettyPrinter->prettyPrintFile($stmts);
Chris@0 321
Chris@0 322 $this->assertEquals(
Chris@0 323 str_replace("\r\n", "\n", $expected),
Chris@0 324 str_replace("\r\n", "\n", $generated)
Chris@0 325 );
Chris@0 326 }
Chris@0 327 }