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
35 changes: 32 additions & 3 deletions PHPCSUtils/Utils/ObjectDeclarations.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,11 @@ public static function getClassProperties(File $phpcsFile, $stackPtr)

/**
* Retrieves the name of the class that the specified class extends.
* (works for classes, anonymous classes and interfaces)
*
* Works for classes, anonymous classes and interfaces, though it is strongly recommended
* to use the {@see \PHPCSUtils\Utils\ObjectDeclarations::findExtendedInterfaceNames()}
* method to examine interfaces instead. Interfaces can extend multiple parent interfaces,
* and that use case is not handled by this method.
*
* Main differences with the PHPCS version:
* - Bugs fixed:
Expand All @@ -222,8 +226,10 @@ public static function getClassProperties(File $phpcsFile, $stackPtr)
* - Improved handling of parse errors.
* - The returned name will be clean of superfluous whitespace and/or comments.
*
* @see \PHP_CodeSniffer\Files\File::findExtendedClassName() Original source.
* @see \PHPCSUtils\BackCompat\BCFile::findExtendedClassName() Cross-version compatible version of the original.
* @see \PHP_CodeSniffer\Files\File::findExtendedClassName() Original source.
* @see \PHPCSUtils\BackCompat\BCFile::findExtendedClassName() Cross-version compatible version of
* the original.
* @see \PHPCSUtils\Utils\ObjectDeclarations::findExtendedInterfaceNames() Similar method for extended interfaces.
*
* @since 1.0.0
*
Expand Down Expand Up @@ -271,6 +277,29 @@ public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr)
return self::findNames($phpcsFile, $stackPtr, \T_IMPLEMENTS, Collections::$OOCanImplement);
}

/**
* Retrieves the names of the interfaces that the specified interface extends.
*
* @see \PHPCSUtils\Utils\ObjectDeclarations::findExtendedClassName() Similar method for extended classes.
*
* @since 1.0.0
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
* @param int $stackPtr The stack position of the interface keyword.
*
* @return array|false Array with names of the extended interfaces or FALSE on
* error or if there are no extended interface names.
*/
public static function findExtendedInterfaceNames(File $phpcsFile, $stackPtr)
{
return self::findNames(
$phpcsFile,
$stackPtr,
\T_EXTENDS,
[\T_INTERFACE => \T_INTERFACE]
);
}

/**
* Retrieves the names of the extended classes or interfaces or the implemented
* interfaces that the specific class/interface declaration extends/implements.
Expand Down
33 changes: 33 additions & 0 deletions Tests/Utils/ObjectDeclarations/FindExtendedInterfaceNamesTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/* testNotAnInterface */
function notAnInterface() {}

/* testInterface */
interface testInterface {}

/* testExtendedInterface */
interface testExtendedInterface extends testInterface {}

/* testMultiExtendedInterface */
interface testMultiExtendedInterface extends testInterfaceA, testInterfaceB {}

/* testExtendedNamespacedInterface */
interface testNamespacedInterface extends \PHPCSUtils\Tests\ObjectDeclarations\testInterface {}

/* testMultiExtendedNamespacedInterface */
interface testMultiNamespacedInterface extends \PHPCSUtils\Tests\ObjectDeclarations\testInterfaceA, \PHPCSUtils\Tests\ObjectDeclarations\testFEINInterfaceB {}

/* testMultiExtendedInterfaceWithComments */
interface testMultiExtendedInterfaceWithComments
extends
/* a comment */
testInterfaceA,
\PHPCSUtils\Tests /* comment */ \Some \ Declarations \testInterfaceB,
\testInterfaceC /* comment */
{
}

// Intentional parse error. Has to be the last test in the file.
/* testParseError */
interface testParseError extends testInterface
119 changes: 119 additions & 0 deletions Tests/Utils/ObjectDeclarations/FindExtendedInterfaceNamesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Tests\Utils\ObjectDeclarations;

use PHPCSUtils\TestUtils\UtilityMethodTestCase;
use PHPCSUtils\Utils\ObjectDeclarations;

/**
* Tests for the \PHPCSUtils\Utils\ObjectDeclarations::findExtendedInterfaceNames() method.
*
* @covers \PHPCSUtils\Utils\ObjectDeclarations::findExtendedInterfaceNames
* @covers \PHPCSUtils\Utils\ObjectDeclarations::findNames
*
* @group objectdeclarations
*
* @since 1.0.0
*/
class FindExtendedInterfaceNamesTest extends UtilityMethodTestCase
{

/**
* Test getting a `false` result when a non-existent token is passed.
*
* @return void
*/
public function testNonExistentToken()
{
$result = ObjectDeclarations::findExtendedInterfaceNames(self::$phpcsFile, 100000);
$this->assertFalse($result);
}

/**
* Test getting a `false` result when a token other than one of the supported tokens is passed.
*
* @return void
*/
public function testNotAnInterface()
{
$token = $this->getTargetToken('/* testNotAnInterface */', [\T_FUNCTION]);
$result = ObjectDeclarations::findExtendedInterfaceNames(self::$phpcsFile, $token);
$this->assertFalse($result);
}

/**
* Test retrieving the names of the interfaces being extended by another interface.
*
* @dataProvider dataFindExtendedInterfaceNames
*
* @param string $testMarker The comment which prefaces the target token in the test file.
* @param array|false $expected Expected function output.
*
* @return void
*/
public function testFindExtendedInterfaceNames($testMarker, $expected)
{
$interface = $this->getTargetToken($testMarker, [\T_INTERFACE]);
$result = ObjectDeclarations::findExtendedInterfaceNames(self::$phpcsFile, $interface);
$this->assertSame($expected, $result);
}

/**
* Data provider.
*
* @see testFindExtendedInterfaceNames() For the array format.
*
* @return array
*/
public function dataFindExtendedInterfaceNames()
{
return [
'not-extended' => [
'/* testInterface */',
false,
],
'extends-one' => [
'/* testExtendedInterface */',
['testInterface'],
],
'extends-two' => [
'/* testMultiExtendedInterface */',
[
'testInterfaceA',
'testInterfaceB',
],
],
'extends-one-namespaced' => [
'/* testExtendedNamespacedInterface */',
['\PHPCSUtils\Tests\ObjectDeclarations\testInterface'],
],
'extends-two-namespaced' => [
'/* testMultiExtendedNamespacedInterface */',
[
'\PHPCSUtils\Tests\ObjectDeclarations\testInterfaceA',
'\PHPCSUtils\Tests\ObjectDeclarations\testFEINInterfaceB',
],
],
'extends-with-comments' => [
'/* testMultiExtendedInterfaceWithComments */',
[
'testInterfaceA',
'\PHPCSUtils\Tests\Some\Declarations\testInterfaceB',
'\testInterfaceC',
],
],
'parse-error' => [
'/* testParseError */',
false,
],
];
}
}