public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($request->isFormPost()) {
         $source = $request->getStr('source');
         $future = xhpast_get_parser_future($source);
         $resolved = $future->resolve();
         // This is just to let it throw exceptions if stuff is broken.
         $parse_tree = XHPASTTree::newFromDataAndResolvedExecFuture($source, $resolved);
         list($err, $stdout, $stderr) = $resolved;
         $storage_tree = new PhabricatorXHPASTViewParseTree();
         $storage_tree->setInput($source);
         $storage_tree->setStdout($stdout);
         $storage_tree->setAuthorPHID($user->getPHID());
         $storage_tree->save();
         return id(new AphrontRedirectResponse())->setURI('/xhpast/view/' . $storage_tree->getID() . '/');
     }
     $form = id(new AphrontFormView())->setUser($user)->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Source')->setName('source')->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL))->appendChild(id(new AphrontFormSubmitControl())->setValue('Parse'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Generate XHP AST');
     $panel->setWidth(AphrontPanelView::WIDTH_WIDE);
     $panel->appendChild($form);
     return $this->buildStandardPageResponse($panel, array('title' => 'XHPAST View'));
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $source = $request->getValue('code');
     $future = xhpast_get_parser_future($source);
     list($stdout) = $future->resolvex();
     return json_decode($stdout, true);
 }
 public function willLintPaths(array $paths)
 {
     $futures = array();
     foreach ($paths as $path) {
         if (array_key_exists($path, $this->trees)) {
             continue;
         }
         $futures[$path] = xhpast_get_parser_future($this->getData($path));
     }
     foreach (Futures($futures)->limit(8) as $path => $future) {
         $this->willLintPath($path);
         $this->trees[$path] = null;
         try {
             $this->trees[$path] = XHPASTTree::newFromDataAndResolvedExecFuture($this->getData($path), $future->resolve());
             $root = $this->trees[$path]->getRootNode();
             $root->buildSelectCache();
             $root->buildTokenCache();
         } catch (XHPASTSyntaxErrorException $ex) {
             $this->raiseLintAtLine($ex->getErrorLine(), 1, self::LINT_PHP_SYNTAX_ERROR, 'This file contains a syntax error: ' . $ex->getMessage());
             $this->stopAllLinters();
             return;
         } catch (Exception $ex) {
             $this->raiseLintAtPath(self::LINT_UNABLE_TO_PARSE, 'XHPAST could not parse this file, probably because the AST is too ' . 'deep. Some lint issues may not have been detected. You may safely ' . 'ignore this warning.');
             return;
         }
     }
 }
 public function getHighlightFuture($source)
 {
     $scrub = false;
     if (strpos($source, '<?') === false) {
         $source = "<?php\n" . $source . "\n";
         $scrub = true;
     }
     return new PhutilXHPASTSyntaxHighlighterFuture(xhpast_get_parser_future($source), $source, $scrub);
 }
 protected function buildFutures(array $paths)
 {
     foreach ($paths as $path) {
         if (!isset($this->futures[$path])) {
             $this->futures[$path] = xhpast_get_parser_future($this->getData($path));
         }
     }
     return array_select_keys($this->futures, $paths);
 }
 */
$root = dirname(dirname(dirname(__FILE__)));
require_once $root . '/scripts/__init_script__.php';
if ($argc !== 1 || posix_isatty(STDIN)) {
    echo phutil_console_format("usage: find . -type f -name '*.php' | ./generate_php_symbols.php\n");
    exit(1);
}
$input = file_get_contents('php://stdin');
$input = trim($input);
$input = explode("\n", $input);
$data = array();
$futures = array();
foreach ($input as $file) {
    $file = Filesystem::readablePath($file);
    $data[$file] = Filesystem::readFile($file);
    $futures[$file] = xhpast_get_parser_future($data[$file]);
}
foreach (Futures($futures)->limit(8) as $file => $future) {
    $tree = XHPASTTree::newFromDataAndResolvedExecFuture($data[$file], $future->resolve());
    $root = $tree->getRootNode();
    $scopes = array();
    $functions = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION');
    foreach ($functions as $function) {
        $name = $function->getChildByIndex(2);
        print_symbol($file, 'function', $name);
    }
    $classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
    foreach ($classes as $class) {
        $class_name = $class->getChildByIndex(1);
        print_symbol($file, 'class', $class_name);
        $scopes[] = array($class, $class_name);
 private function executeParserTest($name, $data)
 {
     $data = explode("\n", $data, 2);
     if (count($data) !== 2) {
         throw new Exception(pht('Expected multiple lines in parser test file "%s".', $name));
     }
     $head = head($data);
     $body = last($data);
     if (!preg_match('/^#/', $head)) {
         throw new Exception(pht('Expected first line of parser test file "%s" to begin with "#" ' . 'and specify test options.', $name));
     }
     $head = preg_replace('/^#\\s*/', '', $head);
     $options_parser = new PhutilSimpleOptions();
     $options = $options_parser->parse($head);
     $type = null;
     foreach ($options as $key => $value) {
         switch ($key) {
             case 'pass':
             case 'fail-syntax':
             case 'fail-parse':
                 if ($type !== null) {
                     throw new Exception(pht('Test file "%s" unexpectedly specifies multiple expected ', 'test outcomes.', $name));
                 }
                 $type = $key;
                 break;
             case 'comment':
                 // Human readable comment providing test case information.
                 break;
             case 'rtrim':
                 // Allows construction of tests which rely on EOF without newlines.
                 $body = rtrim($body);
                 break;
             default:
                 throw new Exception(pht('Test file "%s" has unknown option "%s" in its options ' . 'string.', $name, $key));
         }
     }
     if ($type === null) {
         throw new Exception(pht('Test file "%s" does not specify a test result (like "pass") in ' . 'its options string.', $name));
     }
     $future = xhpast_get_parser_future($body);
     list($err, $stdout, $stderr) = $future->resolve();
     switch ($type) {
         case 'pass':
         case 'fail-parse':
             $this->assertEqual(0, $err, pht('Exit code for "%s".', $name));
             $expect_name = preg_replace('/\\.test$/', '.expect', $name);
             $dir = dirname(__FILE__) . '/data/';
             $expect = Filesystem::readFile($dir . $expect_name);
             $expect = json_decode($expect, true);
             if (!is_array($expect)) {
                 throw new Exception(pht('Test ".expect" file "%s" for test "%s" is not valid JSON.', $expect_name, $name));
             }
             $stdout = json_decode($stdout, true);
             if (!is_array($stdout)) {
                 throw new Exception(pht('Output for test file "%s" is not valid JSON.', $name));
             }
             $json = new PhutilJSON();
             $expect_nice = $json->encodeFormatted($expect);
             $stdout_nice = $json->encodeFormatted($stdout);
             if ($type == 'pass') {
                 $this->assertEqual($expect_nice, $stdout_nice, pht('Parser output for "%s".', $name));
             } else {
                 $this->assertFalse($expect_nice == $stdout_nice, pht('Expected parser to parse "%s" incorrectly.', $name));
             }
             break;
         case 'fail-syntax':
             $this->assertEqual(1, $err, pht('Exit code for "%s".', $name));
             $this->assertTrue((bool) preg_match('/syntax error/', $stderr), pht('Expect "syntax error" in stderr or "%s".', $name));
             break;
     }
 }
Example #8
0
 public static function newFromData($php_source)
 {
     $future = xhpast_get_parser_future($php_source);
     return self::newFromDataAndResolvedExecFuture($php_source, $future->resolve());
 }
 protected function executeAtomize($file_name, $file_data)
 {
     $future = xhpast_get_parser_future($file_data);
     $tree = XHPASTTree::newFromDataAndResolvedExecFuture($file_data, $future->resolve());
     $atoms = array();
     $root = $tree->getRootNode();
     $func_decl = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION');
     foreach ($func_decl as $func) {
         $name = $func->getChildByIndex(2);
         // Don't atomize closures
         if ($name->getTypeName() === 'n_EMPTY') {
             continue;
         }
         $atom = $this->newAtom(DivinerAtom::TYPE_FUNCTION)->setName($name->getConcreteString())->setLine($func->getLineNumber())->setFile($file_name);
         $this->findAtomDocblock($atom, $func);
         $this->parseParams($atom, $func);
         $this->parseReturnType($atom, $func);
         $atoms[] = $atom;
     }
     $class_types = array(DivinerAtom::TYPE_CLASS => 'n_CLASS_DECLARATION', DivinerAtom::TYPE_INTERFACE => 'n_INTERFACE_DECLARATION');
     foreach ($class_types as $atom_type => $node_type) {
         $class_decls = $root->selectDescendantsOfType($node_type);
         foreach ($class_decls as $class) {
             $name = $class->getChildByIndex(1, 'n_CLASS_NAME');
             $atom = $this->newAtom($atom_type)->setName($name->getConcreteString())->setFile($file_name)->setLine($class->getLineNumber());
             // This parses "final" and "abstract".
             $attributes = $class->getChildByIndex(0, 'n_CLASS_ATTRIBUTES');
             foreach ($attributes->selectDescendantsOfType('n_STRING') as $attr) {
                 $atom->setProperty($attr->getConcreteString(), true);
             }
             // If this exists, it is n_EXTENDS_LIST.
             $extends = $class->getChildByIndex(2);
             $extends_class = $extends->selectDescendantsOfType('n_CLASS_NAME');
             foreach ($extends_class as $parent_class) {
                 $atom->addExtends($this->newRef(DivinerAtom::TYPE_CLASS, $parent_class->getConcreteString()));
             }
             // If this exists, it is n_IMPLEMENTS_LIST.
             $implements = $class->getChildByIndex(3);
             $iface_names = $implements->selectDescendantsOfType('n_CLASS_NAME');
             foreach ($iface_names as $iface_name) {
                 $atom->addExtends($this->newRef(DivinerAtom::TYPE_INTERFACE, $iface_name->getConcreteString()));
             }
             $this->findAtomDocblock($atom, $class);
             $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION');
             foreach ($methods as $method) {
                 $matom = $this->newAtom(DivinerAtom::TYPE_METHOD);
                 $this->findAtomDocblock($matom, $method);
                 $attribute_list = $method->getChildByIndex(0);
                 $attributes = $attribute_list->selectDescendantsOfType('n_STRING');
                 if ($attributes) {
                     foreach ($attributes as $attribute) {
                         $attr = strtolower($attribute->getConcreteString());
                         switch ($attr) {
                             case 'final':
                             case 'abstract':
                             case 'static':
                                 $matom->setProperty($attr, true);
                                 break;
                             case 'public':
                             case 'protected':
                             case 'private':
                                 $matom->setProperty('access', $attr);
                                 break;
                         }
                     }
                 } else {
                     $matom->setProperty('access', 'public');
                 }
                 $this->parseParams($matom, $method);
                 $matom->setName($method->getChildByIndex(2)->getConcreteString());
                 $matom->setLine($method->getLineNumber());
                 $matom->setFile($file_name);
                 $this->parseReturnType($matom, $method);
                 $atom->addChild($matom);
                 $atoms[] = $matom;
             }
             $atoms[] = $atom;
         }
     }
     return $atoms;
 }