From 3b4082f059fb9e2d8b7039ea51b554427336af67 Mon Sep 17 00:00:00 2001 From: Arne Blankerts Date: Sun, 23 Aug 2020 23:54:20 +0200 Subject: [PATCH] Close #95 --- CHANGELOG.md | 6 +++- composer.json | 3 +- composer.lock | 8 +++-- phive.xml | 4 +-- phpunit.xml.dist | 46 ++++++++++++------------ src/Parser.php | 19 +++++++++- tests/AutoloadRendererTest.php | 28 ++++++--------- tests/FactoryTest.php | 2 +- tests/ParserTest.php | 55 +++++++++++------------------ tests/_data/parser/relative.php | 4 +++ tests/classdependencysorterTest.php | 5 ++- 11 files changed, 93 insertions(+), 87 deletions(-) create mode 100644 tests/_data/parser/relative.php diff --git a/src/Parser.php b/src/Parser.php index c658b28..3d50bbf 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -43,6 +43,12 @@ define('T_TRAIT', -1); } + // PHP 8.0 forward compat + if (!defined('T_NAME_FULLY_QUALIFIED')) { + define('T_NAME_FULLY_QUALIFIED', -1); + define('T_NAME_QUALIFIED', -1); + } + /** * Namespace aware parser to find and extract defined classes within php source files * @@ -168,6 +174,9 @@ private function processClass($pos) { case T_WHITESPACE: { break; } + + case T_NAME_FULLY_QUALIFIED: + case T_NAME_QUALIFIED: case T_STRING: { $$mode .= $tok[1]; break; @@ -186,6 +195,7 @@ private function processClass($pos) { $mode = 'implements'; break; } + case ',': { if ($mode === 'implements') { $implementsList[] = $this->resolveDependencyName($implements); @@ -195,7 +205,8 @@ private function processClass($pos) { } default: { throw new ParserException(sprintf( - 'Parse error while trying to process class definition (unexpected token in name).' + 'Parse error while trying to process class definition (unexpected token "%s" in name).', + \token_name($tok[0]) ), ParserException::ParseError ); } @@ -237,6 +248,8 @@ private function processInterface($pos) { foreach(array_slice($stack, 1, -1) as $tok) { switch ($tok[0]) { case T_NS_SEPARATOR: + case T_NAME_QUALIFIED: + case T_NAME_FULLY_QUALIFIED: case T_STRING: { $$mode .= $tok[1]; break; @@ -406,6 +419,8 @@ private function parseUseOfTrait($stackSize, $stack) { break; } case T_NS_SEPARATOR: + case T_NAME_QUALIFIED: + case T_NAME_FULLY_QUALIFIED: case T_STRING: { $use .= $current[1]; break; @@ -458,6 +473,8 @@ private function parseUseAsImport($stack) { break; } case T_NS_SEPARATOR: + case T_NAME_QUALIFIED: + case T_NAME_FULLY_QUALIFIED: case T_STRING: { $$mode .= $current[1]; break; diff --git a/tests/AutoloadRendererTest.php b/tests/AutoloadRendererTest.php index fcf0d0e..c1dd00f 100644 --- a/tests/AutoloadRendererTest.php +++ b/tests/AutoloadRendererTest.php @@ -37,12 +37,10 @@ namespace TheSeer\Autoload\Tests { - use TheSeer\Autoload\Parser; + use TheSeer\Autoload\AutoloadBuilderException; use TheSeer\Autoload\AutoloadRenderer; /** - * Unit tests for PHPFilter iterator class - * * @author Arne Blankerts * @copyright Arne Blankerts , All rights reserved. */ @@ -51,7 +49,7 @@ class AutoloadRendererTest extends \PHPUnit\Framework\TestCase { private $classlist; private $template; - public function setUp() { + public function setUp(): void { $this->classlist = array(); $this->classlist['demo1'] = realpath(__DIR__ . '/_data/parser/class.php'); $this->classlist['demo2'] = realpath(__DIR__ . '/_data/parser/class.php'); @@ -59,7 +57,6 @@ public function setUp() { } /** - * * @covers \TheSeer\Autoload\AutoloadRenderer::__construct * @covers \TheSeer\Autoload\AutoloadRenderer::render */ @@ -67,9 +64,9 @@ public function testDefaultRendering() { $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); $expected = " \$classes = array(\n 'demo1' => '".__DIR__."/_data/parser/class.php',\n"; $expected = strtr($expected, '\\', '/'); - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); $expected = "require \$classes[\$cn]"; - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); } /** @@ -81,7 +78,7 @@ public function testWindowsLFRendering() { $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); $ab->setLineBreak("\r\n"); $expected = "_data/parser/class.php',\r\n"; - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); } /** @@ -104,7 +101,7 @@ public function testIndentWithTabsRendering() { $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); $ab->setIndent("\t"); $expected = "\t'demo2'"; - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); } @@ -120,10 +117,10 @@ public function testSetBaseDirRendering() { $expected = "require __DIR__ . \$classes[\$cn];"; $expected = strtr($expected, '\\', '/'); - $this->assertContains($expected, $result); + $this->assertStringContainsString($expected, $result); $expected = " \$classes = array(\n 'demo1' => '/tests/_data/parser/class.php',\n"; - $this->assertContains($expected, $result); + $this->assertStringContainsString($expected, $result); } /** @@ -135,7 +132,7 @@ public function testRenderingInCompatMode() { $ab->setCompat(true); $ab->setBaseDir(realpath(__DIR__)); $expected = "require dirname(__FILE__) . \$classes[\$cn];"; - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); } @@ -146,15 +143,12 @@ public function testRelativeSubBaseDirRendering() { $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); $ab->setBaseDir(realpath(__DIR__.'/_data/dependency')); $expected = "'demo1' => '/../parser/class.php'"; - $this->assertContains($expected, $ab->render($this->template)); + $this->assertStringContainsString($expected, $ab->render($this->template)); } - /** - * - * @expectedException \TheSeer\Autoload\AutoloadBuilderException - */ public function testSettingInvalidTimestamp() { $ab = new \TheSeer\Autoload\AutoloadRenderer($this->classlist); + $this->expectException(AutoloadBuilderException::class); $ab->setTimestamp('Bad'); } diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index df2978d..1e36a86 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -44,7 +44,7 @@ class FactoryTest extends \PHPUnit\Framework\TestCase { - public function setUp() { + public function setUp(): void { $this->factory = new Factory(); $this->config = new Config(array()); $this->factory->setConfig($this->config); diff --git a/tests/ParserTest.php b/tests/ParserTest.php index f28f16f..3b3f27d 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -38,14 +38,9 @@ namespace TheSeer\Autoload\Tests { use TheSeer\Autoload\Parser; + use TheSeer\Autoload\ParserException; use TheSeer\Autoload\SourceFile; - /** - * Unit tests for ClassFinder class - * - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - */ class ParserTest extends \PHPUnit\Framework\TestCase { public function testNoClassDefined() { @@ -84,66 +79,52 @@ public function testRedeclaringThrowsException() { $this->assertContains('demo', $rc->getRedeclarations()); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidClassnameThrowsException() { $parser = new \TheSeer\Autoload\Parser; + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/parseerror1.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidClassnameWithExtendsThrowsException() { $parser = new \TheSeer\Autoload\Parser; + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/parseerror2.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidClassnameForExtendsThrowsException() { $parser = new \TheSeer\Autoload\Parser(true); + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/parseerror3.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidClassnameForImplementsThrowsException() { $parser = new \TheSeer\Autoload\Parser(true); + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/parseerror4.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testSyntacticallyInvalidClassnameThrowsException() { $parser = new \TheSeer\Autoload\Parser; + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/invalid1.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidTokenInClassnameThrowsException() { $parser = new \TheSeer\Autoload\Parser; + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/invalid2.php'))); } - /** - * @expectedException \TheSeer\Autoload\ParserException - * @expectedExceptionCode \TheSeer\Autoload\ParserException::ParseError - */ public function testInvalidTokenInClassnameWithinNamespaceThrowsException() { $parser = new \TheSeer\Autoload\Parser; + $this->expectException(ParserException::class); + $this->expectExceptionCode(ParserException::ParseError); $parser->parse(new SourceFile((__DIR__.'/_data/parser/invalid3.php'))); } @@ -542,6 +523,12 @@ public function testInlineUseOfKeywordTraitGetsIgnored() { $this->assertEquals(array('demo'), $rc->getUnits()); } + public function testPHP80Relative() { + $parser = new Parser(); + $rc = $parser->parse(new SourceFile((__DIR__.'/_data/parser/relative.php'))); + $this->assertEquals(array('foo\\demo'), $rc->getUnits()); + } + } } diff --git a/tests/_data/parser/relative.php b/tests/_data/parser/relative.php new file mode 100644 index 0000000..6e3c185 --- /dev/null +++ b/tests/_data/parser/relative.php @@ -0,0 +1,4 @@ +assertEquals($expectFilesOrder, array_unique(array_values($r))); } - /** - * @expectedException \TheSeer\Autoload\ClassDependencySorterException - */ public function testRecusriveDependencyThrowsException() { $classes=array('test1' => 'file1'); $dependency=array('test1' => array('test1')); $x = new ClassDependencySorter($classes, $dependency); + $this->expectException(ClassDependencySorterException::class); $r = $x->process(); }