Skip to content

Commit

Permalink
Added correct calculation of operator chains.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rarst committed Dec 24, 2019
1 parent 42089f9 commit 0e60509
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added
- correct calculation of operator chains

### Fixed
- binary OR not handled as increment

Expand Down
47 changes: 47 additions & 0 deletions src/CognitiveComplexity/Analyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ final class Analyzer
/** @var bool */
private $isInTryConstruction = false;

/** @var int */
private $lastBooleanOperator = 0;

/**
* B1. Increments
*
* Boolean operators are handled separately due to their chain logic.
*
* @var int[]|string[]
*/
private $increments = [
Expand All @@ -34,11 +40,23 @@ final class Analyzer
T_WHILE,
T_DO,
T_CATCH,
];

/** @var int[]|string[] */
private $booleanOperators = [
T_BOOLEAN_AND, // &&
T_BOOLEAN_OR, // ||
];

/** @var int[]|string[] */
private $operatorChainBreaks = [
T_OPEN_PARENTHESIS,
T_CLOSE_PARENTHESIS,
T_SEMICOLON,
T_INLINE_THEN,
T_INLINE_ELSE,
];

/**
* B3. Nesting increments
* @var int[]|string[]
Expand Down Expand Up @@ -75,12 +93,14 @@ public function computeForFunctionFromTokensAndPosition(array $tokens, int $posi
$functionEndPosition = $tokens[$position]['scope_closer'];

$this->isInTryConstruction = false;
$this->lastBooleanOperator = 0;
$this->cognitiveComplexity = 0;

for ($i = $functionStartPosition + 1; $i < $functionEndPosition; ++$i) {
$currentToken = $tokens[$i];

$this->resolveTryControlStructure($currentToken);
$this->resolveBooleanOperatorChain($currentToken);

if (!$this->isIncrementingToken($currentToken, $tokens, $i)) {
continue;
Expand All @@ -104,6 +124,33 @@ public function computeForFunctionFromTokensAndPosition(array $tokens, int $posi
return $this->cognitiveComplexity;
}

/**
* Keep track of consecutive matching boolean operators, that don't receive increment.
*
* @param mixed[] $token
*/
private function resolveBooleanOperatorChain(array $token): void
{
// Whenever we cross anything that interrupts possible condition we reset chain.
if ($this->lastBooleanOperator && in_array($token['code'], $this->operatorChainBreaks, true)) {
$this->lastBooleanOperator = 0;

return;
}

if (!in_array($token['code'], $this->booleanOperators, true)) {
return;
}

// If we match last operator, there is no increment added for current one.
if ($this->lastBooleanOperator === $token['code']) {
return;
}

++$this->cognitiveComplexity;
$this->lastBooleanOperator = $token['code'];
}

/**
* @param mixed[] $token
*/
Expand Down
2 changes: 1 addition & 1 deletion tests/AnalyzerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function provideTokensAndExpectedCognitiveComplexity(): Iterator
yield [__DIR__ . '/Data/function7.php.inc', 3];
yield [__DIR__ . '/Data/function8.php.inc', 7];
yield [__DIR__ . '/Data/function9.php.inc', 5];
yield [__DIR__ . '/Data/function10.php.inc', 4];
yield [__DIR__ . '/Data/function10.php.inc', 19];
}

/**
Expand Down
25 changes: 22 additions & 3 deletions tests/Data/function10.php.inc
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
<?php

// TODO handle sequences of multiple operators as per spec.

function binary_logical_operators() {

if( true && true ) {} // +1 +1

if( true || true ) {} // +1 +1

if( true && true && true ) {} // +1 +1 +0

if( true || true || true ) {} // +1 +1 +0

if ( // +1
true && true && true // +1 +0
|| true || true // +1 +0
&& true) {} // +1

if ( // +1
true && // +1
!(true && true)) {} // +1

true && true && true; // +1 +0

echo( true && true && true ); // +1 +0

$foo = true && true && true; // +1 +0

return true && true && true; // +1 +0
}

// Cognitive Complexity 4
// Cognitive Complexity 19

0 comments on commit 0e60509

Please sign in to comment.