public function parse(Class_ $node, Entity\FQN $fqn, $file) { $fqcn = new Entity\FQCN($node->name, $fqn); $classData = new Node\ClassData($fqcn, $file); if ($node->extends instanceof Name) { $classData->setParent($this->useParser->getFQCN($node->extends)); } foreach ($node->implements as $interfaceName) { $classData->addInterface($this->useParser->getFQCN($interfaceName)); } $classData->startLine = $node->getAttribute("startLine"); $this->parseDocComments($classData, $node->getAttribute("comments")); foreach ($node->stmts as $child) { if ($child instanceof ClassMethod) { $classData->addMethod($this->parseMethod($child)); } elseif ($child instanceof Property) { foreach ($child->props as $prop) { $classData->addProp($this->parseProperty($prop, $child->type, $child->getAttribute('comments'))); } } elseif ($child instanceof ClassConst) { foreach ($child->consts as $const) { $classData->addConst($const->name); } } } return $classData; }
public function store_class(Node\Stmt\Class_ $class) { if ($class->extends) { $parent = end($class->extends->parts); $parent_namespace = implode('\\', array_slice($class->extends->parts, 0, -1)); } else { $parent = ''; $parent_namespace = ''; } $description = ''; if ($comments = $class->getAttribute('comments')) { $phpdoc = new DocBlock($comments[0]->getText()); $description = $phpdoc->getShortDescription(); // short circuit @ignore functions if ($phpdoc->hasTag('ignore')) { return; } } $this->store_model('classes', array('class' => $class->name, 'namespace' => !empty($class->namespacedName) ? implode('\\', array_slice($class->namespacedName->parts, 0, -1)) : '', 'file' => $this->_current_file, 'line' => $class->getLine(), 'parent' => $parent, 'parent_namespace' => $parent_namespace, 'description' => $description)); $methods = array_filter($class->stmts, function ($node) { return $node instanceof Node\Stmt\ClassMethod; }); foreach ($methods as $method) { $this->store_class_method($class, $method); } $constants = array_filter($class->stmts, function ($node) { return $node instanceof Node\Stmt\ClassConst; }); foreach ($constants as $constant) { $this->store_class_constant($class, $constant); } }
/** * Create from a Class Node * * @param ClassNode $node * @param LocatedSource $locatedSource * @param NamespaceNode|null $namespace optional - if omitted, we assume it is global namespaced class * @return ReflectionClass */ public static function createFromNode(ClassNode $node, LocatedSource $locatedSource, NamespaceNode $namespace = null) { $class = new self(); $class->locatedSource = $locatedSource; $class->name = $node->name; if (null !== $namespace) { $class->declaringNamespace = $namespace; } $methodNodes = $node->getMethods(); foreach ($methodNodes as $methodNode) { $class->methods[] = ReflectionMethod::createFromNode($methodNode, $class); } foreach ($node->stmts as $stmt) { if ($stmt instanceof ConstNode) { $constName = $stmt->consts[0]->name; $constValue = (new CompileNodeToValue())->__invoke($stmt->consts[0]->value); $class->constants[$constName] = $constValue; } if ($stmt instanceof PropertyNode) { $prop = ReflectionProperty::createFromNode($stmt, $class); $class->properties[$prop->getName()] = $prop; } } return $class; }
/** * @param Class_ $node * @param PHPNamespace $target */ public function handleClass(Class_ $node, PHPNamespace $target) { $name = $node->name; $modifiers = 0; $modifiers |= $node->isAbstract() ? PHPClass::IS_ABSTRACT : 0; $modifiers |= $node->isFinal() ? PHPClass::IS_FINAL : 0; $class = $this->codeFactory->buildClass($name, $modifiers); $target->addClass($class); $this->parse($node->stmts, $class); }
/** * Finds or creates a class method (and eventually attaches it to the class itself) * * @param Class_ $class * @param string $name * * @return ClassMethod */ protected function findOrCreateMethod(Class_ $class, $name) { $foundMethods = array_filter($class->getMethods(), function (ClassMethod $method) use($name) { return $name === $method->name; }); $method = reset($foundMethods); if (!$method) { $class->stmts[] = $method = new ClassMethod($name); } return $method; }
public function visitClass(Class_ $node) { $struct = $this->getStruct(); if ($node->extends !== null) { $struct->setParentClassName(implode('\\', $node->extends->parts)); } foreach ($node->implements as $name) { $struct->addInterface(implode('\\', $name->parts)); } $struct->setAbstract($node->isAbstract()); $struct->setFinal($node->isFinal()); }
/** * @param Node\Stmt\Class_ $node */ protected function parseClassNode(Node\Stmt\Class_ $node) { if (!isset($node->namespacedName)) { return; // Ticket #45 - This could potentially not be set for PHP 7 anonymous classes. } $this->currentStructuralElement = $node; $interfaces = []; /** @var Node\Name $implementedName */ foreach ($node->implements as $implementedName) { $interfaces[] = $implementedName->toString(); } $this->structuralElements[$node->namespacedName->toString()] = ['name' => $node->name, 'type' => 'class', 'startLine' => $node->getLine(), 'isAbstract' => $node->isAbstract(), 'docComment' => $node->getDocComment() ? $node->getDocComment()->getText() : null, 'parents' => $node->extends ? [$node->extends->toString()] : [], 'interfaces' => $interfaces, 'traits' => [], 'methods' => [], 'properties' => [], 'constants' => []]; }
/** * @param Node\Stmt\Class_ $node */ private function collectMetaOfClass(Node\Stmt\Class_ $node) { $this->getAdtMeta()->setClass(); if ($node->isAbstract()) { $this->getAdtMeta()->setAbstract(); } if ($node->isFinal()) { $this->getAdtMeta()->setFinal(); } foreach ($node->implements as $name) { if ($name = $this->filter($name)) { $this->getAdtMeta()->addImplementedNamespace($name); } } $this->collectExtends($node->extends); }
/** * @return int */ protected function getNewTraitUseLine() { $line = $this->classAbstractTree->getLine() + 1; /* // -1 because we want place it before // another -1 because phpParser counts lines from 1 $line = array_values($this->classAbstractTree->stmts)[0]->getLine() - 2;*/ /* * If class definition is like this: * * class Foo * { * // Content * } * * not like this: * * class Foo { * // Content * } * * we need to subtract one line */ if (strpos($this->content[$this->classAbstractTree->getLine() - 1], '{') !== false) { --$line; } return $line; }
/** * @return ParsedMethod[] */ public function getMethods() { if (NULL === $this->methods) { $this->methods = array_map(function (ClassMethod $method) { return new ParsedMethod($this, $method); }, $this->node->getMethods()); } return $this->methods; }
private function handleClass(Node\Stmt\Class_ $class) { $classHint = new ClassHint(); if (!$class->isAbstract()) { $classHint->setStmtType("Class"); $classHint->setName($class->name); $classHint->setFqn($this->namespace . "\\" . $class->name); $classHint->setClassType($class->type); if ($class->extends instanceof Node) { $classHint->setExtends($class->extends->toString()); } foreach ($class->stmts as $stmt) { $paramNames = []; $docComment = null; if ($stmt instanceof Node\Stmt\ClassMethod && ($stmt->isPublic() || $stmt->isProtected())) { $docComment = $stmt->getDocComment(); if ($docComment !== null) { $docComment = $docComment->getReformattedText(); } $classHint->addMethod($stmt->name, $stmt->type, $stmt->byRef, $stmt->params, $docComment); } if ($stmt instanceof Node\Stmt\Property && ($stmt->isPublic() || $stmt->isProtected())) { $docComment = $stmt->getDocComment(); if ($docComment !== null) { $docComment = $docComment->getReformattedText(); } $classHint->addProperty($stmt->props, $stmt->type, $docComment); } if ($stmt instanceof Node\Stmt\ClassConst) { $docComment = $stmt->getDocComment(); if ($docComment !== null) { $docComment = $docComment->getReformattedText(); } $classHint->addConstant($stmt->consts, $docComment); } } $this->fileStmts[] = ['stmtType' => $classHint->getStmtType(), 'name' => $classHint->getName(), 'fqn' => $classHint->getFqn(), 'type' => $classHint->getClassType(), 'extendsClass' => $classHint->getExtends(), 'methods' => $classHint->getMethods(), 'properties' => $classHint->getProperties(), 'constants' => $classHint->getConstants()]; } }
protected function reduceRule180($attributes) { Node\Stmt\Class_::verifyModifier($this->semStack[$this->stackPos - (2 - 1)], $this->semStack[$this->stackPos - (2 - 2)]); $this->semValue = $this->semStack[$this->stackPos - (2 - 1)] | $this->semStack[$this->stackPos - (2 - 2)]; }
/** * Sets a modifier in the $this->type property. * * @param int $modifier Modifier to set */ protected function setModifier($modifier) { Stmt\Class_::verifyModifier($this->type, $modifier); $this->type |= $modifier; }
/** * Gets a single class generated by the template. * * @param Class_ $statement * @param string $namespace * @param string $fileLocation * @param string $uses * @returns string $code */ protected function getClass(Class_ $statement, $namespace, $fileLocation, $uses = '') { $comments = $statement->getDocComment(); $comments = isset($comments) ? $comments->getText() : ''; if ($namespace == 'tmp') { $namespace = ''; } else { $namespace = 'namespace ' . $namespace . ';'; } $event = new GetClassEvent($statement, $fileLocation, $namespace, $uses); $this->dispatcher->dispatch(GetClassEvent::BEFORE, $event); $namespace = $event->getNamespace(); $uses = $event->getUses(); $statement = $event->getStatements(); $code = $this->prettyPrinter->pStmt_Class($statement); if (isset($this->template)) { $code = call_user_func($this->template, $namespace, $uses, $comments, $code); } $event->setCode($code); $this->dispatcher->dispatch(GetClassEvent::AFTER, $event); $code = $event->getCode(); return $code; }
public function getLine() { return $this->classBefore->getLine(); }
/** * validate if the modifier can be added to the current modifiers or not * * @param $modifier * @throws \EBT\ExtensionBuilder\Exception\FileNotFoundException * @throws \EBT\ExtensionBuilder\Exception\SyntaxErrorException */ protected function validateModifier($modifier) { if ($modifier == \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL && $this->isAbstract() || $modifier == \PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT && $this->isFinal()) { throw new \EBT\ExtensionBuilder\Exception\SyntaxErrorException('Abstract and Final can\'t be applied both to same object'); } elseif ($modifier == \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC && $this->isAbstract() || $modifier == \PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT && $this->isStatic()) { throw new \EBT\ExtensionBuilder\Exception\FileNotFoundException('Abstract and Static can\'t be applied both to same object'); } try { \PhpParser\Node\Stmt\Class_::verifyModifier($this->modifiers, $modifier); } catch (\PhpParser\Error $e) { throw new \EBT\ExtensionBuilder\Exception\SyntaxErrorException('Only one access modifier can be applied to one object. Use setModifier to avoid this exception'); } }
/** * @return int */ public function getLine() { return $this->classAfter->getLine(); }
public function testGetMethods() { $methods = array(new ClassMethod('foo'), new ClassMethod('bar')); $interface = new Class_('Foo', array('stmts' => array(new Node\Stmt\ClassConst(array(new Node\Const_('C1', new Node\Scalar\String_('C1')))), $methods[0], new Node\Stmt\ClassConst(array(new Node\Const_('C2', new Node\Scalar\String_('C2')))), $methods[1], new Node\Stmt\ClassConst(array(new Node\Const_('C3', new Node\Scalar\String_('C3'))))))); $this->assertSame($methods, $interface->getMethods()); }
/** * Find the last/nearest PHPDOC of the class. * @param Class_ $class * @return null|Doc */ private static function getLastPhpDocComment(Class_ $class) { $comments = $class->getAttribute('comments'); if (NULL === $comments) { return NULL; } $lastPhpdocComment = NULL; foreach ($comments as $comment) { if ($comment instanceof Doc) { $lastPhpdocComment = $comment; } } return $lastPhpdocComment; }
private function detectAndHandlePhp4Ctor(Node\Stmt\Class_ $cls) { if ($this->mode & self::MODE_DEPRECATION && !$cls->isAnonymous()) { $name = isset($cls->namespacedName) ? $cls->namespacedName->toString() : $cls->name; $possibleCtorInfo = null; /** @var Node\Stmt\ClassMethod $method */ foreach ($cls->getMethods() as $method) { if (strcasecmp($method->name, '__construct') === 0) { return; // This will always be treated as ctor. Drop everything else } elseif (strcasecmp($method->name, ltrim($name, '\\')) === 0) { $possibleCtorInfo = [Reason::PHP4_CONSTRUCTOR, $method->getLine(), null, ['name' => $method->name]]; } } if ($possibleCtorInfo !== null) { call_user_func_array([$this->getResult(), 'addLimit'], $possibleCtorInfo); } } }
protected function reduceRule176() { Stmt\Class_::verifyModifier($this->semStack[$this->stackPos - (2 - 1)], $this->semStack[$this->stackPos - (2 - 2)]); $this->semValue = $this->semStack[$this->stackPos - (2 - 1)] | $this->semStack[$this->stackPos - (2 - 2)]; }
protected function checkModifier($a, $b, $modifierPos) { // Jumping through some hoops here because verifyModifier() is also used elsewhere try { Class_::verifyModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } }