diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index b479e25..fde79db 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -342,7 +342,7 @@ class DefinitionResolver implements DefinitionResolverInterface * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null */ - private static function resolveVariableToNode(Node\Expr $var) + private function resolveVariableToNode(Node\Expr $var) { $n = $var; // When a use is passed, start outside the closure to not return immediatly @@ -648,7 +648,7 @@ class DefinitionResolver implements DefinitionResolverInterface * @param Node $class * @return Type */ - private static function resolveClassNameToType(Node $class): Type + private function resolveClassNameToType(Node $class): Type { if ($class instanceof Node\Expr) { return new Types\Mixed; diff --git a/src/LoggedDefinitionResolver.php b/src/LoggedDefinitionResolver.php new file mode 100644 index 0000000..e0a4238 --- /dev/null +++ b/src/LoggedDefinitionResolver.php @@ -0,0 +1,9 @@ +getString($param1) . ", " . $this->getString($param2) . ")\n"; + echo $callStr; + } + $start = microtime(true); + for ($i = 0; $i < self::$repeat; $i++) { + + $result = parent::$methodName($param1, $param2); + } + + $end = microtime(true) - $start; + + } else { + if (self::$logger === true) { + $callStr .= $this->getString($param1) . ")\n"; + echo $callStr; + } + $start = microtime(true); + for ($i = 0; $i < self::$repeat; $i++) { + $result = parent::$methodName($param1); + } + $end = microtime(true) - $start; + } + self::$recursion--; + if (self::$recursion === 1) { + if (!isset(self::$times[$methodName])) { + self::$times[$methodName] = $end; + } else { + self::$times[$methodName] += $end; + } + } + + if (self::$logger === true) { + if ($result instanceof Definition) { + $resultText = $result->fqn; + } elseif ($result instanceof DocBlock) { + $resultText = $result->getDescription(); + } else { + $resultText = $result ?? "NULL"; + } + echo "> RESULT[$callStr]: " . $resultText . "\n"; + } + return $result; + } + + private function getString($param) { + if ($param instanceof Tolerant\Node) { + return "[" . $param->getNodeKindName() . "] " . $param->getText(); + } + return (string)$param; + } + + /** + * Builds the declaration line for a given node. + * + * + * @param Tolerant\Node $node + * @return string + */ + public function getDeclarationLineFromNode($node): string + { + return $this->logMethod('getDeclarationLineFromNode', $node); + } + + /** + * Gets the documentation string for a node, if it has one + * + * @param Tolerant\Node $node + * @return string|null + */ + public function getDocumentationFromNode($node) + { + return $this->logMethod('getDocumentationFromNode', $node); + } + + function getDocBlock(Tolerant\Node $node) { + return $this->logMethod('getDocBlock', $node); + + } + + /** + * Create a Definition for a definition node + * + * @param Tolerant\Node $node + * @param string $fqn + * @return Definition + */ + public function createDefinitionFromNode($node, string $fqn = null): Definition + { + return $this->logMethod('createDefinitionFromNode', $node, $fqn); + } + + /** + * Given any node, returns the Definition object of the symbol that is referenced + * + * @param Tolerant\Node $node Any reference node + * @return Definition|null + */ + public function resolveReferenceNodeToDefinition($node) + { +// var_dump(array_keys(self::$instance->index->getDefinitions())); + self::$logger = true; + return $this->logMethod('resolveReferenceNodeToDefinition', $node); + } + + /** + * Given any node, returns the FQN of the symbol that is referenced + * Returns null if the FQN could not be resolved or the reference node references a variable + * + * @param Tolerant\Node $node + * @return string|null + */ + public function resolveReferenceNodeToFqn($node) { + return $this->logMethod('resolveReferenceNodeToFqn', $node); + } + + /** + * Returns the assignment or parameter node where a variable was defined + * + * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access + * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null + */ + public function resolveVariableToNode(Tolerant\Node $var) + { + return $this->logMethod('resolveVariableToNode', $var); + } + + /** + * Given an expression node, resolves that expression recursively to a type. + * If the type could not be resolved, returns Types\Mixed. + * + * @param \PhpParser\Node\Expr $expr + * @return \phpDocumentor\Reflection\Type + */ + public function resolveExpressionNodeToType($expr): Type + { + return $this->logMethod('resolveExpressionNodeToType', $expr); + } + + /** + * Takes any class name node (from a static method call, or new node) and returns a Type object + * Resolves keywords like self, static and parent + * + * @param Tolerant\Node || Tolerant\Token $class + * @return Type + */ + public function resolveClassNameToType($class): Type + { + return $this->logMethod('resolveClassNameToType', $class); + } + + /** + * Returns the type a reference to this symbol will resolve to. + * For properties and constants, this is the type of the property/constant. + * For functions and methods, this is the return type. + * For parameters, this is the type of the parameter. + * For classes and interfaces, this is the class type (object). + * For variables / assignments, this is the documented type or type the assignment resolves to. + * Can also be a compound type. + * If it is unknown, will be Types\Mixed. + * Returns null if the node does not have a type. + * + * @param Tolerant\Node $node + * @return \phpDocumentor\Reflection\Type|null + */ + public function getTypeFromNode($node) + { + return $this->logMethod('getTypeFromNode', $node); + } + + + /** + * Returns the fully qualified name (FQN) that is defined by a node + * Returns null if the node does not declare any symbol that can be referenced by an FQN + * + * @param Tolerant\Node $node + * @return string|null + */ + public static function getDefinedFqn($node) + { + $result = parent::getDefinedFqn($node); + if (self::$logger === true) { + echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; + var_dump($result); + } + return $result; + } + + public function printLogs() { + var_dump(self::$times); + var_dump(self::$maxRecursion); + } +} diff --git a/src/LoggedTolerantDefinitionResolver.php b/src/LoggedTolerantDefinitionResolver.php index 7fb7982..9466ce0 100644 --- a/src/LoggedTolerantDefinitionResolver.php +++ b/src/LoggedTolerantDefinitionResolver.php @@ -3,200 +3,7 @@ declare(strict_types = 1); namespace LanguageServer; -use LanguageServer\Protocol\TolerantSymbolInformation; -use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard as PrettyPrinter; -use phpDocumentor\Reflection\{ - DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver -}; -use LanguageServer\Protocol\SymbolInformation; -use LanguageServer\Index\ReadableIndex; -use Microsoft\PhpParser as Tolerant; - class LoggedTolerantDefinitionResolver extends TolerantDefinitionResolver { - - private static $logger = false; - - private static $stackLevel = 0; - /** - * @param ReadableIndex $index - */ - public function __construct(ReadableIndex $index) - { - self::$logger = false; - parent::__construct($index); - } - - public function logMethod($methodName, $param1, $param2 = -1) { - $callStr = "FUNCTION: $methodName("; - if ($param2 !== -1) { - $callStr .= $this->getString($param1) . ", " . $this->getString($param2) . ")\n"; - if (self::$logger === true) { - echo $callStr; - } - $result = parent::$methodName($param1, $param2); - } else { - $callStr .= $this->getString($param1) . ")\n"; - if (self::$logger === true) { - echo $callStr; - } - $result = parent::$methodName($param1); - } - - if (self::$logger === true) { - if ($result instanceof Definition) { - $resultText = $result->fqn; - } elseif ($result instanceof DocBlock) { - $resultText = $result->getDescription(); - } else { - $resultText = $result ?? "NULL"; - } - echo "> RESULT[$callStr]: " . $resultText . "\n"; - } - return $result; - } - - private function getString($param) { - if ($param instanceof Tolerant\Node) { - return "[" . $param->getNodeKindName() . "] " . $param->getText(); - } - return (string)$param; - } - - /** - * Builds the declaration line for a given node. - * - * - * @param Tolerant\Node $node - * @return string - */ - public function getDeclarationLineFromNode($node): string - { - return $this->logMethod('getDeclarationLineFromNode', $node); - } - - /** - * Gets the documentation string for a node, if it has one - * - * @param Tolerant\Node $node - * @return string|null - */ - public function getDocumentationFromNode($node) - { - return $this->logMethod('getDocumentationFromNode', $node); - } - - function getDocBlock(Tolerant\Node $node) { - return $this->logMethod('getDocBlock', $node); - - } - - /** - * Create a Definition for a definition node - * - * @param Tolerant\Node $node - * @param string $fqn - * @return Definition - */ - public function createDefinitionFromNode($node, string $fqn = null): Definition - { - return $this->logMethod('createDefinitionFromNode', $node, $fqn); - } - - /** - * Given any node, returns the Definition object of the symbol that is referenced - * - * @param Tolerant\Node $node Any reference node - * @return Definition|null - */ - public function resolveReferenceNodeToDefinition($node) - { - var_dump(array_keys($this->index->getDefinitions())); - self::$logger = true; - return $this->logMethod('resolveReferenceNodeToDefinition', $node); - } - - /** - * Given any node, returns the FQN of the symbol that is referenced - * Returns null if the FQN could not be resolved or the reference node references a variable - * - * @param Tolerant\Node $node - * @return string|null - */ - public function resolveReferenceNodeToFqn($node) { - return $this->logMethod('resolveReferenceNodeToFqn', $node); - } - - /** - * Returns the assignment or parameter node where a variable was defined - * - * @param Node\Expr\Variable|Node\Expr\ClosureUse $var The variable access - * @return Node\Expr\Assign|Node\Expr\AssignOp|Node\Param|Node\Expr\ClosureUse|null - */ - public function resolveVariableToNode(Tolerant\Node $var) - { - return $this->logMethod('resolveVariableToNode', $var); - } - - /** - * Given an expression node, resolves that expression recursively to a type. - * If the type could not be resolved, returns Types\Mixed. - * - * @param \PhpParser\Node\Expr $expr - * @return \phpDocumentor\Reflection\Type - */ - public function resolveExpressionNodeToType($expr): Type - { - return $this->logMethod('resolveExpressionNodeToType', $expr); - } - - /** - * Takes any class name node (from a static method call, or new node) and returns a Type object - * Resolves keywords like self, static and parent - * - * @param Tolerant\Node || Tolerant\Token $class - * @return Type - */ - public function resolveClassNameToType($class): Type - { - return $this->logMethod('resolveClassNameToType', $class); - } - - /** - * Returns the type a reference to this symbol will resolve to. - * For properties and constants, this is the type of the property/constant. - * For functions and methods, this is the return type. - * For parameters, this is the type of the parameter. - * For classes and interfaces, this is the class type (object). - * For variables / assignments, this is the documented type or type the assignment resolves to. - * Can also be a compound type. - * If it is unknown, will be Types\Mixed. - * Returns null if the node does not have a type. - * - * @param Tolerant\Node $node - * @return \phpDocumentor\Reflection\Type|null - */ - public function getTypeFromNode($node) - { - return $this->logMethod('getTypeFromNode', $node); - } - - - /** - * Returns the fully qualified name (FQN) that is defined by a node - * Returns null if the node does not declare any symbol that can be referenced by an FQN - * - * @param Tolerant\Node $node - * @return string|null - */ - public static function getDefinedFqn($node) - { - $result = parent::getDefinedFqn($node); - if (self::$logger === true) { - echo "FUNCTION: getDefinedFqn(" . $node->getNodeKindName() . ")\n"; - var_dump($result); - } - return $result; - } + use LoggedDefinitionResolverTrait; } diff --git a/src/ParserKind.php b/src/ParserKind.php index b09145e..a7944a4 100644 --- a/src/ParserKind.php +++ b/src/ParserKind.php @@ -8,4 +8,5 @@ class ParserKind const PHP_PARSER = 1; const TOLERANT_PHP_PARSER = 2; const DIAGNOSTIC_TOLERANT_PHP_PARSER = 3; + const DIAGNOSTIC_PHP_PARSER = 4; } \ No newline at end of file diff --git a/src/ParserResourceFactory.php b/src/ParserResourceFactory.php index 0861522..d66dc84 100644 --- a/src/ParserResourceFactory.php +++ b/src/ParserResourceFactory.php @@ -6,10 +6,14 @@ use Microsoft\PhpParser as Tolerant; use LanguageServer\Index\ReadableIndex; class ParserResourceFactory { - const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER; - + const PARSER_KIND = ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER; + private static function getParserKind () { + global $parserKind; + return isset($parserKind) ? $parserKind : self::PARSER_KIND; + } + public static function getParser() { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { + if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) { return new Parser; } else { return new Tolerant\Parser; @@ -17,18 +21,21 @@ class ParserResourceFactory { } public static function getDefinitionResolver(ReadableIndex $index) { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { - return new DefinitionResolver($index); - } elseif (self::PARSER_KIND === ParserKind::TOLERANT_PHP_PARSER) { - return new TolerantDefinitionResolver($index); - } elseif (self::PARSER_KIND === ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER) { - return new LoggedTolerantDefinitionResolver($index); + switch (self::getParserKind()) { + case ParserKind::PHP_PARSER: + return new DefinitionResolver($index); + case ParserKind::TOLERANT_PHP_PARSER: + return new TolerantDefinitionResolver($index); + case ParserKind::DIAGNOSTIC_PHP_PARSER: + return new LoggedDefinitionResolver($index); + case ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER: + return new LoggedTolerantDefinitionResolver($index); } } public static function getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri) { - if (self::PARSER_KIND === ParserKind::PHP_PARSER) { + if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) { return new TreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); } else { return new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); diff --git a/validation/frameworks/tolerant-php-parser b/validation/frameworks/tolerant-php-parser new file mode 160000 index 0000000..6ce1e1f --- /dev/null +++ b/validation/frameworks/tolerant-php-parser @@ -0,0 +1 @@ +Subproject commit 6ce1e1f978f1c17d555b83660b97899f0d9dbeec