mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-29 00:40:57 +01:00
Write a linter rule for unexpected return
values
Summary: Although it is technically possible to return a value from a PHP constructor, it is rather odd and should be avoided. See some discussion on [[http://stackoverflow.com/q/11904255 | StackOverflow]]. Consider the following example: ```lang=php class SomeClass { public function __construct() { return 'quack'; } } ``` This doesn't work: ```lang=php, counterexample echo new SomeClas(); ``` This, strangely, does work: ```lang=php echo id(new SomeClass())->__construct(); ``` Test Plan: Added unit tests. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D14516
This commit is contained in:
parent
149e7895fb
commit
3ac313ad1e
6 changed files with 86 additions and 0 deletions
|
@ -333,6 +333,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistUndeclaredVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUndeclaredVariableXHPASTLinterRule.php',
|
||||
'ArcanistUndeclaredVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUndeclaredVariableXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistUnexpectedReturnValueXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnexpectedReturnValueXHPASTLinterRule.php',
|
||||
'ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistUnitConsoleRenderer' => 'unit/renderer/ArcanistUnitConsoleRenderer.php',
|
||||
'ArcanistUnitRenderer' => 'unit/renderer/ArcanistUnitRenderer.php',
|
||||
'ArcanistUnitTestEngine' => 'unit/engine/ArcanistUnitTestEngine.php',
|
||||
|
@ -707,6 +709,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistUndeclaredVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistUndeclaredVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistUnexpectedReturnValueXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistUnitConsoleRenderer' => 'ArcanistUnitRenderer',
|
||||
'ArcanistUnitRenderer' => 'Phobject',
|
||||
'ArcanistUnitTestEngine' => 'Phobject',
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistUnexpectedReturnValueXHPASTLinterRule
|
||||
extends ArcanistXHPASTLinterRule {
|
||||
|
||||
const ID = 92;
|
||||
|
||||
public function getLintName() {
|
||||
return pht('Unexpected `%s` Value', 'return');
|
||||
}
|
||||
|
||||
public function getLintSeverity() {
|
||||
return ArcanistLintSeverity::SEVERITY_WARNING;
|
||||
}
|
||||
|
||||
public function process(XHPASTNode $root) {
|
||||
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
|
||||
|
||||
foreach ($methods as $method) {
|
||||
$method_name = $method
|
||||
->getChildOfType(2, 'n_STRING')
|
||||
->getConcreteString();
|
||||
|
||||
switch (strtolower($method_name)) {
|
||||
case '__construct':
|
||||
case '__destruct':
|
||||
$returns = $method->selectDescendantsOfType('n_RETURN');
|
||||
|
||||
foreach ($returns as $return) {
|
||||
$return_value = $return->getChildByIndex(0);
|
||||
|
||||
if ($return_value->getTypeName() == 'n_EMPTY') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->raiseLintAtNode(
|
||||
$return,
|
||||
pht(
|
||||
'Unexpected `%s` value in `%s` method.',
|
||||
'return',
|
||||
$method_name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase
|
||||
extends ArcanistXHPASTLinterRuleTestCase {
|
||||
|
||||
public function testLinter() {
|
||||
$this->executeTestsInDirectory(
|
||||
dirname(__FILE__).'/unexpected-return-value/');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
class SomeClass {
|
||||
public function __construct() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~
|
||||
warning:4:5
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
class SomeClass {
|
||||
public function __destruct() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~
|
||||
warning:4:5
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
class SomeClass {
|
||||
public function __construct() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~
|
Loading…
Reference in a new issue