public function analyze(File $file) { if (!$file instanceof PhpFile) { return; } NodeTraversal::traverseWithCallback($file->getAst(), $this); }
public function analyze(File $file) { if (!$file instanceof PhpFile) { return; } $this->file = $file; NodeTraversal::traverseWithCallback($file->getAst(), $this, $this->scopeCreator); }
public function process(\PHPParser_Node $root) { $this->root = $root; $this->astPositionCounter = 0; $this->exceptionHandlers = new \SplStack(); $this->graph = new ControlFlowGraph(self::computeFallThrough($root)); NodeTraversal::traverseWithCallback($root, $this); $this->assignPriorities(); }
public function analyze(File $file) { if (!$file instanceof PhpFile) { return; } if (!$this->getSetting('enabled')) { return; } $this->file = $file; NodeTraversal::traverseWithCallback($file->getAst(), $this); }
private function updateAst() { try { $this->ast = ParseUtils::parse($this->getContent()); NodeTraversal::traverseWithCallback($this->ast, $this->typeInferencePass, $this->typeInferencePass->getScopeCreator()); NodeTraversal::traverseWithCallback($this->ast, $this->typeInferencePass, $this->typeInferencePass->getScopeCreator()); } catch (\PHPParser_Error $ex) { // The original content of the file is not valid PHP code. We just ignore this. // Passes that require an AST, have to check with hasAst() manually. } }
protected function execute(InputInterface $input, OutputInterface $output) { if (!is_file($file = $input->getArgument('file'))) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $file)); } if (false === strpos($input->getArgument('element'), '::')) { throw new \InvalidArgumentException(sprintf('The element must be of the form "ClassName::methodName", but got "%s".', $input->getArgument('element'))); } list($class, $method) = explode('::', $input->getArgument('element')); $ast = ParseUtils::parse(file_get_contents($file)); NodeTraversal::traverseWithCallback($ast, $callback = new SearchCallback($class, $method)); if (null === ($cfg = $callback->getCfg())) { throw new \RuntimeException(sprintf('The code element "%s" was not found in the given file.', $input->getArgument('element'))); } $output->writeln((new GraphvizSerializer())->serialize($cfg)); }
public function createScope(\PHPParser_Node $node, Scope $parent = null) { $thisType = $this->getThisType($node, $parent); // Constructing the global scope is very different than constructing inner scopes, because only global scopes // can contain named classes that show up in the type registry. $newScope = null; if (null === $parent) { $newScope = new Scope($node, null, $thisType); $builder = new GlobalScopeBuilder($newScope, $this->typeRegistry); NodeTraversal::traverseWithCallback($node, $builder); } else { $newScope = new Scope($node, $parent, $thisType); $builder = new LocalScopeBuilder($newScope, $this->typeRegistry); NodeTraversal::traverseWithCallback($node, $builder); } if (null !== $thisType) { $newScope->declareVar('this', $thisType); } return $newScope; }
private function computeUseDef($code) { $code = sprintf('<?php function foo($param1, $param2) { %s }', $code); $ast = \JMS\PhpManipulator\PhpParser\ParseUtils::parse($code); $scope = (new \Scrutinizer\PhpAnalyzer\PhpParser\Scope\SyntacticScopeCreator())->createScope($ast); $cfa = new \Scrutinizer\PhpAnalyzer\ControlFlow\ControlFlowAnalysis(); $cfa->process($ast); $cfg = $cfa->getGraph(); $this->analysis = new \Scrutinizer\PhpAnalyzer\DataFlow\VariableReachability\MayBeReachingUseAnalysis($cfg, $scope); $this->analysis->analyze(); $this->def = null; $this->uses = array(); \Scrutinizer\PhpAnalyzer\PhpParser\NodeTraversal::traverseWithCallback($ast, new \Scrutinizer\PhpAnalyzer\PhpParser\PreOrderCallback(function ($t, \PHPParser_Node $node) { if (!$node instanceof \PHPParser_Node_Stmt_Label) { return; } if ('D' === $node->name) { $this->def = $node->getAttribute('next'); } else { if (0 === strpos($node->name, 'U')) { $this->uses[] = $node->getAttribute('next'); } } })); $this->assertNotNull($this->def); $this->assertNotEmpty($this->uses); }
private function addToDefIfLocal($name, \PHPParser_Node $node = null, \PHPParser_Node $rValue = null, DefinitionLattice $definitions) { $var = $this->scope->getVar($name); if (null === $var) { return; } // Invalidate other definitions if they depended on this variable as it has been changed. foreach ($definitions as $otherVar) { if (null === ($otherDef = $definitions[$otherVar])) { continue; } if ($otherDef->dependsOn($var)) { $definitions[$otherVar] = null; } } // The node can be null if we are dealing with a conditional definition. For conditional // definitions, this analysis cannot do much. if (null === $node) { $definitions[$var] = null; return; } $definition = new Definition($node, $rValue); if (null !== $rValue) { NodeTraversal::traverseWithCallback($rValue, new PreOrderCallback(function ($t, \PHPParser_Node $node) use($definition) { if (NodeUtil::isScopeCreator($node)) { return false; } if (!NodeUtil::isName($node)) { return; } if (null === ($var = $this->scope->getVar($node->name))) { if (null !== $this->logger) { $this->logger->debug(sprintf('Could not find variable "%s" in the current scope. ' . 'This could imply an error in SyntacticScopeCreator.', $node->name)); } // We simply assume that the variable was declared so that we can properly // invalidate the definition if it is changed. For this analysis, it does not // matter whether it actually exists. A later pass will add a warning anyway. $var = $this->scope->declareVar($node->name); } $definition->addDependentVar($var); })); } $definitions[$var] = $definition; }
private function computeDefUse($code) { $code = sprintf('<?php function foo($param1, $param2) { %s }', $code); $ast = ParseUtils::parse($code); $scope = (new SyntacticScopeCreator())->createScope($ast); $cfa = new ControlFlowAnalysis(); $cfa->process($ast); $cfg = $cfa->getGraph(); $this->analysis = new MustBeReachingDefAnalysis($cfg, $scope); $this->analysis->analyze(); $this->def = $this->use = null; NodeTraversal::traverseWithCallback($ast, new PreOrderCallback(function (NodeTraversal $t, \PHPParser_Node $node) { if (!$node instanceof \PHPParser_Node_Stmt_Label) { return; } if ('D' === $node->name) { $this->def = $node->getAttribute('next'); } else { if ('U' === $node->name) { $this->use = $node->getAttribute('next'); } else { if (0 === strpos($node->name, 'DP_')) { $className = 'PHPParser_Node_' . substr($node->name, 3); $parent = $node; while (null !== ($parent = $parent->getAttribute('parent'))) { if ($parent instanceof $className) { $this->def = $parent; return; } } throw new \RuntimeException(sprintf('Did not find any parent of class "%s".', $className)); } } } })); $this->assertNotNull($this->def, 'Did not find "D" (definition) label in the code.'); $this->assertNotNull($this->use, 'Did not find "U" (usage) label in the code.'); }