tolerant-php-parser/tests/ParserInvariantsTest.php

192 строки
7.1 KiB
PHP
Исходник Обычный вид История

<?php
2016-12-19 01:49:28 +03:00
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// TODO autoload classes
require_once(__DIR__ . "/../src/TokenStreamProviderFactory.php");
require_once(__DIR__ . "/../src/Parser.php");
require_once(__DIR__ . "/../src/Token.php");
require_once(__DIR__ . "/LexerInvariantsTest.php");
use PhpParser\Node;
use PhpParser\Token;
use PHPUnit\Framework\TestCase;
use PhpParser\TokenKind;
class ParserInvariantsTest extends LexerInvariantsTest {
const FILENAME_PATTERN = __dir__ . "/cases/{parser,}/*.php";
public static function sourceFileNodeProvider() {
$testFiles = array();
$testCases = glob(self::FILENAME_PATTERN, GLOB_BRACE);
foreach ($testCases as $filename) {
2016-12-29 00:46:00 +03:00
$parser = new \PhpParser\Parser();
$testFiles[basename($filename)] = [$filename, $parser->parseSourceFile(file_get_contents($filename))];
}
return $testFiles;
}
public static function tokensArrayProvider() {
$testFiles = array();
$testCases = glob(self::FILENAME_PATTERN, GLOB_BRACE);
foreach ($testCases as $filename) {
2016-12-29 00:46:00 +03:00
$parser = new \PhpParser\Parser();
$sourceFileNode = $parser->parseSourceFile(file_get_contents($filename));
$tokensArray = array();
2016-12-25 01:41:12 +03:00
foreach ($sourceFileNode->getDescendantNodesAndTokens() as $child) {
if ($child instanceof \PhpParser\Token) {
array_push($tokensArray, $child);
}
}
$testFiles[basename($filename)] = [$filename, $tokensArray];
}
return $testFiles;
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testSourceFileNodeLengthEqualsDocumentLength($filename, Node $sourceFileNode) {
$this->assertEquals(
2017-01-13 22:00:51 +03:00
filesize($filename), $sourceFileNode->getFullWidth(),
"Invariant: The tree length exactly matches the file length.");
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testNodesAllHaveAtLeastOneChild($filename, Node $sourceFileNode) {
2016-12-25 01:41:12 +03:00
foreach ($sourceFileNode->getDescendantNodesAndTokens() as $child) {
if ($child instanceof Node) {
2016-10-16 07:43:25 +03:00
$encode = json_encode($child);
$this->assertGreaterThanOrEqual(
2016-12-25 01:41:12 +03:00
1, count($child->getChildNodesAndTokens()),
2016-10-16 07:43:25 +03:00
"Invariant: All Nodes have at least one child. $encode"
);
}
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testEveryNodeSpanIsSumOfChildSpans($filename, Node $sourceFileNode) {
$treeElements = iterator_to_array($sourceFileNode->getDescendantNodesAndTokens(), false);
array_push($treeElements, $sourceFileNode);
foreach ($treeElements as $element) {
if ($element instanceof Node) {
$expectedLength = 0;
2016-12-25 01:41:12 +03:00
foreach ($element->getChildNodesAndTokens() as $child) {
if ($child instanceof Node) {
2017-01-13 22:00:51 +03:00
$expectedLength += $child->getFullWidth();
2016-11-13 22:54:51 +03:00
} elseif ($child instanceof \PhpParser\Token) {
$expectedLength += $child->length;
}
}
$this->assertEquals(
2017-01-13 22:00:51 +03:00
$expectedLength, $element->getFullWidth(),
"Invariant: Span of any Node is span of child nodes and tokens."
);
}
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testParentOfNodeHasSameChildNode($filename, Node $sourceFileNode) {
foreach ($sourceFileNode->getDescendantNodesAndTokens() as $child) {
if ($child instanceof Node) {
$this->assertContains(
2016-12-25 01:41:12 +03:00
$child, $child->parent->getChildNodesAndTokens(),
"Invariant: Parent of Node contains same child node."
);
}
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testEachChildHasExactlyOneParent($filename, Node $sourceFileNode) {
$allTreeElements = iterator_to_array($sourceFileNode->getDescendantNodesAndTokens(), false);
array_push($allTreeElements, $sourceFileNode);
foreach ($sourceFileNode->getDescendantNodesAndTokens() as $childWithParent) {
$count = 0;
foreach ($allTreeElements as $element) {
if ($element instanceof Node) {
$values = iterator_to_array($element->getChildNodesAndTokens(), false);
if (in_array($childWithParent, $values, true)) {
$count++;
}
}
}
$this->assertEquals(
1, $count,
"Invariant: each child has exactly one parent.");
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
public function testEveryChildIsNodeOrTokenType($filename, Node $sourceFileNode) {
$treeElements = iterator_to_array($sourceFileNode->getDescendantNodesAndTokens(), false);
array_push($treeElements, $sourceFileNode);
foreach ($sourceFileNode->getDescendantNodes() as $descendant) {
foreach ($descendant->getChildNodesAndTokens() as $child) {
if ($child instanceof Node || $child instanceof Token) {
continue;
}
$this->fail("Invariant: Every child is Node or Token type");
}
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testRootNodeHasNoParent($filename, Node $sourceFileNode) {
$this->assertEquals(
null, $sourceFileNode->parent,
"Invariant: Root node of tree has no parent.");
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testRootNodeIsNeverAChild($filename, Node $sourceFileNode) {
$treeElements = iterator_to_array($sourceFileNode->getDescendantNodesAndTokens(), false);
array_push($treeElements, $sourceFileNode);
foreach($treeElements as $element) {
if ($element instanceof Node) {
$this->assertNotContains(
2016-12-25 01:41:12 +03:00
$sourceFileNode, $element->getChildNodesAndTokens(),
"Invariant: root node of tree is never a child.");
}
}
}
/**
* @dataProvider sourceFileNodeProvider
*/
2016-12-25 01:41:12 +03:00
public function testEveryNodeHasAKind($filename, Node $sourceFileNode) {
$treeElements = iterator_to_array($sourceFileNode->getDescendantNodes(), false);
array_push($treeElements, $sourceFileNode);
foreach($treeElements as $element) {
2016-12-27 04:36:20 +03:00
$this->assertNotNull(
$element->getKind(),
2016-12-27 04:36:20 +03:00
"Invariant: Every Node has a Kind");
}
}
}