Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detecting duplicated array keys #350

Closed

Conversation

rafalwrzeszcz
Copy link
Contributor

This is the implementation fo #322 request.

I added it to Design section, any better idea?

@ravage84 ravage84 changed the title Detectign duplicated array keys. Detecting duplicated array keys Feb 29, 2016
@ravage84
Copy link
Member

@rafalwrzeszcz thanks for the PR.

About the Ruleset, I think CleanCode or UnusedCode would be a better fit, as duplicated array keys have nothing to do with software design.

https://phpmd.org/rules/index.html

https://phpmd.org/rules/index.html#clean-code-rules
https://phpmd.org/rules/index.html#unused-code-rules

@ravage84
Copy link
Member

AppVeyor fails:
https://ci.appveyor.com/project/phpmd/phpmd/build/57

There were 10 errors:

1) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleNotAppliesToMethodWithAssotiativeArrayDefinitionWithoutDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

2) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToMethodWithAssotiativeArrayDefinitionWithDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

3) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToMethodWithAssotiativeArrayDefinitionWithDuplicatedMixedTypeKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

4) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToMethodWithAssotiativeArrayDefinitionWithDuplicatedMixedQuotedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

5) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesMultipleTimesToMethodWithAssotiativeArrayDefinitionWithDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

6) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleNotAppliesToFunctionWithAssotiativeArrayDefinitionWithoutDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

7) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToFunctionWithAssotiativeArrayDefinitionWithDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

8) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToFunctionWithAssotiativeArrayDefinitionWithDuplicatedMixedTypeKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

9) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesToFunctionWithAssotiativeArrayDefinitionWithDuplicatedMixedQuotedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

10) PHPMD\Rule\Design\DuplicatedArrayKeyTest::testRuleAppliesMultipleTimesToFunctionWithAssotiativeArrayDefinitionWithDuplicatedKeys
TypeError: Argument 1 passed to PHPUnit_Framework_TestCase::onNotSuccessfulTest() must be an instance of Exception, instance of Error given, called in C:\projects\phpmd\vendor\phpunit\phpunit\src\Framework\TestCase.php on line 851

FAILURES! 
Tests: 434, Assertions: 513, Errors: 10. 

@rafalwrzeszcz
Copy link
Contributor Author

@ravage84 Moved to clean code. Any clue why AppVeyor is failing? The same test suite runs fine on Scrutinizer and Travis (and also locally).

It may be PHP7-related, but Travis build for PHP7 succeeds.

@ravage84
Copy link
Member

Nope, no idea. Can you try to execute the tests on a Windows machine with PHP7?

@@ -0,0 +1,8 @@
<?php

class testRuleNotAppliesToMethodWithoutArrayDefinition
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, if that's really necessary.

@ravage84
Copy link
Member

Would your code be able to detect duplicated array keys, if one would use a constant or class constant as the array key(s)?

For example:

define('FOO', 'foobar');
return array(
   FOO => 42,
   FOO => 43,
);
const FOO = 'foobar';
public function testBla() {
    return array(
       self::FOO => 42,
       self::FOO => 43,
    );
}

or mixed:

define('FOO', 'foobar');
return array(
   FOO => 42,
   'foobar' => 43,
);
const FOO = 'foobar';
public function testBla() {
    return array(
       self::FOO => 42,
       'foobar' => 43,
    );
}

@ravage84 ravage84 self-assigned this Feb 29, 2016
@ravage84 ravage84 added this to the 2.4.0 milestone Feb 29, 2016
@rafalwrzeszcz
Copy link
Contributor Author

@ravage84 No and I don't think it's feasible in a reasonable time/PR size - constant can come from outside of the file or even a library.

But it should detect keys defined with same constant twice (like self::FOO => 'one', self::FOO => 'two') as it checks the literal definition.

@ravage84
Copy link
Member

That's fine for me. Just wanted to check.

@rafalwrzeszcz
Copy link
Contributor Author

@ravage84 Then it has to wait few days, not sure if I will find some time to set up env for Win before the weekend.

@ravage84
Copy link
Member

ravage84 commented Mar 1, 2016

Take your time. I would like @manuelpichler to have an eye on this anyway. But I know he is very busy lately.

@ravage84 ravage84 modified the milestones: 2.4.0, 2.5.0 Mar 8, 2016
@ravage84 ravage84 modified the milestones: 2.5.0, 2.6.0 Jun 28, 2016
@ravage84 ravage84 modified the milestones: 2.6.0, 2.7.0 Jan 30, 2017
@ravage84
Copy link
Member

@rafalwrzeszcz how is your status on this?

@ravage84
Copy link
Member

ravage84 commented Jun 2, 2017

@rafalwrzeszcz can you give me an update on this?

foreach ($node->findChildrenOfType('ArrayElement') as $arrayElement) {
// member of nested array - will be handled when `apply()` moves to that array
// could be nice if PDepend provides a method to fetch just direct children
if ($arrayElement->getParent() != $node) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one will end up with:
PHP Fatal error: Nesting level too deep - recursive dependency? in src\main\php\PHPMD\Rule\CleanCode\DuplicatedArrayKey.php on line 87
Comparing objects in PHP is recursive (deep-comparison).


$children = $arrayElement->getChildren();
// non-associative array
if (count($children) == 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one could be improved, as given array:

$arr = [
    'foo',
    'bar',
    '' => 'baz',
    0 => '20',
    '0' => '30',
    false => '40',
    1 => '50',
    '1' => '60',
    true => '70',
    null => '80',
];

Will result in:

Array
(
    [0] => 40
    [1] => 70
    [] => 80
)

All due to casting.

// numbers don't need any processing, they have plain value

// this is string literal, not number
if (in_array($key[0], array('"', '\''))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be simplified to trim($key, '\'"');

eeree added a commit to eeree/phpmd that referenced this pull request Jun 5, 2017
@ravage84
Copy link
Member

ravage84 commented Jun 6, 2017

Closing as superseded by #484

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

None yet

3 participants