Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Fix: Ignore method named after reserved keywords #41

Merged
merged 3 commits into from
Apr 25, 2018
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
28 changes: 27 additions & 1 deletion src/ClassFileLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,22 @@ public function accept()
$contents = file_get_contents($file->getRealPath());
$tokens = token_get_all($contents);
$count = count($tokens);
$inFunctionDeclaration = false;
for ($i = 0; $i < $count; $i++) {
$token = $tokens[$i];

// single character token found; skip
if (! is_array($token)) {
// single character token found; skip
// If we were in a function declaration, and we encounter an
// opening paren, reset the $inFunctionDeclaration flag.
if ('(' === $token) {
$inFunctionDeclaration = false;
}

$i++;
continue;
}

switch ($token[0]) {
case T_NAMESPACE:
// Namespace found; grab it for later
Expand Down Expand Up @@ -116,13 +125,23 @@ public function accept()
$savedNamespace = $namespace;
}
break;
case T_FUNCTION:
$inFunctionDeclaration = true;
break;
case T_TRAIT:
case T_CLASS:
// ignore T_CLASS after T_DOUBLE_COLON to allow PHP >=5.5 FQCN scalar resolution
if ($i > 0 && is_array($tokens[$i - 1]) && $tokens[$i - 1][0] === T_DOUBLE_COLON) {
break;
}

// Ignore if we are within a function declaration;
// functions are allowed to be named after keywords
// such as class, interface, and trait.
if ($inFunctionDeclaration) {
break;
}

// ignore anonymous classes on PHP 7.1 and greater
if ($i >= 2
&& \is_array($tokens[$i - 1])
Expand All @@ -137,6 +156,13 @@ public function accept()
case T_INTERFACE:
// Abstract class, class, interface or trait found

// Ignore if we are within a function declaration;
// functions are allowed to be named after keywords
// such as class, interface, and trait.
if ($inFunctionDeclaration) {
break;
}

// Get the classname
for ($i++; $i < $count; $i++) {
$token = $tokens[$i];
Expand Down
39 changes: 29 additions & 10 deletions test/ClassFileLocatorTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see https://github.com/zendframework/zend-file for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-file/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\File;
Expand All @@ -14,11 +12,6 @@
use Zend\File\Exception;
use Zend\File\PhpClassFile;

/**
* Test class for Zend\File\ClassFileLocator
*
* @group Zend_File
*/
class ClassFileLocatorTest extends TestCase
{
public function testConstructorThrowsInvalidArgumentExceptionForInvalidStringDirectory()
Expand Down Expand Up @@ -177,4 +170,30 @@ public function testIgnoresAnonymousClasses()

$this->assertEquals($expected, $classNames);
}

/**
* @requires PHP 7.1
*/
public function testIgnoresMethodsNamedAfterKeywords()
{
$classFileLocator = new ClassFileLocator(__DIR__ . '/TestAsset/WithMethodsNamedAfterKeywords');

$classFiles = \iterator_to_array($classFileLocator);

$this->assertCount(2, $classFiles);

$classNames = \array_reduce($classFiles, function (array $classNames, PhpClassFile $classFile) {
return \array_merge(
$classNames,
$classFile->getClasses()
);
}, []);

$expected = [
TestAsset\WithMethodsNamedAfterKeywords\WithoutReturnTypeDeclaration::class,
TestAsset\WithMethodsNamedAfterKeywords\WithReturnTypeDeclaration::class,
];

$this->assertEquals($expected, $classNames, '', 0.0, 10, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/zendframework/zend-file for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-file/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\File\TestAsset\WithMethodsNamedAfterKeywords;

final class WithReturnTypeDeclaration
{
public function class() : string
{
}

public function interface() : string
{
}

public function trait() : string
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/zendframework/zend-file for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-file/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\File\TestAsset\WithMethodsNamedAfterKeywords;

final class WithoutReturnTypeDeclaration
{
public function class()
{
}

public function interface()
{
}

public function trait()
{
}
}