1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-09-20 08:58:55 +02:00

Add PHP lint check for expressions which can be statically evaluated

Summary:
This is pretty coarse and could be refined, but I often do this when testing:

  lang=diff
  - if (some_complicated_condition())
  + if (true || some_complicated_condition())

aran has caught me not only doing it but sending out diffs with it like 30
times. Catch it in lint instead.

Test Plan:
Unit test, added a "true || $junk" to the code and linted it.

Reviewed By: aran
Reviewers: aran, jungejason, tuomaspelkonen, pad
CC: aran
Differential Revision: 447
This commit is contained in:
epriestley 2011-06-13 08:58:01 -07:00
parent 42c6f00315
commit 65c0d07935
2 changed files with 62 additions and 10 deletions

View file

@ -172,25 +172,70 @@ class ArcanistXHPASTLinter extends ArcanistLinter {
'>' => true, '>' => true,
); );
static $logical = array(
'||' => true,
'&&' => true,
);
foreach ($expressions as $expr) { foreach ($expressions as $expr) {
$operator = $expr->getChildByIndex(1)->getConcreteString(); $operator = $expr->getChildByIndex(1)->getConcreteString();
if (empty($operators[$operator])) { if (!empty($operators[$operator])) {
continue; $left = $expr->getChildByIndex(0)->getSemanticString();
$right = $expr->getChildByIndex(2)->getSemanticString();
if ($left == $right) {
$this->raiseLintAtNode(
$expr,
self::LINT_TAUTOLOGICAL_EXPRESSION,
'Both sides of this expression are identical, so it always '.
'evaluates to a constant.');
}
} }
$left = $expr->getChildByIndex(0)->getSemanticString(); if (!empty($logical[$operator])) {
$right = $expr->getChildByIndex(2)->getSemanticString(); $left = $expr->getChildByIndex(0)->getSemanticString();
$right = $expr->getChildByIndex(2)->getSemanticString();
if ($left == $right) { // NOTE: These will be null to indicate "could not evaluate".
$this->raiseLintAtNode( $left = $this->evaluateStaticBoolean($left);
$expr, $right = $this->evaluateStaticBoolean($right);
self::LINT_TAUTOLOGICAL_EXPRESSION,
'Both sides of this expression are identical, so it always '. if (($operator == '||' && ($left === true || $right === true)) ||
'evaluates to a constant.'); ($operator == '&&' && ($left === false || $right === false))) {
$this->raiseLintAtNode(
$expr,
self::LINT_TAUTOLOGICAL_EXPRESSION,
'The logical value of this expression is static. Did you forget '.
'to remove some debugging code?');
}
} }
} }
} }
/**
* Statically evaluate a boolean value from an XHP tree.
*
* TODO: Improve this and move it to XHPAST proper?
*
* @param string The "semantic string" of a single value.
* @return mixed ##true## or ##false## if the value could be evaluated
* statically; ##null## if static evaluation was not possible.
*/
private function evaluateStaticBoolean($string) {
switch (strtolower($string)) {
case '0':
case 'null':
case 'false':
return false;
case '1':
case 'true':
return true;
}
return null;
}
protected function lintHashComments($root) { protected function lintHashComments($root) {
$tokens = $root->getTokens(); $tokens = $root->getTokens();
foreach ($tokens as $token) { foreach ($tokens as $token) {

View file

@ -15,7 +15,14 @@ if ($x == $y) {
// See xhpast 0.54 -> 0.55. // See xhpast 0.54 -> 0.55.
return $a->sub->value < $b->sub->value; return $a->sub->value < $b->sub->value;
$skip_cache = true || $some_complicated_expression;
$skip_cache = $a || $b;
$skip_cache = false && something();
$skip_cache = f();
~~~~~~~~~~ ~~~~~~~~~~
error:3:5 error:3:5
error:6:5 error:6:5
error:9:5 error:9:5
error:18:15
error:20:15