mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 14:52:40 +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:
parent
ddfdfce3f5
commit
9862d7c0cb
3 changed files with 90 additions and 78 deletions
|
@ -196,6 +196,35 @@ abstract class ArcanistBaseXHPASTLinter extends ArcanistFutureLinter {
|
||||||
return idx($this->exceptions, $path);
|
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() {
|
public function getSuperGlobalNames() {
|
||||||
return array(
|
return array(
|
||||||
'$GLOBALS',
|
'$GLOBALS',
|
||||||
|
|
|
@ -21,21 +21,6 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
'linter is intended for use in Phabricator libraries and extensions.');
|
'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() {
|
public function getLintNameMap() {
|
||||||
return array(
|
return array(
|
||||||
self::LINT_ARRAY_COMBINE => pht(
|
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() {
|
public function getLinterName() {
|
||||||
return 'PHLXHP';
|
return 'PHLXHP';
|
||||||
}
|
}
|
||||||
|
@ -67,9 +42,15 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
return 'phutil-xhpast';
|
return 'phutil-xhpast';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVersion() {
|
public function getLintSeverityMap() {
|
||||||
// The version number should be incremented whenever a new rule is added.
|
$warning = ArcanistLintSeverity::SEVERITY_WARNING;
|
||||||
return '3';
|
|
||||||
|
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() {
|
public function getLinterConfigurationOptions() {
|
||||||
|
@ -107,9 +88,15 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
case 'phutil-xhpast.dynamic-string.classes':
|
case 'phutil-xhpast.dynamic-string.classes':
|
||||||
$this->setDynamicStringClasses($value);
|
$this->setDynamicStringClasses($value);
|
||||||
return;
|
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) {
|
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) {
|
private function lintUnsafeDynamicString(XHPASTNode $root) {
|
||||||
$safe = $this->dynamicStringFunctions + array(
|
$safe = $this->dynamicStringFunctions + array(
|
||||||
'pht' => 0,
|
'pht' => 0,
|
||||||
|
@ -206,40 +214,42 @@ final class ArcanistPhutilXHPASTLinter extends ArcanistBaseXHPASTLinter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function lintArrayCombine(XHPASTNode $root) {
|
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) {
|
foreach ($function_calls as $call) {
|
||||||
$name = $call->getChildByIndex(0)->getConcreteString();
|
$name = $call->getChildByIndex(0)->getConcreteString();
|
||||||
if (strcasecmp($name, 'array_combine') == 0) {
|
$parameter_list = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
|
||||||
$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$first = $parameter_list->getChildByIndex(0);
|
if (count($parameter_list->getChildren()) !== 2) {
|
||||||
$second = $parameter_list->getChildByIndex(1);
|
// Wrong number of parameters, but raise that elsewhere if we want.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($first->getConcreteString() == $second->getConcreteString()) {
|
$first = $parameter_list->getChildByIndex(0);
|
||||||
$this->raiseLintAtNode(
|
$second = $parameter_list->getChildByIndex(1);
|
||||||
$call,
|
|
||||||
self::LINT_ARRAY_COMBINE,
|
if ($first->getConcreteString() == $second->getConcreteString()) {
|
||||||
pht(
|
$this->raiseLintAtNode(
|
||||||
'Prior to PHP 5.4, `%s` fails when given empty arrays. '.
|
$call,
|
||||||
'Prefer to write `%s` as `%s`.',
|
self::LINT_ARRAY_COMBINE,
|
||||||
'array_combine()',
|
pht(
|
||||||
'array_combine(x, x)',
|
'Prior to PHP 5.4, `%s` fails when given empty arrays. '.
|
||||||
'array_fuse(x)'));
|
'Prefer to write `%s` as `%s`.',
|
||||||
}
|
'array_combine()',
|
||||||
|
'array_combine(x, x)',
|
||||||
|
'array_fuse(x)'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function lintDeprecatedFunctions(XHPASTNode $root) {
|
private function lintDeprecatedFunctions(XHPASTNode $root) {
|
||||||
$map = $this->deprecatedFunctions;
|
$map = $this->deprecatedFunctions;
|
||||||
|
$function_calls = $this->getFunctionCalls($root, array_keys($map));
|
||||||
|
|
||||||
$function_calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
|
|
||||||
foreach ($function_calls as $call) {
|
foreach ($function_calls as $call) {
|
||||||
$name = $call->getChildByIndex(0)->getConcreteString();
|
$name = $call
|
||||||
|
->getChildByIndex(0)
|
||||||
|
->getConcreteString();
|
||||||
|
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
if (empty($map[$name])) {
|
if (empty($map[$name])) {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue