diff --git a/src/lint/engine/phutil/PhutilLintEngine.php b/src/lint/engine/phutil/PhutilLintEngine.php index 42d81184..881ec99f 100644 --- a/src/lint/engine/phutil/PhutilLintEngine.php +++ b/src/lint/engine/phutil/PhutilLintEngine.php @@ -94,6 +94,8 @@ class PhutilLintEngine extends ArcanistLintEngine { array( ArcanistXHPASTLinter::LINT_RAGGED_CLASSTREE_EDGE => ArcanistLintSeverity::SEVERITY_WARNING, + ArcanistXHPASTLinter::LINT_PHP_53_FEATURES + => ArcanistLintSeverity::SEVERITY_ERROR, )); $license_linter = new ArcanistApacheLicenseLinter(); $linters[] = $xhpast_linter; diff --git a/src/lint/linter/xhpast/ArcanistXHPASTLinter.php b/src/lint/linter/xhpast/ArcanistXHPASTLinter.php index dd5861bf..75191f5e 100644 --- a/src/lint/linter/xhpast/ArcanistXHPASTLinter.php +++ b/src/lint/linter/xhpast/ArcanistXHPASTLinter.php @@ -54,6 +54,7 @@ final class ArcanistXHPASTLinter extends ArcanistLinter { const LINT_ARRAY_INDEX_SPACING = 28; const LINT_RAGGED_CLASSTREE_EDGE = 29; const LINT_IMPLICIT_FALLTHROUGH = 30; + const LINT_PHP_53_FEATURES = 31; public function getLintNameMap() { @@ -87,6 +88,7 @@ final class ArcanistXHPASTLinter extends ArcanistLinter { self::LINT_ARRAY_INDEX_SPACING => 'Spacing Before Array Index', self::LINT_RAGGED_CLASSTREE_EDGE => 'Class Not abstract Or final', self::LINT_IMPLICIT_FALLTHROUGH => 'Implicit Fallthrough', + self::LINT_PHP_53_FEATURES => 'Use Of PHP 5.3 Features', ); } @@ -120,6 +122,11 @@ final class ArcanistXHPASTLinter extends ArcanistLinter { // which isn't necessary in the general case. self::LINT_RAGGED_CLASSTREE_EDGE => ArcanistLintSeverity::SEVERITY_DISABLED, + + // This is disabled by default because projects don't necessarily target + // a specific minimum version. + self::LINT_PHP_53_FEATURES + => ArcanistLintSeverity::SEVERITY_DISABLED, ); } @@ -190,6 +197,56 @@ final class ArcanistXHPASTLinter extends ArcanistLinter { $this->lintBraceFormatting($root); $this->lintRaggedClasstreeEdges($root); $this->lintImplicitFallthrough($root); + $this->lintPHP53Features($root); + } + + public function lintPHP53Features($root) { + + $functions = $root->selectTokensOfType('T_FUNCTION'); + foreach ($functions as $function) { + + $next = $function->getNextToken(); + while ($next) { + if ($next->isSemantic()) { + break; + } + $next = $next->getNextToken(); + } + + if ($next) { + if ($next->getTypeName() == '(') { + $this->raiseLintAtToken( + $function, + self::LINT_PHP_53_FEATURES, + 'This codebase targets PHP 5.2, but anonymous functions were '. + 'not introduced until PHP 5.3.'); + } + } + } + + $namespaces = $root->selectTokensOfType('T_NAMESPACE'); + foreach ($namespaces as $namespace) { + $this->raiseLintAtToken( + $namespace, + self::LINT_PHP_53_FEATURES, + 'This codebase targets PHP 5.2, but namespaces were not introduced '. + 'until PHP 5.3.'); + } + + // NOTE: This is only "use x;", in anonymous functions the node type is + // n_LEXICAL_VARIABLE_LIST even though both tokens are T_USE. + + // TODO: We parse n_USE in a slightly crazy way right now; that would be + // a better selector once it's fixed. + + $uses = $root->selectDescendantsOfType('n_USE_LIST'); + foreach ($uses as $use) { + $this->raiseLintAtNode( + $use, + self::LINT_PHP_53_FEATURES, + 'This codebase targets PHP 5.2, but namespaces were not introduced '. + 'until PHP 5.3.'); + } } private function lintImplicitFallthrough($root) { diff --git a/src/lint/linter/xhpast/__tests__/data/naming-conventions.lint-test b/src/lint/linter/xhpast/__tests__/data/naming-conventions.lint-test index 78e16a51..65c3e5ab 100644 --- a/src/lint/linter/xhpast/__tests__/data/naming-conventions.lint-test +++ b/src/lint/linter/xhpast/__tests__/data/naming-conventions.lint-test @@ -61,6 +61,7 @@ warning:5:25 warning:8:11 warning:12:10 warning:12:13 +disabled:24:1 warning:26:13 warning:30:3 warning:31:3 diff --git a/src/lint/linter/xhpast/__tests__/data/php53.lint-test b/src/lint/linter/xhpast/__tests__/data/php53.lint-test new file mode 100644 index 00000000..8622b9ac --- /dev/null +++ b/src/lint/linter/xhpast/__tests__/data/php53.lint-test @@ -0,0 +1,13 @@ +