1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-26 00:32:41 +01:00

Lint TRUE, nUlL, etc., for Phabricator conventions

Summary: Detect and fix unconventional spellings of `true`, `false`, `null` and `array` (these are the only keywords I've seen spelled unconventionally in the wild).

Test Plan: Unit tests.

Reviewers: DurhamGoode, btrahan, vrana

Reviewed By: vrana

CC: aran

Maniphest Tasks: T2985

Differential Revision: https://secure.phabricator.com/D5686
This commit is contained in:
epriestley 2013-04-15 10:22:56 -07:00
parent e573610ce4
commit 2df40b5445
2 changed files with 90 additions and 0 deletions

View file

@ -47,6 +47,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
const LINT_CLOSING_CALL_PAREN = 37; const LINT_CLOSING_CALL_PAREN = 37;
const LINT_CLOSING_DECL_PAREN = 38; const LINT_CLOSING_DECL_PAREN = 38;
const LINT_REUSED_ITERATOR_REFERENCE = 39; const LINT_REUSED_ITERATOR_REFERENCE = 39;
const LINT_KEYWORD_CASING = 40;
public function getLintNameMap() { public function getLintNameMap() {
return array( return array(
@ -87,6 +88,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
self::LINT_CLOSING_CALL_PAREN => 'Call Formatting', self::LINT_CLOSING_CALL_PAREN => 'Call Formatting',
self::LINT_CLOSING_DECL_PAREN => 'Declaration Formatting', self::LINT_CLOSING_DECL_PAREN => 'Declaration Formatting',
self::LINT_REUSED_ITERATOR_REFERENCE => 'Reuse of Iterator References', self::LINT_REUSED_ITERATOR_REFERENCE => 'Reuse of Iterator References',
self::LINT_KEYWORD_CASING => 'Keyword Conventions',
); );
} }
@ -115,6 +117,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
self::LINT_CLOSING_CALL_PAREN => $warning, self::LINT_CLOSING_CALL_PAREN => $warning,
self::LINT_CLOSING_DECL_PAREN => $warning, self::LINT_CLOSING_DECL_PAREN => $warning,
self::LINT_REUSED_ITERATOR_REFERENCE => $warning, self::LINT_REUSED_ITERATOR_REFERENCE => $warning,
self::LINT_KEYWORD_CASING => $warning,
// This is disabled by default because it implies a very strict policy // This is disabled by default because it implies a very strict policy
// which isn't necessary in the general case. // which isn't necessary in the general case.
@ -219,6 +222,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
'lintRaggedClasstreeEdges' => self::LINT_RAGGED_CLASSTREE_EDGE, 'lintRaggedClasstreeEdges' => self::LINT_RAGGED_CLASSTREE_EDGE,
'lintClosingCallParen' => self::LINT_CLOSING_CALL_PAREN, 'lintClosingCallParen' => self::LINT_CLOSING_CALL_PAREN,
'lintClosingDeclarationParen' => self::LINT_CLOSING_DECL_PAREN, 'lintClosingDeclarationParen' => self::LINT_CLOSING_DECL_PAREN,
'lintKeywordCasing' => self::LINT_KEYWORD_CASING,
); );
foreach ($method_codes as $method => $codes) { foreach ($method_codes as $method => $codes) {
@ -2254,6 +2258,54 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
} }
} }
private function lintKeywordCasing($root) {
$keywords = array();
$symbols = $root->selectDescendantsOfType('n_SYMBOL_NAME');
foreach ($symbols as $symbol) {
$keywords[] = head($symbol->getTokens());
}
$arrays = $root->selectDescendantsOfType('n_ARRAY_LITERAL');
foreach ($arrays as $array) {
$keywords[] = head($array->getTokens());
}
$typehints = $root->selectDescendantsOfType('n_TYPE_NAME');
foreach ($typehints as $typehint) {
$keywords[] = head($typehint->getTokens());
}
// NOTE: Although PHP generally allows arbitrary casing for all language
// keywords, it's exceedingly rare for anyone to type, e.g., "CLASS" or
// "cLaSs" in the wild. This list just attempts to cover unconventional
// spellings which see some level of use, not all keywords exhaustively.
// There is no token or node type which spans all keywords, so this is
// significantly simpler.
static $keyword_map = array(
'true' => 'true',
'false' => 'false',
'null' => 'null',
'array' => 'array',
);
foreach ($keywords as $keyword) {
$value = $keyword->getValue();
$value_key = strtolower($value);
if (!isset($keyword_map[$value_key])) {
continue;
}
$expected_spelling = $keyword_map[$value_key];
if ($value !== $expected_spelling) {
$this->raiseLintAtToken(
$keyword,
self::LINT_KEYWORD_CASING,
"Convention: spell keyword '{$value}' as '{$expected_spelling}'.",
$expected_spelling);
}
}
}
public function getSuperGlobalNames() { public function getSuperGlobalNames() {
return array( return array(

View file

@ -0,0 +1,38 @@
<?php
true;
false;
null;
True;
False;
NULL;
nUlL;
array();
Array();
function f(array $x, ArRaY $y) {
}
~~~~~~~~~~
warning:6:1
warning:7:1
warning:8:1
warning:9:1
warning:11:1
warning:13:22
~~~~~~~~~~
<?php
true;
false;
null;
true;
false;
null;
null;
array();
array();
function f(array $x, array $y) {
}