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:
parent
e573610ce4
commit
2df40b5445
2 changed files with 90 additions and 0 deletions
|
@ -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(
|
||||||
|
|
38
src/lint/linter/__tests__/xhpast/keyword-casing.lint-test
Normal file
38
src/lint/linter/__tests__/xhpast/keyword-casing.lint-test
Normal 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) {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue