예제 #1
0
 /**
  * @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));
    }
예제 #5
0
 /**
  * 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;
 }
예제 #6
0
 /**
  * @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());
 }
예제 #8
0
 /**
  * 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();
 }
예제 #9
0
 /**
  * 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;
 }
예제 #10
0
 /**
  * {@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'));
 }
예제 #12
0
 /**
  * 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());
 }
예제 #17
0
 /**
  * {@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());
    }
예제 #19
0
    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());
    }
예제 #20
0
 /**
  * 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();
 }
예제 #23
0
 /**
  * @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());
    }
예제 #25
0
 /**
  * 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);
 }
예제 #29
0
 /**
  * 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());
    }