Пример #1
0
 /**
  * @param $item
  * @param string $tab
  * @return mixed|string
  */
 public static function dump($item, $tab = "")
 {
     switch (gettype($item)) {
         case "integer":
         case "NULL":
         case "double":
         case "string":
         case "boolean":
         case "resource":
             return var_export($item, true);
         case "array":
             foreach ($item as $k => &$v) {
                 $v = $tab . self::$tab . "[{$k}] => " . self::dump($v, $tab . self::$tab);
             }
             return "array(" . count($item) . ") {\n{$tab}" . implode("\n{$tab}", $item) . "\n{$tab}}";
         case "object":
             if ($item instanceof EntityInterface) {
                 return $item->dump($tab);
             } elseif ($item instanceof EntityFunction) {
                 $nodeDumper = new NodeDumper();
                 return $item->dump($tab) . "{\n" . $nodeDumper->dump($item->stmts) . "\n}";
             } elseif ($item instanceof Node) {
                 $nodeDumper = new NodeDumper();
                 return $nodeDumper->dump($item);
             } elseif (method_exists($item, '__toString')) {
                 return $item->__toString();
             } else {
                 return "object(" . get_class($item) . ")";
             }
         default:
             return "unknown type " . gettype($item);
     }
 }
 /**
  * @dataProvider provideTestParse
  */
 public function testParse($name, $code, $dump)
 {
     $parser = new Parser(new Lexer\Emulative());
     $dumper = new NodeDumper();
     $stmts = $parser->parse($code);
     $this->assertSame($this->canonicalize($dump), $this->canonicalize($dumper->dump($stmts)), $name);
 }
Пример #3
0
 /**
  * @param array $statementsA
  * @param array $statementsB
  * @return bool
  */
 public static function isSame(array $statementsA, array $statementsB)
 {
     // Naive way to check if two implementation are the same
     $nodeDumper = new NodeDumper();
     $dumpA = $nodeDumper->dump($statementsA);
     $dumpB = $nodeDumper->dump($statementsB);
     return $dumpA === $dumpB;
 }
Пример #4
0
 private function getParseOutput(Parser $parser, $code)
 {
     $stmts = $parser->parse($code);
     $errors = $parser->getErrors();
     $output = '';
     foreach ($errors as $error) {
         $output .= $this->formatErrorMessage($error, $code) . "\n";
     }
     if (null !== $stmts) {
         $dumper = new NodeDumper();
         $output .= $dumper->dump($stmts);
     }
     return canonicalize($output);
 }
 private function getParseOutput(BaseParser $parser, $code)
 {
     $errors = new ErrorHandler\Collecting();
     $stmts = $parser->parse($code, $errors);
     $output = '';
     foreach ($errors->getErrors() as $error) {
         $output .= $this->formatErrorMessage($error, $code) . "\n";
     }
     if (null !== $stmts) {
         $dumper = new NodeDumper(['dumpComments' => true]);
         $output .= $dumper->dump($stmts);
     }
     return canonicalize($output);
 }
Пример #6
0
 /**
  * @dataProvider provideTestParse
  */
 public function testParse($name, $code, $expected)
 {
     $lexer = new Lexer\Emulative(array('usedAttributes' => array('startLine', 'endLine', 'startFilePos', 'endFilePos')));
     $parser = new Parser($lexer, array('throwOnError' => false));
     $stmts = $parser->parse($code);
     $errors = $parser->getErrors();
     $output = '';
     foreach ($errors as $error) {
         $output .= $this->formatErrorMessage($error, $code) . "\n";
     }
     if (null !== $stmts) {
         $dumper = new NodeDumper();
         $output .= $dumper->dump($stmts);
     }
     $this->assertSame($this->canonicalize($expected), $this->canonicalize($output), $name);
 }
Пример #7
0
 protected function debugDump($php_string)
 {
     $parser = new Parser();
     $stmts = $parser->parsePHPString($php_string);
     $nodeDumper = new NodeDumper();
     print "\n" . $nodeDumper->dump($stmts) . "\n";
 }
Пример #8
0
 protected function commandMain()
 {
     // Load set, change
     $chglist = [];
     $options = [];
     $loaded_sets = [];
     $setstack = [$this->args['--set']];
     while (!empty($setstack)) {
         $setname = array_shift($setstack);
         // Prevent infinite-loop
         if (isset($loaded_sets[$setname])) {
             continue;
         }
         $loaded_sets[$setname] = true;
         // Load
         $setfile = $this->setpath . '/' . $setname . '.json';
         if (!file_exists($setfile)) {
             Logging::error('Unable load setfile {name}', ['name' => $setfile]);
             exit(1);
         }
         if ($this->args['--verbose']) {
             Logging::info('Load set {name}', ['name' => basename($setfile)]);
         }
         $info = json_decode(file_get_contents($setfile));
         // Depend
         if (isset($info->depend)) {
             foreach ($info->depend as $setname) {
                 $setstack[] = $setname;
             }
         }
         // Options
         if (isset($info->options)) {
             foreach ($info->options as $key => $value) {
                 if (!isset($options[$key])) {
                     $options[$key] = $value;
                 }
             }
         }
         // Instantiate
         if (isset($info->changes)) {
             foreach (array_reverse($info->changes) as $chgname) {
                 $chglist[] = $chgname;
             }
         }
     }
     $chglist = array_reverse($chglist);
     // FIXME: use a better method making load order correct
     if ($this->args['--verbose']) {
         Logging::info('Set options ' . print_r($options, true));
     }
     // Instantiate change
     foreach ($chglist as $key => $chgname) {
         if ($this->args['--verbose']) {
             Logging::info('Load change {name}', ['name' => $chgname]);
         }
         $chgname = '\\PhpMigration\\Changes\\' . $chgname;
         $chglist[$key] = new $chgname();
     }
     $chgvisitor = new CheckVisitor($chglist);
     // Instance parser
     if (isset($options['parse_as_version']) && $options['parse_as_version'] == 7) {
         $kind = ParserFactory::ONLY_PHP7;
     } else {
         $kind = ParserFactory::PREFER_PHP7;
     }
     $parser = (new ParserFactory())->create($kind);
     if ($this->args['--verbose']) {
         Logging::info('Parser created ' . get_class($parser));
     }
     // Instance traverser
     $traverser_pre = new NodeTraverser();
     $traverser_pre->addVisitor(new NameResolver());
     $traverser_pre->addVisitor(new ReduceVisitor());
     $traverser = new NodeTraverser();
     $traverser->addVisitor($chgvisitor);
     // Prepare filelist
     $filelist = [];
     foreach ($this->args['<file>'] as $file) {
         if (is_dir($file)) {
             $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($file), 0, \RecursiveIteratorIterator::CATCH_GET_CHILD);
             $iterator = new \RegexIterator($iterator, '/\\.php$/');
             try {
                 foreach ($iterator as $file) {
                     $filelist[] = $file;
                 }
             } catch (Exception $e) {
                 continue;
             }
         } else {
             $filelist[] = new \SplFileInfo($file);
         }
     }
     // Parse
     $chgvisitor->prepare();
     foreach ($filelist as $file) {
         if ($this->args['--verbose']) {
             Logging::info('Parse file {file}', ['file' => $file]);
         }
         if (!file_exists($file)) {
             Logging::warning('No such file or directory "{file}"', ['file' => $file]);
             continue;
         } elseif (!is_readable($file)) {
             Logging::warning('Permission denied "{file}"', ['file' => $file]);
             continue;
         }
         $chgvisitor->setFile($file);
         $chgvisitor->setCode(file_get_contents($file));
         try {
             $stmts = $parser->parse($chgvisitor->getCode());
         } catch (PhpParserError $e) {
             $chgvisitor->addSpot('PARSE', true, $e->getMessage(), 'NONE', $e->getStartLine());
             if ($this->args['--verbose']) {
                 Logging::warning('Parse error {file}, error message "{exception}"', ['exception' => $e, 'file' => $file]);
             }
             continue;
         }
         // Apply traversers
         $stmts = $traverser_pre->traverse($stmts);
         $traverser->traverse($stmts);
     }
     $chgvisitor->finish();
     // Display
     $has_output = false;
     foreach ($chgvisitor->getSpots() as $spotlist) {
         // Init nums
         $nums = ['total' => 0, 'identified' => 0];
         $nums['total'] = count($spotlist);
         foreach ($spotlist as $key => $spot) {
             if ($spot['identified']) {
                 $nums['identified']++;
             } elseif ($this->args['--quite']) {
                 // Remove uncertain
                 unset($spotlist[$key]);
             }
         }
         $has_output = true;
         if (!$spotlist) {
             continue;
         }
         usort($spotlist, function ($a, $b) {
             return $a['line'] - $b['line'];
         });
         $spot = current($spotlist);
         echo "\n";
         echo 'File: ' . $spot['file'] . "\n";
         echo "--------------------------------------------------------------------------------\n";
         echo 'Found ' . $nums['total'] . ' spot(s), ' . $nums['identified'] . " identified\n";
         echo "--------------------------------------------------------------------------------\n";
         foreach ($spotlist as $spot) {
             printf("%5d | %-10s | %1s | %s | %s\n", $spot['line'], $spot['cate'], $spot['identified'] ? '*' : ' ', $spot['version'], $spot['message']);
         }
         echo "--------------------------------------------------------------------------------\n";
     }
     // No spot found
     if (!$has_output) {
         echo "No spot found\n";
     }
     // Dump tree
     if ($this->args['--dump']) {
         $nodeDumper = new NodeDumper();
         echo $nodeDumper->dump($stmts) . "\n";
     }
 }