From f43b74c6052f10b54bb5c97215fdc02d8935226f Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Tue, 11 Aug 2015 06:48:56 +1000 Subject: [PATCH] Improve PHP compatibility linter Summary: Ref T8674. Adds to `ArcanistPHPCompatibilityXHPASTLinterRule` such that an error is raised whenever `self` or `$this` is used in an anonymous closure prior to PHP 5.4. Test Plan: Added test cases. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: Korvin Maniphest Tasks: T8674 Differential Revision: https://secure.phabricator.com/D13841 --- .../__tests__/xhpast/php54-features.lint-test | 17 +++++++ ...canistPHPCompatibilityXHPASTLinterRule.php | 46 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/lint/linter/__tests__/xhpast/php54-features.lint-test b/src/lint/linter/__tests__/xhpast/php54-features.lint-test index bdeff107..91c112c5 100644 --- a/src/lint/linter/__tests__/xhpast/php54-features.lint-test +++ b/src/lint/linter/__tests__/xhpast/php54-features.lint-test @@ -6,9 +6,26 @@ f()[0]; // The check above should be this, see T4334. // $o->m()[0]; +final class SomeClass extends Phobject { + public function someMethod() { + return function () { + $this->someOtherMethod(); + }; + } + + public static function someStaticMethod() { + return function () { + self::someOtherMethod(); + }; + } +} + ~~~~~~~~~~ error:3:5 error:4:9 +error:9:13 +error:12:7 +error:18:7 ~~~~~~~~~~ ~~~~~~~~~~ { diff --git a/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php index 3f118b43..7697356e 100644 --- a/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php @@ -402,6 +402,52 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule break; } } + + $closures = $this->getAnonymousClosures($root); + foreach ($closures as $closure) { + $static_accesses = $closure + ->selectDescendantsOfType('n_CLASS_STATIC_ACCESS'); + + foreach ($static_accesses as $static_access) { + $class = $static_access->getChildByIndex(0); + + if ($class->getTypeName() != 'n_CLASS_NAME') { + continue; + } + + if (strtolower($class->getConcreteString()) != 'self') { + continue; + } + + $this->raiseLintAtNode( + $class, + pht( + 'The use of `%s` in an anonymous closure is not '. + 'available before PHP 5.4.', + 'self')); + } + + $property_accesses = $closure + ->selectDescendantsOfType('n_OBJECT_PROPERTY_ACCESS'); + foreach ($property_accesses as $property_access) { + $variable = $property_access->getChildByIndex(0); + + if ($variable->getTypeName() != 'n_VARIABLE') { + continue; + } + + if ($variable->getConcreteString() != '$this') { + continue; + } + + $this->raiseLintAtNode( + $variable, + pht( + 'The use of `%s` in an anonymous closure is not '. + 'available before PHP 5.4.', + '$this')); + } + } } private function lintPHP54Incompatibilities(XHPASTNode $root) {