public function testEmptyDocBlock() { $doc = '/** * */'; $this->assertEquals([], $this->parser->parseString($doc)); }
/** * Called when entering a node. * * Return value semantics: * * null: $node stays as-is * * otherwise: $node is set to the return value * * @param Node $node * * @return null|Node */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { $this->namespace = '\\' . $node->name; $this->namespaceLine = $node->getLine(); } elseif ($node instanceof Use_) { $use_count = 0; foreach ($node->uses as $use) { if ($use instanceof UseUse) { if (!$this->resolver->isValid("\\{$use->name}")) { $this->result->error(ErrorType::UNABLE_TO_RESOLVE_USE, $use->getLine(), "Use '\\{$use->name}' could not be resolved"); } if (isset($this->aliases[$use->alias])) { $line = $this->aliases[$use->alias]->getNode()->getLine(); $this->result->error(ErrorType::DUPLICATE_ALIAS, $use->getLine(), "Alias '{$use->alias}' is already in use on line {$line}"); } $this->aliases[$use->alias] = new UseTracker($use->alias, (string) $use->name, $use); $this->useStatements[] = $use; } else { // I don't know if this error can ever be generated, as it should be a parse error... $this->result->error(ErrorType::MALFORMED_USE, $use->getLine(), "Malformed use statement"); return; } $use_count++; } if ($use_count > 1) { $this->result->error(ErrorType::MULTI_STATEMENT_USE, $node->getLine(), "Multiple uses in one statement is discouraged"); } } else { if ($node instanceof New_) { $this->validateMethodAccess($node->getLine(), $node->class, '__construct'); } if ($node instanceof StaticCall) { if ($node->name !== '__construct') { $this->validateMethodExists($node->getLine(), $node->class, $node->name); } $this->validateMethodAccess($node->getLine(), $node->class, $node->name); } if (isset($node->class) && $node->class instanceof Name) { $this->resolveType($node->getLine(), $node->class); } if (isset($node->traits)) { foreach ($node->traits as $trait) { $this->resolveType($node->getLine(), $trait); } } if (isset($node->implements)) { foreach ($node->implements as $implements) { $this->resolveType($node->getLine(), $implements); } } if (isset($node->extends)) { if ($node->extends instanceof Name) { $this->resolveType($node->getLine(), $node->extends); } else { foreach ($node->extends as $extends) { $this->resolveType($node->getLine(), $extends); } } } if (isset($node->type) && $node->type instanceof Name) { $this->resolveType($node->getLine(), $node->type); } if ($node instanceof ClassMethod && $node->getReturnType() instanceof Name) { $this->resolveType($node->getLine(), $node->getReturnType()); } if ($node instanceof ClassMethod or $node instanceof Function_ or $node instanceof Property or $node instanceof Class_ or $node instanceof Variable) { /** @var $docblock Doc */ if ($docblock = $node->getDocComment()) { $annotations = $this->annotationParser->parseString($docblock->getText()); foreach ($annotations as $annotation) { if ($annotation instanceof DoctrineAnnotation) { $this->resolveDoctrineComment($docblock->getLine() - 1, $annotation); } elseif ($annotation instanceof NonDoctrineAnnotation) { $this->resolveNonDoctrineComment($docblock->getLine() - 1, $annotation); } } } } if ($node instanceof Catch_) { foreach ($node->types as $type) { $this->resolveType($node->getLine(), $type); } } // eclipse can only handle inline type hints in a normal comment block if ($node instanceof Variable) { $comments = $node->getAttribute('comments'); if (is_array($comments)) { $phpVariableRegex = '[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*'; // regex for matching /* @var $variable Class */ $eclipseInlineTypeHintRegex = '~^/\\* @var \\$' . $phpVariableRegex . ' (\\\\?' . $phpVariableRegex . '(\\\\' . $phpVariableRegex . ')*) \\*/$~'; foreach ($comments as $comment) { /* @var $comment Comment */ $matches = []; $match = preg_match($eclipseInlineTypeHintRegex, $comment->getText(), $matches); if ($match === 1) { $className = $matches[1]; $this->resolveAnnotatedType($comment->getLine(), $className); } } } } } $this->nodeStack[] = $node; }