1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 16:22:42 +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:
Joshua Spence 2015-04-07 07:24:20 +10:00
parent 92713cf922
commit c5df885d7b
2 changed files with 34 additions and 1 deletions

View file

@ -55,6 +55,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
const LINT_CALL_TIME_PASS_BY_REF = 53;
const LINT_FORMATTED_STRING = 54;
const LINT_UNNECESSARY_FINAL_MODIFIER = 55;
const LINT_UNNECESSARY_SEMICOLON = 56;
private $blacklistedFunctions = array();
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_FORMATTED_STRING => 'Formatted String',
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_IMPLICIT_VISIBILITY => $advice,
self::LINT_UNNECESSARY_FINAL_MODIFIER => $advice,
self::LINT_UNNECESSARY_SEMICOLON => $advice,
);
}
@ -233,7 +236,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
public function getVersion() {
// The version number should be incremented whenever a new rule is added.
return '17';
return '18';
}
protected function resolveFuture($path, Future $future) {
@ -312,6 +315,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
'lintCallTimePassByReference' => self::LINT_CALL_TIME_PASS_BY_REF,
'lintFormattedString' => self::LINT_FORMATTED_STRING,
'lintUnnecessaryFinalModifier' => self::LINT_UNNECESSARY_FINAL_MODIFIER,
'lintUnnecessarySemicolons' => self::LINT_UNNECESSARY_SEMICOLON,
);
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() {
return array(
'$GLOBALS',

View 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;