diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4b8d88db..9c914e1b 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -178,6 +178,8 @@ phutil_register_library_map(array( 'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php', 'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php', 'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInstanceofOperatorXHPASTLinterRuleTestCase.php', + 'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php', + 'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php', 'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceMethodBodyXHPASTLinterRule.php', 'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase.php', 'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php', @@ -568,6 +570,8 @@ phutil_register_library_map(array( 'ArcanistInstallCertificateWorkflow' => 'ArcanistWorkflow', 'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', + 'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', diff --git a/src/lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php new file mode 100644 index 00000000..db75c526 --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php @@ -0,0 +1,34 @@ +selectDescendantsOfType('n_INTERFACE_DECLARATION'); + + foreach ($interfaces as $interface) { + $methods = $interface->selectDescendantsOfType('n_METHOD_DECLARATION'); + + foreach ($methods as $method) { + $modifiers = $this->getModifiers($method); + + if (idx($modifiers, 'abstract')) { + $this->raiseLintAtNode( + $method, + pht( + '`%s` methods cannot be marked as `%s`. This construct will '. + 'cause a fatal error.', + 'interface', + 'abstract')); + } + } + } + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php b/src/lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php new file mode 100644 index 00000000..3c305c21 --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php @@ -0,0 +1,11 @@ +executeTestsInDirectory( + dirname(__FILE__).'/interface-abstract-method/'); + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/interface-abstract-method/abstract.lint-test b/src/lint/linter/xhpast/rules/__tests__/interface-abstract-method/abstract.lint-test new file mode 100644 index 00000000..91180e9e --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/interface-abstract-method/abstract.lint-test @@ -0,0 +1,7 @@ +