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);
 }
Ejemplo n.º 5
0
 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.');
 }