Page MenuHomePhabricator

D14560.diff
No OneTemporary

D14560.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- 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(
+ 'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php',
+ 'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php',
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php',
'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php',
@@ -395,6 +397,8 @@
),
'function' => array(),
'xmap' => array(
+ 'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
+ 'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
diff --git a/src/lint/linter/xhpast/ArcanistXHPASTLinterRule.php b/src/lint/linter/xhpast/ArcanistXHPASTLinterRule.php
--- a/src/lint/linter/xhpast/ArcanistXHPASTLinterRule.php
+++ b/src/lint/linter/xhpast/ArcanistXHPASTLinterRule.php
@@ -226,6 +226,34 @@
}
/**
+ * Get class/method modifiers.
+ *
+ * @param XHPASTNode A node of type `n_CLASS_DECLARATION` or
+ * `n_METHOD_DECLARATION`.
+ * @return map<string, bool> Class/method modifiers.
+ */
+ final protected function getModifiers(XHPASTNode $node) {
+ $modifier_list = $node->getChildByIndex(0);
+
+ switch ($modifier_list->getTypeName()) {
+ case 'n_CLASS_ATTRIBUTES':
+ case 'n_METHOD_MODIFIER_LIST':
+ break;
+
+ default:
+ return array();
+ }
+
+ $modifiers = array();
+
+ foreach ($modifier_list->selectDescendantsOfType('n_STRING') as $modifier) {
+ $modifiers[strtolower($modifier->getConcreteString())] = true;
+ }
+
+ return $modifiers;
+ }
+
+ /**
* Get PHP superglobals.
*
* @return list<string>
diff --git a/src/lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php
@@ -0,0 +1,30 @@
+<?php
+
+final class ArcanistAbstractMethodBodyXHPASTLinterRule
+ extends ArcanistXHPASTLinterRule {
+
+ const ID = 108;
+
+ public function getLintName() {
+ return pht('`%s` Method Cannot Contain Body', 'abstract');
+ }
+
+ public function process(XHPASTNode $root) {
+ $methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
+
+ foreach ($methods as $method) {
+ $modifiers = $this->getModifiers($method);
+ $body = $method->getChildByIndex(5);
+
+ if (idx($modifiers, 'abstract') && $body->getTypeName() != 'n_EMPTY') {
+ $this->raiseLintAtNode(
+ $body,
+ pht(
+ '`%s` methods cannot contain a body. This construct will '.
+ 'cause a fatal error.',
+ 'abstract'));
+ }
+ }
+ }
+
+}
diff --git a/src/lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php
--- a/src/lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php
+++ b/src/lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php
@@ -43,32 +43,4 @@
}
}
- /**
- * Get class/method modifiers.
- *
- * @param XHPASTNode A node of type `n_CLASS_DECLARATION` or
- * `n_METHOD_DECLARATION`.
- * @return map<string, bool> Class/method modifiers.
- */
- private function getModifiers(XHPASTNode $node) {
- $modifier_list = $node->getChildByIndex(0);
-
- switch ($modifier_list->getTypeName()) {
- case 'n_CLASS_ATTRIBUTES':
- case 'n_METHOD_MODIFIER_LIST':
- break;
-
- default:
- return array();
- }
-
- $modifiers = array();
-
- foreach ($modifier_list->selectDescendantsOfType('n_STRING') as $modifier) {
- $modifiers[strtolower($modifier->getConcreteString())] = true;
- }
-
- return $modifiers;
- }
-
}
diff --git a/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php b/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php
@@ -0,0 +1,10 @@
+<?php
+
+final class ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase
+ extends ArcanistXHPASTLinterRuleTestCase {
+
+ public function testLinter() {
+ $this->executeTestsInDirectory(dirname(__FILE__).'/abstract-method-body/');
+ }
+
+}
diff --git a/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/body.lint-test b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/body.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/body.lint-test
@@ -0,0 +1,6 @@
+<?php
+abstract class SomeClass {
+ abstract public function someMethod() {}
+}
+~~~~~~~~~~
+error:3:41
diff --git a/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/no-body.lint-test b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/no-body.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/no-body.lint-test
@@ -0,0 +1,5 @@
+<?php
+abstract class SomeClass {
+ abstract public function someMethod();
+}
+~~~~~~~~~~
diff --git a/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/non-abstract.lint-test b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/non-abstract.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/__tests__/abstract-method-body/non-abstract.lint-test
@@ -0,0 +1,5 @@
+<?php
+abstract class SomeClass {
+ public function someMethod() {}
+}
+~~~~~~~~~~

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 12, 7:19 PM (1 d, 9 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6736110
Default Alt Text
D14560.diff (6 KB)

Event Timeline