1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-22 14:52:40 +01:00

Add a linter rule for unnecessary use of the final modifier

Summary: Ref T7409. This was based on rhttps://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php.

Test Plan: Added unit tests.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T7409

Differential Revision: https://secure.phabricator.com/D12135
This commit is contained in:
Joshua Spence 2015-03-24 00:11:19 +11:00
parent 8530cfcec1
commit e79032fec2
3 changed files with 178 additions and 129 deletions

View file

@ -54,6 +54,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
const LINT_IMPLICIT_VISIBILITY = 52; const LINT_IMPLICIT_VISIBILITY = 52;
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;
private $blacklistedFunctions = array(); private $blacklistedFunctions = array();
private $naminghook; private $naminghook;
@ -121,6 +122,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
self::LINT_IMPLICIT_VISIBILITY => 'Implicit Method Visibility', self::LINT_IMPLICIT_VISIBILITY => 'Implicit Method Visibility',
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',
); );
} }
@ -163,6 +165,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
self::LINT_ARRAY_SEPARATOR => $advice, self::LINT_ARRAY_SEPARATOR => $advice,
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,
); );
} }
@ -230,7 +233,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 '16'; return '17';
} }
protected function resolveFuture($path, Future $future) { protected function resolveFuture($path, Future $future) {
@ -308,6 +311,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
'lintPropertyModifier' => self::LINT_IMPLICIT_VISIBILITY, 'lintPropertyModifier' => self::LINT_IMPLICIT_VISIBILITY,
'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,
); );
foreach ($method_codes as $method => $codes) { foreach ($method_codes as $method => $codes) {
@ -3188,6 +3192,43 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
} }
} }
private function lintUnnecessaryFinalModifier(XHPASTNode $root) {
$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
foreach ($classes as $class) {
$attributes = $class->getChildOfType(0, 'n_CLASS_ATTRIBUTES');
$is_final = false;
foreach ($attributes->getChildren() as $attribute) {
if ($attribute->getConcreteString() == 'final') {
$is_final = true;
break;
}
}
if (!$is_final) {
continue;
}
$methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$attributes = $method->getChildOfType(0, 'n_METHOD_MODIFIER_LIST');
foreach ($attributes->getChildren() as $attribute) {
if ($attribute->getConcreteString() == 'final') {
$this->raiseLintAtNode(
$attribute,
self::LINT_UNNECESSARY_FINAL_MODIFIER,
pht(
'Unnecessary %s modifier in %s class.',
'final',
'final'));
}
}
}
}
}
public function getSuperGlobalNames() { public function getSuperGlobalNames() {
return array( return array(
'$GLOBALS', '$GLOBALS',

View file

@ -11,8 +11,8 @@ final class X {
public function a($x) {} public function a($x) {}
public function b($x ) {} public function b($x ) {}
final public static function &c($x) {} public static function &c($x) {}
final public static function &d($x ) {} public static function &d($x ) {}
abstract private function e($x); abstract private function e($x);
abstract private function f($x ); abstract private function f($x );
@ -27,7 +27,7 @@ warning:4:14
warning:7:15 warning:7:15
error:9:13 error:9:13
warning:12:23 warning:12:23
warning:15:37 warning:15:31
warning:18:33 warning:18:33
warning:23:14 warning:23:14
warning:24:14 warning:24:14
@ -45,8 +45,8 @@ final class X {
public function a($x) {} public function a($x) {}
public function b($x) {} public function b($x) {}
final public static function &c($x) {} public static function &c($x) {}
final public static function &d($x) {} public static function &d($x) {}
abstract private function e($x); abstract private function e($x);
abstract private function f($x); abstract private function f($x);

View file

@ -0,0 +1,8 @@
<?php
final class Foo {
public function bar() {}
public final function baz() {}
}
~~~~~~~~~~
error:2:13 XHP19
advice:4:10