/** * @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); }
/** * @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; }
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); }
/** * @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); }
protected function debugDump($php_string) { $parser = new Parser(); $stmts = $parser->parsePHPString($php_string); $nodeDumper = new NodeDumper(); print "\n" . $nodeDumper->dump($stmts) . "\n"; }
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"; } }