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 abstract private methods

Summary:
Methods cannot be marked as both `abstract` and `private`. This language construct will cause a fatal error:

```
PHP Fatal error:  Abstract function X::Y() cannot be declared private in /home/josh/workspace/github.com/phacility/arcanist/test.php on line 4
```

Test Plan: Added unit tests.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D14558
This commit is contained in:
Joshua Spence 2015-11-24 08:18:06 +11:00
parent 6f908f633b
commit 20e99acf0a
4 changed files with 58 additions and 0 deletions

View file

@ -9,6 +9,8 @@
phutil_register_library_map(array( phutil_register_library_map(array(
'__library_version__' => 2, '__library_version__' => 2,
'class' => array( 'class' => array(
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php',
'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php', 'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php',
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAliasFunctionXHPASTLinterRuleTestCase.php', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAliasFunctionXHPASTLinterRuleTestCase.php',
'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php', 'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php',
@ -391,6 +393,8 @@ phutil_register_library_map(array(
), ),
'function' => array(), 'function' => array(),
'xmap' => array( 'xmap' => array(
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasWorkflow' => 'ArcanistWorkflow', 'ArcanistAliasWorkflow' => 'ArcanistWorkflow',

View file

@ -0,0 +1,37 @@
<?php
final class ArcanistAbstractPrivateMethodXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 107;
public function getLintName() {
return pht('`%s` Method Cannot Be Declared `%s`', 'abstract', 'private');
}
public function process(XHPASTNode $root) {
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$method_modifiers = $method
->getChildOfType(0, 'n_METHOD_MODIFIER_LIST')
->selectDescendantsOfType('n_STRING');
$modifiers = array();
foreach ($method_modifiers as $modifier) {
$modifiers[strtolower($modifier->getConcreteString())] = true;
}
if (idx($modifiers, 'abstract') && idx($modifiers, 'private')) {
$this->raiseLintAtNode(
$method,
pht(
'`%s` method cannot be declared `%s`. '.
'This construct will cause a fatal error.',
'abstract',
'private'));
}
}
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/abstract-private-method/');
}
}

View file

@ -0,0 +1,6 @@
<?php
abstract class SomeClass {
private abstract function someMethod();
}
~~~~~~~~~~
error:3:3