mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Add a linter rule for useless overriding methods
Summary: Ref T7409. Adds `ArcanistXHPASTLinter::LINT_USELESS_OVERRIDING_METHOD` for detecting method which only call their parent method. Based on [[https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php | Generic_Sniffs_CodeAnalysis_UselessOverridingMethodSniff]]. 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/D12419
This commit is contained in:
parent
d2b38cdf94
commit
6295134bc7
2 changed files with 104 additions and 1 deletions
|
@ -62,6 +62,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
const LINT_DEFAULT_PARAMETERS = 60;
|
const LINT_DEFAULT_PARAMETERS = 60;
|
||||||
const LINT_LOWERCASE_FUNCTIONS = 61;
|
const LINT_LOWERCASE_FUNCTIONS = 61;
|
||||||
const LINT_CLASS_NAME_LITERAL = 62;
|
const LINT_CLASS_NAME_LITERAL = 62;
|
||||||
|
const LINT_USELESS_OVERRIDING_METHOD = 63;
|
||||||
|
|
||||||
private $blacklistedFunctions = array();
|
private $blacklistedFunctions = array();
|
||||||
private $naminghook;
|
private $naminghook;
|
||||||
|
@ -194,6 +195,8 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
=> pht('Lowercase Functions'),
|
=> pht('Lowercase Functions'),
|
||||||
self::LINT_CLASS_NAME_LITERAL
|
self::LINT_CLASS_NAME_LITERAL
|
||||||
=> pht('Class Name Literal'),
|
=> pht('Class Name Literal'),
|
||||||
|
self::LINT_USELESS_OVERRIDING_METHOD
|
||||||
|
=> pht('Useless Overriding Method'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +247,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
self::LINT_DEFAULT_PARAMETERS => $warning,
|
self::LINT_DEFAULT_PARAMETERS => $warning,
|
||||||
self::LINT_LOWERCASE_FUNCTIONS => $advice,
|
self::LINT_LOWERCASE_FUNCTIONS => $advice,
|
||||||
self::LINT_CLASS_NAME_LITERAL => $advice,
|
self::LINT_CLASS_NAME_LITERAL => $advice,
|
||||||
|
self::LINT_USELESS_OVERRIDING_METHOD => $advice,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +315,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 '25';
|
return '26';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function resolveFuture($path, Future $future) {
|
protected function resolveFuture($path, Future $future) {
|
||||||
|
@ -400,6 +404,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
'lintDefaultParameters' => self::LINT_DEFAULT_PARAMETERS,
|
'lintDefaultParameters' => self::LINT_DEFAULT_PARAMETERS,
|
||||||
'lintLowercaseFunctions' => self::LINT_LOWERCASE_FUNCTIONS,
|
'lintLowercaseFunctions' => self::LINT_LOWERCASE_FUNCTIONS,
|
||||||
'lintClassNameLiteral' => self::LINT_CLASS_NAME_LITERAL,
|
'lintClassNameLiteral' => self::LINT_CLASS_NAME_LITERAL,
|
||||||
|
'lintUselessOverridingMethods' => self::LINT_USELESS_OVERRIDING_METHOD,
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($method_codes as $method => $codes) {
|
foreach ($method_codes as $method => $codes) {
|
||||||
|
@ -3766,6 +3771,85 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function lintUselessOverridingMethods(XHPASTNode $root) {
|
||||||
|
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
|
||||||
|
|
||||||
|
foreach ($methods as $method) {
|
||||||
|
$method_name = $method
|
||||||
|
->getChildOfType(2, 'n_STRING')
|
||||||
|
->getConcreteString();
|
||||||
|
|
||||||
|
$parameter_list = $method
|
||||||
|
->getChildOfType(3, 'n_DECLARATION_PARAMETER_LIST');
|
||||||
|
$parameters = array();
|
||||||
|
|
||||||
|
foreach ($parameter_list->getChildren() as $parameter) {
|
||||||
|
$parameters[] = $parameter
|
||||||
|
->getChildOfType(1, 'n_VARIABLE')
|
||||||
|
->getConcreteString();
|
||||||
|
}
|
||||||
|
|
||||||
|
$statements = $method->getChildByIndex(5);
|
||||||
|
|
||||||
|
if ($statements->getTypeName() != 'n_STATEMENT_LIST') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($statements->getChildren()) != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$statement = $statements
|
||||||
|
->getChildOfType(0, 'n_STATEMENT')
|
||||||
|
->getChildByIndex(0);
|
||||||
|
|
||||||
|
if ($statement->getTypeName() == 'n_RETURN') {
|
||||||
|
$statement = $statement->getChildByIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($statement->getTypeName() != 'n_FUNCTION_CALL') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$function = $statement->getChildByIndex(0);
|
||||||
|
|
||||||
|
if ($function->getTypeName() != 'n_CLASS_STATIC_ACCESS') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$called_class = $function->getChildOfType(0, 'n_CLASS_NAME');
|
||||||
|
$called_method = $function->getChildOfType(1, 'n_STRING');
|
||||||
|
|
||||||
|
if ($called_class->getConcreteString() != 'parent') {
|
||||||
|
continue;
|
||||||
|
} else if ($called_method->getConcreteString() != $method_name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = $statement
|
||||||
|
->getChildOfType(1, 'n_CALL_PARAMETER_LIST')
|
||||||
|
->getChildren();
|
||||||
|
|
||||||
|
foreach ($params as $param) {
|
||||||
|
if ($param->getTypeName() != 'n_VARIABLE') {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$expected = array_shift($parameters);
|
||||||
|
|
||||||
|
if ($param->getConcreteString() != $expected) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->raiseLintAtNode(
|
||||||
|
$method,
|
||||||
|
self::LINT_USELESS_OVERRIDING_METHOD,
|
||||||
|
pht('Useless overriding method.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all calls to some specified function(s).
|
* Retrieve all calls to some specified function(s).
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class MyClass extends SomeOtherClass {
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uselessMethod($x, array $y) {
|
||||||
|
return parent::uselessMethod($x, $y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function usefulMethod($x, array $y) {
|
||||||
|
return parent::usefulMethod($x, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~~~~~~~~~~
|
||||||
|
error:3:13
|
||||||
|
advice:4:3
|
||||||
|
advice:8:3
|
Loading…
Reference in a new issue