private function isInAnonymousFunction(XHPASTNode $node) { while ($node) { if ($node->getTypeName() == 'n_FUNCTION_DECLARATION' && $node->getChildByIndex(2)->getTypeName() == 'n_EMPTY') { return true; } $node = $node->getParentNode(); } }
/** * Get class/method modifiers. * * @param XHPASTNode A node of type `n_CLASS_DECLARATION` or * `n_METHOD_DECLARATION`. * @return map<string, bool> Class/method modifiers. */ protected final function getModifiers(XHPASTNode $node) { $modifier_list = $node->getChildByIndex(0); switch ($modifier_list->getTypeName()) { case 'n_CLASS_ATTRIBUTES': case 'n_CLASS_MEMBER_MODIFIER_LIST': case 'n_METHOD_MODIFIER_LIST': break; default: return array(); } $modifiers = array(); foreach ($modifier_list->selectDescendantsOfType('n_STRING') as $modifier) { $modifiers[strtolower($modifier->getConcreteString())] = true; } return $modifiers; }
/** * Parses meaning from calls to phutil_require_module() in __init__.php files. * * @group module */ function analyze_phutil_require_module(XHPASTNode $call, PhutilModuleRequirements $requirements, $create_dependency) { $name = $call->getChildByIndex(0); $params = $call->getChildByIndex(1)->getChildren(); if (count($params) !== 2) { $requirements->addLint($call, $call->getConcreteString(), ArcanistPhutilModuleLinter::LINT_ANALYZER_SIGNATURE, "Call to phutil_require_module() must have exactly two arguments."); return; } $module_param = array_pop($params); $library_param = array_pop($params); $library_value = $library_param->getStringLiteralValue(); if ($library_value === null) { $requirements->addLint($library_param, $library_param->getConcreteString(), ArcanistPhutilModuleLinter::LINT_ANALYZER_SIGNATURE, "phutil_require_module() parameters must be string literals."); return; } $module_value = $module_param->getStringLiteralValue(); if ($module_value === null) { $requirements->addLint($module_param, $module_param->getConcreteString(), ArcanistPhutilModuleLinter::LINT_ANALYZER_SIGNATURE, "phutil_require_module() parameters must be string literals."); return; } if ($create_dependency) { $requirements->addModuleDependency($name, $library_value . ':' . $module_value); } }
private function parseReturnType(DivinerAtom $atom, XHPASTNode $decl) { $return_spec = array(); $metadata = $atom->getDocblockMeta(); $return = idx($metadata, 'return'); $type = null; $docs = null; if (!$return) { $return = idx($metadata, 'returns'); if ($return) { $atom->addWarning(pht('Documentation uses `%s`, but should use `%s`.', '@returns', '@return')); } } $return = (array) $return; if (count($return) > 1) { $atom->addWarning(pht('Documentation specifies `%s` multiple times.', '@return')); } $return = head($return); if ($atom->getName() == '__construct' && $atom->getType() == 'method') { $return_spec = array('doctype' => 'this', 'docs' => '//Implicit.//'); if ($return) { $atom->addWarning(pht('Method `%s` has explicitly documented `%s`. The `%s` method ' . 'always returns `%s`. Diviner documents this implicitly.', '__construct()', '@return', '__construct()', '$this')); } } else { if ($return) { $split = preg_split('/(?<!,)\\s+/', trim($return), 2); if (!empty($split[0])) { $type = $split[0]; } if ($decl->getChildByIndex(1)->getTypeName() == 'n_REFERENCE') { $type = $type . ' &'; } if (!empty($split[1])) { $docs = $split[1]; } $return_spec = array('doctype' => $type, 'docs' => $docs); } else { $return_spec = array('type' => 'wild'); } } $atom->setProperty('return', $return_spec); }
private function parseReturnType(DivinerAtom $atom, XHPASTNode $decl) { $return_spec = array(); $metadata = $atom->getDocblockMeta(); $return = idx($metadata, 'return'); if (!$return) { $return = idx($metadata, 'returns'); if ($return) { $atom->addWarning(pht('Documentation uses `@returns`, but should use `@return`.')); } } if ($atom->getName() == '__construct' && $atom->getType() == 'method') { $return_spec = array('doctype' => 'this', 'docs' => '//Implicit.//'); if ($return) { $atom->addWarning('Method __construct() has explicitly documented @return. The ' . '__construct() method always returns $this. Diviner documents ' . 'this implicitly.'); } } else { if ($return) { $split = preg_split('/\\s+/', trim($return), $limit = 2); if (!empty($split[0])) { $type = $split[0]; } if ($decl->getChildByIndex(1)->getTypeName() == 'n_REFERENCE') { $type = $type . ' &'; } $docs = null; if (!empty($split[1])) { $docs = $split[1]; } $return_spec = array('doctype' => $type, 'docs' => $docs); } else { $return_spec = array('type' => 'wild'); } } $atom->setProperty('return', $return_spec); }