Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ http://pear.php.net/dtd/package-2.0.xsd">
<file baseinstalldir="" name="AcceptTest.php" role="test" />
</dir>
</dir>
<dir name="Tokenizer">
<dir name="PHP">
<file baseinstalldir="" name="T_AnonClassParenthesisOwnerTest.inc" role="test" />
<file baseinstalldir="" name="T_AnonClassParenthesisOwnerTest.php" role="test" />
</dir>
</dir>
<file baseinstalldir="" name="AbstractMethodUnitTest.php" role="test" />
<file baseinstalldir="" name="AllTests.php" role="test" />
<file baseinstalldir="" name="ErrorSuppressionTest.php" role="test" />
Expand Down Expand Up @@ -1988,6 +1994,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<install as="CodeSniffer/Core/File/IsReferenceTest.inc" name="tests/Core/File/IsReferenceTest.inc" />
<install as="CodeSniffer/Core/Filters/Filter/AcceptTest.php" name="tests/Core/Filters/Filter/AcceptTest.php" />
<install as="CodeSniffer/Core/Filters/Filter/AcceptTest.xml" name="tests/Core/Filters/Filter/AcceptTest.xml" />
<install as="CodeSniffer/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.php" name="tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.php" />
<install as="CodeSniffer/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.inc" name="tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.inc" />
<install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
<install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
</filelist>
Expand Down Expand Up @@ -2025,6 +2033,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<install as="CodeSniffer/Core/File/IsReferenceTest.inc" name="tests/Core/File/IsReferenceTest.inc" />
<install as="CodeSniffer/Core/Filters/Filter/AcceptTest.php" name="tests/Core/Filters/Filter/AcceptTest.php" />
<install as="CodeSniffer/Core/Filters/Filter/AcceptTest.xml" name="tests/Core/Filters/Filter/AcceptTest.xml" />
<install as="CodeSniffer/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.php" name="tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.php" />
<install as="CodeSniffer/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.inc" name="tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.inc" />
<install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
<install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
<ignore name="bin/phpcs.bat" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public function register()
$this->ignoreTokens[T_CLOSE_SQUARE_BRACKET] = T_CLOSE_SQUARE_BRACKET;
$this->ignoreTokens[T_CLOSE_SHORT_ARRAY] = T_CLOSE_SHORT_ARRAY;

$this->ignoreTokens[T_ANON_CLASS] = T_ANON_CLASS;
$this->ignoreTokens[T_USE] = T_USE;
$this->ignoreTokens[T_DECLARE] = T_DECLARE;
$this->ignoreTokens[T_THROW] = T_THROW;
Expand Down
19 changes: 18 additions & 1 deletion src/Tokenizers/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,23 @@ protected function processAdditional()
echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL;
}

if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS
&& isset($this->tokens[$x]['parenthesis_closer']) === true
) {
$closer = $this->tokens[$x]['parenthesis_closer'];

$this->tokens[$i]['parenthesis_opener'] = $x;
$this->tokens[$i]['parenthesis_closer'] = $closer;
$this->tokens[$i]['parenthesis_owner'] = $i;
$this->tokens[$x]['parenthesis_owner'] = $i;
$this->tokens[$closer]['parenthesis_owner'] = $i;

if (PHP_CODESNIFFER_VERBOSITY > 1) {
$line = $this->tokens[$i]['line'];
echo "\t\t* added parenthesis keys to T_ANON_CLASS token $i on line $line".PHP_EOL;
}
}

for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) {
if (isset($this->tokens[$x]['conditions'][$i]) === false) {
continue;
Expand All @@ -1570,7 +1587,7 @@ protected function processAdditional()
echo "\t\t* cleaned $x ($type) *".PHP_EOL;
}
}
}
}//end if

continue;
} else if ($this->tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) {
Expand Down
25 changes: 13 additions & 12 deletions src/Util/Tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,19 @@ final class Tokens
* @var array<int, int>
*/
public static $parenthesisOpeners = [
T_ARRAY => T_ARRAY,
T_LIST => T_LIST,
T_FUNCTION => T_FUNCTION,
T_CLOSURE => T_CLOSURE,
T_WHILE => T_WHILE,
T_FOR => T_FOR,
T_FOREACH => T_FOREACH,
T_SWITCH => T_SWITCH,
T_IF => T_IF,
T_ELSEIF => T_ELSEIF,
T_CATCH => T_CATCH,
T_DECLARE => T_DECLARE,
T_ARRAY => T_ARRAY,
T_LIST => T_LIST,
T_FUNCTION => T_FUNCTION,
T_CLOSURE => T_CLOSURE,
T_ANON_CLASS => T_ANON_CLASS,
T_WHILE => T_WHILE,
T_FOR => T_FOR,
T_FOREACH => T_FOREACH,
T_SWITCH => T_SWITCH,
T_IF => T_IF,
T_ELSEIF => T_ELSEIF,
T_CATCH => T_CATCH,
T_DECLARE => T_DECLARE,
];

/**
Expand Down
19 changes: 19 additions & 0 deletions tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/* testNoParentheses */
$anonClass = new class {
function __construct() {}
};

/* testNoParenthesesAndEmptyTokens */
$anonClass = new class // phpcs:ignore Standard.Cat
{
function __construct() {}
};

/* testWithParentheses */
$anonClass = new class() {};

/* testWithParenthesesAndEmptyTokens */
$anonClass = new class /*comment */
() {};
144 changes: 144 additions & 0 deletions tests/Core/Tokenizer/PHP/T_AnonClassParenthesisOwnerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php
/**
* Tests the adding of the "parenthesis" keys to an anonymous class token.
*
* @author Juliette Reinders Folmer <[email protected]>
* @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
*/

namespace PHP_CodeSniffer\Tests\Core\Tokenizer\PHP;

use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;

class T_AnonClassParenthesisOwnerTest extends AbstractMethodUnitTest
{


/**
* Test that anonymous class tokens without parenthesis do not get assigned a parenthesis owner.
*
* @param string $testMarker The comment which prefaces the target token in the test file.
*
* @dataProvider dataAnonClassNoParentheses
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
*
* @return void
*/
public function testAnonClassNoParentheses($testMarker)
{
$tokens = self::$phpcsFile->getTokens();

$anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS);
$this->assertFalse(array_key_exists('parenthesis_owner', $tokens[$anonClass]));
$this->assertFalse(array_key_exists('parenthesis_opener', $tokens[$anonClass]));
$this->assertFalse(array_key_exists('parenthesis_closer', $tokens[$anonClass]));

}//end testAnonClassNoParentheses()


/**
* Test that the next open/close parenthesis after an anonymous class without parenthesis
* do not get assigned the anonymous class as a parenthesis owner.
*
* @param string $testMarker The comment which prefaces the target token in the test file.
*
* @dataProvider dataAnonClassNoParentheses
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
*
* @return void
*/
public function testAnonClassNoParenthesesNextOpenClose($testMarker)
{
$tokens = self::$phpcsFile->getTokens();
$function = $this->getTargetToken($testMarker, T_FUNCTION);

$opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS);
$this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener]));
$this->assertSame($function, $tokens[$opener]['parenthesis_owner']);

$closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS);
$this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer]));
$this->assertSame($function, $tokens[$closer]['parenthesis_owner']);

}//end testAnonClassNoParenthesesNextOpenClose()


/**
* Data provider.
*
* @see testAnonClassNoParentheses()
* @see testAnonClassNoParenthesesNextOpenClose()
*
* @return array
*/
public function dataAnonClassNoParentheses()
{
return [
['/* testNoParentheses */'],
['/* testNoParenthesesAndEmptyTokens */'],
];

}//end dataAnonClassNoParentheses()


/**
* Test that anonymous class tokens with parenthesis get assigned a parenthesis owner,
* opener and closer; and that the opener/closer get the anonymous class assigned as owner.
*
* @param string $testMarker The comment which prefaces the target token in the test file.
*
* @dataProvider dataAnonClassWithParentheses
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
*
* @return void
*/
public function testAnonClassWithParentheses($testMarker)
{
$tokens = self::$phpcsFile->getTokens();
$anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS);
$opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS);
$closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS);

$this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$anonClass]));
$this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$anonClass]));
$this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$anonClass]));
$this->assertSame($anonClass, $tokens[$anonClass]['parenthesis_owner']);
$this->assertSame($opener, $tokens[$anonClass]['parenthesis_opener']);
$this->assertSame($closer, $tokens[$anonClass]['parenthesis_closer']);

$this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener]));
$this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$opener]));
$this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$opener]));
$this->assertSame($anonClass, $tokens[$opener]['parenthesis_owner']);
$this->assertSame($opener, $tokens[$opener]['parenthesis_opener']);
$this->assertSame($closer, $tokens[$opener]['parenthesis_closer']);

$this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer]));
$this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$closer]));
$this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$closer]));
$this->assertSame($anonClass, $tokens[$closer]['parenthesis_owner']);
$this->assertSame($opener, $tokens[$closer]['parenthesis_opener']);
$this->assertSame($closer, $tokens[$closer]['parenthesis_closer']);

}//end testAnonClassWithParentheses()


/**
* Data provider.
*
* @see testAnonClassWithParentheses()
*
* @return array
*/
public function dataAnonClassWithParentheses()
{
return [
['/* testWithParentheses */'],
['/* testWithParenthesesAndEmptyTokens */'],
];

}//end dataAnonClassWithParentheses()


}//end class