Differential D20146 Diff 48104 src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php
Changeset View
Changeset View
Standalone View
Standalone View
src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php
Show All 20 Lines | if ($compat_info === null) { | ||||
'/../resources/php_compat_info.json'; | '/../resources/php_compat_info.json'; | ||||
$compat_info = phutil_json_decode(Filesystem::readFile($target)); | $compat_info = phutil_json_decode(Filesystem::readFile($target)); | ||||
} | } | ||||
// Create a whitelist for symbols which are being used conditionally. | // Create a whitelist for symbols which are being used conditionally. | ||||
$whitelist = array( | $whitelist = array( | ||||
'class' => array(), | 'class' => array(), | ||||
'function' => array(), | 'function' => array(), | ||||
'constant' => array(), | |||||
); | ); | ||||
$conditionals = $root->selectDescendantsOfType('n_IF'); | $conditionals = $root->selectDescendantsOfType('n_IF'); | ||||
foreach ($conditionals as $conditional) { | foreach ($conditionals as $conditional) { | ||||
$condition = $conditional->getChildOfType(0, 'n_CONTROL_CONDITION'); | $condition = $conditional->getChildOfType(0, 'n_CONTROL_CONDITION'); | ||||
$function = $condition->getChildByIndex(0); | $function = $condition->getChildByIndex(0); | ||||
if ($function->getTypeName() != 'n_FUNCTION_CALL') { | if ($function->getTypeName() != 'n_FUNCTION_CALL') { | ||||
Show All 9 Lines | foreach ($conditionals as $conditional) { | ||||
} | } | ||||
$function_name = $function_token->getConcreteString(); | $function_name = $function_token->getConcreteString(); | ||||
switch ($function_name) { | switch ($function_name) { | ||||
case 'class_exists': | case 'class_exists': | ||||
case 'function_exists': | case 'function_exists': | ||||
case 'interface_exists': | case 'interface_exists': | ||||
case 'defined': | |||||
$type = null; | $type = null; | ||||
switch ($function_name) { | switch ($function_name) { | ||||
case 'class_exists': | case 'class_exists': | ||||
$type = 'class'; | $type = 'class'; | ||||
break; | break; | ||||
case 'function_exists': | case 'function_exists': | ||||
$type = 'function'; | $type = 'function'; | ||||
break; | break; | ||||
case 'interface_exists': | case 'interface_exists': | ||||
$type = 'interface'; | $type = 'interface'; | ||||
break; | break; | ||||
case 'defined': | |||||
$type = 'constant'; | |||||
break; | |||||
} | } | ||||
$params = $function->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); | $params = $function->getChildOfType(1, 'n_CALL_PARAMETER_LIST'); | ||||
$symbol = $params->getChildByIndex(0); | $symbol = $params->getChildByIndex(0); | ||||
if (!$symbol->isStaticScalar()) { | if (!$symbol->isStaticScalar()) { | ||||
break; | break; | ||||
} | } | ||||
Show All 18 Lines | public function process(XHPASTNode $root) { | ||||
foreach ($calls as $call) { | foreach ($calls as $call) { | ||||
$node = $call->getChildByIndex(0); | $node = $call->getChildByIndex(0); | ||||
$name = $node->getConcreteString(); | $name = $node->getConcreteString(); | ||||
$version = idx($compat_info['functions'], $name, array()); | $version = idx($compat_info['functions'], $name, array()); | ||||
$min = idx($version, 'php.min'); | $min = idx($version, 'php.min'); | ||||
$max = idx($version, 'php.max'); | $max = idx($version, 'php.max'); | ||||
// Check if whitelisted. | |||||
$whitelisted = false; | $whitelisted = false; | ||||
foreach (idx($whitelist['function'], $name, array()) as $range) { | foreach (idx($whitelist['function'], $name, array()) as $range) { | ||||
if (array_intersect($range, array_keys($node->getTokens()))) { | if (array_intersect($range, array_keys($node->getTokens()))) { | ||||
$whitelisted = true; | $whitelisted = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | public function process(XHPASTNode $root) { | ||||
$classes = $root->selectDescendantsOfType('n_CLASS_NAME'); | $classes = $root->selectDescendantsOfType('n_CLASS_NAME'); | ||||
foreach ($classes as $node) { | foreach ($classes as $node) { | ||||
$name = $node->getConcreteString(); | $name = $node->getConcreteString(); | ||||
$version = idx($compat_info['interfaces'], $name, array()); | $version = idx($compat_info['interfaces'], $name, array()); | ||||
$version = idx($compat_info['classes'], $name, $version); | $version = idx($compat_info['classes'], $name, $version); | ||||
$min = idx($version, 'php.min'); | $min = idx($version, 'php.min'); | ||||
$max = idx($version, 'php.max'); | $max = idx($version, 'php.max'); | ||||
// Check if whitelisted. | |||||
$whitelisted = false; | $whitelisted = false; | ||||
foreach (idx($whitelist['class'], $name, array()) as $range) { | foreach (idx($whitelist['class'], $name, array()) as $range) { | ||||
if (array_intersect($range, array_keys($node->getTokens()))) { | if (array_intersect($range, array_keys($node->getTokens()))) { | ||||
$whitelisted = true; | $whitelisted = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if ($whitelisted) { | if ($whitelisted) { | ||||
continue; | continue; | ||||
} | } | ||||
if ($min && version_compare($min, $this->version, '>')) { | if ($min && version_compare($min, $this->version, '>')) { | ||||
$this->raiseLintAtNode( | $this->raiseLintAtNode( | ||||
$node, | $node, | ||||
pht( | pht( | ||||
'This codebase targets PHP %s, but `%s` was not '. | 'This codebase targets PHP %s, but `%s` was not '. | ||||
'introduced until PHP %s.', | 'introduced until PHP %s.', | ||||
$this->version, | $this->version, | ||||
Show All 19 Lines | $constants = $root->selectDescendantsOfTypes(array( | ||||
'n_MAGIC_SCALAR', | 'n_MAGIC_SCALAR', | ||||
)); | )); | ||||
foreach ($constants as $node) { | foreach ($constants as $node) { | ||||
$name = $node->getConcreteString(); | $name = $node->getConcreteString(); | ||||
$version = idx($compat_info['constants'], $name, array()); | $version = idx($compat_info['constants'], $name, array()); | ||||
$min = idx($version, 'php.min'); | $min = idx($version, 'php.min'); | ||||
$max = idx($version, 'php.max'); | $max = idx($version, 'php.max'); | ||||
$whitelisted = false; | |||||
foreach (idx($whitelist['constant'], $name, array()) as $range) { | |||||
if (array_intersect($range, array_keys($node->getTokens()))) { | |||||
$whitelisted = true; | |||||
break; | |||||
} | |||||
} | |||||
if ($whitelisted) { | |||||
continue; | |||||
} | |||||
if ($min && version_compare($min, $this->version, '>')) { | if ($min && version_compare($min, $this->version, '>')) { | ||||
$this->raiseLintAtNode( | $this->raiseLintAtNode( | ||||
$node, | $node, | ||||
pht( | pht( | ||||
'This codebase targets PHP %s, but `%s` was not '. | 'This codebase targets PHP %s, but `%s` was not '. | ||||
'introduced until PHP %s.', | 'introduced until PHP %s.', | ||||
$this->version, | $this->version, | ||||
$name, | $name, | ||||
▲ Show 20 Lines • Show All 235 Lines • Show Last 20 Lines |