1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2025-02-19 18:28:38 +01:00

Improve LINT_KEYWORD_CASING linter rule

Summary: Ref T7409. Improve `ArcanistXHPASTLinter::LINT_KEYWORD_CASING` to include additional token types. Based on [[https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php | Generic_Sniffs_PHP_LowerCaseKeywordSniff]].

Test Plan: `arc unit`

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T7409

Differential Revision: https://secure.phabricator.com/D12367
This commit is contained in:
Joshua Spence 2015-04-13 07:25:54 +10:00
parent f86f4f24e6
commit 515e98f1d2

View file

@ -2696,62 +2696,114 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
} }
private function lintKeywordCasing(XHPASTNode $root) { private function lintKeywordCasing(XHPASTNode $root) {
$keywords = array(); $keywords = $root->selectTokensOfTypes(array(
'T_REQUIRE_ONCE',
$symbols = $root->selectDescendantsOfType('n_SYMBOL_NAME'); 'T_REQUIRE',
foreach ($symbols as $symbol) { 'T_EVAL',
$keywords[] = head($symbol->getTokens()); 'T_INCLUDE_ONCE',
} 'T_INCLUDE',
'T_LOGICAL_OR',
$arrays = $root->selectDescendantsOfType('n_ARRAY_LITERAL'); 'T_LOGICAL_XOR',
foreach ($arrays as $array) { 'T_LOGICAL_AND',
$keywords[] = head($array->getTokens()); 'T_PRINT',
} 'T_INSTANCEOF',
'T_CLONE',
$typehints = $root->selectDescendantsOfType('n_TYPE_NAME'); 'T_NEW',
foreach ($typehints as $typehint) { 'T_EXIT',
$keywords[] = head($typehint->getTokens()); 'T_IF',
} 'T_ELSEIF',
'T_ELSE',
$new_invocations = $root->selectDescendantsOfType('n_NEW'); 'T_ENDIF',
foreach ($new_invocations as $invocation) { 'T_ECHO',
$keywords[] = head($invocation->getTokens()); 'T_DO',
} 'T_WHILE',
'T_ENDWHILE',
$class_declarations = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); 'T_FOR',
foreach ($class_declarations as $declaration) { 'T_ENDFOR',
$keywords[] = head($declaration->getTokens()); 'T_FOREACH',
} 'T_ENDFOREACH',
'T_DECLARE',
// NOTE: Although PHP generally allows arbitrary casing for all language 'T_ENDDECLARE',
// keywords, it's exceedingly rare for anyone to type, e.g., "CLASS" or 'T_AS',
// "cLaSs" in the wild. This list just attempts to cover unconventional 'T_SWITCH',
// spellings which see some level of use, not all keywords exhaustively. 'T_ENDSWITCH',
// There is no token or node type which spans all keywords, so this is 'T_CASE',
// significantly simpler. 'T_DEFAULT',
'T_BREAK',
static $keyword_map = array( 'T_CONTINUE',
'true' => 'true', 'T_GOTO',
'false' => 'false', 'T_FUNCTION',
'null' => 'null', 'T_CONST',
'array' => 'array', 'T_RETURN',
'new' => 'new', 'T_TRY',
'class' => 'class', '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) { foreach ($keywords as $keyword) {
$value = $keyword->getValue(); $value = $keyword->getValue();
$value_key = strtolower($value);
if (!isset($keyword_map[$value_key])) { if ($value != strtolower($value)) {
continue;
}
$expected_spelling = $keyword_map[$value_key];
if ($value !== $expected_spelling) {
$this->raiseLintAtToken( $this->raiseLintAtToken(
$keyword, $keyword,
self::LINT_KEYWORD_CASING, self::LINT_KEYWORD_CASING,
"Convention: spell keyword '{$value}' as '{$expected_spelling}'.", pht(
$expected_spelling); "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,
self::LINT_KEYWORD_CASING,
pht(
"Convention: spell keyword '%s' as '%s'.",
$symbol_name,
strtolower($symbol_name)),
strtolower($symbol_name));
}
} }
} }
} }