/** * Called when entering a node. * * Return value semantics: * * null: $node stays as-is * * otherwise: $node is set to the return value * * @param Node $node Node * * @return null|Node Node */ public function enterNode(Node $node) { if (isset($node->returnType)) { var_dump($node->returnType); die; } elseif ($node instanceof Node\Param) { if ($node->hasAttribute("generic_name")) { $type = $node->getAttribute("generic_name"); if (isset($this->genericTypes[$type])) { $node->type = new Node\Name\FullyQualified($this->genericTypes[$type]); } else { throw new \LogicException("Bad generic found"); } } elseif ($node->type instanceof Node\Name && $node->type->hasAttribute("generics") && $node->type->getAttribute("generics")) { $type = $node->getAttribute("original_type")->parts; foreach ($node->type->getAttribute("generics") as $generic) { if (isset($this->genericTypes[$generic])) { $value = str_replace("\\", Engine::NS_TOKEN, $this->genericTypes[$generic]); $type[] = Engine::CLASS_TOKEN . $value . Engine::CLASS_TOKEN; } else { throw new \LogicException("Bad generic found"); } } $node->type = new Node\Name\FullyQualified($type); } elseif ((string) $node->name == "item") { var_dump($node); die; } } }
public function enterNode(AstNode $node) { // Determine information about the closure's location if (!$this->closureNode) { if ($node instanceof NamespaceNode) { $namespace = $node->name && is_array($node->name->parts) ? implode('\\', $node->name->parts) : null; $this->location['namespace'] = $namespace; } if ($node instanceof TraitNode) { $this->location['trait'] = $node->name; $this->location['class'] = null; } elseif ($node instanceof ClassNode) { $this->location['class'] = $node->name; $this->location['trait'] = null; } } // Locate the node of the closure if ($node instanceof ClosureNode) { if ($node->getAttribute('startLine') == $this->location['line']) { if ($this->closureNode) { $line = $this->location['file'] . ':' . $node->getAttribute('startLine'); throw new ClosureAnalysisException("Two closures were " . "declared on the same line ({$line}) of code. Cannot " . "determine which closure was the intended target."); } else { $this->closureNode = $node; } } } }
/** * Checks if a function, class or method is too long according to its lines of code * * @param Node $node * @param int $threshold * @return bool */ protected function isTooLong(Node $node, $threshold) { $startLine = $node->getAttribute('startLine'); $endLine = $node->getAttribute('endLine'); $loc = $endLine - $startLine; return $loc > $threshold; }
public function leaveNode(\PhpParser\Node $node) { if (($parentFile = $this->getCurrentFile()) !== null) { if ($node instanceof \PhpParser\Node\Expr\Include_) { $currentFile = self::getIncludeFile($node->expr, ['__DIR__' => dirname($parentFile), '__FILE__' => $parentFile]); if ($node->type == \PhpParser\Node\Expr\Include_::TYPE_INCLUDE_ONCE || $node->type == \PhpParser\Node\Expr\Include_::TYPE_REQUIRE_ONCE) { if ($this->getPhpFileCombine()->isParsed($currentFile)) { return \PhpParser\NodeTraverser::REMOVE_NODE; } } if ($this->getPhpFileCombine()->parseFile($currentFile, $parentFile) === false) { return \PhpParser\NodeTraverser::REMOVE_NODE; } $stmts = $this->getPhpFileCombine()->traverseIncludeNodes()->getStmts(); if (isset($stmts[0])) { if ($stmts[0] instanceof \PhpParser\Node\Stmt\Namespace_ === false) { $stmts[0]->setAttribute('comments', array_merge($node->getAttribute('comments', []), $stmts[0]->getAttribute('comments', []))); } else { $stmts[0]->stmts[0]->setAttribute('comments', array_merge($node->getAttribute('comments', []), $stmts[0]->stmts[0]->getAttribute('comments', []))); } } return $stmts; } } }
public function __construct($message, AbstractRule $rule, Node $node, $file) { $this->message = $message; $this->rule = $rule; $this->file = $file; $this->startLine = $node->getAttribute('startLine'); $this->endLine = $node->getAttribute('endLine'); }
/** * Get the line number of the error. * * @return string */ public function getLineNumber() { $sl = $this->node->getAttribute('startLine'); $el = $this->node->getAttribute('endLine'); if ($sl != $el) { return "{$sl}-{$el}"; } else { return (string) $sl; } }
public function enterNode(Node $node) { if ($node instanceof Node\Expr\Yield_) { $startTokenPosition = $node->getAttribute('startTokenPos'); $endTokenPosition = $node->getAttribute('endTokenPos'); if (!($this->tokenCollection->isTokenPrecededBy($startTokenPosition, '(') && $this->tokenCollection->isTokenFollowedBy($endTokenPosition, ')')) && !$this->expressionStack->isEmpty()) { $this->addContextMessage('"yield" usage in expression context', $this->expressionStack->top()); } } elseif ($node instanceof Node\Expr) { $this->expressionStack->push($node); } }
public function enterNode(Node $node) { if (empty($this->node) && $this->line == $node->getAttribute('endLine')) { $this->node = $node; } parent::enterNode($node); }
public function leaveNode(Node $node) { if (!$node instanceof ConstFetch) { $callback = [$this, 'rewrite' . ucfirst($node->getType())]; if (is_callable($callback)) { call_user_func_array($callback, [$node]); } return; } if ($this->disable_const_rewrite_level > 0) { return; } if (!$node->name instanceof Name) { return; } if (!$node->name->isUnqualified()) { return; } if (!ConstantPatcher::isBlacklisted((string) $node->name)) { $replacement = new FullyQualified(array()); $replacement->set('\\__ConstProxy__::get(\'' . (string) $node->name . '\')'); $pos = $node->getAttribute('startTokenPos'); ConstantPatcher::$replacement[$pos] = '\\__ConstProxy__::get(\'' . (string) $node->name . '\')'; $node->name = $replacement; } }
public function enterNode(PhpParser\Node $node) { if ($node instanceof Stmt\Function_) { // create new context, keep parent $this->stack->start(new FunctionContext($node->name, $node->getLine(), $node->getAttribute('endLine'))); } }
/** * @inheritDoc */ public function resolveVariableType(Node $node) { // $this->call() if ($node instanceof Node\Expr\MethodCall && property_exists($node->var, 'name') && null === $node->getAttribute('guessedType', null)) { if ('container' == $node->var->name && $this->isController($this->table->lookUp('this')->type())) { $context = self::CONTAINER; } else { $context = $this->table->lookUp($node->var->name)->type(); } $type = $this->getType($context, $node->name, $node); if (null !== $type) { $node->setAttribute('guessedType', $type); } } // $x = $this->call() if ($node instanceof Node\Expr\Assign && $node->var instanceof Node\Expr\Variable && $node->expr instanceof Node\Expr\MethodCall && property_exists($node->expr->var, 'name') && null === $node->getAttribute('guessedType', null)) { if ('container' == $node->expr->var->name && $this->isController($this->table->lookUp('this')->type())) { $context = self::CONTAINER; } else { $context = $this->table->lookUp($node->expr->var->name)->type(); } $type = $this->getType($context, $node->expr->name, $node->expr); if (null !== $type) { $node->var->setAttribute('guessedType', $type); $this->table->setSymbol($node->var->name, $type); } } }
public function enterNode(Node $node) { if (!$node instanceof Exit_) { return; } $name = $node->getAttribute('kind') === Exit_::KIND_EXIT ? 'exit' : 'die'; $this->reporter->addViolation("Found {$name}() call", $this, $node); }
public function leaveNode(Node $node) { if (!$node instanceof ClassMethod) { return; } $pos = $node->getAttribute('startTokenPos'); MethodPatcher::$replacement[$pos] = true; }
private function getCommentsText(Node $node) { $text = ''; $comments = $node->getAttribute('comments'); foreach ($comments as $comment) { $text .= $comment->getReformattedText(); } return $text; }
/** * {@inheritdoc} */ public function enterNode(Node $node) { if ($node instanceof Node\Scalar\LNumber) { $originalValue = $node->getAttribute('originalValue'); if ($originalValue && $this->isInvalidOctalLiteral($originalValue)) { $this->errorCollection->add(new Error($this->parserContext->getFilename(), $node->getLine(), sprintf('"%s" is an invalid octal literal and will now triggers a parse error.', $originalValue))); } } }
public function enterNode(\PhpParser\Node $node) { if ($this->deprecatedClass) { return; } if ($node instanceof \PhpParser\Node\Stmt\Namespace_) { $this->namespace = $node->name; } if ($node instanceof \PhpParser\Node\Stmt\Interface_ or $node instanceof \PhpParser\Node\Stmt\Class_) { $this->className = $node->name; /** @var \PhpParser\Comment\Doc[] $comments */ $comments = $node->getAttribute('comments'); if (count($comments) === 0) { $this->errors[] = 'PHPDoc is needed for ' . $this->namespace . '\\' . $this->className . '::' . $node->name; return; } $comment = $comments[count($comments) - 1]; $text = $comment->getText(); if (strpos($text, '@deprecated') !== false) { $this->deprecatedClass = true; } if ($this->deprecatedClass === false && strpos($text, '@since') === false && strpos($text, '@deprecated') === false) { $type = $node instanceof \PhpParser\Node\Stmt\Interface_ ? 'interface' : 'class'; $this->errors[] = '@since or @deprecated tag is needed in PHPDoc for ' . $type . ' ' . $this->namespace . '\\' . $this->className; return; } } if ($node instanceof \PhpParser\Node\Stmt\ClassMethod) { /** @var \PhpParser\Node\Stmt\ClassMethod $node */ /** @var \PhpParser\Comment\Doc[] $comments */ $comments = $node->getAttribute('comments'); if (count($comments) === 0) { $this->errors[] = 'PHPDoc is needed for ' . $this->namespace . '\\' . $this->className . '::' . $node->name; return; } $comment = $comments[count($comments) - 1]; $text = $comment->getText(); if (strpos($text, '@since') === false && strpos($text, '@deprecated') === false) { $this->errors[] = '@since or @deprecated tag is needed in PHPDoc for ' . $this->namespace . '\\' . $this->className . '::' . $node->name; return; } } }
/** * {@inheritdoc} */ public function enterNode(Node $node) { if (!$node instanceof Node\Scalar\LNumber) { return; } $originalNumberValue = $node->getAttribute('originalValue', ''); if (preg_match('/^0[0-7]*[89]+/', $originalNumberValue)) { $this->addContextMessage(sprintf('Invalid octal literal %s', $originalNumberValue), $node); } }
public function enterNode(Node $node) { $endCurlyBraceOffset = 0; $startCurlyBraceOffset = 2; if (($node instanceof Node\Expr\PropertyFetch || $node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\Variable) && $node->name instanceof Node\Expr\ArrayDimFetch) { if ($node instanceof Node\Expr\Variable) { $startCurlyBraceOffset = 1; } elseif (!$node instanceof Node\Expr\PropertyFetch) { $endCurlyBraceOffset = -2; } } else { return; } $nextToStartToken = $this->tokens[$node->getAttribute('startTokenPos') + $startCurlyBraceOffset]; $endToken = $this->tokens[$node->getAttribute('endTokenPos') + $endCurlyBraceOffset]; if ($nextToStartToken === '{' && $endToken === '}') { return; } $this->addContextMessage('Indirect variable, property or method access', $node); }
public function leaveNode(Node $node) { if ($node->hasAttribute(NameResolver::TAG_NAMES_ATTRIBUTE)) { $tags = $node->getAttribute(NameResolver::TAG_NAMES_ATTRIBUTE); foreach ($tags as $tagName) { $name = new Node\Name($tagName); $name->setAttribute('isComment', true); $this->collect($name, $node); } } }
public function enterNode(Node $node) { if (!$node instanceof Node\Scalar\String_) { return; } $unquotedStringValue = null; if ($node->getAttribute('isDoubleQuoted')) { $unquotedStringValue = substr($node->getAttribute('originalValue'), 1, -1); } elseif ($node->getAttribute('isHereDoc')) { // Skip T_START_HEREDOC, T_END_HEREDOC $unquotedStringValue = ''; $startTokenPosition = $node->getAttribute('startTokenPos') + 1; $tokenLength = $node->getAttribute('endTokenPos') - $node->getAttribute('startTokenPos') - 1; foreach (array_slice($this->tokens, $startTokenPosition, $tokenLength) as $token) { if (is_string($token)) { $unquotedStringValue .= $token; } else { $unquotedStringValue .= $token[1]; } } } if (!$unquotedStringValue) { return; } $matches = array(); if (preg_match('/((?<!\\\\)\\\\u{.*})/', $unquotedStringValue, $matches)) { $this->addContextMessage(sprintf('Unicode codepoint escaping "%s" in a string', $matches[0]), $node); } }
/** * @param \PhpParser\Node $node * @return string|null */ public static function getDocComment(Node $node) { $phpDoc = $node->getDocComment(); $phpDocText = null; if ($phpDoc !== null) { return $phpDoc->getText(); } $comments = $node->getAttribute('comments'); if ($comments === null) { return null; } return $comments[count($comments) - 1]->getText(); }
public function enterNode(Node $node) { if (!$node instanceof Node\Scalar\String_) { return; } $unquotedStringValue = null; if ($node->getAttribute('isDoubleQuoted')) { $unquotedStringValue = substr($node->getAttribute('originalValue'), 1, -1); } elseif ($node->getAttribute('isHereDoc')) { // Skip T_START_HEREDOC, T_END_HEREDOC $unquotedStringValue = ''; foreach (range($node->getAttribute('startTokenPos') + 1, $node->getAttribute('endTokenPos') - 1) as $i) { $unquotedStringValue .= $this->tokenCollection->getToken($i)->__toString(); } } if (!$unquotedStringValue) { return; } $matches = array(); if (preg_match('/((?<!\\\\)\\\\u{.*})/', $unquotedStringValue, $matches)) { $this->addContextMessage(sprintf('Unicode codepoint escaping "%s" in a string', $matches[0]), $node); } }
public function enterNode(Node $node) { $node->setAttribute("scope", end($this->scope)); if ($node instanceof Stmt\Namespace_ and !empty($node->name)) { $this->namespace = new NamespaceName($node->name->parts); } elseif ($node instanceof Stmt\Class_) { $this->scope[] = new Scope\ClassScope($this->namespace, $node->name); } elseif ($node instanceof Stmt\Function_) { $this->scope[] = new Scope\FunctionScope($this->namespace, $node->name); } elseif ($node instanceof Stmt\ClassMethod) { $this->scope[] = new Scope\ClassMethodScope(end($this->scope), $node->name); } elseif ($node instanceof Expr\Closure) { $this->scope[] = new Scope\ClosureScope(end($this->scope), $node->getAttribute("startFilePos", mt_rand())); } }
public function enterNode(PhpParser\Node $node) { if ($node instanceof Stmt\ClassMethod) { // create new context, keep parent $this->stack->start(new MethodContext($node->name, $node->getLine(), $node->getAttribute('endLine'))); // report non public methods if ($node->isPrivate()) { $this->stack->addIssue(new PrivateMethodIssue($node)); } elseif ($node->isProtected()) { $this->stack->addIssue(new ProtectedMethodIssue($node)); } // report final methods if ($node->isFinal()) { $this->stack->addIssue(new FinalMethodIssue($node)); } } }
public function enterNode(Node $node) { if (null === ($comments = $node->getAttribute('comments'))) { return; } foreach ($this->processComments($comments) as $comment) { $text = $comment->getText(); if (0 !== strpos($text, '<?php')) { $text = '<?php ' . $text; } try { $this->getParser()->parse($text); $wrapNode = new CommentNode($comment); $this->reporter->addViolation('Found commented code', $this, $wrapNode); } catch (Error $e) { } } }
/** * @param Node $node A PHP-Parser Node object to parse var comments of * * @return array An array of the types, or empty array if no return comment exists */ public static function parseNode(Node $node) { /** @var Comment[] $varComments */ $varComments = self::filterComments($node->getAttribute("comments", [])); if (empty($varComments)) { return []; } return array_filter(array_unique(array_map(function (DocBlock\Tag $var) use($node) { $var = DocTypeNormaliser::sanitise($var->getContent()); return self::resolveImplicitVarName(self::parse($var), $node); }, array_flatten(array_map(function (Comment $comment) { return (new DocBlock($comment->getReformattedText()))->getTagsByName("var"); }, $varComments))), SORT_REGULAR), function ($element) { var_dump($element); return $element['name'] !== null; // Filter null names - see self::resolveImplicitVarName() }); }
public function leaveNode(Node $node) { if (!$node instanceof FuncCall) { return; } if (!$node->name instanceof Name) { return; } if (!$node->name->isUnqualified()) { return; } if (FunctionPatcher::isWhitelisted((string) $node->name) && !FunctionPatcher::isBlacklisted((string) $node->name)) { $replacement = new FullyQualified(array()); $replacement->set('\\__FuncProxy__::' . (string) $node->name); $pos = $node->getAttribute('startTokenPos'); FunctionPatcher::$replacement[$pos] = '\\__FuncProxy__::' . (string) $node->name; $node->name = $replacement; } }
public function enterNode(Node $node) { $node->setAttribute("scope", end($this->scope)); if ($node instanceof Stmt\Namespace_ and !empty($node->name)) { $this->namespace = new NamespaceName($node->name->parts); $this->scope[] = new Scope\NamespaceScope($this->namespace); } elseif ($node instanceof Stmt\Class_) { $this->scope[] = new Scope\ClassScope($this->namespace, $node->name); } elseif ($node instanceof Stmt\Function_) { $this->scope[] = new Scope\FunctionScope($this->namespace, $node->name); } elseif ($node instanceof Stmt\ClassMethod) { $this->scope[] = new Scope\ClassMethodScope(end($this->scope), $node->name); } elseif ($node instanceof Expr\Closure) { $identifier = $node->getAttribute("startFilePos", mt_rand()); $node->setAttribute("identifier", $identifier); // The Closure node now has identifier for common use $this->scope[] = new Scope\ClosureScope(end($this->scope), $identifier); } $node->setAttribute("scopeInner", end($this->scope)); }
public function leaveNode(AstNode $node) { switch ($node->getType()) { case 'Scalar_MagicConst_Class': return new StringNode($this->location['class']); case 'Scalar_MagicConst_Dir': return new StringNode($this->location['directory']); case 'Scalar_MagicConst_File': return new StringNode($this->location['file']); case 'Scalar_MagicConst_Function': return new StringNode($this->location['function']); case 'Scalar_MagicConst_Line': return new NumberNode($node->getAttribute('startLine')); case 'Scalar_MagicConst_Method': return new StringNode($this->location['method']); case 'Scalar_MagicConst_Namespace': return new StringNode($this->location['namespace']); case 'Scalar_MagicConst_Trait': return new StringNode($this->location['trait']); } }
protected function applyGlobal(array &$def, Node $node, $filename, $test) { $def['File'] = $filename; $def['Test'] = $test; $def['DefStart'] = $node->getAttribute('startFilePos'); $def['DefEnd'] = $node->getAttribute('endFilePos'); if (!isset($def['Exported'])) { $def['Exported'] = true; } }