/** * @param string $property * Property name. * @return ClassMemberListNode */ public static function create($property) { /** @var ClassNode $class_node */ $class_node = Parser::parseSnippet("class Property {private \${$property};}"); $property = $class_node->getStatements()[0]->remove(); return $property; }
public function testSetVisibilityTokenText() { /** @var ClassNode $class_node */ $class_node = Parser::parseSnippet('class Foo { public function wrassle() {} }'); /** @var ClassMethodNode $method */ $method = $class_node->getStatements()[0]; $method->setVisibility('private'); $this->assertSame('private', $method->getVisibility()->getText()); $method->setVisibility('protected'); $this->assertSame('protected', $method->getVisibility()->getText()); $method->setVisibility('public'); $this->assertSame('public', $method->getVisibility()->getText()); $method->setVisibility(T_PRIVATE); $this->assertSame('private', $method->getVisibility()->getText()); $method->setVisibility(T_PROTECTED); $this->assertSame('protected', $method->getVisibility()->getText()); $method->setVisibility(T_PUBLIC); $this->assertSame('public', $method->getVisibility()->getText()); $method->setVisibility(Token::_private()); $this->assertSame('private', $method->getVisibility()->getText()); $method->setVisibility(Token::_protected()); $this->assertSame('protected', $method->getVisibility()->getText()); $method->setVisibility(Token::_public()); $this->assertSame('public', $method->getVisibility()->getText()); }
public function execute() { $ns = $this->extractNS($this->configuration['class']); $class = $this->extractLocal($this->configuration['class']); $doc = RootNode::create($ns); $ns = $doc->getNamespace($ns); Token::newline()->insertBefore($ns); Token::newline()->appendTo($ns); $class = ClassNode::create($class); if ($parent = $this->configuration['parent']) { Parser::parseSnippet('use ' . ltrim($parent, '\\') . ';')->appendTo($ns)->after(Token::newline()); $class->setExtends($this->extractLocal($parent)); } $interfaces = (array) $this->configuration['interfaces']; foreach ($interfaces as $interface) { Parser::parseSnippet('use ' . ltrim($interface, '\\') . ';')->appendTo($ns)->after(Token::newline()); } $class->setImplements(array_map([$this, 'extractLocal'], $interfaces)); if (isset($this->configuration['doc'])) { $class->setDocComment(DocCommentNode::create($this->configuration['doc'])); } $class->appendTo($ns)->before(Token::newline()); $destination = $this->getUnaliasedPath($this->configuration['destination']); $dir = subStr($destination, 0, strrPos($destination, '/')); $this->fs->mkdir($dir); file_put_contents($destination, $doc->getText()); // Need to store the class' local name as its index identifier because // \Pharborist\Filter::isClass() doesn't support lookup by qualified path. $this->target->getIndexer('class')->addFile($destination); }
public function testUseDeclarations() { $snippet = <<<'EOF' namespace Test { use const Other\MY_CONST; use function Other\my_func; use Other\MyClass; use Other\OtherClass as Bind; class TestClass {} } EOF; /** @var NamespaceNode $namespace */ $namespace = Parser::parseSnippet($snippet); $declarations = $namespace->getUseDeclarations(); $this->assertCount(4, $declarations); $aliases = $namespace->getClassAliases(); $this->assertCount(2, $aliases); $this->assertArrayHasKey('MyClass', $aliases); $this->assertEquals('\\Other\\MyClass', $aliases['MyClass']); $this->assertArrayHasKey('Bind', $aliases); $this->assertEquals('\\Other\\OtherClass', $aliases['Bind']); $class_node = $namespace->find(Filter::isClass('TestClass'))[0]; $this->assertTrue($namespace->owns($class_node)); $class_node = ClassNode::create('Dummy'); $this->assertFalse($namespace->owns($class_node)); }
/** * Create namespace declaration. * * @param NameNode|string $name * Namespace path. * * @return NamespaceNode */ public static function create($name) { $name = (string) $name; $name = ltrim($name, '\\'); $namespace_node = Parser::parseSnippet("namespace {$name};"); return $namespace_node; }
/** * @param string $method_name * @return InterfaceMethodNode */ public static function create($method_name) { /** @var InterfaceNode $interface_node */ $interface_node = Parser::parseSnippet("interface Method {public function {$method_name}();}"); $method_node = $interface_node->getStatements()[0]->remove(); return $method_node; }
public function testVisibility() { /** @var ClassNode $class_node */ $class_node = Parser::parseSnippet('class Foo { public $bar; }'); /** @var ClassMemberNode $a */ $a = $class_node->getProperties()[0]; $this->assertEquals('private $bar;', $a->setVisibility('private')->parent()->parent()->getText()); }
/** * Creates a new class member. * * @param string $name * The name of the member, with or without the leading $. * @param \Pharborist\ExpressionNode $value * The default value of the member, if any. * @param string $visibility * The member's visibility. Can be public, private, or protected. Defaults to * public. * * @return ClassMemberListNode * * @todo Not all expressions can be default values, but I forget what sorts of * expressions are valid for this. Will need better sanity checking here. */ public static function create($name, ExpressionNode $value = NULL, $visibility = 'public') { $code = $visibility . ' $' . ltrim($name, '$'); if ($value instanceof ExpressionNode) { $code .= ' = ' . $value->getText(); } /** @var ClassNode $class_node */ $class_node = Parser::parseSnippet('class Foo { ' . $code . '; }'); return $class_node->getStatements()[0]->remove(); }
/** * Create method from function declaration. * * @param FunctionDeclarationNode $function_node * @return ClassMethodNode */ public static function fromFunction(FunctionDeclarationNode $function_node) { $method_name = $function_node->getName()->getText(); $parameters = $function_node->getParameterList()->getText(); $body = $function_node->getBody()->getText(); /** @var ClassNode $class_node */ $class_node = Parser::parseSnippet("class Method {public function {$method_name}({$parameters}) {$body}}"); FormatterFactory::format($class_node); $method_node = $class_node->getStatements()[0]->remove(); return $method_node; }
/** * {@inheritdoc} */ public function rewrite(FunctionCallNode $call, TargetInterface $target) { $arguments = $call->getArguments(); if ($arguments[1] instanceof StringNode) { // Create a call to url() and let the parent class rewrite it like normal, // so we don't have to duplicate that code. $url = Parser::parseSnippet('url(' . $arguments[1] . ');')->firstChild(); $url_rewritten = parent::rewrite($url, $target); if ($url_rewritten) { return ClassMethodCallNode::create('\\Drupal', 'l')->appendArgument($arguments[0])->appendArgument($url_rewritten); } } }
public function testImportFunction() { /** @var UseDeclarationBlockNode $use_block */ $use_block = Parser::parseSnippet('use function MyNamespace\\test_func;'); $use_declaration_statement = $use_block->getDeclarationStatements()[0]; $this->assertCount(1, $use_declaration_statement->getDeclarations()); $this->assertEquals($use_declaration_statement->getDeclarations(), $use_declaration_statement->getDeclarationList()->getItems()); $this->assertTrue($use_declaration_statement->importsFunction()); $this->assertFalse($use_declaration_statement->importsConst()); $this->assertFalse($use_declaration_statement->importsClass()); $this->assertTrue($use_declaration_statement->importsFunction('MyNamespace\\test_func')); $this->assertFalse($use_declaration_statement->importsFunction('MyNamespace\\not_found')); }
/** * Create a function declaration. * * @param NameNode|string $function_name * The function name. * @param array $parameters * (Optional) List of parameters. * * @return FunctionDeclarationNode */ public static function create($function_name, $parameters = NULL) { /** @var FunctionDeclarationNode $function */ $function = Parser::parseSnippet("function {$function_name}() {}"); if (is_array($parameters)) { foreach ($parameters as $parameter) { if (is_string($parameter)) { $parameter = ParameterNode::create($parameter); } $function->appendParameter($parameter); } } return $function; }
public function testCloneInto() { /** @var ClassNode $source */ $source = Parser::parseSnippet('class Foo { protected $bar; }'); /** @var ClassNode $target */ $target = Parser::parseSnippet('class Bar {}'); /** @var ClassMemberListNode $original_list */ $original_list = $source->getStatements()[0]; $cloned_list = $original_list->cloneInto($target); $this->assertInstanceOf('\\Pharborist\\Objects\\ClassMemberListNode', $cloned_list); $this->assertNotSame($original_list, $cloned_list); $this->assertTrue($source->hasProperty('bar')); $this->assertTrue($target->hasProperty('bar')); }
public function testRewriteWithCacheReset() { $original = <<<'END' user_load(30, TRUE); END; $expected = <<<'END' // @FIXME // To reset the user cache, use EntityStorageInterface::resetCache(). \Drupal::entityManager()->getStorage('user')->load(30); END; $snippet = Parser::parseSnippet($original); $function_call = $snippet->children(Filter::isFunctionCall('user_load'))->get(0); $rewritten = $this->plugin->rewrite($function_call, $this->target); $function_call->replaceWith($rewritten); $this->assertEquals($expected, $snippet->getText()); }
public function testReturnType() { /** @var \Pharborist\Functions\FunctionDeclarationNode $func */ $func = Parser::parseSnippet('function hello() {}'); $this->assertFalse($func->hasReturnTypes()); $this->assertEquals(['void'], $func->getReturnTypes()); $func = Parser::parseSnippet('/** @return */ function hello() {}'); $this->assertFalse($func->hasReturnTypes()); $this->assertEquals(['void'], $func->getReturnTypes()); $func = Parser::parseSnippet('/** @return void */ function hello() {}'); $this->assertTrue($func->hasReturnTypes()); $this->assertEquals(['void'], $func->getReturnTypes()); $func = Parser::parseSnippet('/** @return string */ function hello() {}'); $this->assertTrue($func->hasReturnTypes()); $this->assertEquals(['string'], $func->getReturnTypes()); $func = Parser::parseSnippet('/** @return string|int */ function hello() {}'); $this->assertTrue($func->hasReturnTypes()); $this->assertEquals(['string', 'int'], $func->getReturnTypes()); }
public function test() { $callback = Parser::parseSnippet('function foo_submit(&$form, &$form_state) {}'); $function_indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface'); $function_indexer->method('get')->with('foo_submit')->willReturn(new NodeCollection([$callback])); $class = ClassNode::create('FooForm'); $class_indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface'); $class_indexer->method('get')->with('FooForm')->willReturn(new NodeCollection([$class])); $this->container->get('plugin.manager.drupalmoduleupgrader.indexer')->method('createInstance')->willReturnCallback(function ($which) use($class_indexer, $function_indexer) { switch ($which) { case 'class': return $class_indexer; case 'function': return $function_indexer; default: break; } }); $config = ['callback' => 'foo_submit', 'destination' => 'FooForm::submitForm']; $plugin = new FormCallbackToMethod($config, uniqID(), []); $plugin->setTarget($this->target); try { // We expect a CodeManagerIOException because we're implementing the // method on a class that is not officially part of the target's code. // That's OK, though. $plugin->execute(); } catch (IOException $e) { } $this->assertTrue($class->hasMethod('submitForm')); $parameters = $class->getMethod('submitForm')->getParameters(); $this->assertCount(2, $parameters); $this->assertEquals('form', $parameters[0]->getName()); $this->assertInstanceOf('\\Pharborist\\TokenNode', $parameters[0]->getTypeHint()); $this->assertSame(T_ARRAY, $parameters[0]->getTypeHint()->getType()); $this->assertInstanceOf('\\Pharborist\\TokenNode', $parameters[0]->getReference()); $this->assertEquals('form_state', $parameters[1]->getName()); $this->assertInstanceOf('\\Pharborist\\Namespaces\\NameNode', $parameters[1]->getTypeHint()); $this->assertEquals('Drupal\\Core\\Form\\FormStateInterface', $parameters[1]->getTypeHint()->getText()); $this->assertNull($parameters[1]->getReference()); }
/** * {@inheritdoc} */ public function execute() { /** @var \Pharborist\Objects\ClassNode $class */ $class = $this->target->getIndexer('class')->get($this->configuration['source']); $ns = substr($this->configuration['destination'], 0, strrpos($this->configuration['destination'], '\\')); $doc = RootNode::create($ns); $ns = $doc->getNamespace($ns); WhitespaceNode::create("\n")->appendTo($ns); $import = []; if ($parent = $class->getExtends()) { $import[] = $parent->getAbsolutePath(); } $interfaces = $class->getImplementList(); if ($interfaces) { foreach ($interfaces->getItems() as $interface) { $import[] = $interface->getAbsolutePath(); } } foreach ($class->getMethods() as $method) { foreach ($method->getParameters() as $parameter) { $type_hint = $parameter->getTypeHint(); if ($type_hint instanceof NameNode) { $import[] = $type_hint->getAbsolutePath(); } } } foreach (array_unique($import) as $i) { Parser::parseSnippet('use ' . ltrim($i, '\\') . ';')->appendTo($ns); WhitespaceNode::create("\n")->appendTo($ns); } WhitespaceNode::create("\n")->appendTo($ns); $class->remove()->appendTo($ns); $search_for = ['Drupal\\' . $this->target->id(), '\\']; $replace_with = ['src', '/']; $path = str_replace($search_for, $replace_with, $this->configuration['destination']) . '.php'; file_put_contents($this->target->getPath($path), $doc->getText()); }
/** * This test is failing at the moment because for whatever reason, * $snippet->children() is only fetching the first call to node_load(). */ public function _testRewriteWithCacheReset() { $original = <<<'END' node_load(30); node_load(30, TRUE); node_load(30, 32); node_load(30, 32, TRUE); END; $expected = <<<'END' \Drupal::entityManager()->getStorage('user')->load(30); // FIXME: To reset the node cache, use EntityStorageInterface::resetCache(). \Drupal::entityManager()->getStorage('user')->load(30); \Drupal::entityManager()->getStorage('user')->loadRevision(32); // FIXME: To reset the node cache, use EntityStorageInterface::resetCache(). \Drupal::entityManager()->getStorage('user')->loadRevision(32); END; $snippet = Parser::parseSnippet($original); $function_calls = $snippet->children(Filter::isFunctionCall('node_load')); foreach ($function_calls as $function_call) { $rewritten = $this->plugin->rewrite($function_call, $this->target); $function_call->replaceWith($rewritten); } $this->assertEquals($expected, $snippet->getText()); }
public function testGetStatement() { $function = <<<END function foobaz() { return foo(); } END; $function = Parser::parseSnippet($function); $foo = $function->find(Filter::isFunctionCall('foo'))->get(0)->getStatement(); $this->assertInstanceOf('\\Pharborist\\StatementNode', $foo); $this->assertEquals('return foo();', $foo->getText()); $this->assertSame($function, $function->getStatement()); }
/** * Creates a new return statement. * * @param \Pharborist\ExpressionNode $expr * The expression to return. * * @return static */ public static function create(ExpressionNode $expr) { return Parser::parseSnippet('return ' . $expr->getText() . ';'); }
public function testPath() { $snippet = <<<'EOF' namespace Top\Sub { new \IsGlobal(); new NonGlobal(); } EOF; /** @var NamespaceNode $namespace */ $namespace = Parser::parseSnippet($snippet); $this->assertEquals('\\', $namespace->getName()->getParentPath()); /** @var StatementNode[] $statements */ $statements = $namespace->getBody()->getStatements(); /** @var ExpressionStatementNode $statement */ $statement = $statements[0]; /** @var NewNode $new */ $new = $statement->getExpression(); $name = $new->getClassName(); $this->assertTrue($name->isGlobal()); $this->assertEquals('\\', $name->getParentPath()); $this->assertEquals('IsGlobal', $name->getBaseName()); $statement = $statements[1]; $new = $statement->getExpression(); $name = $new->getClassName(); $this->assertFalse($name->isGlobal()); $this->assertEquals('\\Top\\Sub\\', $name->getParentPath()); $this->assertEquals('NonGlobal', $name->getBaseName()); }
public function __construct() { $this->op = Parser::parseSnippet('$doAliensExist = TRUE;')->firstChild(); }
/** * @param string $class_name * @return ClassNode */ public static function create($class_name) { $class_node = Parser::parseSnippet("class {$class_name} {}")->remove(); return $class_node; }
public function testRewriteIsset() { $code = <<<'END' function foo($baz) { if (isset($baz->title)) { } } END; /** @var \Pharborist\Functions\FunctionDeclarationNode $func */ $func = Parser::parseSnippet($code); $this->plugin->rewrite($func->getParameterAtIndex(0)); $expected = <<<'END' function foo($baz) { if (!$baz->getTitle()) { } } END; $this->assertEquals($expected, $func->getText()); }
/** * Sets the test's $modules property. * * @param \Pharborist\Objects\ClassNode $test */ private function setModules(ClassNode $test) { $modules = $this->extractModules($test); if ($modules) { // @todo Use ClassNode::createProperty() when #124 lands in Pharborist $property = Parser::parseSnippet('class Foo { public static $modules = ["' . implode('", "', $modules) . '"]; }')->getBody()->firstChild()->remove(); $test->appendProperty($property); } }
/** * @expectedException \InvalidArgumentException */ public function testHasParamterInvalidArgumentException() { Parser::parseSnippet('function foo($bar) {}')->hasParameter(1); }
public function testObjectInstantiationIsLogic() { $this->assertTrue(Parser::parseSnippet('function foo() { return new Entity(); }')->is($this->filter)); }
/** * @expectedException \InvalidArgumentException */ public function testSetAliasInvalidArgument() { /** @var \Pharborist\Namespaces\UseDeclarationBlockNode $declaration_block */ $declaration_block = Parser::parseSnippet('use Cleese as Chapman;'); $declaration = $declaration_block->getDeclarationStatements()[0]->getDeclarations()[0]; $declaration->setAlias(3.141); }
/** * A helper function to ease exception catching in the __toString() method. * * @return string */ protected function toString() { $doc = RootNode::create($this->getNamespace()); $class = ClassNode::create($this->getName()); $constructor = ClassMethodNode::create('__construct'); $class->appendMethod($constructor); $constructorDocString = ''; foreach ($this->getProperties() as $name => $info) { $class->createProperty($name, isset($info['default']) ? $info['default'] : NULL, 'protected'); if (isset($info['description'])) { $propertyDocString = "@var {$info['type']} {$name}\n {$info['description']}"; $constructorDocString .= "@param {$info['type']} {$name}\n {$info['description']}\n\n"; } else { $propertyDocString = "@var {$info['type']} {$name}"; $constructorDocString .= "@param {$info['type']} {$name}\n\n"; } $class->getProperty($name)->closest(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassMemberListNode'))->setDocComment(DocCommentNode::create($propertyDocString)); $constructor->appendParameter(ParameterNode::create($name)); $expression = Parser::parseSnippet("\$this->{$name} = \${$name};"); $constructor->getBody()->lastChild()->before($expression); $getter = ClassMethodNode::create('get' . ucfirst($name)); $class->appendMethod($getter); $class->getMethod('get' . ucfirst($name))->setDocComment(DocCommentNode::create("Gets the {$name} value.")); $getter_expression = Parser::parseSnippet("return \$this->{$name};"); $getter->getBody()->lastChild()->before($getter_expression); } $class->getMethod('__construct')->setDocComment(DocCommentNode::create($constructorDocString)); $doc->getNamespace($this->getNamespace())->getBody()->append($class); /* @todo dispatch an event to allow subscribers to alter $doc */ $formatter = FormatterFactory::getPsr2Formatter(); $formatter->format($doc->getNamespace($this->getNamespace())); return $doc->getText(); }
public function testFunctionToMethod() { $class = <<<END class DefaultController extends ControllerBase {} END; $function = <<<'END' function diff_diffs_overview($node) { drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH); if ($cond) { test(); } return drupal_get_form('diff_node_revisions', $node); } END; $expected = <<<'END' class DefaultController extends ControllerBase { public function diff_diffs_overview($node) { drupal_set_title(t('Revisions for %title', ['%title' => $node->title]), PASS_THROUGH); if ($cond) { test(); } return drupal_get_form('diff_node_revisions', $node); } } END; /** @var ClassNode $class */ $class = Parser::parseSnippet($class); $function = Parser::parseSnippet($function); $class->appendMethod(ClassMethodNode::fromFunction($function)); $this->assertEquals($expected, $class->getText()); }