Changeset View
Changeset View
Standalone View
Standalone View
scripts/symbols/generate_php_symbols.php
| #!/usr/bin/env php | #!/usr/bin/env php | ||||
| <?php | <?php | ||||
| $root = dirname(dirname(dirname(__FILE__))); | $root = dirname(dirname(dirname(__FILE__))); | ||||
| require_once $root.'/scripts/__init_script__.php'; | require_once $root.'/scripts/__init_script__.php'; | ||||
| if ($argc !== 1 || posix_isatty(STDIN)) { | $args = new PhutilArgumentParser($argv); | ||||
| $args->setSynopsis(<<<EOSYNOPSIS | |||||
| **generate_php_symbols.php** [__options__] | |||||
| Generate repository symbols using XHPAST. Paths are read from stdin. | |||||
| EOSYNOPSIS | |||||
| ); | |||||
| $args->parseStandardArguments(); | |||||
| if (posix_isatty(STDIN)) { | |||||
| echo phutil_console_format( | echo phutil_console_format( | ||||
| "usage: find . -type f -name '*.php' | ./generate_php_symbols.php\n"); | "%s\n", | ||||
| pht( | |||||
| 'Usage: %s', | |||||
| "find . -type f -name '*.php' | ./generate_php_symbols.php")); | |||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| $input = file_get_contents('php://stdin'); | $input = file_get_contents('php://stdin'); | ||||
| $input = trim($input); | |||||
| $input = explode("\n", $input); | |||||
| $data = array(); | $data = array(); | ||||
| $futures = array(); | $futures = array(); | ||||
| foreach ($input as $file) { | foreach (explode("\n", trim($input)) as $file) { | ||||
| $file = Filesystem::readablePath($file); | $file = Filesystem::readablePath($file); | ||||
| $data[$file] = Filesystem::readFile($file); | $data[$file] = Filesystem::readFile($file); | ||||
| $futures[$file] = PhutilXHPASTBinary::getParserFuture($data[$file]); | $futures[$file] = PhutilXHPASTBinary::getParserFuture($data[$file]); | ||||
| } | } | ||||
| $futures = id(new FutureIterator($futures)) | $futures = new FutureIterator($futures); | ||||
| ->limit(8); | foreach ($futures->limit(8) as $file => $future) { | ||||
| foreach ($futures as $file => $future) { | |||||
| $tree = XHPASTTree::newFromDataAndResolvedExecFuture( | $tree = XHPASTTree::newFromDataAndResolvedExecFuture( | ||||
| $data[$file], | $data[$file], | ||||
| $future->resolve()); | $future->resolve()); | ||||
| $root = $tree->getRootNode(); | $root = $tree->getRootNode(); | ||||
| $scopes = array(); | $scopes = array(); | ||||
| $functions = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION'); | $functions = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION'); | ||||
| foreach ($functions as $function) { | foreach ($functions as $function) { | ||||
| $name = $function->getChildByIndex(2); | $name = $function->getChildByIndex(2); | ||||
| // Skip anonymous functions | // Skip anonymous functions. | ||||
| if (!$name->getConcreteString()) { | if (!$name->getConcreteString()) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| print_symbol($file, 'function', $name); | print_symbol($file, 'function', $name); | ||||
| } | } | ||||
| $classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); | $classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); | ||||
| foreach ($classes as $class) { | foreach ($classes as $class) { | ||||
| Show All 14 Lines | foreach ($futures->limit(8) as $file => $future) { | ||||
| foreach ($constants as $constant_list) { | foreach ($constants as $constant_list) { | ||||
| foreach ($constant_list->getChildren() as $constant) { | foreach ($constant_list->getChildren() as $constant) { | ||||
| $constant_name = $constant->getChildByIndex(0); | $constant_name = $constant->getChildByIndex(0); | ||||
| print_symbol($file, 'constant', $constant_name); | print_symbol($file, 'constant', $constant_name); | ||||
| } | } | ||||
| } | } | ||||
| foreach ($scopes as $scope) { | foreach ($scopes as $scope) { | ||||
| // this prints duplicate symbols in the case of nested classes | // This prints duplicate symbols in the case of nested classes. | ||||
| // luckily, PHP doesn't allow those | // Luckily, PHP doesn't allow those. | ||||
| list($class, $class_name) = $scope; | list($class, $class_name) = $scope; | ||||
| $consts = $class->selectDescendantsOfType( | $consts = $class->selectDescendantsOfType( | ||||
| 'n_CLASS_CONSTANT_DECLARATION_LIST'); | 'n_CLASS_CONSTANT_DECLARATION_LIST'); | ||||
| foreach ($consts as $const_list) { | foreach ($consts as $const_list) { | ||||
| foreach ($const_list->getChildren() as $const) { | foreach ($const_list->getChildren() as $const) { | ||||
| $const_name = $const->getChildByIndex(0); | $const_name = $const->getChildByIndex(0); | ||||
| print_symbol($file, 'class_const', $const_name, $class_name); | print_symbol($file, 'class_const', $const_name, $class_name); | ||||
| Show All 15 Lines | foreach ($scopes as $scope) { | ||||
| $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); | $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); | ||||
| foreach ($methods as $method) { | foreach ($methods as $method) { | ||||
| $method_name = $method->getChildByIndex(2); | $method_name = $method->getChildByIndex(2); | ||||
| print_symbol($file, 'method', $method_name, $class_name); | print_symbol($file, 'method', $method_name, $class_name); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| function print_symbol($file, $type, $token, $context = null) { | function print_symbol($file, $type, XHPASTNode $node, $context = null) { | ||||
| $parts = array( | $parts = array( | ||||
| $context ? $context->getConcreteString() : '', | $context ? $context->getConcreteString() : '', | ||||
| // variable tokens are `$name`, not just `name`, so strip the $ off of | // Variable tokens are `$name`, not just `name`, so strip the "$"" off of | ||||
| // class field names | // class field names | ||||
| ltrim($token->getConcreteString(), '$'), | ltrim($node->getConcreteString(), '$'), | ||||
| $type, | $type, | ||||
| 'php', | 'php', | ||||
| $token->getLineNumber(), | $node->getLineNumber(), | ||||
| '/'.ltrim($file, './'), | '/'.ltrim($file, './'), | ||||
| ); | ); | ||||
| echo implode(' ', $parts)."\n"; | echo implode(' ', $parts)."\n"; | ||||
| } | } | ||||