mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Add a linter rule to detect unnecessary semicolons
Summary: Ref T7409. Adds a rule to detect unnecessary semicolons. The most common scenario I've seen in the wild is the use of semicolons after a class definition: ```lang=php class MyClass { // ... }; ``` Test Plan: Added unit tests. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7409 Differential Revision: https://secure.phabricator.com/D12139
This commit is contained in:
parent
92713cf922
commit
c5df885d7b
2 changed files with 34 additions and 1 deletions
|
@ -55,6 +55,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
const LINT_CALL_TIME_PASS_BY_REF = 53;
|
const LINT_CALL_TIME_PASS_BY_REF = 53;
|
||||||
const LINT_FORMATTED_STRING = 54;
|
const LINT_FORMATTED_STRING = 54;
|
||||||
const LINT_UNNECESSARY_FINAL_MODIFIER = 55;
|
const LINT_UNNECESSARY_FINAL_MODIFIER = 55;
|
||||||
|
const LINT_UNNECESSARY_SEMICOLON = 56;
|
||||||
|
|
||||||
private $blacklistedFunctions = array();
|
private $blacklistedFunctions = array();
|
||||||
private $naminghook;
|
private $naminghook;
|
||||||
|
@ -123,6 +124,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
self::LINT_CALL_TIME_PASS_BY_REF => 'Call-Time Pass-By-Reference',
|
self::LINT_CALL_TIME_PASS_BY_REF => 'Call-Time Pass-By-Reference',
|
||||||
self::LINT_FORMATTED_STRING => 'Formatted String',
|
self::LINT_FORMATTED_STRING => 'Formatted String',
|
||||||
self::LINT_UNNECESSARY_FINAL_MODIFIER => 'Unnecessary Final Modifier',
|
self::LINT_UNNECESSARY_FINAL_MODIFIER => 'Unnecessary Final Modifier',
|
||||||
|
self::LINT_UNNECESSARY_SEMICOLON => 'Unnecessary Semicolon',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +168,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
self::LINT_CONSTRUCTOR_PARENTHESES => $advice,
|
self::LINT_CONSTRUCTOR_PARENTHESES => $advice,
|
||||||
self::LINT_IMPLICIT_VISIBILITY => $advice,
|
self::LINT_IMPLICIT_VISIBILITY => $advice,
|
||||||
self::LINT_UNNECESSARY_FINAL_MODIFIER => $advice,
|
self::LINT_UNNECESSARY_FINAL_MODIFIER => $advice,
|
||||||
|
self::LINT_UNNECESSARY_SEMICOLON => $advice,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +236,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
|
|
||||||
public function getVersion() {
|
public function getVersion() {
|
||||||
// The version number should be incremented whenever a new rule is added.
|
// The version number should be incremented whenever a new rule is added.
|
||||||
return '17';
|
return '18';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function resolveFuture($path, Future $future) {
|
protected function resolveFuture($path, Future $future) {
|
||||||
|
@ -312,6 +315,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
'lintCallTimePassByReference' => self::LINT_CALL_TIME_PASS_BY_REF,
|
'lintCallTimePassByReference' => self::LINT_CALL_TIME_PASS_BY_REF,
|
||||||
'lintFormattedString' => self::LINT_FORMATTED_STRING,
|
'lintFormattedString' => self::LINT_FORMATTED_STRING,
|
||||||
'lintUnnecessaryFinalModifier' => self::LINT_UNNECESSARY_FINAL_MODIFIER,
|
'lintUnnecessaryFinalModifier' => self::LINT_UNNECESSARY_FINAL_MODIFIER,
|
||||||
|
'lintUnnecessarySemicolons' => self::LINT_UNNECESSARY_SEMICOLON,
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($method_codes as $method => $codes) {
|
foreach ($method_codes as $method => $codes) {
|
||||||
|
@ -3229,6 +3233,24 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function lintUnnecessarySemicolons(XHPASTNode $root) {
|
||||||
|
$statements = $root->selectDescendantsOfType('n_STATEMENT');
|
||||||
|
|
||||||
|
foreach ($statements as $statement) {
|
||||||
|
if ($statement->getParentNode()->getTypeName() == 'n_DECLARE') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($statement->getSemanticString() == ';') {
|
||||||
|
$this->raiseLintAtNode(
|
||||||
|
$statement,
|
||||||
|
self::LINT_UNNECESSARY_SEMICOLON,
|
||||||
|
pht('Unnecessary semicolons after statement.'),
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getSuperGlobalNames() {
|
public function getSuperGlobalNames() {
|
||||||
return array(
|
return array(
|
||||||
'$GLOBALS',
|
'$GLOBALS',
|
||||||
|
|
11
src/lint/linter/__tests__/xhpast/empty-statement.lint-test
Normal file
11
src/lint/linter/__tests__/xhpast/empty-statement.lint-test
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
final class Foo {};
|
||||||
|
$x = null;;
|
||||||
|
~~~~~~~~~~
|
||||||
|
error:2:13 XHP19
|
||||||
|
advice:2:19
|
||||||
|
advice:3:11
|
||||||
|
~~~~~~~~~~
|
||||||
|
<?php
|
||||||
|
final class Foo {}
|
||||||
|
$x = null;
|
Loading…
Reference in a new issue