本文整理汇总了PHP中XHPASTNode::selectDescendantsOfTypes方法的典型用法代码示例。如果您正苦于以下问题:PHP XHPASTNode::selectDescendantsOfTypes方法的具体用法?PHP XHPASTNode::selectDescendantsOfTypes怎么用?PHP XHPASTNode::selectDescendantsOfTypes使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类XHPASTNode
的用法示例。
在下文中一共展示了XHPASTNode::selectDescendantsOfTypes方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: process
public function process(XHPASTNode $root)
{
$calls = $root->selectDescendantsOfTypes(array('n_FUNCTION_CALL', 'n_METHOD_CALL'));
foreach ($calls as $call) {
$params = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
$tokens = $params->getTokens();
$first = head($tokens);
$leading = $first->getNonsemanticTokensBefore();
$leading_text = implode('', mpull($leading, 'getValue'));
if (preg_match('/^\\s+$/', $leading_text)) {
$this->raiseLintAtOffset($first->getOffset() - strlen($leading_text), pht('Convention: no spaces before opening parenthesis in calls.'), $leading_text, '');
}
}
foreach ($calls as $call) {
// If the last parameter of a call is a HEREDOC, don't apply this rule.
$params = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST')->getChildren();
if ($params) {
$last_param = last($params);
if ($last_param->getTypeName() === 'n_HEREDOC') {
continue;
}
}
$tokens = $call->getTokens();
$last = array_pop($tokens);
$trailing = $last->getNonsemanticTokensBefore();
$trailing_text = implode('', mpull($trailing, 'getValue'));
if (preg_match('/^\\s+$/', $trailing_text)) {
$this->raiseLintAtOffset($last->getOffset() - strlen($trailing_text), pht('Convention: no spaces before closing parenthesis in calls.'), $trailing_text, '');
}
}
}
示例2: process
public function process(XHPASTNode $root)
{
$all_paren_groups = $root->selectDescendantsOfTypes(array('n_ARRAY_VALUE_LIST', 'n_ASSIGNMENT_LIST', 'n_CALL_PARAMETER_LIST', 'n_DECLARATION_PARAMETER_LIST', 'n_CONTROL_CONDITION', 'n_FOR_EXPRESSION', 'n_FOREACH_EXPRESSION'));
foreach ($all_paren_groups as $group) {
$tokens = $group->getTokens();
$token_o = array_shift($tokens);
$token_c = array_pop($tokens);
$nonsem_o = $token_o->getNonsemanticTokensAfter();
$nonsem_c = $token_c->getNonsemanticTokensBefore();
if (!$nonsem_o) {
continue;
}
$raise = array();
$string_o = implode('', mpull($nonsem_o, 'getValue'));
if (preg_match('/^[ ]+$/', $string_o)) {
$raise[] = array($nonsem_o, $string_o);
}
if ($nonsem_o !== $nonsem_c) {
$string_c = implode('', mpull($nonsem_c, 'getValue'));
if (preg_match('/^[ ]+$/', $string_c)) {
$raise[] = array($nonsem_c, $string_c);
}
}
foreach ($raise as $warning) {
list($tokens, $string) = $warning;
$this->raiseLintAtOffset(reset($tokens)->getOffset(), pht('Parentheses should hug their contents.'), $string, '');
}
}
}
示例3: process
public function process(XHPASTNode $root)
{
foreach ($root->selectDescendantsOfType('n_STATEMENT_LIST') as $list) {
$tokens = $list->getTokens();
if (!$tokens || head($tokens)->getValue() != '{') {
continue;
}
list($before, $after) = $list->getSurroundingNonsemanticTokens();
if (!$before) {
$first = head($tokens);
// Only insert the space if we're after a closing parenthesis. If
// we're in a construct like "else{}", other rules will insert space
// after the 'else' correctly.
$prev = $first->getPrevToken();
if (!$prev || $prev->getValue() !== ')') {
continue;
}
$this->raiseLintAtToken($first, pht('Put opening braces on the same line as control statements and ' . 'declarations, with a single space before them.'), ' ' . $first->getValue());
} else {
if (count($before) === 1) {
$before = reset($before);
if ($before->getValue() !== ' ') {
$this->raiseLintAtToken($before, pht('Put opening braces on the same line as control statements and ' . 'declarations, with a single space before them.'), ' ');
}
}
}
}
$nodes = $root->selectDescendantsOfType('n_STATEMENT');
foreach ($nodes as $node) {
$parent = $node->getParentNode();
if (!$parent) {
continue;
}
$type = $parent->getTypeName();
if ($type != 'n_STATEMENT_LIST' && $type != 'n_DECLARE') {
$this->raiseLintAtNode($node, pht('Use braces to surround a statement block.'));
}
}
$nodes = $root->selectDescendantsOfTypes(array('n_DO_WHILE', 'n_ELSE', 'n_ELSEIF'));
foreach ($nodes as $list) {
$tokens = $list->getTokens();
if (!$tokens || last($tokens)->getValue() != '}') {
continue;
}
list($before, $after) = $list->getSurroundingNonsemanticTokens();
if (!$before) {
$first = last($tokens);
$this->raiseLintAtToken($first, pht('Put opening braces on the same line as control statements and ' . 'declarations, with a single space before them.'), ' ' . $first->getValue());
} else {
if (count($before) === 1) {
$before = reset($before);
if ($before->getValue() !== ' ') {
$this->raiseLintAtToken($before, pht('Put opening braces on the same line as control statements and ' . 'declarations, with a single space before them.'), ' ');
}
}
}
}
}
示例4: process
public function process(XHPASTNode $root)
{
$nodes = $root->selectDescendantsOfTypes(array('n_CONCATENATION_LIST', 'n_STRING_SCALAR'));
foreach ($nodes as $node) {
$strings = array();
if ($node->getTypeName() === 'n_CONCATENATION_LIST') {
$strings = $node->selectDescendantsOfType('n_STRING_SCALAR');
} else {
if ($node->getTypeName() === 'n_STRING_SCALAR') {
$strings = array($node);
if ($node->getParentNode()->getTypeName() === 'n_CONCATENATION_LIST') {
continue;
}
}
}
$valid = false;
$invalid_nodes = array();
$fixes = array();
foreach ($strings as $string) {
$concrete_string = $string->getConcreteString();
$single_quoted = $concrete_string[0] === "'";
$contents = substr($concrete_string, 1, -1);
// Double quoted strings are allowed when the string contains the
// following characters.
static $allowed_chars = array('\\n', '\\r', '\\t', '\\v', '\\e', '\\f', '\'', '\\0', '\\1', '\\2', '\\3', '\\4', '\\5', '\\6', '\\7', '\\x');
$contains_special_chars = false;
foreach ($allowed_chars as $allowed_char) {
if (strpos($contents, $allowed_char) !== false) {
$contains_special_chars = true;
}
}
if (!$string->isConstantString()) {
$valid = true;
} else {
if ($contains_special_chars && !$single_quoted) {
$valid = true;
} else {
if (!$contains_special_chars && !$single_quoted) {
$invalid_nodes[] = $string;
$fixes[$string->getID()] = "'" . str_replace('\\"', '"', $contents) . "'";
}
}
}
}
if (!$valid) {
foreach ($invalid_nodes as $invalid_node) {
$this->raiseLintAtNode($invalid_node, pht('String does not require double quotes. For consistency, ' . 'prefer single quotes.'), $fixes[$invalid_node->getID()]);
}
}
}
}
示例5: process
public function process(XHPASTNode $root)
{
$decs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($decs as $dec) {
$params = $dec->getChildOfType(3, 'n_DECLARATION_PARAMETER_LIST');
$tokens = $params->getTokens();
$last = array_pop($tokens);
$trailing = $last->getNonsemanticTokensBefore();
$trailing_text = implode('', mpull($trailing, 'getValue'));
if (preg_match('/^\\s+$/', $trailing_text)) {
$this->raiseLintAtOffset($last->getOffset() - strlen($trailing_text), pht('Convention: no spaces before closing parenthesis in ' . 'function and method declarations.'), $trailing_text, '');
}
}
}
开发者ID:sophie-nextdoor,项目名称:arcanist,代码行数:14,代码来源:ArcanistClosingDeclarationParenthesesXHPASTLinterRule.php
示例6: process
public function process(XHPASTNode $root)
{
$methods = $root->selectDescendantsOfTypes(array('n_CLASS_MEMBER_MODIFIER_LIST', 'n_METHOD_MODIFIER_LIST'));
foreach ($methods as $method) {
$modifiers = $method->getChildren();
$is_abstract = false;
$is_final = false;
$is_static = false;
$visibility = null;
foreach ($modifiers as $modifier) {
switch ($modifier->getConcreteString()) {
case 'abstract':
if ($method->getTypeName() == 'n_CLASS_MEMBER_MODIFIER_LIST') {
$this->raiseLintAtNode($modifier, pht('Properties cannot be declared %s.', 'abstract'));
}
if ($is_abstract) {
$this->raiseLintAtNode($modifier, pht('Multiple %s modifiers are not allowed.', 'abstract'));
}
if ($is_final) {
$this->raiseLintAtNode($modifier, pht('Cannot use the %s modifier on an %s class member', 'final', 'abstract'));
}
$is_abstract = true;
break;
case 'final':
if ($is_abstract) {
$this->raiseLintAtNode($modifier, pht('Cannot use the %s modifier on an %s class member', 'final', 'abstract'));
}
if ($is_final) {
$this->raiseLintAtNode($modifier, pht('Multiple %s modifiers are not allowed.', 'final'));
}
$is_final = true;
break;
case 'public':
case 'protected':
case 'private':
if ($visibility) {
$this->raiseLintAtNode($modifier, pht('Multiple access type modifiers are not allowed.'));
}
$visibility = $modifier->getConcreteString();
break;
case 'static':
if ($is_static) {
$this->raiseLintAtNode($modifier, pht('Multiple %s modifiers are not allowed.', 'static'));
}
break;
}
}
}
}
示例7: process
public function process(XHPASTNode $root)
{
$nodes = $root->selectDescendantsOfTypes(array('n_ARRAY_LITERAL', 'n_FUNCTION_CALL', 'n_METHOD_CALL', 'n_LIST'));
foreach ($nodes as $node) {
switch ($node->getTypeName()) {
case 'n_ARRAY_LITERAL':
if (head($node->getTokens())->getTypeName() == '[') {
// Short array syntax.
continue 2;
}
$params = $node->getChildOfType(0, 'n_ARRAY_VALUE_LIST');
break;
case 'n_FUNCTION_CALL':
case 'n_METHOD_CALL':
$params = $node->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
break;
case 'n_LIST':
$params = $node->getChildOfType(0, 'n_ASSIGNMENT_LIST');
break;
default:
throw new Exception(pht("Unexpected node of type '%s'!", $node->getTypeName()));
}
$tokens = $params->getTokens();
$first = head($tokens);
$leading = $first->getNonsemanticTokensBefore();
$leading_text = implode('', mpull($leading, 'getValue'));
if (preg_match('/^\\s+$/', $leading_text)) {
$this->raiseLintAtOffset($first->getOffset() - strlen($leading_text), pht('Convention: no spaces before opening parentheses.'), $leading_text, '');
}
// If the last parameter of a call is a HEREDOC, don't apply this rule.
$params = $params->getChildren();
if ($params) {
$last_param = last($params);
if ($last_param->getTypeName() === 'n_HEREDOC') {
continue;
}
}
$tokens = $node->getTokens();
$last = array_pop($tokens);
if ($node->getTypeName() == 'n_ARRAY_LITERAL') {
continue;
}
$trailing = $last->getNonsemanticTokensBefore();
$trailing_text = implode('', mpull($trailing, 'getValue'));
if (preg_match('/^\\s+$/', $trailing_text)) {
$this->raiseLintAtOffset($last->getOffset() - strlen($trailing_text), pht('Convention: no spaces before closing parentheses.'), $trailing_text, '');
}
}
}
示例8: process
public function process(XHPASTNode $root)
{
$nodes = $root->selectDescendantsOfTypes(array('n_INCLUDE_FILE', 'n_ECHO_LIST'));
foreach ($nodes as $node) {
$child = head($node->getChildren());
if ($child->getTypeName() === 'n_PARENTHETICAL_EXPRESSION') {
list($before, $after) = $child->getSurroundingNonsemanticTokens();
$replace = preg_replace('/^\\((.*)\\)$/', '$1', $child->getConcreteString());
if (!$before) {
$replace = ' ' . $replace;
}
$this->raiseLintAtNode($child, pht('Language constructs do not require parentheses.'), $replace);
}
}
}
示例9: process
public function process(XHPASTNode $root)
{
$decs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($decs as $dec) {
$params = $dec->getChildOfType(3, 'n_DECLARATION_PARAMETER_LIST');
$tokens = $params->getTokens();
$first = head($tokens);
$last = last($tokens);
$leading = $first->getNonsemanticTokensBefore();
$leading_text = implode('', mpull($leading, 'getValue'));
$trailing = $last->getNonsemanticTokensBefore();
$trailing_text = implode('', mpull($trailing, 'getValue'));
if ($dec->getChildByIndex(2)->getTypeName() == 'n_EMPTY') {
// Anonymous functions.
if ($leading_text != ' ') {
$this->raiseLintAtOffset($first->getOffset() - strlen($leading_text), pht('Convention: space before opening parenthesis in ' . 'anonymous function declarations.'), $leading_text, ' ');
}
} else {
if (preg_match('/^\\s+$/', $leading_text)) {
$this->raiseLintAtOffset($first->getOffset() - strlen($leading_text), pht('Convention: no spaces before opening parenthesis in ' . 'function and method declarations.'), $leading_text, '');
}
}
if (preg_match('/^\\s+$/', $trailing_text)) {
$this->raiseLintAtOffset($last->getOffset() - strlen($trailing_text), pht('Convention: no spaces before closing parenthesis in ' . 'function and method declarations.'), $trailing_text, '');
}
$use_list = $dec->getChildByIndex(4);
if ($use_list->getTypeName() == 'n_EMPTY') {
continue;
}
$use_token = $use_list->selectTokensOfType('T_USE');
foreach ($use_token as $use) {
$before = $use->getNonsemanticTokensBefore();
$after = $use->getNonsemanticTokensAfter();
if (!$before) {
$this->raiseLintAtOffset($use->getOffset(), pht('Convention: space before `%s` token.', 'use'), '', ' ');
}
if (!$after) {
$this->raiseLintAtOffset($use->getOffset() + strlen($use->getValue()), pht('Convention: space after `%s` token.', 'use'), '', ' ');
}
}
}
}
开发者ID:barcelonascience,项目名称:arcanist,代码行数:42,代码来源:ArcanistDeclarationParenthesesXHPASTLinterRule.php
示例10: process
public function process(XHPASTNode $root)
{
// These things declare variables in a function:
// Explicit parameters
// Assignment
// Assignment via list()
// Static
// Global
// Lexical vars
// Builtins ($this)
// foreach()
// catch
//
// These things make lexical scope unknowable:
// Use of extract()
// Assignment to variable variables ($$x)
// Global with variable variables
//
// These things don't count as "using" a variable:
// isset()
// empty()
// Static class variables
//
// The general approach here is to find each function/method declaration,
// then:
//
// 1. Identify all the variable declarations, and where they first occur
// in the function/method declaration.
// 2. Identify all the uses that don't really count (as above).
// 3. Everything else must be a use of a variable.
// 4. For each variable, check if any uses occur before the declaration
// and warn about them.
//
// We also keep track of where lexical scope becomes unknowable (e.g.,
// because the function calls extract() or uses dynamic variables,
// preventing us from keeping track of which variables are defined) so we
// can stop issuing warnings after that.
//
// TODO: Support functions defined inside other functions which is commonly
// used with anonymous functions.
$defs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($defs as $def) {
// We keep track of the first offset where scope becomes unknowable, and
// silence any warnings after that. Default it to INT_MAX so we can min()
// it later to keep track of the first problem we encounter.
$scope_destroyed_at = PHP_INT_MAX;
$declarations = array('$this' => 0) + array_fill_keys($this->getSuperGlobalNames(), 0);
$declaration_tokens = array();
$exclude_tokens = array();
$vars = array();
// First up, find all the different kinds of declarations, as explained
// above. Put the tokens into the $vars array.
$param_list = $def->getChildOfType(3, 'n_DECLARATION_PARAMETER_LIST');
$param_vars = $param_list->selectDescendantsOfType('n_VARIABLE');
foreach ($param_vars as $var) {
$vars[] = $var;
}
// This is PHP5.3 closure syntax: function () use ($x) {};
$lexical_vars = $def->getChildByIndex(4)->selectDescendantsOfType('n_VARIABLE');
foreach ($lexical_vars as $var) {
$vars[] = $var;
}
$body = $def->getChildByIndex(5);
if ($body->getTypeName() === 'n_EMPTY') {
// Abstract method declaration.
continue;
}
$static_vars = $body->selectDescendantsOfType('n_STATIC_DECLARATION')->selectDescendantsOfType('n_VARIABLE');
foreach ($static_vars as $var) {
$vars[] = $var;
}
$global_vars = $body->selectDescendantsOfType('n_GLOBAL_DECLARATION_LIST');
foreach ($global_vars as $var_list) {
foreach ($var_list->getChildren() as $var) {
if ($var->getTypeName() === 'n_VARIABLE') {
$vars[] = $var;
} else {
// Dynamic global variable, i.e. "global $$x;".
$scope_destroyed_at = min($scope_destroyed_at, $var->getOffset());
// An error is raised elsewhere, no need to raise here.
}
}
}
// Include "catch (Exception $ex)", but not variables in the body of the
// catch block.
$catches = $body->selectDescendantsOfType('n_CATCH');
foreach ($catches as $catch) {
$vars[] = $catch->getChildOfType(1, 'n_VARIABLE');
}
$binary = $body->selectDescendantsOfType('n_BINARY_EXPRESSION');
foreach ($binary as $expr) {
if ($expr->getChildByIndex(1)->getConcreteString() !== '=') {
continue;
}
$lval = $expr->getChildByIndex(0);
if ($lval->getTypeName() === 'n_VARIABLE') {
$vars[] = $lval;
} else {
if ($lval->getTypeName() === 'n_LIST') {
// Recursively grab everything out of list(), since the grammar
//.........这里部分代码省略.........
示例11: lintPHP54Incompatibilities
private function lintPHP54Incompatibilities(XHPASTNode $root)
{
$breaks = $root->selectDescendantsOfTypes(array('n_BREAK', 'n_CONTINUE'));
foreach ($breaks as $break) {
$arg = $break->getChildByIndex(0);
switch ($arg->getTypeName()) {
case 'n_EMPTY':
break;
case 'n_NUMERIC_SCALAR':
if ($arg->getConcreteString() != '0') {
break;
}
default:
$this->raiseLintAtNode($break->getChildByIndex(0), pht('The `%s` and `%s` statements no longer accept ' . 'variable arguments.', 'break', 'continue'));
break;
}
}
}
示例12: process
public function process(XHPASTNode $root)
{
$defs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($defs as $def) {
$body = $def->getChildByIndex(6);
if ($body->getTypeName() === 'n_EMPTY') {
// Abstract method declaration.
continue;
}
$exclude = array();
// Exclude uses of variables, unsets, and foreach loops
// within closures - they are checked on their own
$func_defs = $body->selectDescendantsOfType('n_FUNCTION_DECLARATION');
foreach ($func_defs as $func_def) {
$vars = $func_def->selectDescendantsOfType('n_VARIABLE');
foreach ($vars as $var) {
$exclude[$var->getID()] = true;
}
$unset_lists = $func_def->selectDescendantsOfType('n_UNSET_LIST');
foreach ($unset_lists as $unset_list) {
$exclude[$unset_list->getID()] = true;
}
$foreaches = $func_def->selectDescendantsOfType('n_FOREACH');
foreach ($foreaches as $foreach) {
$exclude[$foreach->getID()] = true;
}
}
// Find all variables that are unset within the scope
$unset_vars = array();
$unset_lists = $body->selectDescendantsOfType('n_UNSET_LIST');
foreach ($unset_lists as $unset_list) {
if (isset($exclude[$unset_list->getID()])) {
continue;
}
$unset_list_vars = $unset_list->selectDescendantsOfType('n_VARIABLE');
foreach ($unset_list_vars as $var) {
$concrete = $this->getConcreteVariableString($var);
$unset_vars[$concrete][] = $var->getOffset();
$exclude[$var->getID()] = true;
}
}
// Find all reference variables in foreach expressions
$reference_vars = array();
$foreaches = $body->selectDescendantsOfType('n_FOREACH');
foreach ($foreaches as $foreach) {
if (isset($exclude[$foreach->getID()])) {
continue;
}
$foreach_expr = $foreach->getChildOfType(0, 'n_FOREACH_EXPRESSION');
$var = $foreach_expr->getChildByIndex(2);
if ($var->getTypeName() !== 'n_VARIABLE_REFERENCE') {
continue;
}
$reference = $var->getChildByIndex(0);
if ($reference->getTypeName() !== 'n_VARIABLE') {
continue;
}
$reference_name = $this->getConcreteVariableString($reference);
$reference_vars[$reference_name][] = $reference->getOffset();
$exclude[$reference->getID()] = true;
// Exclude uses of the reference variable within the foreach loop
$foreach_vars = $foreach->selectDescendantsOfType('n_VARIABLE');
foreach ($foreach_vars as $var) {
$name = $this->getConcreteVariableString($var);
if ($name === $reference_name) {
$exclude[$var->getID()] = true;
}
}
}
// Allow usage if the reference variable is assigned to another
// reference variable
$binary = $body->selectDescendantsOfType('n_BINARY_EXPRESSION');
foreach ($binary as $expr) {
if ($expr->getChildByIndex(1)->getConcreteString() !== '=') {
continue;
}
$lval = $expr->getChildByIndex(0);
if ($lval->getTypeName() !== 'n_VARIABLE') {
continue;
}
$rval = $expr->getChildByIndex(2);
if ($rval->getTypeName() !== 'n_VARIABLE_REFERENCE') {
continue;
}
// Counts as unsetting a variable
$concrete = $this->getConcreteVariableString($lval);
$unset_vars[$concrete][] = $lval->getOffset();
$exclude[$lval->getID()] = true;
}
$all_vars = array();
$all = $body->selectDescendantsOfType('n_VARIABLE');
foreach ($all as $var) {
if (isset($exclude[$var->getID()])) {
continue;
}
$name = $this->getConcreteVariableString($var);
if (!isset($reference_vars[$name])) {
continue;
}
// Find the closest reference offset to this variable
//.........这里部分代码省略.........
示例13: process
public function process(XHPASTNode $root)
{
// We're going to build up a list of <type, name, token, error> tuples
// and then try to instantiate a hook class which has the opportunity to
// override us.
$names = array();
$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
foreach ($classes as $class) {
$name_token = $class->getChildByIndex(1);
$name_string = $name_token->getConcreteString();
$names[] = array('class', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isUpperCamelCase($name_string) ? null : pht('Follow naming conventions: classes should be named using `%s`.', 'UpperCamelCase'));
}
$ifaces = $root->selectDescendantsOfType('n_INTERFACE_DECLARATION');
foreach ($ifaces as $iface) {
$name_token = $iface->getChildByIndex(1);
$name_string = $name_token->getConcreteString();
$names[] = array('interface', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isUpperCamelCase($name_string) ? null : pht('Follow naming conventions: interfaces should be named using `%s`.', 'UpperCamelCase'));
}
$functions = $root->selectDescendantsOfType('n_FUNCTION_DECLARATION');
foreach ($functions as $function) {
$name_token = $function->getChildByIndex(2);
if ($name_token->getTypeName() === 'n_EMPTY') {
// Unnamed closure.
continue;
}
$name_string = $name_token->getConcreteString();
$names[] = array('function', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isLowercaseWithUnderscores(ArcanistXHPASTLintNamingHook::stripPHPFunction($name_string)) ? null : pht('Follow naming conventions: functions should be named using `%s`.', 'lowercase_with_underscores'));
}
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$name_token = $method->getChildByIndex(2);
$name_string = $name_token->getConcreteString();
$names[] = array('method', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isLowerCamelCase(ArcanistXHPASTLintNamingHook::stripPHPFunction($name_string)) ? null : pht('Follow naming conventions: methods should be named using `%s`.', 'lowerCamelCase'));
}
$param_tokens = array();
$params = $root->selectDescendantsOfType('n_DECLARATION_PARAMETER_LIST');
foreach ($params as $param_list) {
foreach ($param_list->getChildren() as $param) {
$name_token = $param->getChildByIndex(1);
if ($name_token->getTypeName() === 'n_VARIABLE_REFERENCE') {
$name_token = $name_token->getChildOfType(0, 'n_VARIABLE');
}
$param_tokens[$name_token->getID()] = true;
$name_string = $name_token->getConcreteString();
$names[] = array('parameter', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isLowercaseWithUnderscores(ArcanistXHPASTLintNamingHook::stripPHPVariable($name_string)) ? null : pht('Follow naming conventions: parameters ' . 'should be named using `%s`', 'lowercase_with_underscores'));
}
}
$constants = $root->selectDescendantsOfType('n_CLASS_CONSTANT_DECLARATION_LIST');
foreach ($constants as $constant_list) {
foreach ($constant_list->getChildren() as $constant) {
$name_token = $constant->getChildByIndex(0);
$name_string = $name_token->getConcreteString();
$names[] = array('constant', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isUppercaseWithUnderscores($name_string) ? null : pht('Follow naming conventions: class constants ' . 'should be named using `%s`', 'UPPERCASE_WITH_UNDERSCORES'));
}
}
$member_tokens = array();
$props = $root->selectDescendantsOfType('n_CLASS_MEMBER_DECLARATION_LIST');
foreach ($props as $prop_list) {
foreach ($prop_list->getChildren() as $token_id => $prop) {
if ($prop->getTypeName() === 'n_CLASS_MEMBER_MODIFIER_LIST') {
continue;
}
$name_token = $prop->getChildByIndex(0);
$member_tokens[$name_token->getID()] = true;
$name_string = $name_token->getConcreteString();
$names[] = array('member', $name_string, $name_token, ArcanistXHPASTLintNamingHook::isLowerCamelCase(ArcanistXHPASTLintNamingHook::stripPHPVariable($name_string)) ? null : pht('Follow naming conventions: class properties ' . 'should be named using `%s`.', 'lowerCamelCase'));
}
}
$superglobal_map = array_fill_keys($this->getSuperGlobalNames(), true);
$defs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($defs as $def) {
$globals = $def->selectDescendantsOfType('n_GLOBAL_DECLARATION_LIST');
$globals = $globals->selectDescendantsOfType('n_VARIABLE');
$globals_map = array();
foreach ($globals as $global) {
$global_string = $global->getConcreteString();
$globals_map[$global_string] = true;
$names[] = array('user', $global_string, $global, null);
}
// Exclude access of static properties, since lint will be raised at
// their declaration if they're invalid and they may not conform to
// variable rules. This is slightly overbroad (includes the entire
// RHS of a "Class::..." token) to cover cases like "Class:$x[0]". These
// variables are simply made exempt from naming conventions.
$exclude_tokens = array();
$statics = $def->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
foreach ($statics as $static) {
$rhs = $static->getChildByIndex(1);
if ($rhs->getTypeName() == 'n_VARIABLE') {
$exclude_tokens[$rhs->getID()] = true;
} else {
$rhs_vars = $rhs->selectDescendantsOfType('n_VARIABLE');
foreach ($rhs_vars as $var) {
$exclude_tokens[$var->getID()] = true;
}
}
}
$vars = $def->selectDescendantsOfType('n_VARIABLE');
foreach ($vars as $token_id => $var) {
if (isset($member_tokens[$token_id])) {
//.........这里部分代码省略.........
示例14: process
public function process(XHPASTNode $root)
{
$defs = $root->selectDescendantsOfTypes(array('n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION'));
foreach ($defs as $def) {
// We keep track of the first offset where scope becomes unknowable, and
// silence any warnings after that. Default it to INT_MAX so we can min()
// it later to keep track of the first problem we encounter.
$scope_destroyed_at = PHP_INT_MAX;
$declarations = array('$this' => 0) + array_fill_keys($this->getSuperGlobalNames(), 0);
$declaration_tokens = array();
$exclude_tokens = array();
$vars = array();
// First up, find all the different kinds of declarations, as explained
// above. Put the tokens into the $vars array.
$param_list = $def->getChildOfType(3, 'n_DECLARATION_PARAMETER_LIST');
$param_vars = $param_list->selectDescendantsOfType('n_VARIABLE');
foreach ($param_vars as $var) {
$vars[] = $var;
}
// This is PHP5.3 closure syntax: function () use ($x) {};
$lexical_vars = $def->getChildByIndex(4)->selectDescendantsOfType('n_VARIABLE');
foreach ($lexical_vars as $var) {
$vars[] = $var;
}
$body = $def->getChildByIndex(5);
if ($body->getTypeName() === 'n_EMPTY') {
// Abstract method declaration.
continue;
}
$static_vars = $body->selectDescendantsOfType('n_STATIC_DECLARATION')->selectDescendantsOfType('n_VARIABLE');
foreach ($static_vars as $var) {
$vars[] = $var;
}
$global_vars = $body->selectDescendantsOfType('n_GLOBAL_DECLARATION_LIST');
foreach ($global_vars as $var_list) {
foreach ($var_list->getChildren() as $var) {
if ($var->getTypeName() === 'n_VARIABLE') {
$vars[] = $var;
} else {
// Dynamic global variable, i.e. "global $$x;".
$scope_destroyed_at = min($scope_destroyed_at, $var->getOffset());
// An error is raised elsewhere, no need to raise here.
}
}
}
// Include "catch (Exception $ex)", but not variables in the body of the
// catch block.
$catches = $body->selectDescendantsOfType('n_CATCH');
foreach ($catches as $catch) {
$vars[] = $catch->getChildOfType(1, 'n_VARIABLE');
}
$binary = $body->selectDescendantsOfType('n_BINARY_EXPRESSION');
foreach ($binary as $expr) {
if ($expr->getChildByIndex(1)->getConcreteString() !== '=') {
continue;
}
$lval = $expr->getChildByIndex(0);
if ($lval->getTypeName() === 'n_VARIABLE') {
$vars[] = $lval;
} else {
if ($lval->getTypeName() === 'n_LIST') {
// Recursivey grab everything out of list(), since the grammar
// permits list() to be nested. Also note that list() is ONLY valid
// as an lval assignments, so we could safely lift this out of the
// n_BINARY_EXPRESSION branch.
$assign_vars = $lval->selectDescendantsOfType('n_VARIABLE');
foreach ($assign_vars as $var) {
$vars[] = $var;
}
}
}
if ($lval->getTypeName() === 'n_VARIABLE_VARIABLE') {
$scope_destroyed_at = min($scope_destroyed_at, $lval->getOffset());
// No need to raise here since we raise an error elsewhere.
}
}
$calls = $body->selectDescendantsOfType('n_FUNCTION_CALL');
foreach ($calls as $call) {
$name = strtolower($call->getChildByIndex(0)->getConcreteString());
if ($name === 'empty' || $name === 'isset') {
$params = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST')->selectDescendantsOfType('n_VARIABLE');
foreach ($params as $var) {
$exclude_tokens[$var->getID()] = true;
}
continue;
}
if ($name !== 'extract') {
continue;
}
$scope_destroyed_at = min($scope_destroyed_at, $call->getOffset());
}
// Now we have every declaration except foreach(), handled below. Build
// two maps, one which just keeps track of which tokens are part of
// declarations ($declaration_tokens) and one which has the first offset
// where a variable is declared ($declarations).
foreach ($vars as $var) {
$concrete = $this->getConcreteVariableString($var);
$declarations[$concrete] = min(idx($declarations, $concrete, PHP_INT_MAX), $var->getOffset());
$declaration_tokens[$var->getID()] = true;
}
//.........这里部分代码省略.........