Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / scripts / symbols / generate_php_symbols.php
blobaf87d580d8153cb64b06fb169fc8d581b4093db7
1 #!/usr/bin/env php
2 <?php
4 $root = dirname(dirname(dirname(__FILE__)));
5 require_once $root.'/scripts/__init_script__.php';
7 $args = new PhutilArgumentParser($argv);
8 $args->setSynopsis(<<<EOSYNOPSIS
9 **generate_php_symbols.php** [__options__]
11 Generate repository symbols using XHPAST. Paths are read from stdin.
12 EOSYNOPSIS
14 $args->parseStandardArguments();
16 if (posix_isatty(STDIN)) {
17 echo phutil_console_format(
18 "%s\n",
19 pht(
20 'Usage: %s',
21 "find . -type f -name '*.php' | ./generate_php_symbols.php"));
22 exit(1);
25 $input = file_get_contents('php://stdin');
26 $data = array();
27 $futures = array();
29 foreach (explode("\n", trim($input)) as $file) {
30 if (!strlen($file)) {
31 continue;
34 $file = Filesystem::readablePath($file);
35 $data[$file] = Filesystem::readFile($file);
36 $futures[$file] = PhutilXHPASTBinary::getParserFuture($data[$file]);
39 $futures = new FutureIterator($futures);
40 foreach ($futures->limit(8) as $file => $future) {
41 $tree = XHPASTTree::newFromDataAndResolvedExecFuture(
42 $data[$file],
43 $future->resolve());
45 $root = $tree->getRootNode();
46 $scopes = array();
48 $functions = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION');
49 foreach ($functions as $function) {
50 $name = $function->getChildByIndex(2);
51 // Skip anonymous functions.
52 if (!$name->getConcreteString()) {
53 continue;
55 print_symbol($file, 'function', $name);
58 $classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
59 foreach ($classes as $class) {
60 $class_name = $class->getChildByIndex(1);
61 print_symbol($file, 'class', $class_name);
62 $scopes[] = array($class, $class_name);
65 $interfaces = $root->selectDescendantsOfType('n_INTERFACE_DECLARATION');
66 foreach ($interfaces as $interface) {
67 $interface_name = $interface->getChildByIndex(1);
68 // We don't differentiate classes and interfaces in highlighters.
69 print_symbol($file, 'class', $interface_name);
70 $scopes[] = array($interface, $interface_name);
73 $constants = $root->selectDescendantsOfType('n_CONSTANT_DECLARATION_LIST');
74 foreach ($constants as $constant_list) {
75 foreach ($constant_list->getChildren() as $constant) {
76 $constant_name = $constant->getChildByIndex(0);
77 print_symbol($file, 'constant', $constant_name);
81 foreach ($scopes as $scope) {
82 // This prints duplicate symbols in the case of nested classes.
83 // Luckily, PHP doesn't allow those.
84 list($class, $class_name) = $scope;
86 $consts = $class->selectDescendantsOfType(
87 'n_CLASS_CONSTANT_DECLARATION_LIST');
88 foreach ($consts as $const_list) {
89 foreach ($const_list->getChildren() as $const) {
90 $const_name = $const->getChildByIndex(0);
91 print_symbol($file, 'class_const', $const_name, $class_name);
95 $members = $class->selectDescendantsOfType(
96 'n_CLASS_MEMBER_DECLARATION_LIST');
97 foreach ($members as $member_list) {
98 foreach ($member_list->getChildren() as $member) {
99 if ($member->getTypeName() == 'n_CLASS_MEMBER_MODIFIER_LIST') {
100 continue;
102 $member_name = $member->getChildByIndex(0);
103 print_symbol($file, 'member', $member_name, $class_name);
107 $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION');
108 foreach ($methods as $method) {
109 $method_name = $method->getChildByIndex(2);
110 print_symbol($file, 'method', $method_name, $class_name);
115 function print_symbol($file, $type, XHPASTNode $node, $context = null) {
116 $parts = array(
117 $context ? $context->getConcreteString() : '',
118 // Variable tokens are `$name`, not just `name`, so strip the "$"" off of
119 // class field names
120 ltrim($node->getConcreteString(), '$'),
121 $type,
122 'php',
123 $node->getLineNumber(),
124 '/'.ltrim($file, './'),
126 echo implode(' ', $parts)."\n";