Skip to content

Commit

Permalink
WIP #100
Browse files Browse the repository at this point in the history
  • Loading branch information
bmitch committed Sep 12, 2017
1 parent 0caccd2 commit 4a3b388
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 0 deletions.
96 changes: 96 additions & 0 deletions src/Codor/Sniffs/Files/DuplicateArrayKeySniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php declare(strict_types = 1);

namespace Codor\Sniffs\Files;

use PHP_CodeSniffer_Sniff;
use PHP_CodeSniffer_File;

class DuplicateArrayKeySniff implements PHP_CodeSniffer_Sniff
{

private $keysFound = [];

/**
* Returns the token types that this sniff is interested in.
* @return array
*/
public function register(): array
{
return [T_ARRAY, T_OPEN_SHORT_ARRAY];
}

/**
* Processes the tokens that this sniff is interested in.
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
* @param integer $stackPtr The position in the stack where
* the token was found.
* @return void
*/
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$this->keysFound = [];

$tokens = $phpcsFile->getTokens();
dd($tokens);
$arrayTokenIndex = $stackPtr;

$scope = array_slice($tokens, $arrayTokenIndex, null, true);

$tokensToProcess = [];

foreach ($scope as $key => $token) {
if (! in_array($token['type'], ['T_OPEN_SHORT_ARRAY', 'T_ARRAY'])) {
continue;
}
$tokensToProcess[] = $token;

// if ($token['type'] === 'T_ARRAY') {
// unset($scope[$key]);
// }
//
// if ($token['type'] === 'T_WHITESPACE') {
// unset($scope[$key]);
// }
//
// if ($token['type'] === 'T_OPEN_PARENTHESIS') {
// unset($scope[$key]);
// }
//
// if ($token['type'] === 'T_CLOSE_PARENTHESIS') {
// unset($scope[$key]);
// }
//
// if ($token['type'] === 'T_SEMICOLON') {
// unset($scope[$key]);
// }
//
// if ($token['type'] === 'T_CLOSE_CURLY_BRACKET') {
// unset($scope[$key]);
// }
}
dd($tokensToProcess);
$scope = array_values($scope);

foreach ($scope as $key => $token) {
if ($token['type'] !== 'T_DOUBLE_ARROW') {
continue;
}

$arrayKeyTokenFound = $scope[$key - 1];
$keyFound = $arrayKeyTokenFound['content'];
if (in_array($keyFound, $this->keysFound)) {
$phpcsFile->addError("Array contains a duplicate key: {$keyFound}.", $stackPtr);
continue;
}
$this->keysFound[] = $keyFound;
}
}

private function handleToken($token)
{
$opener = $token['bracket_opener'];
$closer = $token['bracket_closer'];
// dd($opener, $closer);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

// $arrayOne = [
// 'foo' => 0,
// 'bar' => 1,
// 'baz' => 2,
// ];
//
$arrayTwo = [
1 => 0,
'2' => ['a','b'],
2 => 1,
3 => 2,
];

$arrayThree = array(
'foo' => 0,
'bar' => 1,
'baz' => 2,
);

$arrayFour = array(
1 => 0,
2 => 1,
3 => 2,
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types = 1);

$array = [
0 => 'foo',
1 => 'bar',
2 => 'baz',
0 => 'bah',
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types = 1);

$array = [
'foo' => 0,
'bar' => 1,
'baz' => 2,
'foo' => 3,
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types = 1);

$array = array(
0 => 'foo',
1 => 'bar',
2 => 'baz',
0 => 'bah',
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types = 1);

$array = array(
'foo' => 0,
'bar' => 1,
'baz' => 2,
'foo' => 3,
);
}
78 changes: 78 additions & 0 deletions tests/Sniffs/Files/DuplicateArrayKeySniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php declare(strict_types = 1);

namespace Codor\Tests\Sniffs\Files;

use Codor\Tests\BaseTestCase;

/** @group Files */
class DuplicateArrayKeySniffTest extends BaseTestCase
{

/**
* Sets up the test class.
* @return void
*/
public function setup()
{
parent::setup();

$this->runner->setSniff('Codor.Files.DuplicateArrayKey')->setFolder(__DIR__.'/Assets/DuplicateArrayKeySniff/');
}

/** @test */
public function it_detects_no_errors_for_an_array_with_no_duplicate_keys()
{
$results = $this->runner->sniff('ArraysWithNoDuplicateKeys.inc');
$this->assertEquals(0, $results->getErrorCount());
$this->assertEquals(0, $results->getWarningCount());
}


/** @test */
public function it_detects_an_array_declared_the_old_way_with_a_duplicate_string_key()
{
$results = $this->runner->sniff('OldArrayWithDuplicateStringKey.inc');
$this->assertEquals(1, $results->getErrorCount());
$this->assertEquals(0, $results->getWarningCount());

$errorMessages = $results->getAllErrorMessages();
$this->assertCount(1, $errorMessages);
$this->assertAllEqual("Array contains a duplicate key: 'foo'.", $errorMessages);
}

/** @test */
public function it_detects_an_array_declared_the_old_way_with_a_duplicate_int_key()
{
$results = $this->runner->sniff('OldArrayWithDuplicateIntKey.inc');
$this->assertEquals(1, $results->getErrorCount());
$this->assertEquals(0, $results->getWarningCount());

$errorMessages = $results->getAllErrorMessages();
$this->assertCount(1, $errorMessages);
$this->assertAllEqual("Array contains a duplicate key: 0.", $errorMessages);
}

/** @test */
public function it_detects_an_array_declared_the_new_way_with_a_duplicate_string_key()
{
$results = $this->runner->sniff('NewArrayWithDuplicateStringKey.inc');
$this->assertEquals(1, $results->getErrorCount());
$this->assertEquals(0, $results->getWarningCount());

$errorMessages = $results->getAllErrorMessages();
$this->assertCount(1, $errorMessages);
$this->assertAllEqual("Array contains a duplicate key: 'foo'.", $errorMessages);
}

/** @test */
public function it_detects_an_array_declared_the_new_way_with_a_duplicate_int_key()
{
$results = $this->runner->sniff('NewArrayWithDuplicateIntKey.inc');
$this->assertEquals(1, $results->getErrorCount());
$this->assertEquals(0, $results->getWarningCount());

$errorMessages = $results->getAllErrorMessages();
$this->assertCount(1, $errorMessages);
$this->assertAllEqual("Array contains a duplicate key: 0.", $errorMessages);
}
}

0 comments on commit 4a3b388

Please sign in to comment.