1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-22 23:02:41 +01:00

Add a linter rule for incorrect use of parent scope

Summary:
The following code is invalid:

```
final class MyClass {
  public function __construct() {
    parent::__construct(null);
  }
}

$x = new MyClass();
```

Running the above code will produce a fatal error:

```
PHP Fatal error:  Cannot access parent:: when current class scope has no parent
```

Test Plan: Added unit tests.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Differential Revision: https://secure.phabricator.com/D12420
This commit is contained in:
Joshua Spence 2015-05-14 18:01:43 +10:00
parent a6a26bb3a3
commit f00d4219dd
2 changed files with 49 additions and 0 deletions

View file

@ -63,6 +63,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
const LINT_LOWERCASE_FUNCTIONS = 61; const LINT_LOWERCASE_FUNCTIONS = 61;
const LINT_CLASS_NAME_LITERAL = 62; const LINT_CLASS_NAME_LITERAL = 62;
const LINT_USELESS_OVERRIDING_METHOD = 63; const LINT_USELESS_OVERRIDING_METHOD = 63;
const LINT_NO_PARENT_SCOPE = 64;
private $blacklistedFunctions = array(); private $blacklistedFunctions = array();
private $naminghook; private $naminghook;
@ -197,6 +198,8 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
=> pht('Class Name Literal'), => pht('Class Name Literal'),
self::LINT_USELESS_OVERRIDING_METHOD self::LINT_USELESS_OVERRIDING_METHOD
=> pht('Useless Overriding Method'), => pht('Useless Overriding Method'),
self::LINT_NO_PARENT_SCOPE
=> pht('No Parent Scope'),
); );
} }
@ -405,6 +408,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
'lintLowercaseFunctions' => self::LINT_LOWERCASE_FUNCTIONS, 'lintLowercaseFunctions' => self::LINT_LOWERCASE_FUNCTIONS,
'lintClassNameLiteral' => self::LINT_CLASS_NAME_LITERAL, 'lintClassNameLiteral' => self::LINT_CLASS_NAME_LITERAL,
'lintUselessOverridingMethods' => self::LINT_USELESS_OVERRIDING_METHOD, 'lintUselessOverridingMethods' => self::LINT_USELESS_OVERRIDING_METHOD,
'lintNoParentScope' => self::LINT_NO_PARENT_SCOPE,
); );
foreach ($method_codes as $method => $codes) { foreach ($method_codes as $method => $codes) {
@ -3849,6 +3853,36 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
} }
} }
private function lintNoParentScope(XHPASTNode $root) {
$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
foreach ($classes as $class) {
$methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION');
if ($class->getChildByIndex(2)->getTypeName() == 'n_EXTENDS_LIST') {
continue;
}
foreach ($methods as $method) {
$static_accesses = $method
->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
foreach ($static_accesses as $static_access) {
$called_class = $static_access->getChildOfType(0, 'n_CLASS_NAME');
if ($called_class->getConcreteString() == 'parent') {
$this->raiseLintAtNode(
$static_access,
self::LINT_NO_PARENT_SCOPE,
pht(
'Cannot access %s when current class scope has no parent.',
'parent::'));
}
}
}
}
}
/** /**
* Retrieve all calls to some specified function(s). * Retrieve all calls to some specified function(s).

View file

@ -0,0 +1,15 @@
<?php
final class MyValidClass extends SomeOtherClass {
public function __construct() {
parent::__construct(null);
}
}
final class MyInvalidClass {
public function __construct() {
parent::__construct(null);
}
}
~~~~~~~~~~
error:11:5