Skip to content

Commit

Permalink
git push origin masterMerge branch 'UFOMelkor-feature/fluent-interfac…
Browse files Browse the repository at this point in the history
…e-detection'
  • Loading branch information
TomasVotruba committed Mar 10, 2017
2 parents ad681f4 + 2b9449f commit 4c0168f
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 8 deletions.
10 changes: 9 additions & 1 deletion src/ObjectCalisthenics/Helper/PropertyFilter.php
Expand Up @@ -2,6 +2,8 @@

namespace ObjectCalisthenics\Helper;

use Nette\Utils\Strings;

final class PropertyFilter
{
/**
Expand All @@ -14,7 +16,13 @@ final class PropertyFilter
public static function filterOutScalarProperties(array $propertyList): array
{
return array_filter($propertyList, function ($property) {
return !in_array($property['type'], self::$scalarPropertyTypes, true);
foreach (self::$scalarPropertyTypes as $scalarPropertyType) {
if (Strings::startsWith($property['type'], $scalarPropertyType)) {
return false;
}
}

return true;
});
}
}
Expand Up @@ -7,6 +7,21 @@

final class OneObjectOperatorPerLineSniff implements Sniff
{
/**
* @var string[]
*/
public $variablesHoldingAFluentInterface = ['$queryBuilder'];

/**
* @var string[]
*/
public $methodsStartingAFluentInterface = ['createQueryBuilder'];

/**
* @var string[]
*/
public $methodsEndingAFluentInterface = ['execute', 'getQuery'];

/**
* @var File
*/
Expand All @@ -23,10 +38,15 @@ final class OneObjectOperatorPerLineSniff implements Sniff
private $callerTokens;

/**
* mixed[]
* mixed[].
*/
private $tokens;

/**
* @var string
*/
private $variableName;

/**
* @return int[]
*/
Expand All @@ -47,8 +67,8 @@ public function process(File $file, $position): void

$this->callerTokens = [];

// $tokens = $file->getTokens();
$pointer = $this->ignoreWhitespace($position + 1);
$this->variableName = $this->tokens[$this->position]['content'];

$token = $this->tokens[$position];
$isOwnCall = ($token['content'] === '$this');
Expand All @@ -69,7 +89,7 @@ private function ignoreWhitespace(int $start): int

private function handleTwoObjectOperators(bool $isOwnCall): void
{
if ($this->callerTokens && !$isOwnCall) {
if ($this->callerTokens && !$isOwnCall && !$this->isInFluentInterfaceMode()) {
$this->file->addError('Only one object operator per line.', $this->position, self::class);
}
}
Expand All @@ -87,13 +107,45 @@ private function handleExcludedFluentInterfaces(array $tmpToken, string $tmpToke
if (
($memberTokenType === 'property' && $tmpTokenType === 'property') ||
($memberTokenType === 'method' && $tmpTokenType === 'property') ||
($memberTokenType === 'method' && $tmpTokenType === 'method' && $memberTokenCount > 1 && $memberToken['token']['content'] !== $tmpToken['content'])
($memberTokenType === 'method' && $tmpTokenType === 'method'
&& $memberTokenCount > 1 && $memberToken['token']['content'] !== $tmpToken['content'] && !$this->isInFluentInterfaceMode())
) {
$this->file->addError('Only one object operator per line.', $this->position, self::class);
}
}

private function handleObjectOperators(int $pointer, bool $isOwnCall): void
private function isInFluentInterfaceMode(): bool
{
$lastEndPoint = $this->computeLastCallOfAnyFrom($this->methodsEndingAFluentInterface);
$lastStartPoint = $this->computeLastCallOfAnyFrom($this->methodsStartingAFluentInterface);

if (in_array($this->variableName, $this->variablesHoldingAFluentInterface)) {
$lastStartPoint = max($lastStartPoint, -1);
}

return $lastStartPoint > -2
&& $lastStartPoint > $lastEndPoint;
}

/**
* @param array $methods
*
* @return int The last position of the method calls within the callerTokens
* or -2 if none of the methods has been called
*/
private function computeLastCallOfAnyFrom(array $methods): int
{
$calls = array_filter($this->callerTokens, function (array $token) use ($methods) {
return in_array($token['token']['content'], $methods);
});
if (count($calls) > 0) {
return array_search(end($calls), $this->callerTokens);
}

return -2;
}

private function handleObjectOperators(int $pointer, bool $isOwnCall)
{
while ($this->tokens[$pointer]['code'] === T_OBJECT_OPERATOR) {
$tmpToken = $this->tokens[++$pointer];
Expand Down
2 changes: 1 addition & 1 deletion src/ObjectCalisthenics/ruleset.xml
Expand Up @@ -71,7 +71,7 @@
<rule ref="ObjectCalisthenics.Classes.ForbiddenPublicProperty">
<properties>
<property name="filesToBeSkipped" type="array"
value="ForbiddenPublicPropertySniff.php,ClassElementLengthSniff.php,FunctionNameLengthSniff.php,AbstractDataStructureLengthSniff.php,MaxNestingLevelSniff.php,FunctionLengthSniff.php,ConstantNameLengthSniff.php,ClassNameLengthSniff.php,VariableNameLengthSniff.php,MethodPerClassLimitSniff.php,PropertyPerClassLimitSniff.php,InstancePropertyPerClassLimitSniff.php"
value="ForbiddenPublicPropertySniff.php,ClassElementLengthSniff.php,FunctionNameLengthSniff.php,AbstractDataStructureLengthSniff.php,MaxNestingLevelSniff.php,FunctionLengthSniff.php,ConstantNameLengthSniff.php,ClassNameLengthSniff.php,VariableNameLengthSniff.php,MethodPerClassLimitSniff.php,PropertyPerClassLimitSniff.php,InstancePropertyPerClassLimitSniff.php,OneObjectOperatorPerLineSniff.php"
/>
</properties>
</rule>
Expand Down
Expand Up @@ -129,7 +129,17 @@ trait TestTrait
trait OkTestTrait
{
/**
* @var array
* @var string[]
*/
protected $array1;

/**
* @var string[]
*/
protected $array2;

/**
* @var string[]
*/
protected $array3;
}
11 changes: 11 additions & 0 deletions tests/Sniffs/CodeAnalysis/OneObjectOperatorPerLineSniffTest.php
Expand Up @@ -18,4 +18,15 @@ public function test(): void

$this->assertSame(2, $errorCount);
}

public function testFluentInterfaces()
{
$codeSnifferRunner = new CodeSnifferRunner();
$errorCount = $codeSnifferRunner->detectErrorCountInFileForSniff(
__DIR__.'/OneObjectOperatorPerLineSniffTestFluentInterface.inc',
OneObjectOperatorPerLineSniff::class
);

$this->assertSame(1, $errorCount);
}
}
@@ -0,0 +1,21 @@
<?php

class Repository
{
public $connection;

public function findSomething()
{
$queryBuilder = $this->connection
->createQueryBuilder()
->select('a.id', 'a.name')
->from('table', 'a');
$this->addConditions($queryBuilder);
return $queryBuilder->execute()->fetchAll();
}

private function addConditions($queryBuilder)
{
$queryBuilder->where('a.active = 1')->andWhere('a.email IS NOT NULL');
}
}

0 comments on commit 4c0168f

Please sign in to comment.