From 20e99acf0ad1a2e7e37ba7aa8ae997308f7af296 Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Tue, 24 Nov 2015 08:18:06 +1100 Subject: [PATCH] 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 --- src/__phutil_library_map__.php | 4 ++ ...tAbstractPrivateMethodXHPASTLinterRule.php | 37 +++++++++++++++++++ ...tPrivateMethodXHPASTLinterRuleTestCase.php | 11 ++++++ .../abstract-private-method.lint-test | 6 +++ 4 files changed, 58 insertions(+) create mode 100644 src/lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php create mode 100644 src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php create mode 100644 src/lint/linter/xhpast/rules/__tests__/abstract-private-method/abstract-private-method.lint-test diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 40d0bfb7..65f00f2c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -9,6 +9,8 @@ phutil_register_library_map(array( '__library_version__' => 2, 'class' => array( + 'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php', + 'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php', 'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAliasFunctionXHPASTLinterRuleTestCase.php', 'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php', @@ -391,6 +393,8 @@ phutil_register_library_map(array( ), 'function' => array(), 'xmap' => array( + 'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAliasWorkflow' => 'ArcanistWorkflow', diff --git a/src/lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php new file mode 100644 index 00000000..b4a95abf --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php @@ -0,0 +1,37 @@ +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')); + } + } + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php b/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php new file mode 100644 index 00000000..127149dc --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php @@ -0,0 +1,11 @@ +executeTestsInDirectory( + dirname(__FILE__).'/abstract-private-method/'); + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/abstract-private-method/abstract-private-method.lint-test b/src/lint/linter/xhpast/rules/__tests__/abstract-private-method/abstract-private-method.lint-test new file mode 100644 index 00000000..ea96208e --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/abstract-private-method/abstract-private-method.lint-test @@ -0,0 +1,6 @@ +