function enterNode(\PhpParser\Node $node) { if ($node instanceof \PhpParser\Node\Stmt\Namespace_) { $this->addNamespace(array('namespace' => $node->name->toString(), 'line' => $node->getLine(), 'file' => $this->file)); } if ($node instanceof \PhpParser\Node\Stmt\Use_) { foreach ($node->uses as $use) { $this->addUse(array('name' => $use->name, 'alias' => $use->alias)); } } if ($node instanceof \PhpParser\Node\Stmt\Class_) { $this->addClass(array('name' => $node->name, 'extends' => $node->extends, 'implements' => $node->implements, 'abstract' => $node->isAbstract(), 'final' => $node->isFinal(), 'comment' => $node->getDocComment(), 'doc' => $this->doc_comment_parser->parse($node->getDocComment()), 'line' => $node->getLine(), 'file' => $this->file)); } if ($node instanceof \PhpParser\Node\Stmt\Interface_) { $this->addInterface(array('name' => $node->name, 'extends' => $node->extends, 'comment' => $node->getDocComment(), 'doc' => $this->doc_comment_parser->parse($node->getDocComment()), 'line' => $node->getLine(), 'file' => $this->file)); } if ($node instanceof \PhpParser\Node\Stmt\ClassMethod) { $this->addClassMethod(array('byRef' => $node->byRef, 'name' => $node->name, 'params' => $node->params, 'returnType' => $node->returnType, 'public' => $node->isPublic(), 'protected' => $node->isProtected(), 'private' => $node->isPrivate(), 'abstract' => $node->isAbstract(), 'final' => $node->isFinal(), 'static' => $node->isStatic(), 'comment' => $node->getDocComment(), 'doc' => $this->doc_comment_parser->parse($node->getDocComment()), 'line' => $node->getLine(), 'file' => $this->file)); } if ($node instanceof \PhpParser\Node\Stmt\Property) { $this->last_property = $node; } if ($node instanceof \PhpParser\Node\Stmt\PropertyProperty) { $this->addClassProperty(array('name' => $node->name, 'default' => $node->default, 'public' => $this->last_property->isPublic(), 'protected' => $this->last_property->isProtected(), 'private' => $this->last_property->isPrivate(), 'static' => $this->last_property->isStatic(), 'comment' => $node->getDocComment(), 'doc' => $this->doc_comment_parser->parse($node->getDocComment()), 'line' => $node->getLine(), 'file' => $this->file)); } // $this->logger->info(get_class($node)); }
/** * @throws RuntimeException if the node is a non-abstract class with abstract methods. * * @param Node $node */ public function leaveNode(Node $node) { if ($node instanceof ClassStmt) { $count = count($this->abstractMethods); if ($count > 0 && !$node->isAbstract()) { throw new FatalErrorException(sprintf('Class %s contains %d abstract method%s must therefore be declared abstract or implement the remaining methods (%s)', $node->name, $count, $count === 0 ? '' : 's', implode(', ', $this->abstractMethods))); } } }
/** * Initialize a new User Class * * @param Node $node * * @return void */ private function initUserClass(Node $node) { if (isset($node->namespacedName) && $node->namespacedName instanceof Node\Name && $node->namespacedName->isQualified()) { $min = '5.3.0'; } else { if ($node->isAbstract() || $node->isFinal()) { $min = '5.0.0'; } else { $min = '4.0.0'; } } $max = ''; $element = 'classes'; $name = (string) $node->namespacedName; $this->contextStack[] = array($element, $name); // parent class if (isset($node->extends)) { $name = (string) $node->extends; $group = $this->findObjectType($name); $versions = $this->metrics[$group][$name]; if ('user' == $versions['ext.name']) { if ($node->extends->isFullyQualified()) { if (count($node->extends->parts) === 1) { // PHP4 syntax (global namespace) $versions = array('php.min' => '4.0.0'); } else { $versions = array('php.min' => '5.3.0'); } } else { $versions = array(); } } $this->updateElementVersion('classes', $name, $versions); ++$this->metrics['classes'][$name]['matches']; if ('objects' == $group) { // now object is categorized, remove from temp queue unset($this->metrics[$group][$name]); } $this->updateLocalVersions($versions); } // interfaces foreach ($node->implements as $interface) { $name = (string) $interface; $group = $this->findObjectType($name); $versions = $this->metrics[$group][$name]; $this->updateElementVersion('interfaces', $name, $versions); ++$this->metrics['interfaces'][$name]['matches']; if ('objects' == $group) { // now object is categorized, remove from temp queue unset($this->metrics[$group][$name]); } $this->updateLocalVersions($versions); } $name = (string) $node->namespacedName; $group = $this->findObjectType($name); $versions = $this->metrics[$group][$name]; if ('objects' == $group) { // now object is categorized, remove from temp queue unset($this->metrics[$group][$name]); } $versions = array_merge($versions, array('php.min' => $min, 'php.max' => $max, 'declared' => true)); $this->updateLocalVersions($versions); }
public function enterNode(Node $node) { if ($node instanceof Node\Stmt\Namespace_) { /** * Namespace declaration. * * namespace <name>; */ $this->current_namespace_name = implode("\\", $node->name->parts); } elseif ($node instanceof Node\Stmt\Use_) { /** * Namespace reference. * * use <name> [ as <alias> ]; */ foreach ($node->uses as $use_node) { $this->alias_namespace[$use_node->alias] = implode("\\", $use_node->name->parts); } } elseif ($node instanceof Node\Stmt\ClassLike) { /** * Class-like declaration. * This is a hierarchical dependency. * * class <name> [ extends <name> ] [ implements <name> ] { ... } */ $this->current_class_name = $this->get_namespace_prefixed($node->name); // Node: Class $node_key = $this->get_namespace_prefixed($node->name); $node_def = ['namespace' => $this->current_namespace_name, 'name' => $node->name, 'canonical_name' => $node_key, 'file' => $this->current_file_path, 'stereotype' => '']; if ($node instanceof Node\Stmt\Class_) { // Class $node_def['type'] = 'class'; if ($node->isAbstract()) { $node_def['stereotype'] = 'abstract'; } $implements = $node->implements; $extends = $node->extends; } elseif ($node instanceof Node\Stmt\Interface_) { // Interface $node_def['type'] = 'interface'; $node_def['stereotype'] = 'interface'; $implements = $node->extends; $extends = null; } elseif ($node instanceof Node\Stmt\Trait_) { // Trait $node_def['type'] = 'trait'; $node_def['stereotype'] = 'trait'; $implements = []; $extends = null; } else { // Unsupported class type error_log('Skipping unsupported class node type: ' . get_class($node)); return; } $this->nodes[$node_key] = $node_def; // Edges: Implements (interfaces) foreach ($implements as $name_node) { $this->add_edge($node_key, $this->get_full_name($name_node), EdgeType::REALIZATION); } // Edges: Extends (superclass) if ($extends) { $this->add_edge($node_key, $this->get_full_name($extends), EdgeType::GENERALIZATION); } } elseif ($node instanceof Node\Expr\New_) { /** * Class instantiation. * This is a dependency. * * [ <name> = ] new <name> [ (...) ]; */ $this->add_dependency_edge($node); } elseif ($node instanceof Node\Expr\StaticCall) { /** * Static method call. * This is a dependency. * * <class>::<method_name>(...) */ $this->add_dependency_edge($node); } elseif ($node instanceof Node\Expr\StaticPropertyFetch) { /** * Static property reference. * This is a dependency. * * <class>::$<property_name> */ $this->add_dependency_edge($node); } elseif ($node instanceof Node\Expr\ClassConstFetch) { /** * Class constant property fetch (also used for <class_name>::class fetches). * This is a dependency. * * <class>::<const_name> */ $this->add_dependency_edge($node); } }
protected function compareModifier(Node $a, Node $b) { // Within same visibility, goes first $cmp = strcmp($b->isStatic(), $a->isStatic()); if ($cmp !== 0) { return $cmp; } // Within same visibility and ess, abstract goes first if ($a instanceof ClassMethod) { $cmp = strcmp($b->isAbstract(), $a->isAbstract()); } return $cmp; }