1
0
Fork 0

Fix misc. issues, add more test cases, update validation test

pull/357/head
Sara Itani 2017-04-16 15:11:14 -07:00
parent 4382821b8c
commit 54f385f9ec
12 changed files with 184 additions and 42 deletions

View File

@ -6,7 +6,8 @@ use Microsoft\PhpParser as Tolerant;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
class ParserResourceFactory { class ParserResourceFactory {
const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER;
private static function getParserKind () { private static function getParserKind () {
global $parserKind; global $parserKind;
return isset($parserKind) ? $parserKind : self::PARSER_KIND; return isset($parserKind) ? $parserKind : self::PARSER_KIND;

View File

@ -280,12 +280,14 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
$name = $node->getResolvedName(); $name = $node->getResolvedName();
if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) { if (($useClause = $node->getFirstAncestor(Tolerant\Node\NamespaceUseGroupClause::class, Tolerant\Node\Statement\NamespaceUseDeclaration::class)) !== null) {
$name = (string)($name ?? $node->getText()); $name = (string)($name ?? Tolerant\ResolvedName::buildName($node->nameParts, $node->getFileContents()));
if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) {
$prefix = $useClause->parent->parent->namespaceName; $prefix = $useClause->parent->parent->namespaceName;
$prefix = $prefix === null ? "" : $prefix->getText(); if ($prefix === null) {
return null;
$name = $prefix . "\\" . $name; }
$prefixName = Tolerant\ResolvedName::buildName($prefix->nameParts, $useClause->getFileContents());
$name = (string)$prefixName . "\\" . $name;
if ($useClause->functionOrConst === null) { if ($useClause->functionOrConst === null) {
$useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class); $useClause = $node->getFirstAncestor(Tolerant\Node\Statement\NamespaceUseDeclaration::class);
@ -449,12 +451,25 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
return return
( (
$node instanceof Tolerant\Node\QualifiedName && $node instanceof Tolerant\Node\QualifiedName &&
($node->parent instanceof Tolerant\Node\Statement\ExpressionStatement || $node->parent instanceof Tolerant\Node\Expression || $node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList) && (
// $node->parent instanceof Tolerant\Node\Statement\ExpressionStatement ||
$node->parent instanceof Tolerant\Node\Expression ||
$node->parent instanceof Tolerant\Node\DelimitedList\ExpressionList ||
$node->parent instanceof Tolerant\Node\ArrayElement ||
($node->parent instanceof Tolerant\Node\Parameter && $node->parent->default === $node) ||
$node->parent instanceof Tolerant\Node\StatementNode ||
$node->parent instanceof Tolerant\Node\CaseStatementNode
) &&
!( !(
$node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression || $node->parent instanceof Tolerant\Node\Expression\CallExpression || $node->parent instanceof Tolerant\Node\Expression\MemberAccessExpression ||
$node->parent instanceof Tolerant\Node\Expression\CallExpression ||
$node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression || $node->parent instanceof Tolerant\Node\Expression\ObjectCreationExpression ||
$node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression || $node->parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ||
($node->parent instanceof Tolerant\Node\Expression\BinaryExpression && $node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword) $node->parent instanceof Tolerant\Node\Expression\AnonymousFunctionCreationExpression ||
(
$node->parent instanceof Tolerant\Node\Expression\BinaryExpression &&
$node->parent->operator->kind === Tolerant\TokenKind::InstanceOfKeyword
)
)); ));
} }
@ -859,6 +874,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
return new Types\Object_; return new Types\Object_;
} }
$className = (string)$class->getResolvedName(); $className = (string)$class->getResolvedName();
var_dump($className);
if ($className === 'static') { if ($className === 'static') {
return new Types\Static_; return new Types\Static_;
} }

View File

@ -112,7 +112,7 @@ class TolerantTreeAnalyzer implements TreeAnalyzerInterface {
if ( if (
$node instanceof Tolerant\Node\QualifiedName $node instanceof Tolerant\Node\QualifiedName
&& $node->isQualifiedName() && ($node->isQualifiedName() || $node->parent instanceof Tolerant\Node\NamespaceUseClause)
&& !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() && !($parent instanceof Tolerant\Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart()
) )
) { ) {

View File

@ -29,13 +29,13 @@ class ValidationTest extends TestCase
foreach ($frameworks as $frameworkDir) { foreach ($frameworks as $frameworkDir) {
$frameworkName = basename($frameworkDir); $frameworkName = basename($frameworkDir);
if ($frameworkName !== "broken") { if ($frameworkName !== "broken") {
continue; // continue;
} }
$iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName); $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../../validation/frameworks/" . $frameworkName);
foreach (new RecursiveIteratorIterator($iterator) as $file) { foreach (new RecursiveIteratorIterator($iterator) as $file) {
if (strpos(\strrev((string)$file), \strrev(".php")) === 0 if (strpos(\strrev((string)$file), \strrev(".php")) === 0
// && strpos((string)$file, "ConsoleIoTest.php")!== false // && strpos((string)$file, "taxonomy.php")!== false
) { ) {
if ($file->getSize() < 100000) { if ($file->getSize() < 100000) {
$testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName]; $testProviderArray[$frameworkName . "::" . $file->getBasename()] = [$file->getPathname(), $frameworkName];
@ -106,14 +106,15 @@ class ValidationTest extends TestCase
$parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER]; $parserKinds = [ParserKind::PHP_PARSER, ParserKind::TOLERANT_PHP_PARSER];
$maxRecursion = []; $maxRecursion = [];
$definitions = [];
$instantiated = []; $definitions = null;
$types = []; $instantiated = null;
$symbolInfo = []; $types = null;
$extend = []; $symbolInfo = null;
$isGlobal = []; $extend = null;
$documentation = []; $isGlobal = null;
$isStatic = []; $documentation = null;
$isStatic = null;
foreach ($parserKinds as $kind) { foreach ($parserKinds as $kind) {
echo ("=====================================\n"); echo ("=====================================\n");
@ -128,8 +129,12 @@ class ValidationTest extends TestCase
try { try {
$document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);
} catch (\Exception $e) { } catch (Exception $e) {
continue; if ($kind === $parserKinds[0]) {
$this->markTestIncomplete("baseline parser failed: " . $e->getTraceAsString());
}
throw $e;
} }
if ($document->getStmts() === null) { if ($document->getStmts() === null) {
@ -157,21 +162,26 @@ class ValidationTest extends TestCase
$docs[$defn->fqn] = $defn->documentation; $docs[$defn->fqn] = $defn->documentation;
$static[$defn->fqn] = $defn->isStatic; $static[$defn->fqn] = $defn->isStatic;
} }
if ($definitions !== null) {
if (isset($definitions[$testCaseFile])) { $this->assertEquals($definitions, $fqns, 'defn->fqn does not match');
$this->assertEquals($definitions[$testCaseFile], $fqns, 'defn->fqn does not match'); // $this->assertEquals($types, $currentTypes, "defn->type does not match");
// $this->assertEquals($types[$testCaseFile], $currentTypes, "defn->type does not match"); $this->assertEquals($instantiated, $canBeInstantiated, "defn->canBeInstantiated does not match");
$this->assertEquals($instantiated[$testCaseFile], $canBeInstantiated, "defn->canBeInstantiated does not match"); $this->assertEquals($extend, $extends, 'defn->extends does not match');
$this->assertEquals($extend[$testCaseFile], $extends, 'defn->extends does not match'); $this->assertEquals($isGlobal, $global, 'defn->isGlobal does not match');
$this->assertEquals($isGlobal[$testCaseFile], $global, 'defn->isGlobal does not match'); $this->assertEquals($documentation, $docs, 'defn->documentation does not match');
$this->assertEquals($documentation[$testCaseFile], $docs, 'defn->documentation does not match'); $this->assertEquals($isStatic, $static, 'defn->isStatic does not match');
$this->assertEquals($isStatic[$testCaseFile], $static, 'defn->isStatic does not match');
$this->assertEquals($symbolInfo[$testCaseFile], $symbols, "defn->symbolInformation does not match"); $this->assertEquals($symbolInfo, $symbols, "defn->symbolInformation does not match");
// $skipped = ['false', 'true', 'null', 'FALSE', 'TRUE', 'NULL', 'parent', 'PARENT', 'self', 'static'];
$skipped = []; $skipped = [];
$skipped = [
'false', 'true', 'null', 'FALSE', 'TRUE', 'NULL',
'__', // magic constants are treated as normal constants
'Exception', // catch exception types missing from old definition resolver
'Trait' // use Trait references are missing from old definition resolve
];
foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) { foreach ($this->getIndex($parserKinds[0], $frameworkName)->references as $key=>$value) {
foreach ($skipped as $s) { foreach ($skipped as $s) {
if (strpos($key, $s) !== false) { if (strpos($key, $s) !== false) {
@ -179,6 +189,13 @@ class ValidationTest extends TestCase
} }
} }
} }
foreach ($this->getIndex($parserKinds[1], $frameworkName)->references as $key=>$value) {
foreach ($skipped as $s) {
if (strpos($key, $s) !== false) {
unset($this->getIndex($parserKinds[1], $frameworkName)->references[$key]);
}
}
}
// unset($this->getIndex($parserKinds[1])->references['__LINE__']); // unset($this->getIndex($parserKinds[1])->references['__LINE__']);
// unset($this->getIndex($parserKinds[1])->references['__FILE__']); // unset($this->getIndex($parserKinds[1])->references['__FILE__']);
@ -188,22 +205,31 @@ class ValidationTest extends TestCase
// unset($this->getIndex($parserKinds[1])->references['Requests_Exception']); // unset($this->getIndex($parserKinds[1])->references['Requests_Exception']);
try { try {
// $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references,
// "references do not match");
$this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references); $this->assertArraySubset($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references);
var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references)); // var_dump(array_keys($this->getIndex($parserKinds[1], $frameworkName)->references));
} catch (\Throwable $e) { }
catch (\Throwable $e) {
$this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references, $this->assertEquals($this->getIndex($parserKinds[0], $frameworkName)->references, $this->getIndex($parserKinds[1], $frameworkName)->references,
"references do not match"); "references do not match");
} }
finally {
unset($this->index[$parserKinds[0]][$frameworkName]);
unset($this->index[$parserKinds[1]][$frameworkName]);
}
} }
$definitions[$testCaseFile] = $fqns; $definitions = $fqns;
$types[$testCaseFile] = $currentTypes; $types = $currentTypes;
$instantiated[$testCaseFile] = $canBeInstantiated; $instantiated = $canBeInstantiated;
$symbolInfo[$testCaseFile] = $symbols; $symbolInfo = $symbols;
$extend[$testCaseFile] = $extends; $extend = $extends;
$isGlobal[$testCaseFile] = $global; $isGlobal = $global;
$documentation[$testCaseFile] = $docs; $documentation = $docs;
$isStatic[$testCaseFile] = $static; $isStatic = $static;
// $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion; // $maxRecursion[$testCaseFile] = $definitionResolver::$maxRecursion;
} }

View File

@ -0,0 +1,7 @@
<?php
namespace MyNamespace;
switch ($a) {
case A:
}

View File

@ -0,0 +1,11 @@
<?php
namespace MyNamespace;
class A
{
public function suite()
{
return HI;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace MyNamespace;
try {
} catch (Exception $e) {
}

View File

@ -0,0 +1,53 @@
<?php
namespace Drupal\Core\Batch;
/**
* Helper methods for the batch system.
*/
class Percentage {
/**
* Formats the percent completion for a batch set.
*
* @param int $total
* The total number of operations.
* @param int $current
* The number of the current operation. This may be a floating point number
* rather than an integer in the case of a multi-step operation that is not
* yet complete; in that case, the fractional part of $current represents the
* fraction of the operation that has been completed.
*
* @return string
* The properly formatted percentage, as a string. We output percentages
* using the correct number of decimal places so that we never print "100%"
* until we are finished, but we also never print more decimal places than
* are meaningful.
*
* @see _batch_process()
*/
public static function format($total, $current) {
if (!$total || $total == $current) {
// If $total doesn't evaluate as true or is equal to the current set, then
// we're finished, and we can return "100".
$percentage = '100';
}
else {
// We add a new digit at 200, 2000, etc. (since, for example, 199/200
// would round up to 100% if we didn't).
$decimal_places = max(0, floor(log10($total / 2.0)) - 1);
do {
// Calculate the percentage to the specified number of decimal places.
$percentage = sprintf('%01.' . $decimal_places . 'f', round($current / $total * 100, $decimal_places));
// When $current is an integer, the above calculation will always be
// correct. However, if $current is a floating point number (in the case
// of a multi-step batch operation that is not yet complete), $percentage
// may be erroneously rounded up to 100%. To prevent that, we add one
// more decimal place and try again.
$decimal_places++;
} while ($percentage == '100');
}
return $percentage;
}
}

View File

@ -0,0 +1,6 @@
<?php
namespace MyNamespace;
if (A) {
}

View File

@ -0,0 +1,5 @@
<?php
namespace B;
echo __FILE__;

View File

@ -0,0 +1,3 @@
<?php
namespace B;
use LanguageServer\Protocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range};

View File

@ -0,0 +1,6 @@
<?php
namespace MyNamespace;
function init(Hi $view)
{
}