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

Raise a linter error when removed symbols are used

Summary: Ref T5141. Utilize the `'max'` key from the `php_compat_info.json` compatibility map to lint for the use of classes/functions/symbols which have been removed from the target PHP version.

Test Plan: Added a test case for `arc unit`.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: epriestley, Korvin

Maniphest Tasks: T5141

Differential Revision: https://secure.phabricator.com/D10538
This commit is contained in:
Joshua Spence 2015-01-04 18:38:07 +11:00
parent b31e9c0cfe
commit a10002adec
2 changed files with 101 additions and 31 deletions

View file

@ -201,7 +201,7 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
public function getVersion() {
// The version number should be incremented whenever a new rule is added.
return '11';
return '12';
}
protected function resolveFuture($path, Future $future) {
@ -451,27 +451,44 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
foreach ($calls as $call) {
$node = $call->getChildByIndex(0);
$name = $node->getConcreteString();
$version = idx($compat_info['functions'], $name);
if ($version && version_compare($version['min'], $this->version, '>')) {
// Check if whitelisted.
$whitelisted = false;
foreach (idx($whitelist['function'], $name, array()) as $range) {
if (array_intersect($range, array_keys($node->getTokens()))) {
$whitelisted = true;
break;
}
$version = idx($compat_info['functions'], $name, array());
$min = idx($version, 'min');
$max = idx($version, 'max');
// Check if whitelisted.
$whitelisted = false;
foreach (idx($whitelist['function'], $name, array()) as $range) {
if (array_intersect($range, array_keys($node->getTokens()))) {
$whitelisted = true;
break;
}
}
if ($whitelisted) {
continue;
}
if ($whitelisted) {
continue;
}
if ($min && version_compare($min, $this->version, '>')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->version}, but `{$name}()` was ".
"not introduced until PHP {$version['min']}.");
pht(
'This codebase targets PHP %s, but `%s()` was not '.
'introduced until PHP %s.',
$this->version,
$name,
$min));
} else if ($max && version_compare($max, $this->version, '<')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
pht(
'This codebase targets PHP %s, but `%s()` was '.
'removed in PHP %s.',
$this->version,
$name,
$max));
} else if (array_key_exists($name, $compat_info['params'])) {
$params = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
foreach (array_values($params->getChildren()) as $i => $param) {
@ -480,9 +497,13 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
$this->raiseLintAtNode(
$param,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->version}, but parameter ".
($i + 1)." of `{$name}()` was not introduced until PHP ".
"{$version}.");
pht(
'This codebase targets PHP %s, but parameter %d '.
'of `%s()` was not introduced until PHP %s.',
$this->version,
$i + 1,
$name,
$version));
}
}
}
@ -494,15 +515,21 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->windowsVersion} on Windows, ".
"but `{$name}()` is not available there.");
pht(
'This codebase targets PHP %s on Windows, '.
'but `%s()` is not available there.',
$this->windowsVersion,
$name));
} else if (version_compare($windows, $this->windowsVersion, '>')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->windowsVersion} on Windows, ".
"but `{$name}()` is not available there until PHP ".
"{$this->windowsVersion}.");
pht(
'This codebase targets PHP %s on Windows, '.
'but `%s()` is not available there until PHP %s.',
$this->windowsVersion,
$name,
$windows));
}
}
}
@ -510,9 +537,10 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
$classes = $root->selectDescendantsOfType('n_CLASS_NAME');
foreach ($classes as $node) {
$name = $node->getConcreteString();
$version = idx($compat_info['interfaces'], $name);
$version = idx($compat_info['interfaces'], $name, array());
$version = idx($compat_info['classes'], $name, $version);
if ($version && version_compare($version['min'], $this->version, '>')) {
$min = idx($version, 'min');
$max = idx($version, 'max');
// Check if whitelisted.
$whitelisted = false;
foreach (idx($whitelist['class'], $name, array()) as $range) {
@ -526,11 +554,26 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
continue;
}
if ($min && version_compare($min, $this->version, '>')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->version}, but `{$name}` was not ".
"introduced until PHP {$version['min']}.");
pht(
'This codebase targets PHP %s, but `%s` was not '.
'introduced until PHP %s.',
$this->version,
$name,
$min));
} else if ($max && version_compare($max, $this->version, '<')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
pht(
'This codebase targets PHP %s, but `%s` was '.
'removed in PHP %s.',
$this->version,
$name,
$max));
}
}
@ -540,13 +583,30 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
$constants = $root->selectDescendantsOfType('n_SYMBOL_NAME');
foreach ($constants as $node) {
$name = $node->getConcreteString();
$version = idx($compat_info['constants'], $name);
if ($version && version_compare($version['min'], $this->version, '>')) {
$version = idx($compat_info['constants'], $name, array());
$min = idx($version, 'min');
$max = idx($version, 'max');
if ($min && version_compare($min, $this->version, '>')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
"This codebase targets PHP {$this->version}, but `{$name}` was not ".
"introduced until PHP {$version['min']}.");
pht(
'This codebase targets PHP %s, but `%s` was not '.
'introduced until PHP %s.',
$this->version,
$name,
$min));
} else if ($max && version_compare($max, $this->version, '<')) {
$this->raiseLintAtNode(
$node,
self::LINT_PHP_COMPATIBILITY,
pht(
'This codebase targets PHP %s, but `%s` was '.
'removed in PHP %s.',
$this->version,
$name,
$max));
}
}

View file

@ -0,0 +1,10 @@
<?php
define_syslog_variables();
var_dump(STREAM_ENFORCE_SAFE_MODE);
~~~~~~~~~~
error:3:1
error:4:10
~~~~~~~~~~
~~~~~~~~~~
{"config": {"xhpast.php-version": "5.4.0"}}