public function visit(NodeTraversal $t, \PHPParser_Node $n, \PHPParser_Node $parent = null) { if ($n instanceof \PHPParser_Node_Stmt_Property) { $containerNode = NodeUtil::getContainer($n)->get(); $class = $this->typeRegistry->getClassByNode($containerNode); if ($class->isInterface()) { $this->phpFile->addComment($n->getLine(), Comment::error('basic_semantics.property_on_interface', 'In PHP, declaring a method on an interface is not yet allowed.')); } } if (NodeUtil::isMethodContainer($n)) { $class = $this->typeRegistry->getClassByNode($n); if ($class instanceof Clazz && !$class->isAbstract()) { $abstractMethods = array(); foreach ($class->getMethods() as $method) { assert($method instanceof ClassMethod); /** @var $method ClassMethod */ if ($method->isAbstract()) { $abstractMethods[] = $method->getMethod()->getName(); } } if (!empty($abstractMethods)) { switch (count($abstractMethods)) { case 1: $this->phpFile->addComment($n->getLine(), Comment::error('basic_semantics.abstract_method_on_non_abstract_class', 'There is one abstract method ``%method%`` in this class; you could implement it, or declare this class as abstract.', array('method' => reset($abstractMethods)))); break; default: $this->phpFile->addComment($n->getLine(), Comment::error('basic_semantics.abstract_methods_on_non_abstract_class', 'There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: %methods%', array('methods' => implode(', ', $abstractMethods)))); } } } } }