diff --git a/src/lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php index 659bd30b..8d500c29 100644 --- a/src/lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php @@ -1,44 +1,44 @@ getFunctionCalls($root, array('array_combine')); foreach ($function_calls as $call) { $name = $call->getChildByIndex(0)->getConcreteString(); $parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); if (count($parameter_list->getChildren()) !== 2) { // Wrong number of parameters, but raise that elsewhere if we want. continue; } $first = $parameter_list->getChildByIndex(0); $second = $parameter_list->getChildByIndex(1); if ($first->getConcreteString() == $second->getConcreteString()) { $this->raiseLintAtNode( $call, pht( 'Prior to PHP 5.4, `%s` fails when given empty arrays. '. 'Prefer to write `%s` as `%s`.', 'array_combine()', - 'array_combine(x, x)', - 'array_fuse(x)')); + 'array_combine($x, $x)', + 'array_fuse($x)')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php index d712b3fe..c24dbc6c 100644 --- a/src/lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php @@ -1,40 +1,40 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { // TODO: This doesn't quite work for namespaced classes (see T8534). $name = $class->getChildOfType(1, 'n_CLASS_NAME'); $extends = $class->getChildByIndex(2); if ($name->getConcreteString() == 'Phobject') { continue; } if ($extends->getTypeName() == 'n_EMPTY') { $this->raiseLintAtNode( $class, pht( - 'Classes should extend from %s or from some other class. '. - 'All classes (except for %s itself) should have a base class.', + 'Classes should extend from `%s` or from some other class. '. + 'All classes (except for `%s` itself) should have a base class.', 'Phobject', 'Phobject')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php index 5b91f3ca..6c8c2f41 100644 --- a/src/lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php @@ -1,54 +1,54 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); $interfaces = $root->selectDescendantsOfType('n_INTERFACE_DECLARATION'); if (count($classes) + count($interfaces) !== 1) { return; } $declarations = count($classes) ? $classes : $interfaces; $declarations->rewind(); $declaration = $declarations->current(); $decl_name = $declaration->getChildByIndex(1); $decl_string = $decl_name->getConcreteString(); // Exclude strangely named classes, e.g. XHP tags. if (!preg_match('/^\w+$/', $decl_string)) { return; } $rename = $decl_string.'.php'; $path = $this->getActivePath(); $filename = basename($path); if ($rename === $filename) { return; } $this->raiseLintAtNode( $decl_name, pht( "The name of this file differs from the name of the ". - "class or interface it declares. Rename the file to '%s'.", + 'class or interface it declares. Rename the file to `%s`.', $rename)); } } diff --git a/src/lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php index cfa0bf93..a22a9859 100644 --- a/src/lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php @@ -1,49 +1,49 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($class_declarations as $class_declaration) { $class_name = $class_declaration ->getChildOfType(1, 'n_CLASS_NAME') ->getConcreteString(); $strings = $class_declaration->selectDescendantsOfType('n_STRING_SCALAR'); foreach ($strings as $string) { $contents = substr($string->getSemanticString(), 1, -1); $replacement = null; if ($contents == $class_name) { $replacement = '__CLASS__'; } $regex = '/\b'.preg_quote($class_name, '/').'\b/'; if (!preg_match($regex, $contents)) { continue; } $this->raiseLintAtNode( $string, pht( - "Don't hard-code class names, use %s instead.", + "Don't hard-code class names, use `%s` instead.", '__CLASS__'), $replacement); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php index a5fe569c..3a493e2b 100644 --- a/src/lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php @@ -1,28 +1,31 @@ selectTokensOfType('T_COMMENT') as $comment) { $value = $comment->getValue(); if ($value[0] !== '#') { continue; } $this->raiseLintAtOffset( $comment->getOffset(), - pht('Use "%s" single-line comments, not "%s".', '//', '#'), + pht( + 'Use `%s` single-line comments, not `%s`.', + '//', + '#'), '#', preg_match('/^#\S/', $value) ? '// ' : '//'); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php index 6606b0b3..1f5de931 100644 --- a/src/lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php @@ -1,97 +1,101 @@ 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'), + pht( + 'Convention: space before `%s` token.', + 'use'), '', ' '); } if (!$after) { $this->raiseLintAtOffset( $use->getOffset() + strlen($use->getValue()), - pht('Convention: space after `%s` token.', 'use'), + pht( + 'Convention: space after `%s` token.', + 'use'), '', ' '); } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php index 4148df3b..be144625 100644 --- a/src/lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php @@ -1,29 +1,29 @@ getFunctionCalls($root, array('define')); foreach ($calls as $call) { $parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); $defined = $parameter_list->getChildByIndex(0); if (!$defined->isStaticScalar()) { $this->raiseLintAtNode( $defined, pht( - 'First argument to %s must be a string literal.', - 'define()')); + 'First argument to `%s` must be a string literal.', + 'define')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php index 986859f8..246e8048 100644 --- a/src/lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php @@ -1,27 +1,30 @@ selectTokensOfType('T_ELSEIF'); foreach ($tokens as $token) { $this->raiseLintAtToken( $token, - pht('Usage of `%s` is preferred over `%s`.', 'else if', 'elseif'), + pht( + 'Usage of `%s` is preferred over `%s`.', + 'else if', + 'elseif'), 'else if'); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php index 60ce126c..ceac22c3 100644 --- a/src/lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php @@ -1,43 +1,45 @@ selectDescendantsOfType('n_UNARY_PREFIX_EXPRESSION'); foreach ($unaries as $unary) { $operator = $unary->getChildByIndex(0)->getConcreteString(); if (strtolower($operator) === 'exit') { if ($unary->getParentNode()->getTypeName() !== 'n_STATEMENT') { $this->raiseLintAtNode( $unary, - pht('Use `%s` as a statement, not an expression.', 'exit')); + pht( + 'Use `%s` as a statement, not an expression.', + 'exit')); } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php index 88a655cc..1c6976de 100644 --- a/src/lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php @@ -1,24 +1,24 @@ getFunctionCalls($root, array('extract')); foreach ($calls as $call) { $this->raiseLintAtNode( $call, pht( - 'Avoid %s. It is confusing and hinders static analysis.', - 'extract()')); + 'Avoid `%s`. It is confusing and hinders static analysis.', + 'extract')); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistFormattedStringXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistFormattedStringXHPASTLinterRule.php index 2f25dccc..333d7ab1 100644 --- a/src/lint/linter/xhpast/rules/ArcanistFormattedStringXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistFormattedStringXHPASTLinterRule.php @@ -1,103 +1,103 @@ array( 'type' => 'optional map', 'help' => pht( - '%s-style functions which take a format string and list of values '. + '`%s`-style functions which take a format string and list of values '. 'as arguments. The value for the mapping is the start index of the '. 'function parameters (the index of the format string parameter).', 'printf()'), ), ); } public function setLinterConfigurationValue($key, $value) { switch ($key) { case 'xhpast.printf-functions': $this->printfFunctions = $value; return; default: return parent::setLinterConfigurationValue($key, $value); } } public function process(XHPASTNode $root) { static $functions = array( // Core PHP 'fprintf' => 1, 'printf' => 0, 'sprintf' => 0, 'vfprintf' => 1, // libphutil 'csprintf' => 0, 'execx' => 0, 'exec_manual' => 0, 'hgsprintf' => 0, 'hsprintf' => 0, 'jsprintf' => 0, 'pht' => 0, 'phutil_passthru' => 0, 'qsprintf' => 1, 'queryfx' => 1, 'queryfx_all' => 1, 'queryfx_one' => 1, 'vcsprintf' => 0, 'vqsprintf' => 1, ); $function_calls = $root->selectDescendantsOfType('n_FUNCTION_CALL'); foreach ($function_calls as $call) { $name = $call->getChildByIndex(0)->getConcreteString(); $name = strtolower($name); $start = idx($functions + $this->printfFunctions, $name); if ($start === null) { continue; } $parameters = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); $argc = count($parameters->getChildren()) - $start; if ($argc < 1) { $this->raiseLintAtNode( $call, pht('This function is expected to have a format string.')); continue; } $format = $parameters->getChildByIndex($start); if ($format->getTypeName() != 'n_STRING_SCALAR') { continue; } $argv = array($format->evalStatic()) + array_fill(0, $argc, null); try { xsprintf(null, null, $argv); } catch (BadFunctionCallException $ex) { $this->raiseLintAtNode( $call, str_replace('xsprintf', $name, $ex->getMessage())); } catch (InvalidArgumentException $ex) { // Ignore. } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistImplicitConstructorXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistImplicitConstructorXHPASTLinterRule.php index 466f74fe..cf3d567a 100644 --- a/src/lint/linter/xhpast/rules/ArcanistImplicitConstructorXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistImplicitConstructorXHPASTLinterRule.php @@ -1,35 +1,36 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { $class_name = $class->getChildByIndex(1)->getConcreteString(); $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); foreach ($methods as $method) { $method_name_token = $method->getChildByIndex(2); $method_name = $method_name_token->getConcreteString(); if (strtolower($class_name) === strtolower($method_name)) { $this->raiseLintAtNode( $method_name_token, pht( - 'Name constructors %s explicitly. This method is a constructor '. - ' because it has the same name as the class it is defined in.', - '__construct()')); + 'Name constructors `%s` explicitly. This method is a '. + 'constructor because it has the same name as the class '. + 'it is defined in.', + '__construct')); } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistImplicitFallthroughXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistImplicitFallthroughXHPASTLinterRule.php index 74c7d57b..1fe7a2a7 100644 --- a/src/lint/linter/xhpast/rules/ArcanistImplicitFallthroughXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistImplicitFallthroughXHPASTLinterRule.php @@ -1,210 +1,210 @@ array( 'type' => 'optional string', 'help' => pht( - 'Name of a concrete subclass of %s which tunes the '. - 'analysis of %s statements for this linter.', + 'Name of a concrete subclass of `%s` which tunes the '. + 'analysis of `%s` statements for this linter.', 'ArcanistXHPASTLintSwitchHook', - 'switch()'), + 'switch'), ), ); } public function setLinterConfigurationValue($key, $value) { switch ($key) { case 'xhpast.switchhook': $this->switchhook = $value; return; default: return parent::setLinterConfigurationValue($key, $value); } } public function process(XHPASTNode $root) { $hook_obj = null; $hook_class = $this->switchhook; if ($hook_class) { $hook_obj = newv($hook_class, array()); assert_instances_of(array($hook_obj), 'ArcanistXHPASTLintSwitchHook'); } $switches = $root->selectDescendantsOfType('n_SWITCH'); foreach ($switches as $switch) { $blocks = array(); $cases = $switch->selectDescendantsOfType('n_CASE'); foreach ($cases as $case) { $blocks[] = $case; } $defaults = $switch->selectDescendantsOfType('n_DEFAULT'); foreach ($defaults as $default) { $blocks[] = $default; } foreach ($blocks as $key => $block) { // Collect all the tokens in this block which aren't at top level. // We want to ignore "break", and "continue" in these blocks. $lower_level = $block->selectDescendantsOfTypes(array( 'n_WHILE', 'n_DO_WHILE', 'n_FOR', 'n_FOREACH', 'n_SWITCH', )); $lower_level_tokens = array(); foreach ($lower_level as $lower_level_block) { $lower_level_tokens += $lower_level_block->getTokens(); } // Collect all the tokens in this block which aren't in this scope // (because they're inside class, function or interface declarations). // We want to ignore all of these tokens. $decls = $block->selectDescendantsOfTypes(array( 'n_FUNCTION_DECLARATION', 'n_CLASS_DECLARATION', // For completeness; these can't actually have anything. 'n_INTERFACE_DECLARATION', )); $different_scope_tokens = array(); foreach ($decls as $decl) { $different_scope_tokens += $decl->getTokens(); } $lower_level_tokens += $different_scope_tokens; // Get all the trailing nonsemantic tokens, since we need to look for // "fallthrough" comments past the end of the semantic block. $tokens = $block->getTokens(); $last = end($tokens); while ($last && $last = $last->getNextToken()) { if ($last->isSemantic()) { break; } $tokens[$last->getTokenID()] = $last; } $blocks[$key] = array( $tokens, $lower_level_tokens, $different_scope_tokens, ); } foreach ($blocks as $token_lists) { list( $tokens, $lower_level_tokens, $different_scope_tokens) = $token_lists; // Test each block (case or default statement) to see if it's OK. It's // OK if: // // - it is empty; or // - it ends in break, return, throw, continue or exit at top level; or // - it has a comment with "fallthrough" in its text. // Empty blocks are OK, so we start this at `true` and only set it to // false if we find a statement. $block_ok = true; // Keeps track of whether the current statement is one that validates // the block (break, return, throw, continue) or something else. $statement_ok = false; foreach ($tokens as $token_id => $token) { if (!$token->isSemantic()) { // Liberally match "fall" in the comment text so that comments like // "fallthru", "fall through", "fallthrough", etc., are accepted. if (preg_match('/fall/i', $token->getValue())) { $block_ok = true; break; } continue; } $tok_type = $token->getTypeName(); if ($tok_type === 'T_FUNCTION' || $tok_type === 'T_CLASS' || $tok_type === 'T_INTERFACE') { // These aren't statements, but mark the block as nonempty anyway. $block_ok = false; continue; } if ($tok_type === ';') { if ($statement_ok) { $statment_ok = false; } else { $block_ok = false; } continue; } if ($tok_type === 'T_BREAK' || $tok_type === 'T_CONTINUE') { if (empty($lower_level_tokens[$token_id])) { $statement_ok = true; $block_ok = true; } continue; } if ($tok_type === 'T_RETURN' || $tok_type === 'T_THROW' || $tok_type === 'T_EXIT' || ($hook_obj && $hook_obj->checkSwitchToken($token))) { if (empty($different_scope_tokens[$token_id])) { $statement_ok = true; $block_ok = true; } continue; } } if (!$block_ok) { $this->raiseLintAtToken( head($tokens), pht( - "This '%s' or '%s' has a nonempty block which does not end ". - "with '%s', '%s', '%s', '%s' or '%s'. Did you forget to add ". - "one of those? If you intend to fall through, add a '%s' ". + 'This `%s` or `%s` has a nonempty block which does not end '. + 'with `%s`, `%s`, `%s`, `%s` or `%s`. Did you forget to add '. + 'one of those? If you intend to fall through, add a `%s` '. "comment to silence this warning.", 'case', 'default', 'break', 'continue', 'return', 'throw', 'exit', '// fallthrough')); } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php index 519d5645..47cb9ab5 100644 --- a/src/lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php @@ -1,35 +1,35 @@ selectDescendantsOfType('n_BINARY_EXPRESSION'); foreach ($expressions as $expression) { $operator = $expression->getChildOfType(1, 'n_OPERATOR'); if (strtolower($operator->getConcreteString()) != 'instanceof') { continue; } $object = $expression->getChildByIndex(0); if ($object->isStaticScalar() || $object->getTypeName() == 'n_SYMBOL_NAME') { $this->raiseLintAtNode( $object, pht( - '%s expects an object instance, constant given.', + '`%s` expects an object instance, constant given.', 'instanceof')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php index 12bdcf17..482fb396 100644 --- a/src/lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php @@ -1,79 +1,80 @@ selectDescendantsOfType('n_DECLARATION_PARAMETER'); foreach ($parameters as $parameter) { $type = $parameter->getChildByIndex(0); $default = $parameter->getChildByIndex(2); if ($type->getTypeName() == 'n_EMPTY') { continue; } if ($default->getTypeName() == 'n_EMPTY') { continue; } $default_is_null = $default->getTypeName() == 'n_SYMBOL_NAME' && strtolower($default->getConcreteString()) == 'null'; switch (strtolower($type->getConcreteString())) { case 'array': if ($default->getTypeName() == 'n_ARRAY_LITERAL') { break; } if ($default_is_null) { break; } $this->raiseLintAtNode( $default, pht( - 'Default value for parameters with %s type hint '. - 'can only be an %s or %s.', + 'Default value for parameters with `%s` type hint '. + 'can only be an `%s` or `%s`.', 'array', 'array', 'null')); break; case 'callable': if ($default_is_null) { break; } $this->raiseLintAtNode( $default, pht( - 'Default value for parameters with %s type hint can only be %s.', + 'Default value for parameters with `%s` type hint '. + 'can only be `%s`.', 'callable', 'null')); break; default: // Class/interface parameter. if ($default_is_null) { break; } $this->raiseLintAtNode( $default, pht( 'Default value for parameters with a class type hint '. - 'can only be %s.', + 'can only be `%s`.', 'null')); break; } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php index e8c87a3a..c1e6cc6f 100644 --- a/src/lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php @@ -1,103 +1,103 @@ 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.', + 'Properties cannot be declared `%s`.', 'abstract')); } if ($is_abstract) { $this->raiseLintAtNode( $modifier, pht( - 'Multiple %s modifiers are not allowed.', + 'Multiple `%s` modifiers are not allowed.', 'abstract')); } if ($is_final) { $this->raiseLintAtNode( $modifier, pht( - 'Cannot use the %s modifier on an %s class member', + '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', + '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.', + '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.', + 'Multiple `%s` modifiers are not allowed.', 'static')); } break; } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistKeywordCasingXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistKeywordCasingXHPASTLinterRule.php index bc7c6bb6..af0b5903 100644 --- a/src/lint/linter/xhpast/rules/ArcanistKeywordCasingXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistKeywordCasingXHPASTLinterRule.php @@ -1,149 +1,149 @@ selectTokensOfTypes(array( 'T_REQUIRE_ONCE', 'T_REQUIRE', 'T_EVAL', 'T_INCLUDE_ONCE', 'T_INCLUDE', 'T_LOGICAL_OR', 'T_LOGICAL_XOR', 'T_LOGICAL_AND', 'T_PRINT', 'T_INSTANCEOF', 'T_CLONE', 'T_NEW', 'T_EXIT', 'T_IF', 'T_ELSEIF', 'T_ELSE', 'T_ENDIF', 'T_ECHO', 'T_DO', 'T_WHILE', 'T_ENDWHILE', 'T_FOR', 'T_ENDFOR', 'T_FOREACH', 'T_ENDFOREACH', 'T_DECLARE', 'T_ENDDECLARE', 'T_AS', 'T_SWITCH', 'T_ENDSWITCH', 'T_CASE', 'T_DEFAULT', 'T_BREAK', 'T_CONTINUE', 'T_GOTO', 'T_FUNCTION', 'T_CONST', 'T_RETURN', 'T_TRY', 'T_CATCH', 'T_THROW', 'T_USE', 'T_GLOBAL', 'T_PUBLIC', 'T_PROTECTED', 'T_PRIVATE', 'T_FINAL', 'T_ABSTRACT', 'T_STATIC', 'T_VAR', 'T_UNSET', 'T_ISSET', 'T_EMPTY', 'T_HALT_COMPILER', 'T_CLASS', 'T_INTERFACE', 'T_EXTENDS', 'T_IMPLEMENTS', 'T_LIST', 'T_ARRAY', 'T_NAMESPACE', 'T_INSTEADOF', 'T_CALLABLE', 'T_TRAIT', 'T_YIELD', 'T_FINALLY', )); foreach ($keywords as $keyword) { $value = $keyword->getValue(); if ($value != strtolower($value)) { $this->raiseLintAtToken( $keyword, pht( - "Convention: spell keyword '%s' as '%s'.", + 'Convention: spell keyword `%s` as `%s`.', $value, strtolower($value)), strtolower($value)); } } $symbols = $root->selectDescendantsOfType('n_SYMBOL_NAME'); foreach ($symbols as $symbol) { static $interesting_symbols = array( 'false' => true, 'null' => true, 'true' => true, ); $symbol_name = $symbol->getConcreteString(); if ($symbol->getParentNode()->getTypeName() == 'n_FUNCTION_CALL') { continue; } if (idx($interesting_symbols, strtolower($symbol_name))) { if ($symbol_name != strtolower($symbol_name)) { $this->raiseLintAtNode( $symbol, pht( - "Convention: spell keyword '%s' as '%s'.", + 'Convention: spell keyword `%s` as `%s`.', $symbol_name, strtolower($symbol_name)), strtolower($symbol_name)); } } } $magic_constants = $root->selectTokensOfTypes(array( 'T_CLASS_C', 'T_METHOD_C', 'T_FUNC_C', 'T_LINE', 'T_FILE', 'T_NS_C', 'T_DIR', 'T_TRAIT_C', )); foreach ($magic_constants as $magic_constant) { $value = $magic_constant->getValue(); if ($value != strtoupper($value)) { $this->raiseLintAtToken( $magic_constant, pht('Magic constants should be uppercase.'), strtoupper($value)); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistLambdaFuncFunctionXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistLambdaFuncFunctionXHPASTLinterRule.php index 34be9baf..2ddeb722 100644 --- a/src/lint/linter/xhpast/rules/ArcanistLambdaFuncFunctionXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistLambdaFuncFunctionXHPASTLinterRule.php @@ -1,43 +1,43 @@ selectDescendantsOfType('n_FUNCTION_DECLARATION'); foreach ($function_declarations as $function_declaration) { $function_name = $function_declaration->getChildByIndex(2); if ($function_name->getTypeName() == 'n_EMPTY') { // Anonymous closure. continue; } if ($function_name->getConcreteString() != '__lambda_func') { continue; } $this->raiseLintAtNode( $function_declaration, pht( - 'Declaring a function named %s causes any call to %s to fail. '. - 'This is because %s eval-declares the function %s, then '. + 'Declaring a function named `%s` causes any call to %s to fail. '. + 'This is because `%s` eval-declares the function `%s`, then '. 'modifies the symbol table so that the function is instead '. - 'named %s, and returns that name.', + 'named `%s`, and returns that name.', '__lambda_func', 'create_function', 'create_function', '__lambda_func', '"\0lambda_".(++$i)')); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php index 24852abf..3d00ed08 100644 --- a/src/lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php @@ -1,349 +1,353 @@ array( 'type' => 'optional string', 'help' => pht( - 'Name of a concrete subclass of %s which enforces more '. + 'Name of a concrete subclass of `%s` which enforces more '. 'granular naming convention rules for symbols.', 'ArcanistXHPASTLintNamingHook'), ), ); } public function setLinterConfigurationValue($key, $value) { switch ($key) { case 'xhpast.naminghook': $this->naminghook = $value; return; default: return parent::setLinterConfigurationValue($key, $value); } } public function process(XHPASTNode $root) { // We're going to build up a list of 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 '. - 'UpperCamelCase.'), + '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 '. - 'UpperCamelCase.'), + '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 '. - 'lowercase_with_underscores.'), + '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 '. - 'lowerCamelCase.'), + '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 '. - 'lowercase_with_underscores.'), + '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 UPPERCASE_WITH_UNDERSCORES.'), + '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 lowerCamelCase.'), + '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, // No advice for globals, but hooks have an option to provide some. 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])) { continue; } if (isset($param_tokens[$token_id])) { continue; } if (isset($exclude_tokens[$token_id])) { continue; } $var_string = $var->getConcreteString(); // Awkward artifact of "$o->{$x}". $var_string = trim($var_string, '{}'); if (isset($superglobal_map[$var_string])) { continue; } if (isset($globals_map[$var_string])) { continue; } $names[] = array( 'variable', $var_string, $var, ArcanistXHPASTLintNamingHook::isLowercaseWithUnderscores( ArcanistXHPASTLintNamingHook::stripPHPVariable($var_string)) ? null : pht( - 'Follow naming conventions: variables should be named using '. - 'lowercase_with_underscores.'), + 'Follow naming conventions: variables '. + 'should be named using `%s`.', + 'lowercase_with_underscores'), ); } } // If a naming hook is configured, give it a chance to override the // default results for all the symbol names. $hook_class = $this->naminghook; if ($hook_class) { $hook_obj = newv($hook_class, array()); foreach ($names as $k => $name_attrs) { list($type, $name, $token, $default) = $name_attrs; $result = $hook_obj->lintSymbolName($type, $name, $default); $names[$k][3] = $result; } } // Raise anything we're left with. foreach ($names as $k => $name_attrs) { list($type, $name, $token, $result) = $name_attrs; if ($result) { $this->raiseLintAtNode( $token, $result); } } // Lint constant declarations. $defines = $this ->getFunctionCalls($root, array('define')) ->add($root->selectDescendantsOfTypes(array( 'n_CLASS_CONSTANT_DECLARATION', 'n_CONSTANT_DECLARATION', ))); foreach ($defines as $define) { switch ($define->getTypeName()) { case 'n_CLASS_CONSTANT_DECLARATION': case 'n_CONSTANT_DECLARATION': $constant = $define->getChildByIndex(0); if ($constant->getTypeName() !== 'n_STRING') { $constant = null; } break; case 'n_FUNCTION_CALL': $constant = $define ->getChildOfType(1, 'n_CALL_PARAMETER_LIST') ->getChildByIndex(0); if ($constant->getTypeName() !== 'n_STRING_SCALAR') { $constant = null; } break; default: $constant = null; break; } if (!$constant) { continue; } $constant_name = $constant->getConcreteString(); if ($constant_name !== strtoupper($constant_name)) { $this->raiseLintAtNode( $constant, pht('Constants should be uppercase.')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php index 63bed628..4baa4053 100644 --- a/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php @@ -1,46 +1,48 @@ selectTokensOfType('T_OPEN_TAG'); foreach ($tokens as $token) { for ($next = $token->getNextToken(); $next; $next = $next->getNextToken()) { if ($next->getTypeName() == 'T_WHITESPACE' && preg_match('/\n\s*\n/', $next->getValue())) { continue 2; } if ($token->getLineNumber() != $next->getLineNumber()) { break; } if ($next->getTypeName() == 'T_CLOSE_TAG') { continue 2; } } $next = $token->getNextToken(); $this->raiseLintAtToken( $next, - pht('`%s` should be separated from code by an empty line.', 'getValue()); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php index 1574a013..3aa1c4f9 100644 --- a/src/lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php @@ -1,45 +1,45 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); if ($class->getChildByIndex(2)->getTypeName() == 'n_EXTENDS_LIST') { continue; } foreach ($methods as $method) { $static_accesses = $method ->selectDescendantsOfType('n_CLASS_STATIC_ACCESS'); foreach ($static_accesses as $static_access) { $called_class = $static_access->getChildByIndex(0); if ($called_class->getTypeName() != 'n_CLASS_NAME') { continue; } if ($called_class->getConcreteString() == 'parent') { $this->raiseLintAtNode( $static_access, pht( - 'Cannot access %s when current class scope has no parent.', + 'Cannot access `%s` when current class scope has no parent.', 'parent::')); } } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistPHPCloseTagXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPHPCloseTagXHPASTLinterRule.php index 1b943b54..95a9918f 100644 --- a/src/lint/linter/xhpast/rules/ArcanistPHPCloseTagXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistPHPCloseTagXHPASTLinterRule.php @@ -1,26 +1,28 @@ '); + return pht('Use of Close Tag `%s`', '?>'); } public function process(XHPASTNode $root) { $inline_html = $root->selectDescendantsOfType('n_INLINE_HTML'); if ($inline_html) { return; } foreach ($root->selectTokensOfType('T_CLOSE_TAG') as $token) { $this->raiseLintAtToken( $token, - pht('Do not use the PHP closing tag, "%s".', '?>')); + pht( + 'Do not use the PHP closing tag, `%s`.', + '?>')); } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistPHPEchoTagXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPHPEchoTagXHPASTLinterRule.php index 5c863fbb..6862d571 100644 --- a/src/lint/linter/xhpast/rules/ArcanistPHPEchoTagXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistPHPEchoTagXHPASTLinterRule.php @@ -1,24 +1,26 @@ getTokens(); foreach ($tokens as $token) { if ($token->getTypeName() === 'T_OPEN_TAG_WITH_ECHO') { $this->raiseLintAtToken( $token, - pht('Avoid the PHP echo short form, "%s".', 'getTokens(); foreach ($tokens as $token) { if ($token->getTypeName() === 'T_OPEN_TAG') { break; } else if ($token->getTypeName() === 'T_OPEN_TAG_WITH_ECHO') { break; } else { if (!preg_match('/^#!/', $token->getValue())) { $this->raiseLintAtToken( $token, pht( - 'PHP files should start with "%s", which may be preceded by '. - 'a "%s" line for scripts.', + 'PHP files should start with `%s`, which may be preceded by '. + 'a `%s` line for scripts.', 'getTokens(); foreach ($tokens as $token) { if ($token->getTypeName() === 'T_OPEN_TAG') { if (trim($token->getValue()) === 'raiseLintAtToken( $token, pht( - 'Use the full form of the PHP open tag, "%s".', + 'Use the full form of the PHP open tag, `%s`.', 'getFunctionCalls($root, array('parse_str')); foreach ($calls as $call) { $call_params = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); if (count($call_params->getChildren()) < 2) { $this->raiseLintAtNode( $call, pht( - 'Avoid %s unless the second parameter is specified. '. + 'Avoid `%s` unless the second parameter is specified. '. 'It is confusing and hinders static analysis.', - 'parse_str()')); + 'parse_str')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php index 15ee8300..1f8d9ba0 100644 --- a/src/lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php @@ -1,37 +1,38 @@ selectDescendantsOfType('n_BINARY_EXPRESSION'); foreach ($binops as $binop) { $op = $binop->getChildByIndex(1); if ($op->getConcreteString() !== '+') { continue; } $left = $binop->getChildByIndex(0); $right = $binop->getChildByIndex(2); if ($left->getTypeName() === 'n_STRING_SCALAR' || $right->getTypeName() === 'n_STRING_SCALAR') { $this->raiseLintAtNode( $binop, pht( - "In PHP, '%s' is the string concatenation operator, not '%s'. ". - "This expression uses '+' with a string literal as an operand.", + 'In PHP, `%s` is the string concatenation operator, not `%s`. '. + 'This expression uses `%s` with a string literal as an operand.', '.', + '+', '+')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php index 37b3422d..de5b522f 100644 --- a/src/lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php @@ -1,42 +1,42 @@ getFunctionCalls($root, array('preg_quote')); foreach ($function_calls as $call) { $parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); if (count($parameter_list->getChildren()) !== 2) { $this->raiseLintAtNode( $call, pht( 'If you use pattern delimiters that require escaping '. '(such as `%s`, but not `%s`) then you should pass two '. 'arguments to %s, so that %s knows which delimiter to escape.', '//', '()', - 'preg_quote()', - 'preg_quote()')); + 'preg_quote', + 'preg_quote')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php index 64bfd87f..864d1f6e 100644 --- a/src/lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php @@ -1,54 +1,54 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { $is_final = false; $is_abstract = false; $is_concrete_extensible = false; $attributes = $class->getChildOfType(0, 'n_CLASS_ATTRIBUTES'); foreach ($attributes->getChildren() as $child) { if ($child->getConcreteString() == 'final') { $is_final = true; } if ($child->getConcreteString() == 'abstract') { $is_abstract = true; } } $docblock = $class->getDocblockToken(); if ($docblock) { list($text, $specials) = $parser->parse($docblock->getValue()); $is_concrete_extensible = idx($specials, 'concrete-extensible'); } if (!$is_final && !$is_abstract && !$is_concrete_extensible) { $this->raiseLintAtNode( $class->getChildOfType(1, 'n_CLASS_NAME'), pht( - "This class is neither '%s' nor '%s', and does not have ". - "a docblock marking it '%s'.", + 'This class is neither `%s` nor `%s`, and does not have '. + 'a docblock marking it `%s`.', 'final', 'abstract', '@concrete-extensible')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistReusedIteratorReferenceXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistReusedIteratorReferenceXHPASTLinterRule.php index f3373332..65851435 100644 --- a/src/lint/linter/xhpast/rules/ArcanistReusedIteratorReferenceXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistReusedIteratorReferenceXHPASTLinterRule.php @@ -1,185 +1,185 @@ selectDescendantsOfTypes(array( 'n_FUNCTION_DECLARATION', 'n_METHOD_DECLARATION', )); foreach ($defs as $def) { $body = $def->getChildByIndex(5); 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 $reference_offset = null; foreach ($reference_vars[$name] as $offset) { if ($offset < $var->getOffset()) { $reference_offset = $offset; } else { break; } } if (!$reference_offset) { continue; } // Check if an unset exists between reference and usage of this // variable $warn = true; if (isset($unset_vars[$name])) { foreach ($unset_vars[$name] as $unset_offset) { if ($unset_offset > $reference_offset && $unset_offset < $var->getOffset()) { $warn = false; break; } } } if ($warn) { $this->raiseLintAtNode( $var, pht( 'This variable was used already as a by-reference iterator '. - 'variable. Such variables survive outside the %s loop, '. + 'variable. Such variables survive outside the `%s` loop, '. 'do not reuse.', 'foreach')); } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php index 79d33e0a..268ca5d0 100644 --- a/src/lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php @@ -1,111 +1,111 @@ lintStrstrUsedForCheck($root); $this->lintStrposUsedForStart($root); } private function lintStrstrUsedForCheck(XHPASTNode $root) { $expressions = $root->selectDescendantsOfType('n_BINARY_EXPRESSION'); foreach ($expressions as $expression) { $operator = $expression->getChildOfType(1, 'n_OPERATOR'); $operator = $operator->getConcreteString(); if ($operator !== '===' && $operator !== '!==') { continue; } $false = $expression->getChildByIndex(0); if ($false->getTypeName() === 'n_SYMBOL_NAME' && $false->getConcreteString() === 'false') { $strstr = $expression->getChildByIndex(2); } else { $strstr = $false; $false = $expression->getChildByIndex(2); if ($false->getTypeName() !== 'n_SYMBOL_NAME' || $false->getConcreteString() !== 'false') { continue; } } if ($strstr->getTypeName() !== 'n_FUNCTION_CALL') { continue; } $name = strtolower($strstr->getChildByIndex(0)->getConcreteString()); if ($name === 'strstr' || $name === 'strchr') { $this->raiseLintAtNode( $strstr, pht( - 'Use %s for checking if the string contains something.', - 'strpos()')); + 'Use `%s` for checking if the string contains something.', + 'strpos')); } else if ($name === 'stristr') { $this->raiseLintAtNode( $strstr, pht( - 'Use %s for checking if the string contains something.', - 'stripos()')); + 'Use `%s` for checking if the string contains something.', + 'stripos')); } } } private function lintStrposUsedForStart(XHPASTNode $root) { $expressions = $root->selectDescendantsOfType('n_BINARY_EXPRESSION'); foreach ($expressions as $expression) { $operator = $expression->getChildOfType(1, 'n_OPERATOR'); $operator = $operator->getConcreteString(); if ($operator !== '===' && $operator !== '!==') { continue; } $zero = $expression->getChildByIndex(0); if ($zero->getTypeName() === 'n_NUMERIC_SCALAR' && $zero->getConcreteString() === '0') { $strpos = $expression->getChildByIndex(2); } else { $strpos = $zero; $zero = $expression->getChildByIndex(2); if ($zero->getTypeName() !== 'n_NUMERIC_SCALAR' || $zero->getConcreteString() !== '0') { continue; } } if ($strpos->getTypeName() !== 'n_FUNCTION_CALL') { continue; } $name = strtolower($strpos->getChildByIndex(0)->getConcreteString()); if ($name === 'strpos') { $this->raiseLintAtNode( $strpos, pht( - 'Use %s for checking if the string starts with something.', - 'strncmp()')); + 'Use `%s` for checking if the string starts with something.', + 'strncmp')); } else if ($name === 'stripos') { $this->raiseLintAtNode( $strpos, pht( - 'Use %s for checking if the string starts with something.', - 'strncasecmp()')); + 'Use `%s` for checking if the string starts with something.', + 'strncasecmp')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistStaticThisXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistStaticThisXHPASTLinterRule.php index 1750a6df..695d0858 100644 --- a/src/lint/linter/xhpast/rules/ArcanistStaticThisXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistStaticThisXHPASTLinterRule.php @@ -1,60 +1,60 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); foreach ($methods as $method) { $attributes = $method ->getChildByIndex(0, 'n_METHOD_MODIFIER_LIST') ->selectDescendantsOfType('n_STRING'); $method_is_static = false; $method_is_abstract = false; foreach ($attributes as $attribute) { if (strtolower($attribute->getConcreteString()) === 'static') { $method_is_static = true; } if (strtolower($attribute->getConcreteString()) === 'abstract') { $method_is_abstract = true; } } if ($method_is_abstract) { continue; } if (!$method_is_static) { continue; } $body = $method->getChildOfType(5, 'n_STATEMENT_LIST'); $variables = $body->selectDescendantsOfType('n_VARIABLE'); foreach ($variables as $variable) { if ($method_is_static && strtolower($variable->getConcreteString()) === '$this') { $this->raiseLintAtNode( $variable, pht( 'You can not reference `%s` inside a static method.', '$this')); } } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistToStringExceptionXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistToStringExceptionXHPASTLinterRule.php index c6a92314..ab0eba56 100644 --- a/src/lint/linter/xhpast/rules/ArcanistToStringExceptionXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistToStringExceptionXHPASTLinterRule.php @@ -1,43 +1,43 @@ selectDescendantsOfType('n_METHOD_DECLARATION'); foreach ($methods as $method) { $name = $method ->getChildOfType(2, 'n_STRING') ->getConcreteString(); if ($name != '__toString') { continue; } $statements = $method->getChildByIndex(5); if ($statements->getTypeName() != 'n_STATEMENT_LIST') { continue; } $throws = $statements->selectDescendantsOfType('n_THROW'); foreach ($throws as $throw) { $this->raiseLintAtNode( $throw, pht( - 'It is not possible to throw an %s from within the %s method.', + 'It is not possible to throw an `%s` from within the `%s` method.', 'Exception', '__toString')); } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php index 67021b47..1abbaa01 100644 --- a/src/lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php @@ -1,52 +1,52 @@ selectDescendantsOfType('n_CLASS_DECLARATION'); foreach ($classes as $class) { $attributes = $class->getChildOfType(0, 'n_CLASS_ATTRIBUTES'); $is_final = false; foreach ($attributes->getChildren() as $attribute) { if ($attribute->getConcreteString() == 'final') { $is_final = true; break; } } if (!$is_final) { continue; } $methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION'); foreach ($methods as $method) { $attributes = $method->getChildOfType(0, 'n_METHOD_MODIFIER_LIST'); foreach ($attributes->getChildren() as $attribute) { if ($attribute->getConcreteString() == 'final') { $this->raiseLintAtNode( $attribute, pht( - 'Unnecessary %s modifier in %s class.', + 'Unnecessary `%s` modifier in `%s` class.', 'final', 'final')); } } } } } } diff --git a/src/lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php index be483f3c..2cd343bf 100644 --- a/src/lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php @@ -1,103 +1,103 @@ array( 'type' => 'optional map', 'help' => pht( 'Classes which should should not be used because they represent the '. 'unsafe usage of dynamic strings.'), ), 'xhpast.dynamic-string.functions' => array( 'type' => 'optional map', 'help' => pht( 'Functions which should should not be used because they represent '. 'the unsafe usage of dynamic strings.'), ), ); return $options + parent::getLinterConfigurationOptions(); } public function setLinterConfigurationValue($key, $value) { switch ($key) { case 'xhpast.dynamic-string.classes': $this->dynamicStringClasses = $value; return; case 'xhpast.dynamic-string.functions': $this->dynamicStringFunctions = $value; return; default: parent::setLinterConfigurationValue($key, $value); return; } } public function process(XHPASTNode $root) { $this->lintUnsafeDynamicStringClasses($root); $this->lintUnsafeDynamicStringFunctions($root); } private function lintUnsafeDynamicStringClasses(XHPASTNode $root) { $news = $root->selectDescendantsOfType('n_NEW'); $this->lintUnsafeDynamicStringCall($news, $this->dynamicStringClasses); } private function lintUnsafeDynamicStringFunctions(XHPASTNode $root) { $calls = $root->selectDescendantsOfType('n_FUNCTION_CALL'); $this->lintUnsafeDynamicStringCall($calls, $this->dynamicStringFunctions); } private function lintUnsafeDynamicStringCall( AASTNodeList $calls, array $safe) { $safe = array_combine( array_map('strtolower', array_keys($safe)), $safe); foreach ($calls as $call) { $name = $call->getChildByIndex(0)->getConcreteString(); $param = idx($safe, strtolower($name)); if ($param === null) { continue; } $parameters = $call->getChildByIndex(1); if (count($parameters->getChildren()) <= $param) { continue; } $identifier = $parameters->getChildByIndex($param); if (!$identifier->isConstantString()) { $this->raiseLintAtNode( $call, pht( - "Parameter %d of %s should be a scalar string, ". + "Parameter %d of `%s` should be a scalar string, ". "otherwise it's not safe.", $param + 1, - $name.'()')); + $name)); } } } }