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

Move the getFunctionCalls method to ArcanistBaseXHPASTLinter

Summary: Move the `getFunctionCalls` method to the `ArcanistBaseXHPASTLinter` so that it can be used by subclasses.

Test Plan: `arc unit`

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: Korvin, epriestley

Differential Revision: https://secure.phabricator.com/D12472
This commit is contained in:
Joshua Spence 2015-05-20 07:00:29 +10:00
parent ddfdfce3f5
commit 9862d7c0cb
3 changed files with 90 additions and 78 deletions

View file

@ -196,6 +196,35 @@ abstract class ArcanistBaseXHPASTLinter extends ArcanistFutureLinter {
return idx($this->exceptions, $path);
}
/* -( Utility )------------------------------------------------------------ */
/**
* Retrieve all calls to some specified function(s).
*
* Returns all descendant nodes which represent a function call to one of the
* specified functions.
*
* @param XHPASTNode Root node.
* @param list<string> Function names.
* @return AASTNodeList
*/
protected function getFunctionCalls(XHPASTNode $root, array $function_names) {
$calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
$nodes = array();
foreach ($calls as $call) {
$node = $call->getChildByIndex(0);
$name = strtolower($node->getConcreteString());
if (in_array($name, $function_names)) {
$nodes[] = $call;
}
}
return AASTNodeList::newFromTreeAndNodes($root->getTree(), $nodes);
}
public function getSuperGlobalNames() {
return array(
'$GLOBALS',

View file

@ -21,21 +21,6 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
'linter is intended for use in Phabricator libraries and extensions.');
}
public function setDeprecatedFunctions(array $map) {
$this->deprecatedFunctions = $map;
return $this;
}
public function setDynamicStringFunctions(array $map) {
$this->dynamicStringFunctions = $map;
return $this;
}
public function setDynamicStringClasses(array $map) {
$this->dynamicStringClasses = $map;
return $this;
}
public function getLintNameMap() {
return array(
self::LINT_ARRAY_COMBINE => pht(
@ -49,16 +34,6 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
);
}
public function getLintSeverityMap() {
$warning = ArcanistLintSeverity::SEVERITY_WARNING;
return array(
self::LINT_ARRAY_COMBINE => $warning,
self::LINT_DEPRECATED_FUNCTION => $warning,
self::LINT_UNSAFE_DYNAMIC_STRING => $warning,
self::LINT_RAGGED_CLASSTREE_EDGE => $warning,
);
}
public function getLinterName() {
return 'PHLXHP';
}
@ -67,9 +42,15 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
return 'phutil-xhpast';
}
public function getVersion() {
// The version number should be incremented whenever a new rule is added.
return '3';
public function getLintSeverityMap() {
$warning = ArcanistLintSeverity::SEVERITY_WARNING;
return array(
self::LINT_ARRAY_COMBINE => $warning,
self::LINT_DEPRECATED_FUNCTION => $warning,
self::LINT_UNSAFE_DYNAMIC_STRING => $warning,
self::LINT_RAGGED_CLASSTREE_EDGE => $warning,
);
}
public function getLinterConfigurationOptions() {
@ -107,9 +88,15 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
case 'phutil-xhpast.dynamic-string.classes':
$this->setDynamicStringClasses($value);
return;
default:
parent::setLinterConfigurationValue($key, $value);
return;
}
}
return parent::setLinterConfigurationValue($key, $value);
public function getVersion() {
// The version number should be incremented whenever a new rule is added.
return '3';
}
protected function resolveFuture($path, Future $future) {
@ -137,6 +124,27 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
}
}
/* -( Setters )------------------------------------------------------------ */
public function setDeprecatedFunctions(array $map) {
$this->deprecatedFunctions = $map;
return $this;
}
public function setDynamicStringClasses(array $map) {
$this->dynamicStringClasses = $map;
return $this;
}
public function setDynamicStringFunctions(array $map) {
$this->dynamicStringFunctions = $map;
return $this;
}
/* -( Linter Rules )------------------------------------------------------- */
private function lintUnsafeDynamicString(XHPASTNode $root) {
$safe = $this->dynamicStringFunctions + array(
'pht' => 0,
@ -206,40 +214,42 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
}
private function lintArrayCombine(XHPASTNode $root) {
$function_calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
$function_calls = $this->getFunctionCalls($root, array('array_combine'));
foreach ($function_calls as $call) {
$name = $call->getChildByIndex(0)->getConcreteString();
if (strcasecmp($name, 'array_combine') == 0) {
$parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
if (count($parameter_list->getChildren()) !== 2) {
// Wrong number of parameters, but raise that elsewhere if we want.
continue;
}
$parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
$first = $parameter_list->getChildByIndex(0);
$second = $parameter_list->getChildByIndex(1);
if (count($parameter_list->getChildren()) !== 2) {
// Wrong number of parameters, but raise that elsewhere if we want.
continue;
}
if ($first->getConcreteString() == $second->getConcreteString()) {
$this->raiseLintAtNode(
$call,
self::LINT_ARRAY_COMBINE,
pht(
'Prior to PHP 5.4, `%s` fails when given empty arrays. '.
'Prefer to write `%s` as `%s`.',
'array_combine()',
'array_combine(x, x)',
'array_fuse(x)'));
}
$first = $parameter_list->getChildByIndex(0);
$second = $parameter_list->getChildByIndex(1);
if ($first->getConcreteString() == $second->getConcreteString()) {
$this->raiseLintAtNode(
$call,
self::LINT_ARRAY_COMBINE,
pht(
'Prior to PHP 5.4, `%s` fails when given empty arrays. '.
'Prefer to write `%s` as `%s`.',
'array_combine()',
'array_combine(x, x)',
'array_fuse(x)'));
}
}
}
private function lintDeprecatedFunctions(XHPASTNode $root) {
$map = $this->deprecatedFunctions;
$function_calls = $this->getFunctionCalls($root, array_keys($map));
$function_calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
foreach ($function_calls as $call) {
$name = $call->getChildByIndex(0)->getConcreteString();
$name = $call
->getChildByIndex(0)
->getConcreteString();
$name = strtolower($name);
if (empty($map[$name])) {

View file

@ -4298,31 +4298,4 @@ final class ArcanistXHPASTLinter extends ArcanistBaseXHPASTLinter {
}
}
/**
* Retrieve all calls to some specified function(s).
*
* Returns all descendant nodes which represent a function call to one of the
* specified functions.
*
* @param XHPASTNode Root node.
* @param list<string> Function names.
* @return AASTNodeList
*/
protected function getFunctionCalls(XHPASTNode $root, array $function_names) {
$calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
$nodes = array();
foreach ($calls as $call) {
$node = $call->getChildByIndex(0);
$name = strtolower($node->getConcreteString());
if (in_array($name, $function_names)) {
$nodes[] = $call;
}
}
return AASTNodeList::newFromTreeAndNodes($root->getTree(), $nodes);
}
}