diff --git a/.php_cs.dist b/.php_cs.dist index a3d5fa36..2820b890 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -4,7 +4,7 @@ $finder = PhpCsFixer\Finder::create() ->in('lib') ->in('tests') ->exclude([ - 'tests/Workspace' + 'tests/Workspace', ]) ; @@ -13,6 +13,11 @@ return PhpCsFixer\Config::create() '@PSR2' => true, 'no_unused_imports' => true, 'array_syntax' => ['syntax' => 'short'], + 'void_return' => true, + 'ordered_class_elements' => true, + 'single_quote' => true, + 'heredoc_indentation' => true, + 'global_namespace_import' => true, ]) ->setFinder($finder) ; diff --git a/README.md b/README.md index 19a8b093..21267499 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,11 @@ Docblock Parser =============== -Sub-standard docblock parser. +PHP Docblock parser with the following aims: -```php -$docblock = (new DocblockFactory())->create('/** @var Foobar */'); -$vars = $docblock->tags()->byName('var'); - -foreach ($vars as $var) { - $var->type(); - $var->varName(); -} -``` - -Why? ----- - -There is already a [standards-compliant -library](https://github.com/phpDocumentor/ReflectionDocBlock) for -PHP-Documentor, however it is coupled to the PHPDocumentor type reflection -library. This library only cares about parsing docblocks badly for -[Phpactor](https://github.com/phpactor/phpactor). +- Fast: has to be fast enough for IDE analysis. +- Isomorphic: can be transformed back to the original text representation. +- Positional: the positions of nodes are captured. Contributing ------------ diff --git a/composer.json b/composer.json index eda3af40..d15867d4 100644 --- a/composer.json +++ b/composer.json @@ -13,11 +13,15 @@ "php": "^7.3" }, "require-dev": { + "phpbench/phpbench": "dev-master", "ergebnis/composer-normalize": "^2.0", "friendsofphp/php-cs-fixer": "^2.17", "phpstan/phpstan": "~0.12.0", "phpunit/phpunit": "^9.0", - "phpspec/prophecy-phpunit": "^2.0" + "phpspec/prophecy-phpunit": "^2.0", + "symfony/var-dumper": "^5.2", + "phpstan/phpdoc-parser": "^0.4.10", + "jetbrains/phpstorm-stubs": "^2020.2" }, "extra": { "branch-alias": { @@ -35,5 +39,12 @@ } }, "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "scripts": { + "integrate": [ + "vendor/bin/phpunit", + "vendor/bin/php-cs-fixer fix --allow-risky=yes", + "vendor/bin/phpstan analyse" + ] + } } diff --git a/lib/Ast/Docblock.php b/lib/Ast/Docblock.php new file mode 100644 index 00000000..40e10805 --- /dev/null +++ b/lib/Ast/Docblock.php @@ -0,0 +1,75 @@ +children = new ElementList($children); + } + + /** + * @param class-string $tagFqn + */ + public function hasTag(string $tagFqn): bool + { + foreach ($this->tags() as $tag) { + if ($tag instanceof $tagFqn) { + return true; + } + } + + return false; + } + + /** + * @template T + * @param class-string|null $tagFqn + * @return Generator + */ + public function tags(?string $tagFqn = null): Generator + { + foreach ($this->children as $child) { + if ($tagFqn && $child instanceof $tagFqn) { + yield $child; + continue; + } + if (!$tagFqn && $child instanceof TagNode) { + yield $child; + continue; + } + } + } + + public function prose(): string + { + return trim(implode('', array_map(function (Element $token): string { + if ($token instanceof Token) { + if (in_array($token->type, [ + Token::T_PHPDOC_OPEN, + Token::T_PHPDOC_CLOSE, + Token::T_PHPDOC_LEADING + ])) { + return ''; + } + return $token->value; + } + return ''; + }, iterator_to_array($this->children, false)))); + } +} diff --git a/lib/Ast/Element.php b/lib/Ast/Element.php new file mode 100644 index 00000000..38369be3 --- /dev/null +++ b/lib/Ast/Element.php @@ -0,0 +1,21 @@ + + */ +class ElementList extends Node implements IteratorAggregate +{ + protected const CHILD_NAMES = [ + 'elements', + ]; + + /** + * @var T[] + */ + public $elements; + + /** + * @param T[] $elements + */ + public function __construct(array $elements) + { + $this->elements = $elements; + } + + /** + * @return ArrayIterator + */ + public function getIterator(): Iterator + { + return new ArrayIterator($this->elements); + } + + /** + * @return Element[] + */ + public function toArray(): array + { + return $this->elements; + } +} diff --git a/lib/Ast/Node.php b/lib/Ast/Node.php new file mode 100644 index 00000000..0d7ff43a --- /dev/null +++ b/lib/Ast/Node.php @@ -0,0 +1,234 @@ +length()); + ; + $start = $this->start(); + foreach ($this->tokens() as $token) { + $out = substr_replace($out, $token->value, $token->start() - $start, $token->length()); + } + + return $out; + } + + /** + * @return Generator + */ + public function tokens(): Generator + { + yield from $this->findTokens($this->children()); + } + + /** + * Return the short name of the node class (e.g. ParamTag) + */ + public function shortName(): string + { + return substr(get_class($this), strrpos(get_class($this), '\\') + 1); + } + + /** + * @return Generator + */ + public function selfAndDescendantElements(): Generator + { + yield $this; + yield from $this->traverseNodes($this->children()); + } + + /** + * @return Generator + */ + public function descendantElements(?string $elementFqn = null): Generator + { + if (null === $elementFqn) { + yield from $this->traverseNodes($this->children()); + return; + } + + foreach ($this->traverseNodes($this->children()) as $element) { + if ($element instanceof $elementFqn) { + yield $element; + } + } + } + + public function hasDescendant(string $elementFqn): bool + { + foreach ($this->descendantElements($elementFqn) as $element) { + return true; + } + + return false; + } + + /** + * @template T of Element + * @param class-string $elementFqn + * @return T|null + */ + public function firstDescendant(string $elementFqn): ?Element + { + foreach ($this->descendantElements($elementFqn) as $element) { + return $element; + } + + return null; + } + + /** + * @param class-string $elementFqn + * @return Generator + */ + public function children(?string $elementFqn = null): Generator + { + if (!$elementFqn) { + foreach (static::CHILD_NAMES as $name) { + $child = $this->$name; + if (null !== $child) { + yield $child; + } + } + + return; + } + + foreach (static::CHILD_NAMES as $name) { + $child = $this->$name; + if ($child instanceof $elementFqn) { + yield $child; + } + } + } + + /** + * Return the bytes offset for the start of this node. + */ + public function start(): int + { + return $this->startOf($this->children()); + } + + /** + * Return the bytes offset for the end of this node. + */ + public function end(): int + { + return $this->endOf(array_reverse(iterator_to_array($this->children(), false))); + } + + public function hasChild(string $elementFqn): bool + { + foreach ($this->children() as $child) { + if ($child instanceof $elementFqn) { + return true; + } + } + + return false; + } + + /** + * @param iterable> $nodes + * + * @return Generator + */ + private function traverseNodes(iterable $nodes): Generator + { + $result = []; + foreach ($nodes as $child) { + if (is_iterable($child)) { + yield from $this->traverseNodes($child); + continue; + } + + if ($child instanceof Node) { + yield from $child->selfAndDescendantElements(); + continue; + } + + if ($child instanceof Token) { + yield $child; + continue; + } + } + } + + /** + * @param iterable> $elements + */ + private function endOf(iterable $elements): int + { + foreach ($elements as $element) { + if (null === $element) { + continue; + } + + if (is_array($element)) { + return $this->endOf(array_reverse($element)); + } + + if (is_iterable($element)) { + return $this->endOf(array_reverse(iterator_to_array($element))); + } + + return $element->end(); + } + + return 0; + } + + private function length(): int + { + return $this->end() - $this->start(); + } + + /** + * @param iterable> $elements + */ + private function startOf(iterable $elements): int + { + foreach ($elements as $element) { + if ($element instanceof Element) { + return $element->start(); + } + if (is_iterable($element)) { + return $this->startOf($element); + } + } + + return 0; + } + + /** + * @return Generator + * @param iterable> $nodes + */ + private function findTokens(iterable $nodes): Generator + { + foreach ($nodes as $node) { + if ($node instanceof Token) { + yield $node; + continue; + } + + if ($node instanceof Node) { + yield from $node->tokens(); + } + + if (is_iterable($node)) { + yield from $this->findTokens($node); + } + } + } +} diff --git a/lib/Ast/ParameterList.php b/lib/Ast/ParameterList.php new file mode 100644 index 00000000..5fae446c --- /dev/null +++ b/lib/Ast/ParameterList.php @@ -0,0 +1,60 @@ + + */ +class ParameterList extends Node implements IteratorAggregate, Countable +{ + protected const CHILD_NAMES = [ + 'list' + ]; + + /** + * @var ParameterNode[] + */ + public $list; + + /** + * @param ParameterNode[] $list + */ + public function __construct(array $list) + { + $this->list = $list; + } + + /** + * @return Generator + */ + public function parameters(): Generator + { + foreach ($this->list as $element) { + if ($element instanceof ParameterTag) { + yield $element; + } + } + } + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->list); + } + + /** + * {@inheritDoc} + */ + public function count() + { + return count($this->list); + } +} diff --git a/lib/Ast/Tag/DeprecatedTag.php b/lib/Ast/Tag/DeprecatedTag.php new file mode 100644 index 00000000..81500dab --- /dev/null +++ b/lib/Ast/Tag/DeprecatedTag.php @@ -0,0 +1,31 @@ +text = $text; + $this->token = $token; + } +} diff --git a/lib/Ast/Tag/MethodTag.php b/lib/Ast/Tag/MethodTag.php new file mode 100644 index 00000000..f2657f3a --- /dev/null +++ b/lib/Ast/Tag/MethodTag.php @@ -0,0 +1,83 @@ +type = $type; + $this->name = $name; + $this->static = $static; + $this->parameters = $parameters; + $this->text = $text; + $this->parenOpen = $parenOpen; + $this->parenClose = $parenClose; + $this->tag = $tag; + } +} diff --git a/lib/Ast/Tag/MixinTag.php b/lib/Ast/Tag/MixinTag.php new file mode 100644 index 00000000..48dbf7bd --- /dev/null +++ b/lib/Ast/Tag/MixinTag.php @@ -0,0 +1,36 @@ +class = $class; + $this->tag = $tag; + } + + public function class(): ?ClassNode + { + return $this->class; + } +} diff --git a/lib/Ast/Tag/ParamTag.php b/lib/Ast/Tag/ParamTag.php new file mode 100644 index 00000000..580ff43b --- /dev/null +++ b/lib/Ast/Tag/ParamTag.php @@ -0,0 +1,62 @@ +type = $type; + $this->variable = $variable; + $this->text = $text; + $this->tag = $tag; + } + + public function type(): ?TypeNode + { + return $this->type; + } + + public function variable(): ?VariableNode + { + return $this->variable; + } + + public function text(): ?TextNode + { + return $this->text; + } +} diff --git a/lib/Ast/Tag/ParameterTag.php b/lib/Ast/Tag/ParameterTag.php new file mode 100644 index 00000000..9a6636e4 --- /dev/null +++ b/lib/Ast/Tag/ParameterTag.php @@ -0,0 +1,54 @@ +type = $type; + $this->name = $name; + $this->default = $default; + } + + public function name(): ?VariableNode + { + return $this->name; + } + + public function type(): ?TypeNode + { + return $this->type; + } + + public function default(): ?ValueNode + { + return $this->default; + } +} diff --git a/lib/Ast/Tag/PropertyTag.php b/lib/Ast/Tag/PropertyTag.php new file mode 100644 index 00000000..623a389c --- /dev/null +++ b/lib/Ast/Tag/PropertyTag.php @@ -0,0 +1,38 @@ +type = $type; + $this->name = $name; + $this->tag = $tag; + } +} diff --git a/lib/Ast/Tag/ReturnTag.php b/lib/Ast/Tag/ReturnTag.php new file mode 100644 index 00000000..4c34cb62 --- /dev/null +++ b/lib/Ast/Tag/ReturnTag.php @@ -0,0 +1,49 @@ +type = $type; + $this->text = $text; + $this->tag = $tag; + } + + public function type(): ?TypeNode + { + return $this->type; + } + + public function text(): ?TextNode + { + return $this->text; + } +} diff --git a/lib/Ast/Tag/VarTag.php b/lib/Ast/Tag/VarTag.php new file mode 100644 index 00000000..28607e35 --- /dev/null +++ b/lib/Ast/Tag/VarTag.php @@ -0,0 +1,48 @@ +type = $type; + $this->variable = $variable; + $this->tag = $tag; + } + + public function type(): ?TypeNode + { + return $this->type; + } + + public function variable(): ?VariableNode + { + return $this->variable; + } +} diff --git a/lib/Ast/TagNode.php b/lib/Ast/TagNode.php new file mode 100644 index 00000000..93ebc1c8 --- /dev/null +++ b/lib/Ast/TagNode.php @@ -0,0 +1,7 @@ +tokens = $tokens; + } + + public function toString(): string + { + return implode('', array_map(function (Token $token) { + return $token->value; + }, $this->tokens)); + } +} diff --git a/lib/Ast/Token.php b/lib/Ast/Token.php new file mode 100644 index 00000000..15cf7588 --- /dev/null +++ b/lib/Ast/Token.php @@ -0,0 +1,77 @@ +byteOffset = $byteOffset; + $this->type = $type; + $this->value = $value; + } + + public function toString(): string + { + return $this->value; + } + + /** + * {@inheritDoc} + */ + public function start(): int + { + return $this->byteOffset; + } + + /** + * {@inheritDoc} + */ + public function end(): int + { + return $this->byteOffset + strlen($this->value); + } + + public function length(): int + { + return $this->end() - $this->start(); + } +} diff --git a/lib/Ast/Tokens.php b/lib/Ast/Tokens.php new file mode 100644 index 00000000..9a697ad6 --- /dev/null +++ b/lib/Ast/Tokens.php @@ -0,0 +1,151 @@ +tokens = $tokens; + if (count($tokens)) { + $this->current = $tokens[$this->position]; + } + } + + /** + * @return Token[] + */ + public function toArray(): array + { + return $this->tokens; + } + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->tokens); + } + + public function hasCurrent(): bool + { + return isset($this->tokens[$this->position]); + } + + public function hasAnother(): bool + { + return isset($this->tokens[$this->position + 1]); + } + + /** + * Return the current token and move the position ahead. + */ + public function chomp(?string $type = null): ?Token + { + if (!isset($this->tokens[$this->position])) { + return null; + } + + $token = $this->tokens[$this->position++]; + $this->current = @$this->tokens[$this->position]; + + if (null !== $type && $token->type !== $type) { + throw new RuntimeException(sprintf( + 'Expected type "%s" at position "%s": "%s"', + $type, + $this->position, + implode('', array_map(function (Token $token) { + return $token->value; + }, $this->tokens)) + )); + } + + return $token; + } + + /** + * Chomp only if the current node is the given type + */ + public function chompIf(string $type): ?Token + { + if ($this->current === null) { + return null; + } + + if ($this->current->type === $type) { + return $this->chomp($type); + } + + return null; + } + + public function ifNextIs(string $type): bool + { + $next = $this->next(); + if ($next && $next->type === $type) { + $this->current = @$this->tokens[++$this->position]; + return true; + } + + return false; + } + + /** + * If the current or next non-whitespace node matches, + * advance internal pointer and return true; + */ + public function if(string $type): bool + { + if (null === $this->current) { + return false; + } + + if ($this->current->type === $type) { + return true; + } + + if ($this->current->type !== Token::T_WHITESPACE) { + return false; + } + + $next = $this->next(); + if ($next && $this->next()->type === $type) { + $this->current = $this->tokens[++$this->position]; + return true; + } + + return false; + } + + public function next(): ?Token + { + if (!isset($this->tokens[$this->position + 1])) { + return null; + } + + return $this->tokens[$this->position + 1]; + } +} diff --git a/lib/Ast/Type/ClassNode.php b/lib/Ast/Type/ClassNode.php new file mode 100644 index 00000000..aceaa16c --- /dev/null +++ b/lib/Ast/Type/ClassNode.php @@ -0,0 +1,28 @@ +name = $name; + } + + public function name(): Token + { + return $this->name; + } +} diff --git a/lib/Ast/Type/GenericNode.php b/lib/Ast/Type/GenericNode.php new file mode 100644 index 00000000..b74bca37 --- /dev/null +++ b/lib/Ast/Type/GenericNode.php @@ -0,0 +1,64 @@ +open = $open; + $this->close = $close; + $this->parameters = $parameters; + $this->type = $type; + } + + public function close(): Token + { + return $this->close; + } + + public function open(): Token + { + return $this->open; + } + + public function parameters(): TypeList + { + return $this->parameters; + } + + public function type(): TypeNode + { + return $this->type; + } +} diff --git a/lib/Ast/Type/ListNode.php b/lib/Ast/Type/ListNode.php new file mode 100644 index 00000000..78a89b2e --- /dev/null +++ b/lib/Ast/Type/ListNode.php @@ -0,0 +1,40 @@ +type = $type; + $this->listChars = $listChars; + } + + public function type(): TypeNode + { + return $this->type; + } + + public function listChars(): Token + { + return $this->listChars; + } +} diff --git a/lib/Ast/Type/NullNode.php b/lib/Ast/Type/NullNode.php new file mode 100644 index 00000000..00555263 --- /dev/null +++ b/lib/Ast/Type/NullNode.php @@ -0,0 +1,28 @@ +null = $null; + } + + public function null(): Token + { + return $this->null; + } +} diff --git a/lib/Ast/Type/NullableNode.php b/lib/Ast/Type/NullableNode.php new file mode 100644 index 00000000..edbf4327 --- /dev/null +++ b/lib/Ast/Type/NullableNode.php @@ -0,0 +1,40 @@ +nullable = $nullable; + $this->type = $type; + } + + public function nullable(): Token + { + return $this->nullable; + } + + public function type(): TypeNode + { + return $this->type; + } +} diff --git a/lib/Ast/Type/ScalarNode.php b/lib/Ast/Type/ScalarNode.php new file mode 100644 index 00000000..5a8fe25f --- /dev/null +++ b/lib/Ast/Type/ScalarNode.php @@ -0,0 +1,28 @@ +name = $name; + } + + public function name(): Token + { + return $this->name; + } +} diff --git a/lib/Ast/Type/ThisNode.php b/lib/Ast/Type/ThisNode.php new file mode 100644 index 00000000..7b159688 --- /dev/null +++ b/lib/Ast/Type/ThisNode.php @@ -0,0 +1,23 @@ +name = $name; + } +} diff --git a/lib/Ast/Type/UnionNode.php b/lib/Ast/Type/UnionNode.php new file mode 100644 index 00000000..ad96e744 --- /dev/null +++ b/lib/Ast/Type/UnionNode.php @@ -0,0 +1,23 @@ +types = $types; + } +} diff --git a/lib/Ast/TypeList.php b/lib/Ast/TypeList.php new file mode 100644 index 00000000..a3d1d8d4 --- /dev/null +++ b/lib/Ast/TypeList.php @@ -0,0 +1,72 @@ + + */ +class TypeList extends Node implements IteratorAggregate, Countable +{ + protected const CHILD_NAMES = [ + 'list' + ]; + + /** + * @var array + */ + public $list; + + /** + * @param array $list + */ + public function __construct(array $list) + { + $this->list = $list; + } + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->list); + } + + /** + * {@inheritDoc} + */ + public function count() + { + return count($this->list); + } + + /** + * @return T + */ + public function first(): Element + { + if (!isset($this->list[0])) { + throw new RuntimeException(sprintf( + 'List has no first element' + )); + } + + return $this->list[0]; + } + + /** + * @return TypeList + */ + public function types(): self + { + return new self(array_filter($this->list, function (Element $element) { + return $element instanceof TypeNode; + })); + } +} diff --git a/lib/Ast/TypeNode.php b/lib/Ast/TypeNode.php new file mode 100644 index 00000000..4cefe3ea --- /dev/null +++ b/lib/Ast/TypeNode.php @@ -0,0 +1,7 @@ +name = $name; + } +} diff --git a/lib/Ast/Value/NullValue.php b/lib/Ast/Value/NullValue.php new file mode 100644 index 00000000..6b0fa373 --- /dev/null +++ b/lib/Ast/Value/NullValue.php @@ -0,0 +1,32 @@ +null = $null; + } + + public function null(): Token + { + return $this->null; + } + + /** + * {@inheritDoc} + */ + public function value() + { + return null; + } +} diff --git a/lib/Tag/AbstractTag.php b/lib/Ast/Value/UnkownValue.php similarity index 100% rename from lib/Tag/AbstractTag.php rename to lib/Ast/Value/UnkownValue.php diff --git a/lib/Ast/ValueNode.php b/lib/Ast/ValueNode.php new file mode 100644 index 00000000..7fe42ebd --- /dev/null +++ b/lib/Ast/ValueNode.php @@ -0,0 +1,11 @@ +name = $name; + } + + public function name(): Token + { + return $this->name; + } +} diff --git a/lib/DefaultValue.php b/lib/DefaultValue.php deleted file mode 100644 index 6e05838f..00000000 --- a/lib/DefaultValue.php +++ /dev/null @@ -1,40 +0,0 @@ -value = $value; - $this->none = $none; - } - - public function isDefined(): bool - { - return $this->value !== null; - } - - public static function none() - { - return new self(null, true); - } - - public static function ofValue($value) - { - return new self($value); - } - - public function value() - { - return $this->value; - } -} diff --git a/lib/Docblock.php b/lib/Docblock.php deleted file mode 100644 index d2a47267..00000000 --- a/lib/Docblock.php +++ /dev/null @@ -1,42 +0,0 @@ -tags = $tags; - $this->prose = $prose; - } - - public static function fromTags(array $tags) - { - return new self(Tags::fromArray($tags)); - } - - public static function fromProseAndTags(string $prose, array $tags) - { - return new self(Tags::fromArray($tags), $prose); - } - - public function tags(): Tags - { - return $this->tags; - } - - public function prose(): string - { - return $this->prose; - } -} diff --git a/lib/DocblockException.php b/lib/DocblockException.php deleted file mode 100644 index 521f50e7..00000000 --- a/lib/DocblockException.php +++ /dev/null @@ -1,9 +0,0 @@ -parser = $parser ?: new Parser(); - $this->typesParser = $typesParser ?: new TypesParser(); - $this->methodParser = $methodParser ?: new MethodParser($this->typesParser); - } - - public function create(string $docblock): Docblock - { - $tags = []; - list($prose, $tagData) = $this->parser->parse($docblock); - foreach ($tagData as $tagName => $metadatas) { - foreach ($metadatas as $metadata) { - switch (strtolower(trim($tagName))) { - case 'var': - $tags[] = $this->createVarTag($metadata); - break; - case 'param': - $tags[] = $this->createParamTag($metadata); - break; - case 'method': - $tags[] = $this->createMethodTag($metadata); - break; - case 'mixin': - $tags[] = $this->createMixinTag($metadata); - break; - case 'property': - $tags[] = $this->createPropertyTag($metadata); - break; - case 'deprecated': - $tags[] = $this->createDeprecatedTag($metadata); - break; - case 'return': - $tags[] = $this->createReturnTag($metadata); - break; - case 'inheritdoc': - $tags[] = new InheritTag(); - } - } - } - - return Docblock::fromProseAndTags(implode(PHP_EOL, $prose), array_filter( - $tags, - function (Tag $tag) { - return $tag !== null; - } - )); - } - - private function createVarTag(array $metadata): VarTag - { - if (null === $types = array_shift($metadata)) { - $types = ''; - } - - $varName = array_shift($metadata); - - return new VarTag($this->typesParser->parseTypes($types), $varName); - } - - private function createParamTag(array $metadata): ParamTag - { - if (null === $types = array_shift($metadata)) { - $types = ''; - } - - $varName = array_shift($metadata); - - return new ParamTag($this->typesParser->parseTypes($types), $varName); - } - - private function createMethodTag(array $metadata): MethodTag - { - return $this->methodParser->parseMethod($metadata); - } - - private function createReturnTag(array $metadata): ReturnTag - { - if (null === $types = array_shift($metadata)) { - $types = ''; - } - - $methodName = array_shift($metadata); - - return new ReturnTag($this->typesParser->parseTypes($types)); - } - - private function createPropertyTag($metadata) - { - if (null === $types = array_shift($metadata)) { - $types = ''; - } - - $propertyName = array_shift($metadata); - - return new PropertyTag($this->typesParser->parseTypes($types), ltrim($propertyName, '$')); - } - - private function createDeprecatedTag(array $metadata): DeprecatedTag - { - return new DeprecatedTag(implode(' ', $metadata)); - } - - private function createMixinTag(array $metadata): ?MixinTag - { - $fqn = array_shift($metadata); - if (null === $fqn) { - return null; - } - return new MixinTag($fqn); - } -} diff --git a/lib/DocblockType.php b/lib/DocblockType.php deleted file mode 100644 index 30e867f0..00000000 --- a/lib/DocblockType.php +++ /dev/null @@ -1,82 +0,0 @@ -type = $type; - $this->iteratedType = $iteratedType; - } - - public static function collectionOf(string $type, string $iteratedType): DocblockType - { - return new self($type, $iteratedType); - } - - public static function of(string $type): DocblockType - { - return new self($type); - } - - public static function fullyQualifiedNameOf(string $string): self - { - $type = static::of($string); - $type->isFullyQualified = true; - - return $type; - } - - public static function arrayOf(string $type): DocblockType - { - return new self('array', $type); - } - - /** - * @return string|null - */ - public function iteratedType() - { - return $this->iteratedType; - } - - public function isArray(): bool - { - return $this->type === 'array'; - } - - public function isCollection(): bool - { - return $this->iteratedType && $this->type !== 'array'; - } - - public function __toString() - { - if ($this->isFullyQualified) { - return '\\' . $this->type; - } - - return $this->type; - } - - public function isFullyQualified(): bool - { - return $this->isFullyQualified; - } -} diff --git a/lib/DocblockTypes.php b/lib/DocblockTypes.php deleted file mode 100644 index 343c7abc..00000000 --- a/lib/DocblockTypes.php +++ /dev/null @@ -1,42 +0,0 @@ -add($item); - } - } - - public static function empty(): DocblockTypes - { - return new self([]); - } - - public static function fromStringTypes($types) - { - return new self(array_map(function (string $type) { - return DocblockType::of($type); - }, $types)); - } - - public static function fromDocblockTypes(array $docblocktypes): DocblockTypes - { - return new self($docblocktypes); - } - - public function getIterator() - { - return new \ArrayIterator($this->docblocktypes); - } - - private function add(DocblockType $item) - { - $this->docblocktypes[] = $item; - } -} diff --git a/lib/InheritTag.php b/lib/InheritTag.php deleted file mode 100644 index 652ac6aa..00000000 --- a/lib/InheritTag.php +++ /dev/null @@ -1,11 +0,0 @@ -', // brackets + '\$[a-zA-Z0-9_\x80-\xff]+', // variable + '[a-zA-Z0-9_\\\]+', // label + ]; + + private const TOKEN_VALUE_MAP = [ + ']' => Token::T_BRACKET_SQUARE_CLOSE, + '[' => Token::T_BRACKET_SQUARE_OPEN, + '>' => Token::T_BRACKET_ANGLE_CLOSE, + '<' => Token::T_BRACKET_ANGLE_OPEN, + '{' => Token::T_BRACKET_CURLY_OPEN, + '}' => Token::T_BRACKET_CURLY_CLOSE, + '(' => Token::T_PAREN_OPEN, + ')' => Token::T_PAREN_CLOSE, + ',' => Token::T_COMMA, + '[]' => Token::T_LIST, + '?' => Token::T_NULLABLE, + '|' => Token::T_BAR, + '=' => Token::T_EQUALS, + ]; + + /** + * @var string[] + */ + private const IGNORE_PATTERNS = [ + '\s+', + ]; + + /** + * @var string + */ + private $pattern; + + public function __construct() + { + $this->pattern = sprintf( + '{(%s)|%s}', + implode(')|(', self::PATTERNS), + implode('|', self::IGNORE_PATTERNS) + ); + } + + public function lex(string $docblock): Tokens + { + $chunks = (array)preg_split( + $this->pattern, + $docblock, + null, + PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE + ); + + $tokens = []; + $prevChunk = null; + foreach ($chunks as $chunk) { + [ $value, $offset ] = $chunk; + $tokens[] = new Token( + $offset, + $this->resolveType($value, $prevChunk), + $value + ); + $prevChunk = $chunk; + } + + return new Tokens($tokens); + } + + private function resolveType(string $value, ?array $prevChunk = null): string + { + if (false !== strpos($value, '/*')) { + return Token::T_PHPDOC_OPEN; + } + + if (false !== strpos($value, '*/')) { + return Token::T_PHPDOC_CLOSE; + } + + if (trim($value) === '*') { + return Token::T_PHPDOC_LEADING; + } + + if (array_key_exists($value, self::TOKEN_VALUE_MAP)) { + return self::TOKEN_VALUE_MAP[$value]; + } + + if ($value[0] === '$') { + return Token::T_VARIABLE; + } + + if ($value[0] === '@') { + return Token::T_TAG; + } + + if (trim($value) === '') { + return Token::T_WHITESPACE; + } + + if (ctype_alpha($value[0]) || $value[0] === '\\') { + return Token::T_LABEL; + } + + return Token::T_UNKNOWN; + } +} diff --git a/lib/Method/Parameter.php b/lib/Method/Parameter.php deleted file mode 100644 index ceb8fa5d..00000000 --- a/lib/Method/Parameter.php +++ /dev/null @@ -1,46 +0,0 @@ -name = $name; - $this->types = $types ?: DocblockTypes::empty(); - $this->defaultValue = $defaultValue ?: DefaultValue::none(); - } - - public function name(): string - { - return $this->name; - } - - public function types(): DocblockTypes - { - return $this->types; - } - - public function defaultValue(): DefaultValue - { - return $this->defaultValue; - } -} diff --git a/lib/Parser.php b/lib/Parser.php index 64c94885..c4263cef 100644 --- a/lib/Parser.php +++ b/lib/Parser.php @@ -2,61 +2,411 @@ namespace Phpactor\Docblock; -class Parser +use Phpactor\Docblock\Ast\Tag\DeprecatedTag; +use Phpactor\Docblock\Ast\Docblock; +use Phpactor\Docblock\Ast\Tag\MethodTag; +use Phpactor\Docblock\Ast\Tag\MixinTag; +use Phpactor\Docblock\Ast\ParameterList; +use Phpactor\Docblock\Ast\Tag\ParameterTag; +use Phpactor\Docblock\Ast\Tag\PropertyTag; +use Phpactor\Docblock\Ast\Tag\ReturnTag; +use Phpactor\Docblock\Ast\TextNode; +use Phpactor\Docblock\Ast\TypeList; +use Phpactor\Docblock\Ast\Type\ClassNode; +use Phpactor\Docblock\Ast\Node; +use Phpactor\Docblock\Ast\Tag\ParamTag; +use Phpactor\Docblock\Ast\TagNode; +use Phpactor\Docblock\Ast\TypeNode; +use Phpactor\Docblock\Ast\Type\GenericNode; +use Phpactor\Docblock\Ast\Type\ListNode; +use Phpactor\Docblock\Ast\Type\NullNode; +use Phpactor\Docblock\Ast\Type\NullableNode; +use Phpactor\Docblock\Ast\Type\ScalarNode; +use Phpactor\Docblock\Ast\Type\ThisNode; +use Phpactor\Docblock\Ast\Type\UnionNode; +use Phpactor\Docblock\Ast\UnknownTag; +use Phpactor\Docblock\Ast\ValueNode; +use Phpactor\Docblock\Ast\Value\NullValue; +use Phpactor\Docblock\Ast\Tag\VarTag; +use Phpactor\Docblock\Ast\VariableNode; +use Phpactor\Docblock\Ast\Token; +use Phpactor\Docblock\Ast\Tokens; + +final class Parser { - const TAG = '{@([-0-9A-Z_a-z\\\\]+)\s*?([$&(),<=>?\[\\\\\]|\w\s]+)?}'; + /** + * TODO: callable is not a scalar + */ + private const SCALAR_TYPES = [ + 'int', 'float', 'bool', 'string', 'mixed', 'callable', + ]; + /** + * @var Tokens + */ + private $tokens; + + public function parse(Tokens $tokens): Node + { + $children = []; + $this->tokens = $tokens; + + while ($tokens->hasCurrent()) { + if ($tokens->current->type === Token::T_TAG) { + $children[] = $this->parseTag(); + continue; + } + $children[] = $tokens->chomp(); + } + + if (count($children) === 1) { + $node = reset($children); + if ($node instanceof Node) { + return $node; + } + } + + return new Docblock($children); + } - public function parse($docblock): array + private function parseTag(): TagNode { - $lines = explode(PHP_EOL, $docblock); - $tags = []; - $prose = []; + $token = $this->tokens->current; + + switch ($token->value) { + case '@param': + return $this->parseParam(); + + case '@var': + return $this->parseVar(); + + case '@deprecated': + return $this->parseDeprecated(); + + case '@method': + return $this->parseMethod(); + + case '@property': + return $this->parseProperty(); + + case '@mixin': + return $this->parseMixin(); - foreach ($lines as $line) { - if (0 === preg_match(self::TAG, $line, $matches)) { - if (null !== $line = $this->extractProse($line)) { - $prose[] = $line; + case '@return': + return $this->parseReturn(); + } + + return new UnknownTag($this->tokens->chomp()); + } + + private function parseParam(): ParamTag + { + $type = $variable = $textNode = null; + $tag = $this->tokens->chomp(Token::T_TAG); + + if ($this->ifType()) { + $type = $this->parseTypes(); + } + + if ($this->tokens->ifNextIs(Token::T_VARIABLE)) { + $variable = $this->parseVariable(); + } + + return new ParamTag($tag, $type, $variable, $this->parseText()); + } + + private function parseVar(): VarTag + { + $tag = $this->tokens->chomp(Token::T_TAG); + $type = $variable = null; + if ($this->ifType()) { + $type = $this->parseTypes(); + } + if ($this->tokens->ifNextIs(Token::T_VARIABLE)) { + $variable = $this->parseVariable(); + } + + return new VarTag($tag, $type, $variable); + } + + private function parseMethod(): MethodTag + { + $tag = $this->tokens->chomp(Token::T_TAG); + $type = $name = $parameterList = $open = $close = null; + $static = null; + + if ($this->tokens->ifNextIs(Token::T_LABEL)) { + if ($this->tokens->current->value === 'static') { + $static = $this->tokens->chomp(); + } + } + + if ($this->ifType()) { + $type = $this->parseTypes(); + } + + if ($this->tokens->if(Token::T_LABEL)) { + $name = $this->tokens->chomp(); + } + + if ($this->tokens->if(Token::T_PAREN_OPEN)) { + $open = $this->tokens->chomp(Token::T_PAREN_OPEN); + $parameterList = $this->parseParameterList(); + $close = $this->tokens->chompIf(Token::T_PAREN_CLOSE); + } + + return new MethodTag($tag, $type, $name, $static, $open, $parameterList, $close, $this->parseText()); + } + + private function parseProperty(): PropertyTag + { + $tag = $this->tokens->chomp(Token::T_TAG); + $type = $name = null; + if ($this->ifType()) { + $type = $this->parseTypes(); + } + if ($this->tokens->ifNextIs(Token::T_VARIABLE)) { + $name = $this->tokens->chomp(); + } + + return new PropertyTag($tag, $type, $name); + } + + private function parseTypes(): ?TypeNode + { + $type = $this->parseType(); + if (null === $type) { + return $type; + } + $elements = [$type]; + + while (true) { + if ($this->tokens->if(Token::T_BAR)) { + $elements[] = $this->tokens->chomp(); + $elements[] = $this->parseType(); + if (null !== $type) { + continue; } + } + break; + } + + if (count($elements) === 1) { + return $elements[0]; + } + + return new UnionNode(new TypeList($elements)); + } + + private function parseType(): ?TypeNode + { + if (null === $this->tokens->current) { + return null; + } + + if ($this->tokens->current->type === Token::T_NULLABLE) { + $nullable = $this->tokens->chomp(); + return new NullableNode($nullable, $this->parseTypes()); + } + + $type = $this->tokens->chomp(Token::T_LABEL); + + if (null === $this->tokens->current) { + return $this->createTypeFromToken($type); + } + + $isList = false; + + if ($this->tokens->current->type === Token::T_LIST) { + $list = $this->tokens->chomp(); + return new ListNode($this->createTypeFromToken($type), $list); + } + + if ($this->tokens->current->type === Token::T_BRACKET_ANGLE_OPEN) { + $open = $this->tokens->chomp(); + if ($this->tokens->if(Token::T_LABEL)) { + $typeList = $this->parseTypeList(); + } + + if ($this->tokens->current->type !== Token::T_BRACKET_ANGLE_CLOSE) { + return null; + } + + return new GenericNode( + $open, + $this->createTypeFromToken($type), + $typeList, + $this->tokens->chomp() + ); + } + + return $this->createTypeFromToken($type); + } + + private function createTypeFromToken(Token $type): TypeNode + { + if (strtolower($type->value) === 'null') { + return new NullNode($type); + } + if (in_array($type->value, self::SCALAR_TYPES)) { + return new ScalarNode($type); + } + + return new ClassNode($type); + } + + private function parseVariable(): ?VariableNode + { + if ($this->tokens->current->type !== Token::T_VARIABLE) { + return null; + } + + $name = $this->tokens->chomp(Token::T_VARIABLE); + + return new VariableNode($name); + } + + private function parseTypeList(string $delimiter = ','): TypeList + { + $types = []; + while (true) { + if ($this->tokens->if(Token::T_LABEL)) { + $types[] = $this->parseTypes(); + } + if ($this->tokens->if(Token::T_COMMA)) { + $types[] = $this->tokens->chomp(); continue; } + break; + } - $tagName = $matches[1]; + return new TypeList($types); + } + + private function parseParameterList(): ?ParameterList + { + if ($this->tokens->if(Token::T_PAREN_CLOSE)) { + return null; + } - if (!isset($tags[$tagName])) { - $tags[$tagName] = []; + $parameters = []; + while (true) { + $parameters[] = $this->parseParameter(); + if ($this->tokens->if(Token::T_COMMA)) { + $parameters[] = $this->tokens->chomp(); + continue; } + break; + } - $metadata = array_values(array_filter(explode(' ', trim($matches[2] ?? '')))); - $tags[$tagName][] = $metadata; + return new ParameterList($parameters); + } + + private function parseParameter(): ParameterTag + { + $type = $name = $default = null; + if ($this->tokens->if(Token::T_LABEL)) { + $type = $this->parseTypes(); } + if ($this->tokens->if(Token::T_VARIABLE)) { + $name = $this->parseVariable(); + } + if ($this->tokens->if(Token::T_EQUALS)) { + $equals = $this->tokens->chomp(); + $default = $this->parseValue(); + } + return new ParameterTag($type, $name, $default); + } - return [$prose, $tags ]; + private function parseDeprecated(): DeprecatedTag + { + return new DeprecatedTag( + $this->tokens->chomp(Token::T_TAG), + $this->parseText() + ); } - private function extractProse(string $line) + private function parseMixin(): MixinTag { - $line = trim($line); + $tag = $this->tokens->chomp(Token::T_TAG); + $type = null; + + if ($this->tokens->if(Token::T_LABEL)) { + $type = $this->parseTypes(); + if (!$type instanceof ClassNode) { + $type = null; + } + } + + return new MixinTag($tag, $type); + } + + private function parseReturn(): ReturnTag + { + $tag = $this->tokens->chomp(Token::T_TAG); + $type = null; + + if ($this->tokens->if(Token::T_LABEL)) { + $type = $this->parseTypes(); + } - if (empty($line)) { - return; + if ($this->tokens->if(Token::T_VARIABLE)) { + $variable = $this->tokens->chomp(Token::T_VARIABLE); + if ($variable->value === '$this') { + $type = new ThisNode($variable); + } } - if ($line == '/**') { - return; + return new ReturnTag($tag, $type, $this->parseText()); + } + + private function parseText(): ?TextNode + { + if (null === $this->tokens->current) { + return null; } - if ($line == '*') { - return ''; + $text = []; + + if ( + $this->tokens->current->type === Token::T_WHITESPACE && + $this->tokens->next()->type === Token::T_LABEL + ) { + $this->tokens->chomp(); } - if (substr($line, 0, 2) == '* ') { - $line = substr($line, 2); + while ($this->tokens->current) { + if ($this->tokens->current->type === Token::T_PHPDOC_CLOSE) { + break; + } + if ($this->tokens->current->type === Token::T_PHPDOC_LEADING) { + break; + } + if (false !== strpos($this->tokens->current->value, "\n")) { + break; + } + $text[] = $this->tokens->chomp(); } + + if ($text) { + return new TextNode($text); + } + + return null; + } + + private function ifType(): bool + { + return $this->tokens->if(Token::T_LABEL) || $this->tokens->if(Token::T_NULLABLE); + } - if (substr($line, 0, 2) == '*/') { - return; + private function parseValue(): ?ValueNode + { + if ($this->tokens->if(Token::T_LABEL)) { + if (strtolower($this->tokens->current->value) === 'null') { + return new NullValue($this->tokens->chomp()); + } } - return $line; + return null; } } diff --git a/lib/Parser/MethodParser.php b/lib/Parser/MethodParser.php deleted file mode 100644 index ea0fb5fc..00000000 --- a/lib/Parser/MethodParser.php +++ /dev/null @@ -1,79 +0,0 @@ -typesParser = $typesParser ?: new TypesParser(); - $this->parameterParser = $parameterParser ?: new ParameterParser($typesParser); - } - - public function parseMethod(array $parts): MethodTag - { - $method = implode(' ', $parts); - - list($static, $types, $methodName, $parameters) = $this->methodInfo($method, $parts); - - return new MethodTag( - $this->typesParser->parseTypes($types), - $methodName, - $parameters, - $static - ); - } - - private function methodInfo(string $method, array $parts): array - { - if (empty($method)) { - return [ false , '', $method, [] ]; - } - - if (substr($method, -1) !== ')') { - $method .= '()'; - } - - if (preg_match('{(static)?\s*([\w\\\]+)?\s+(\w*?)\s*\((.*)\)}', $method, $parts)) { - $static = $parts[1]; - $types = $parts[2]; - $methodName = $parts[3]; - $paramString = $parts[4]; - - return [ - $static === 'static', - $types, - $methodName, - $this->parseParameters($paramString), - ]; - } - - return [ false, '', $method, [] ]; - } - - private function parseParameters(string $paramString): array - { - $parameters = array_map(function (string $param) { - return trim($param); - }, explode(', ', $paramString)); - - $parameters = array_filter(array_map(function (string $paramString) { - return $this->parameterParser->parse($paramString); - }, $parameters)); - - return $parameters; - } -} diff --git a/lib/Parser/ParameterParser.php b/lib/Parser/ParameterParser.php deleted file mode 100644 index f7157b71..00000000 --- a/lib/Parser/ParameterParser.php +++ /dev/null @@ -1,81 +0,0 @@ -typesParser = $typesParser ?: new TypesParser(); - } - - /** - * @return Parameter|null - */ - public function parse(string $parameterString) - { - list($parameterName, $types, $defaultValue) = $this->extractParts($parameterString); - - if (!$parameterName) { - return null; - } - - return new Parameter($parameterName, $types, $defaultValue); - } - - private function extractParts(string $parameterString) - { - $parts = array_map('trim', explode(' ', $parameterString)); - - $types = DocblockTypes::empty(); - $parameterName = null; - $defaultValue = null; - - foreach ($parts as $index => $part) { - if (substr($part, 0, 1) === '$') { - $parameterName = substr($part, 1); - continue; - } - - if (substr($part, 0, 3) === '...') { - $parameterName = substr($part, 4); - continue; - } - - if ($index === 0) { - $types = $this->typesParser->parseTypes($part); - continue; - } - - if ($part === '=' && isset($parts[$index + 1])) { - $defaultValue = $this->parseDefaultValue($parts[$index + 1]); - break; - } - } - - return [$parameterName, $types, $defaultValue]; - } - - private function parseDefaultValue(string $defaultValueString): DefaultValue - { - if (is_numeric($defaultValueString)) { - // hack to cast to either a float or an int - return DefaultValue::ofValue($defaultValueString + 0); - } - - if (in_array(substr($defaultValueString, 0, 1), ['"', '\''])) { - return DefaultValue::ofValue(trim($defaultValueString, '"\'')); - } - - return DefaultValue::none(); - } -} diff --git a/lib/Parser/TypesParser.php b/lib/Parser/TypesParser.php deleted file mode 100644 index bc7cdd61..00000000 --- a/lib/Parser/TypesParser.php +++ /dev/null @@ -1,53 +0,0 @@ -$}', $type, $matches)) { - $type = $matches[1]; - $collectionType = trim($matches[2], self::MASK_WHITESPACE_AND_IGNORED_PREFIX); - $docblockTypes[] = DocblockType::collectionOf($type, $collectionType); - continue; - } - - if (substr($type, -2) == '[]') { - $type = trim(substr($type, 0, -2), self::MASK_WHITESPACE_AND_IGNORED_PREFIX); - $docblockTypes[] = DocblockType::arrayOf($type); - continue; - } - - if (substr($type, 0, 1) === '\\') { - $docblockTypes[] = DocblockType::fullyQualifiedNameOf(substr($type, 1)); - continue; - } - - $docblockTypes[] = DocblockType::of($type); - } - - return DocblockTypes::fromDocblockTypes($docblockTypes); - } -} diff --git a/lib/Printer.php b/lib/Printer.php new file mode 100644 index 00000000..f7459b3e --- /dev/null +++ b/lib/Printer.php @@ -0,0 +1,10 @@ +indent++; + $out = sprintf('%s: = ', $node->shortName()); + foreach ($node->children() as $child) { + $out .= $this->printElement($child); + } + $this->indent--; + + return $out; + } + + /** + * @param array|Element $element + */ + public function printElement($element): string + { + if ($element instanceof Token) { + return sprintf('%s', $element->value); + } + + if ($element instanceof Node) { + return $this->newLine() . $this->print($element); + } + + return implode('', array_map(function (Element $element) { + return $this->printElement($element); + }, (array)$element)); + } + + private function newLine(): string + { + return "\n".str_repeat(' ', $this->indent); + } +} diff --git a/lib/Tag.php b/lib/Tag.php deleted file mode 100644 index 729ffd54..00000000 --- a/lib/Tag.php +++ /dev/null @@ -1,8 +0,0 @@ -message = $message; - } - - public function name() - { - return 'deprecated'; - } - - public function message(): ?string - { - return $this->message; - } -} diff --git a/lib/Tag/MethodTag.php b/lib/Tag/MethodTag.php deleted file mode 100644 index 8656f3ba..00000000 --- a/lib/Tag/MethodTag.php +++ /dev/null @@ -1,66 +0,0 @@ -types = $types; - $this->methodName = $methodName; - $this->parameters = $parameters; - $this->isStatic = $isStatic; - } - - public function name() - { - return 'method'; - } - - public function types(): DocblockTypes - { - return $this->types; - } - - public function methodName() - { - return $this->methodName; - } - - public function parameters(): array - { - return $this->parameters; - } - - public function isStatic(): bool - { - return $this->isStatic; - } -} diff --git a/lib/Tag/MixinTag.php b/lib/Tag/MixinTag.php deleted file mode 100644 index 5247759b..00000000 --- a/lib/Tag/MixinTag.php +++ /dev/null @@ -1,29 +0,0 @@ -fqn = $fqn; - } - - public function fqn(): string - { - return $this->fqn; - } - - public function name(): string - { - return 'mixin'; - } -} - diff --git a/lib/Tag/ParamTag.php b/lib/Tag/ParamTag.php deleted file mode 100644 index e18de696..00000000 --- a/lib/Tag/ParamTag.php +++ /dev/null @@ -1,11 +0,0 @@ -types = $types; - $this->propertyName = $propertyName; - } - - public function name() - { - return 'property'; - } - - public function propertyName() - { - return $this->propertyName; - } - - public function types(): DocblockTypes - { - return $this->types; - } -} diff --git a/lib/Tag/ReturnTag.php b/lib/Tag/ReturnTag.php deleted file mode 100644 index 680cc62b..00000000 --- a/lib/Tag/ReturnTag.php +++ /dev/null @@ -1,29 +0,0 @@ -types = $types; - } - - public function name() - { - return 'return'; - } - - public function types(): DocblockTypes - { - return $this->types; - } -} diff --git a/lib/Tag/VarTag.php b/lib/Tag/VarTag.php deleted file mode 100644 index c41a96db..00000000 --- a/lib/Tag/VarTag.php +++ /dev/null @@ -1,40 +0,0 @@ -types = $types; - $this->varName = $varName; - } - - public function types(): DocblockTypes - { - return $this->types; - } - - public function varName() - { - return $this->varName; - } -} diff --git a/lib/Tags.php b/lib/Tags.php deleted file mode 100644 index e9535838..00000000 --- a/lib/Tags.php +++ /dev/null @@ -1,46 +0,0 @@ -add($item); - } - } - - public static function fromArray(array $tags): Tags - { - return new self($tags); - } - - public function getIterator() - { - return new \ArrayIterator($this->tags); - } - - public function byName(string $name): Tags - { - $name = strtolower($name); - return new self(array_filter($this->tags, function (Tag $tag) use ($name) { - return $name == strtolower($tag->name()); - })); - } - - /** - * {@inheritDoc} - */ - public function count() - { - return count($this->tags); - } - - private function add(Tag $item) - { - $this->tags[] = $item; - } -} diff --git a/lsp-client.log b/lsp-client.log new file mode 100644 index 00000000..c0eb594a --- /dev/null +++ b/lsp-client.log @@ -0,0 +1,437 @@ +####### +LanguageClient 0.1.120 +####### +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[!!get(g:, 'LanguageClient_autoStart', 1), get(g:, 'LanguageClient_serverCommands', {}), get(g:, 'LanguageClient_selectionUI', v:null), get(g:, 'LanguageClient_trace', v:null), expand(get(g:, 'LanguageClient_settingsPath', '.vim/settings.json')), !!get(g:, 'LanguageClient_loadSettings', 1), get(g:, 'LanguageClient_rootMarkers', v:null), get(g:, 'LanguageClient_changeThrottle', v:null), get(g:, 'LanguageClient_waitOutputTimeout', v:null), !!get(g:, 'LanguageClient_diagnosticsEnable', 1), get(g:, 'LanguageClient_diagnosticsList', 'Quickfix'), get(g:, 'LanguageClient_diagnosticsDisplay', {}), get(g:, 'LanguageClient_windowLogMessageLevel', 'Warning'), get(g:, 'LanguageClient_hoverPreview', 'Auto'), get(g:, 'LanguageClient_completionPreferTextEdit', 0), has('nvim')]"],"id":41} +12:36:37 INFO reader-main src/vim.rs:380 <= None {"id": 41, "jsonrpc": "2.0", "result": [1, {}, null, null, ".vim/settings.json", 1, null, null, null, 1, "Quickfix", {}, "Warning", "Auto", 1, 1]} +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[get(g:, 'LanguageClient_diagnosticsSignsMax', v:null), get(g:, 'LanguageClient_documentHighlightDisplay', {})]"],"id":42} +12:36:37 INFO reader-main src/vim.rs:380 <= None {"id": 42, "jsonrpc": "2.0", "result": [null, {}]} +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["get(g:, 'loaded_fzf')"],"id":43} +12:36:37 INFO reader-main src/vim.rs:380 <= None {"id": 43, "jsonrpc": "2.0", "result": 1} +12:36:37 WARN main src/languageclient.rs:2173 Failed to start language server automatically. No language server command found for file type: markdown. +12:36:37 INFO main src/languageclient.rs:2178 End languageClient/handleBufReadPost +12:36:37 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:37 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(0)] +12:36:37 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:37 INFO main src/languageclient.rs:2283 Updating signs: [] +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"execute","params":[],"id":44} +12:36:37 INFO reader-main src/vim.rs:380 <= None {"id": 44, "jsonrpc": "2.0", "result": 0} +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"nvim_buf_clear_highlight","params":[0,1,0,22]} +12:36:37 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"s:AddHighlights","params":[1,[]]} +12:36:37 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:37 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 1, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:37 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:37 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(1)] +12:36:37 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:37 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 2, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(2)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 3, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(3)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 4, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(4)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 5, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(5)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 6, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(6)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 7, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(7)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 8, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(8)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:36:38 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 9, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:36:38 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:36:38 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(9)] +12:36:38 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:36:38 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:37:06 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 9, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:37:06 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:37:06 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(9)] +12:37:06 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:37:06 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:37:06 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 10, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:37:06 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:37:06 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(10)] +12:37:06 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:37:06 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:37:07 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 11, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +12:37:07 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:37:07 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(11)] +12:37:07 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +12:37:07 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:29 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 2, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:29 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:29 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(2)] +12:47:29 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:29 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:30 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 1, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:30 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:30 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(1)] +12:47:30 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:30 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:31 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 2, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:31 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:31 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(2)] +12:47:31 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:31 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 3, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(3)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 4, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(4)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 5, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(5)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 6, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(6)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 7, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(7)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 8, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(8)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 9, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(9)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 10, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(10)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 11, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(11)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 12, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(12)] +12:47:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:33 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 13, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:33 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:33 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(13)] +12:47:33 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:33 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:33 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 14, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:33 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:33 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(14)] +12:47:33 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:33 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:33 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 13, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:33 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:33 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(13)] +12:47:33 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:33 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 14, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(14)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 15, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(15)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 16, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(16)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 17, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(17)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 18, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(18)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 19, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(19)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 20, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(20)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:34 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 21, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:34 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:34 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(21)] +12:47:34 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:34 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 22, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(22)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 23, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(23)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 25, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(25)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 26, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(26)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 27, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(27)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 28, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 28, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(28)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(28)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 29, "LSP#visible_line_start()": 1, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(29)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(1), Number(29)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 28, "LSP#visible_line_start()": 1, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(28)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(1), Number(29)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 27, "LSP#visible_line_start()": 1, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:35 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(27)] +12:47:35 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(1), Number(29)] +12:47:35 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +12:47:36 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 26, "LSP#visible_line_start()": 1, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +12:47:36 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +12:47:36 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(26)] +12:47:36 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(1), Number(29)] +12:47:36 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:00 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 26, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:00 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:00 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(26)] +21:05:00 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(29)] +21:05:00 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:02 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 25, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:02 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:02 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(25)] +21:05:02 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:02 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:02 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:02 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:02 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +21:05:02 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:02 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:06 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:06 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:06 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +21:05:06 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:06 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:06 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 25, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:06 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:06 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(25)] +21:05:06 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:06 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:07 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 26, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:07 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:07 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(26)] +21:05:07 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:07 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:09 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:09 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:09 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:09 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:09 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":45} +21:05:09 INFO reader-main src/vim.rs:380 <= None {"id": 45, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\",", " \"extra\": {", " \"branch-alias\": {", " \"dev-master\": \"\"", " }", " }", "}", ""]]} +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\","), String(" \"extra\": {"), String(" \"branch-alias\": {"), String(" \"dev-master\": \"\""), String(" }"), String(" }"), String("}"), String("")])] +21:05:09 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"1.0.x-dev\"\n }\n }\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n" +21:05:09 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 13 ==> 14 +21:05:09 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":14}}} +21:05:09 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:09 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:09 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:09 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:09 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":46} +21:05:09 INFO reader-main src/vim.rs:380 <= None {"id": 46, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\",", " \"extra\": {", " \"branch-alias\": {", " \"dev-master\": \"0\"", " }", " }", "}", ""]]} +21:05:09 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\","), String(" \"extra\": {"), String(" \"branch-alias\": {"), String(" \"dev-master\": \"0\""), String(" }"), String(" }"), String("}"), String("")])] +21:05:09 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"0\"\n }\n }\n}\n" +21:05:09 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 14 ==> 15 +21:05:09 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"0\"\n }\n }\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":15}}} +21:05:11 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:11 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:11 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:11 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:11 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":47} +21:05:11 INFO reader-main src/vim.rs:380 <= None {"id": 47, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\",", " \"extra\": {", " \"branch-alias\": {", " \"dev-master\": \"\"", " }", " }", "}", ""]]} +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\","), String(" \"extra\": {"), String(" \"branch-alias\": {"), String(" \"dev-master\": \"\""), String(" }"), String(" }"), String("}"), String("")])] +21:05:11 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"0\"\n }\n }\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n" +21:05:11 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 15 ==> 16 +21:05:11 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":16}}} +21:05:11 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:11 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:11 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:11 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:11 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":48} +21:05:11 INFO reader-main src/vim.rs:380 <= None {"id": 48, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\",", " \"extra\": {", " \"branch-alias\": {", " \"dev-master\": \"1.0.x-dev\"", " }", " }", "}", ""]]} +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\","), String(" \"extra\": {"), String(" \"branch-alias\": {"), String(" \"dev-master\": \"1.0.x-dev\""), String(" }"), String(" }"), String("}"), String("")])] +21:05:11 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 16 ==> 17 +21:05:11 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"\"\n }\n }\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"1.0.x-dev\"\n }\n }\n}\n" +21:05:11 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"1.0.x-dev\"\n }\n }\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":17}}} +21:05:11 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleBufWritePost", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:11 INFO main src/languageclient.rs:2213 Begin languageClient/handleBufWritePost +21:05:11 INFO main src/languageclient.rs:1830 Begin textDocument/didSave +21:05:11 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:11 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json"}}} +21:05:14 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 25, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:14 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:14 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(25)] +21:05:14 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:14 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:14 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 12, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:14 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:14 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +21:05:14 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(12), Number(29)] +21:05:14 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:15 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleBufWritePost", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:15 INFO main src/languageclient.rs:2213 Begin languageClient/handleBufWritePost +21:05:15 INFO main src/languageclient.rs:1830 Begin textDocument/didSave +21:05:15 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:15 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json"}}} +21:05:15 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 23, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:15 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:15 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(23)] +21:05:15 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:15 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:17 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:17 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:17 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +21:05:17 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:17 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:17 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 25, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:17 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:17 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(25)] +21:05:17 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:17 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 26, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(26)] +21:05:18 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:18 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 27, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(27)] +21:05:18 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:18 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 28, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 29, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(28)] +21:05:18 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(29)] +21:05:18 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 24, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 24, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(24)] +21:05:18 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(24)] +21:05:18 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:18 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:18 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:18 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":49} +21:05:18 INFO reader-main src/vim.rs:380 <= None {"id": 49, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\",", "}", ""]]} +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\","), String("}"), String("")])] +21:05:18 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 17 ==> 18 +21:05:18 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"1.0.x-dev\"\n }\n }\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n}\n" +21:05:18 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":18}}} +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 23, "LSP#visible_line_start()": 10, "LSP#visible_line_end()": 24, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(23)] +21:05:18 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(10), Number(24)] +21:05:18 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:05:18 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleTextChanged", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:18 INFO main src/languageclient.rs:2183 Begin languageClient/handleTextChanged +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:18 INFO main src/languageclient.rs:1760 Begin textDocument/didChange +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:18 INFO main src/languageclient.rs:29 Some arguments are not available. Requesting from vim. Keys: ["text"]. Exps: ["LSP#text()"] +21:05:18 INFO main src/vim.rs:92 => None {"jsonrpc":"2.0","method":"eval","params":["[LSP#text()]"],"id":50} +21:05:18 INFO reader-main src/vim.rs:380 <= None {"id": 50, "jsonrpc": "2.0", "result": [["{", " \"name\": \"phpactor/docblock\",", " \"description\": \"Simple Docblock Parser\",", " \"type\": \"library\",", " \"autoload\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\\": \"lib/\"", " }", " },", " \"autoload-dev\": {", " \"psr-4\": {", " \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"", " }", " },", " \"require-dev\": {", " \"phpunit/phpunit\": \"^6.5\"", " },", " \"authors\": [", " {", " \"name\": \"Daniel Leech\",", " \"email\": \"daniel@dantleech.com\"", " }", " ],", " \"license\": \"MIT\"", "}", ""]]} +21:05:18 INFO main src/languageclient.rs:48 gather_args: [Text] = [Array([String("{"), String(" \"name\": \"phpactor/docblock\","), String(" \"description\": \"Simple Docblock Parser\","), String(" \"type\": \"library\","), String(" \"autoload\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\\": \"lib/\""), String(" }"), String(" },"), String(" \"autoload-dev\": {"), String(" \"psr-4\": {"), String(" \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\""), String(" }"), String(" },"), String(" \"require-dev\": {"), String(" \"phpunit/phpunit\": \"^6.5\""), String(" },"), String(" \"authors\": ["), String(" {"), String(" \"name\": \"Daniel Leech\","), String(" \"email\": \"daniel@dantleech.com\""), String(" }"), String(" ],"), String(" \"license\": \"MIT\""), String("}"), String("")])] +21:05:18 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.text: "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\",\n}\n" ==> "{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\"\n}\n" +21:05:18 DEBUG main src/vim.rs:320 state.text_documents./home/daniel/www/phpactor/docblock/composer.json.version: 18 ==> 19 +21:05:18 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"{\n \"name\": \"phpactor/docblock\",\n \"description\": \"Simple Docblock Parser\",\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\\": \"lib/\"\n }\n },\n \"autoload-dev\": {\n \"psr-4\": {\n \"Phpactor\\\\Docblock\\\\Tests\\\\\": \"tests/\"\n }\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^6.5\"\n },\n \"authors\": [\n {\n \"name\": \"Daniel Leech\",\n \"email\": \"daniel@dantleech.com\"\n }\n ],\n \"license\": \"MIT\"\n}\n"}],"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json","version":19}}} +21:05:19 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleBufWritePost", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:05:19 INFO main src/languageclient.rs:2213 Begin languageClient/handleBufWritePost +21:05:19 INFO main src/languageclient.rs:1830 Begin textDocument/didSave +21:05:19 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:05:19 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json"}}} +21:05:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "markdown", "line": 11, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 22, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/README.md"}} +21:05:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:05:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/README.md"), Number(11)] +21:05:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(22)] +21:05:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:07:32 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleCursorMoved", "jsonrpc": "2.0", "params": {"languageId": "json", "line": 23, "LSP#visible_line_start()": 0, "LSP#visible_line_end()": 24, "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:07:32 INFO main src/languageclient.rs:2235 Begin languageClient/handleCursorMoved +21:07:32 INFO main src/languageclient.rs:48 gather_args: [Buftype, Filename, Line] = [String(""), String("/home/daniel/www/phpactor/docblock/composer.json"), Number(23)] +21:07:32 INFO main src/languageclient.rs:48 gather_args: ["LSP#visible_line_start()", "LSP#visible_line_end()"] = [Number(0), Number(24)] +21:07:32 INFO main src/languageclient.rs:2325 End languageClient/handleCursorMoved +21:07:35 INFO reader-main src/vim.rs:380 <= None {"method": "languageClient/handleBufWritePost", "jsonrpc": "2.0", "params": {"languageId": "json", "buftype": "", "filename": "/home/daniel/www/phpactor/docblock/composer.json"}} +21:07:35 INFO main src/languageclient.rs:2213 Begin languageClient/handleBufWritePost +21:07:35 INFO main src/languageclient.rs:1830 Begin textDocument/didSave +21:07:35 INFO main src/languageclient.rs:48 gather_args: [Buftype, LanguageId, Filename] = [String(""), String("json"), String("/home/daniel/www/phpactor/docblock/composer.json")] +21:07:35 INFO main src/vim.rs:92 => Some("json") {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///home/daniel/www/phpactor/docblock/composer.json"}}} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index 54238413..00000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,387 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Property Phpactor\\\\Docblock\\\\DefaultValue\\:\\:\\$value has no typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DefaultValue\\:\\:__construct\\(\\) has parameter \\$value with no typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DefaultValue\\:\\:none\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DefaultValue\\:\\:ofValue\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DefaultValue\\:\\:ofValue\\(\\) has parameter \\$value with no typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DefaultValue\\:\\:value\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DefaultValue.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Docblock\\:\\:\\$tags type has no value type specified in iterable type Phpactor\\\\Docblock\\\\Tags\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:__construct\\(\\) has parameter \\$tags with no value type specified in iterable type Phpactor\\\\Docblock\\\\Tags\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:fromTags\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:fromTags\\(\\) has parameter \\$tags with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:fromProseAndTags\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:fromProseAndTags\\(\\) has parameter \\$tags with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Docblock\\:\\:tags\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\Tags\\.$#" - count: 1 - path: lib/Docblock.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createVarTag\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createParamTag\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createMethodTag\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createReturnTag\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createPropertyTag\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createPropertyTag\\(\\) has parameter \\$metadata with no typehint specified\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockFactory\\:\\:createDeprecatedTag\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockFactory.php - - - - message: "#^Class Phpactor\\\\Docblock\\\\DocblockTypes implements generic interface IteratorAggregate but does not specify its types\\: TKey, TValue$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:\\$docblocktypes has no typehint specified\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:__construct\\(\\) has parameter \\$docblocktypes with no typehint specified\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:empty\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:fromStringTypes\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:fromStringTypes\\(\\) has parameter \\$types with no typehint specified\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:fromDocblockTypes\\(\\) has parameter \\$docblocktypes with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:fromDocblockTypes\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:getIterator\\(\\) return type has no value type specified in iterable type Traversable\\\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\DocblockTypes\\:\\:add\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/DocblockTypes.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\InheritTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/InheritTag.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Method\\\\Parameter\\:\\:\\$types type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Method/Parameter.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Method\\\\Parameter\\:\\:__construct\\(\\) has parameter \\$types with no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Method/Parameter.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Method\\\\Parameter\\:\\:types\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Method/Parameter.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\:\\:parse\\(\\) has parameter \\$docblock with no typehint specified\\.$#" - count: 1 - path: lib/Parser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\:\\:parse\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Parser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\:\\:extractProse\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Parser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\MethodParser\\:\\:parseMethod\\(\\) has parameter \\$parts with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Parser/MethodParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\MethodParser\\:\\:methodInfo\\(\\) has parameter \\$parts with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Parser/MethodParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\MethodParser\\:\\:methodInfo\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Parser/MethodParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\MethodParser\\:\\:parseParameters\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Parser/MethodParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\ParameterParser\\:\\:extractParts\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Parser/ParameterParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Parser\\\\TypesParser\\:\\:parseTypes\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Parser/TypesParser.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\DeprecatedTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/DeprecatedTag.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:\\$types type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:__construct\\(\\) has parameter \\$methodName with no typehint specified\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:__construct\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:__construct\\(\\) has parameter \\$types with no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:types\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:methodName\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\MethodTag\\:\\:parameters\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Tag/MethodTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\ParamTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/ParamTag.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Tag\\\\PropertyTag\\:\\:\\$types type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/PropertyTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\PropertyTag\\:\\:__construct\\(\\) has parameter \\$types with no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/PropertyTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\PropertyTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/PropertyTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\PropertyTag\\:\\:propertyName\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/PropertyTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\PropertyTag\\:\\:types\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/PropertyTag.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Tag\\\\ReturnTag\\:\\:\\$types type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/ReturnTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\ReturnTag\\:\\:__construct\\(\\) has parameter \\$types with no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/ReturnTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\ReturnTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/ReturnTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\ReturnTag\\:\\:types\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/ReturnTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:name\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:\\$types type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:__construct\\(\\) has parameter \\$types with no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:__construct\\(\\) has parameter \\$varName with no typehint specified\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:types\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\DocblockTypes\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tag\\\\VarTag\\:\\:varName\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tag/VarTag.php - - - - message: "#^Class Phpactor\\\\Docblock\\\\Tags implements generic interface IteratorAggregate but does not specify its types\\: TKey, TValue$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Property Phpactor\\\\Docblock\\\\Tags\\:\\:\\$tags has no typehint specified\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:__construct\\(\\) has parameter \\$tags with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:fromArray\\(\\) has parameter \\$tags with no value type specified in iterable type array\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:fromArray\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\Tags\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:getIterator\\(\\) return type has no value type specified in iterable type Traversable\\\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:byName\\(\\) return type has no value type specified in iterable type Phpactor\\\\Docblock\\\\Tags\\.$#" - count: 1 - path: lib/Tags.php - - - - message: "#^Method Phpactor\\\\Docblock\\\\Tags\\:\\:add\\(\\) has no return typehint specified\\.$#" - count: 1 - path: lib/Tags.php - diff --git a/phpstan.neon b/phpstan.neon index 09c3a5c2..0e807a0d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,3 @@ -includes: - - phpstan-baseline.neon parameters: inferPrivatePropertyTypeFromConstructor: true paths: diff --git a/test.php b/test.php new file mode 100644 index 00000000..c583f974 --- /dev/null +++ b/test.php @@ -0,0 +1,4 @@ +parse($doc); + } + + /** + * @Revs(5) + * @Iterations(10) + */ + public function benchAssert(): void + { + $this->parse(file_get_contents(__DIR__ . '/examples/assert.example')); + } + abstract public function parse(string $doc): void; +} diff --git a/tests/Benchmark/LexerBench.php b/tests/Benchmark/LexerBench.php new file mode 100644 index 00000000..a2726f75 --- /dev/null +++ b/tests/Benchmark/LexerBench.php @@ -0,0 +1,55 @@ +lex($docblock['docblock']); + } + + public function provideDocblock(): Generator + { + yield [ + 'docblock' => <<<'EOT' + /** + * This is some complicated method + * @since 5.2 + * + * @param Foobar $barfoo Does a barfoo and then returns + * @param Barfoo $foobar Performs a foobar and then runs away. + * + * @return Baz + */ + EOT + ]; + yield [ + 'docblock' => <<<'EOT' + /** + * Assert library. + * + * @author Benjamin Eberlei + * + * @method static bool allAlnum(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric for all values. + * @method static bool allBase64(string $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. + * @method static bool allBetween(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit for all values. + * @method static bool allBetweenExclusive(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit for all values. + * @method static bool allBetweenLength(mixed $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths for all values. + * @method static bool allBoolean(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean for all values. + * @method static bool allChoice(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices for all values. + * @method static bool allChoicesNotEmpty(array $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content for all values. + * @method static bool allClassExists(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists for all values. + * @method static bool allContains(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars for all values. + * @method static bool allCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count for all values. + * @method static bool allDate(string $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format for all values. + EOT + ]; + } +} diff --git a/tests/Benchmark/PhpactorParserBench.php b/tests/Benchmark/PhpactorParserBench.php new file mode 100644 index 00000000..f7d4cd5a --- /dev/null +++ b/tests/Benchmark/PhpactorParserBench.php @@ -0,0 +1,28 @@ +parser = new Parser(); + $this->lexer = new Lexer(); + } + public function parse(string $doc): void + { + $this->parser->parse($this->lexer->lex($doc)); + } +} diff --git a/tests/Benchmark/PhpstanParserBench.php b/tests/Benchmark/PhpstanParserBench.php new file mode 100644 index 00000000..665f4718 --- /dev/null +++ b/tests/Benchmark/PhpstanParserBench.php @@ -0,0 +1,33 @@ +parser = new PhpDocParser(new TypeParser(), new ConstExprParser()); + $this->lexer = new Lexer(); + } + + public function parse(string $doc): void + { + $tokens = new TokenIterator($this->lexer->tokenize($doc)); + $this->parser->parse($tokens); + } +} diff --git a/tests/Benchmark/examples/assert.example b/tests/Benchmark/examples/assert.example new file mode 100644 index 00000000..ddbbb345 --- /dev/null +++ b/tests/Benchmark/examples/assert.example @@ -0,0 +1,186 @@ +/** + * Assert library. + * + * @author Benjamin Eberlei + * + * @method static bool allAlnum(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric for all values. + * @method static bool allBase64(string $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. + * @method static bool allBetween(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit for all values. + * @method static bool allBetweenExclusive(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit for all values. + * @method static bool allBetweenLength(mixed $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths for all values. + * @method static bool allBoolean(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean for all values. + * @method static bool allChoice(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices for all values. + * @method static bool allChoicesNotEmpty(array $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content for all values. + * @method static bool allClassExists(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists for all values. + * @method static bool allContains(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars for all values. + * @method static bool allCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count for all values. + * @method static bool allDate(string $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format for all values. + * @method static bool allDefined(mixed $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. + * @method static bool allDigit(mixed $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit for all values. + * @method static bool allDirectory(string $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists for all values. + * @method static bool allE164(string $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number for all values. + * @method static bool allEmail(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) for all values. + * @method static bool allEndsWith(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars for all values. + * @method static bool allEq(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) for all values. + * @method static bool allEqArraySubset(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset for all values. + * @method static bool allExtensionLoaded(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded for all values. + * @method static bool allExtensionVersion(string $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed for all values. + * @method static bool allFalse(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False for all values. + * @method static bool allFile(string $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists for all values. + * @method static bool allFloat(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float for all values. + * @method static bool allGreaterOrEqualThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit for all values. + * @method static bool allGreaterThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit for all values. + * @method static bool allImplementsInterface(mixed $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface for all values. + * @method static bool allInArray(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() for all values. + * @method static bool allInteger(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer for all values. + * @method static bool allIntegerish(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish for all values. + * @method static bool allInterfaceExists(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists for all values. + * @method static bool allIp(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address for all values. + * @method static bool allIpv4(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address for all values. + * @method static bool allIpv6(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address for all values. + * @method static bool allIsArray(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array for all values. + * @method static bool allIsArrayAccessible(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object for all values. + * @method static bool allIsCallable(mixed $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable for all values. + * @method static bool allIsCountable(array|Countable|ResourceBundle|SimpleXMLElement $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable for all values. + * @method static bool allIsInstanceOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name for all values. + * @method static bool allIsJsonString(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string for all values. + * @method static bool allIsObject(mixed $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object for all values. + * @method static bool allIsResource(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource for all values. + * @method static bool allIsTraversable(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object for all values. + * @method static bool allKeyExists(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array for all values. + * @method static bool allKeyIsset(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() for all values. + * @method static bool allKeyNotExists(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array for all values. + * @method static bool allLength(mixed $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length for all values. + * @method static bool allLessOrEqualThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit for all values. + * @method static bool allLessThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit for all values. + * @method static bool allMax(mixed $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit for all values. + * @method static bool allMaxCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements for all values. + * @method static bool allMaxLength(mixed $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars for all values. + * @method static bool allMethodExists(string $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object for all values. + * @method static bool allMin(mixed $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit for all values. + * @method static bool allMinCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements for all values. + * @method static bool allMinLength(mixed $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long for all values. + * @method static bool allNoContent(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty for all values. + * @method static bool allNotBlank(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank for all values. + * @method static bool allNotContains(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars for all values. + * @method static bool allNotEmpty(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty for all values. + * @method static bool allNotEmptyKey(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty for all values. + * @method static bool allNotEq(mixed $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) for all values. + * @method static bool allNotInArray(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices for all values. + * @method static bool allNotIsInstanceOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name for all values. + * @method static bool allNotNull(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null for all values. + * @method static bool allNotRegex(mixed $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex for all values. + * @method static bool allNotSame(mixed $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) for all values. + * @method static bool allNull(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is null for all values. + * @method static bool allNumeric(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric for all values. + * @method static bool allObjectOrClass(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists for all values. + * @method static bool allPhpVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version for all values. + * @method static bool allPropertiesExist(mixed $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist for all values. + * @method static bool allPropertyExists(mixed $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists for all values. + * @method static bool allRange(mixed $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers for all values. + * @method static bool allReadable(string $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable for all values. + * @method static bool allRegex(mixed $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex for all values. + * @method static bool allSame(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) for all values. + * @method static bool allSatisfy(mixed $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback for all values. + * @method static bool allScalar(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar for all values. + * @method static bool allStartsWith(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars for all values. + * @method static bool allString(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string for all values. + * @method static bool allSubclassOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name for all values. + * @method static bool allTrue(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True for all values. + * @method static bool allUniqueValues(array $values, string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality) for all values. + * @method static bool allUrl(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL for all values. + * @method static bool allUuid(string $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID for all values. + * @method static bool allVersion(string $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions for all values. + * @method static bool allWriteable(string $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable for all values. + * @method static bool nullOrAlnum(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric or that the value is null. + * @method static bool nullOrBase64(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. + * @method static bool nullOrBetween(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit or that the value is null. + * @method static bool nullOrBetweenExclusive(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit or that the value is null. + * @method static bool nullOrBetweenLength(mixed|null $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths or that the value is null. + * @method static bool nullOrBoolean(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean or that the value is null. + * @method static bool nullOrChoice(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices or that the value is null. + * @method static bool nullOrChoicesNotEmpty(array|null $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content or that the value is null. + * @method static bool nullOrClassExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists or that the value is null. + * @method static bool nullOrContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars or that the value is null. + * @method static bool nullOrCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count or that the value is null. + * @method static bool nullOrDate(string|null $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format or that the value is null. + * @method static bool nullOrDefined(mixed|null $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. + * @method static bool nullOrDigit(mixed|null $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit or that the value is null. + * @method static bool nullOrDirectory(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists or that the value is null. + * @method static bool nullOrE164(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number or that the value is null. + * @method static bool nullOrEmail(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) or that the value is null. + * @method static bool nullOrEndsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars or that the value is null. + * @method static bool nullOrEq(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) or that the value is null. + * @method static bool nullOrEqArraySubset(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset or that the value is null. + * @method static bool nullOrExtensionLoaded(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded or that the value is null. + * @method static bool nullOrExtensionVersion(string|null $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed or that the value is null. + * @method static bool nullOrFalse(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False or that the value is null. + * @method static bool nullOrFile(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists or that the value is null. + * @method static bool nullOrFloat(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float or that the value is null. + * @method static bool nullOrGreaterOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit or that the value is null. + * @method static bool nullOrGreaterThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit or that the value is null. + * @method static bool nullOrImplementsInterface(mixed|null $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface or that the value is null. + * @method static bool nullOrInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() or that the value is null. + * @method static bool nullOrInteger(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer or that the value is null. + * @method static bool nullOrIntegerish(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish or that the value is null. + * @method static bool nullOrInterfaceExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists or that the value is null. + * @method static bool nullOrIp(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address or that the value is null. + * @method static bool nullOrIpv4(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address or that the value is null. + * @method static bool nullOrIpv6(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address or that the value is null. + * @method static bool nullOrIsArray(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or that the value is null. + * @method static bool nullOrIsArrayAccessible(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object or that the value is null. + * @method static bool nullOrIsCallable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable or that the value is null. + * @method static bool nullOrIsCountable(array|Countable|ResourceBundle|SimpleXMLElement|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable or that the value is null. + * @method static bool nullOrIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name or that the value is null. + * @method static bool nullOrIsJsonString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string or that the value is null. + * @method static bool nullOrIsObject(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object or that the value is null. + * @method static bool nullOrIsResource(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource or that the value is null. + * @method static bool nullOrIsTraversable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object or that the value is null. + * @method static bool nullOrKeyExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array or that the value is null. + * @method static bool nullOrKeyIsset(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() or that the value is null. + * @method static bool nullOrKeyNotExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array or that the value is null. + * @method static bool nullOrLength(mixed|null $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length or that the value is null. + * @method static bool nullOrLessOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit or that the value is null. + * @method static bool nullOrLessThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit or that the value is null. + * @method static bool nullOrMax(mixed|null $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit or that the value is null. + * @method static bool nullOrMaxCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements or that the value is null. + * @method static bool nullOrMaxLength(mixed|null $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars or that the value is null. + * @method static bool nullOrMethodExists(string|null $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object or that the value is null. + * @method static bool nullOrMin(mixed|null $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit or that the value is null. + * @method static bool nullOrMinCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements or that the value is null. + * @method static bool nullOrMinLength(mixed|null $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long or that the value is null. + * @method static bool nullOrNoContent(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty or that the value is null. + * @method static bool nullOrNotBlank(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank or that the value is null. + * @method static bool nullOrNotContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars or that the value is null. + * @method static bool nullOrNotEmpty(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty or that the value is null. + * @method static bool nullOrNotEmptyKey(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty or that the value is null. + * @method static bool nullOrNotEq(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) or that the value is null. + * @method static bool nullOrNotInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices or that the value is null. + * @method static bool nullOrNotIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name or that the value is null. + * @method static bool nullOrNotNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null or that the value is null. + * @method static bool nullOrNotRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex or that the value is null. + * @method static bool nullOrNotSame(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) or that the value is null. + * @method static bool nullOrNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is null or that the value is null. + * @method static bool nullOrNumeric(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric or that the value is null. + * @method static bool nullOrObjectOrClass(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists or that the value is null. + * @method static bool nullOrPhpVersion(string|null $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version or that the value is null. + * @method static bool nullOrPropertiesExist(mixed|null $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist or that the value is null. + * @method static bool nullOrPropertyExists(mixed|null $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists or that the value is null. + * @method static bool nullOrRange(mixed|null $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers or that the value is null. + * @method static bool nullOrReadable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable or that the value is null. + * @method static bool nullOrRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex or that the value is null. + * @method static bool nullOrSame(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) or that the value is null. + * @method static bool nullOrSatisfy(mixed|null $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback or that the value is null. + * @method static bool nullOrScalar(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar or that the value is null. + * @method static bool nullOrStartsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars or that the value is null. + * @method static bool nullOrString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string or that the value is null. + * @method static bool nullOrSubclassOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name or that the value is null. + * @method static bool nullOrTrue(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True or that the value is null. + * @method static bool nullOrUniqueValues(array|null $values, string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality) or that the value is null. + * @method static bool nullOrUrl(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL or that the value is null. + * @method static bool nullOrUuid(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID or that the value is null. + * @method static bool nullOrVersion(string|null $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions or that the value is null. + * @method static bool nullOrWriteable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable or that the value is null. + */ + --- + diff --git a/tests/Benchmark/examples/php_core.example b/tests/Benchmark/examples/php_core.example new file mode 100644 index 00000000..32b500d3 --- /dev/null +++ b/tests/Benchmark/examples/php_core.example @@ -0,0 +1,1043 @@ + + * The argument offset. Function arguments are counted starting from + * zero. + *

+ * @return mixed|false the specified argument, or false on error. + */ +#!---!# + +/** + * Returns an array comprising a function's argument list + * @link https://php.net/manual/en/function.func-get-args.php + * @return array an array in which each element is a copy of the corresponding + * member of the current user-defined function's argument list. + */ +#!---!# + +/** + * Get string length + * @link https://php.net/manual/en/function.strlen.php + * @param string $string

+ * The string being measured for length. + *

+ * @return int The length of the string on success, + * and 0 if the string is empty. + */ +#!---!# + +/** + * Binary safe string comparison + * @link https://php.net/manual/en/function.strcmp.php + * @param string $str1

+ * The first string. + *

+ * @param string $str2

+ * The second string. + *

+ * @return int < 0 if str1 is less than + * str2; > 0 if str1 + * is greater than str2, and 0 if they are + * equal. + */ +#!---!# + +/** + * Binary safe string comparison of the first n characters + * @link https://php.net/manual/en/function.strncmp.php + * @param string $str1

+ * The first string. + *

+ * @param string $str2

+ * The second string. + *

+ * @param int $len

+ * Number of characters to use in the comparison. + *

+ * @return int < 0 if str1 is less than + * str2; > 0 if str1 + * is greater than str2, and 0 if they are + * equal. + */ +#!---!# + +/** + * Binary safe case-insensitive string comparison + * @link https://php.net/manual/en/function.strcasecmp.php + * @param string $str1

+ * The first string + *

+ * @param string $str2

+ * The second string + *

+ * @return int < 0 if str1 is less than + * str2; > 0 if str1 + * is greater than str2, and 0 if they are + * equal. + */ +#!---!# + +/** + * Binary safe case-insensitive string comparison of the first n characters + * @link https://php.net/manual/en/function.strncasecmp.php + * @param string $str1

+ * The first string. + *

+ * @param string $str2

+ * The second string. + *

+ * @param int $len

+ * The length of strings to be used in the comparison. + *

+ * @return int < 0 if str1 is less than + * str2; > 0 if str1 is + * greater than str2, and 0 if they are equal. + */ +#!---!# + +/** + * The function returns {@see true} if the passed $haystack starts from the + * $needle string or {@see false} otherwise. + * + * @param string $haystack + * @param string $needle + * @return bool + * @since 8.0 + */ +#!---!# + +/** + * The function returns {@see true} if the passed $haystack ends with the + * $needle string or {@see false} otherwise. + * + * @param string $haystack + * @param string $needle + * @return bool + * @since 8.0 + */ +#!---!# + +/** + * Checks if $needle is found in $haystack and returns a boolean value + * (true/false) whether or not the $needle was found. + * + * @param string $haystack + * @param string $needle + * @return bool + * @since 8.0 + */ +#!---!# + +/** + * Return the current key and value pair from an array and advance the array cursor + * @link https://php.net/manual/en/function.each.php + * @param array|ArrayObject &$array

+ * The input array. + *

+ * @return array the current key and value pair from the array + * array. This pair is returned in a four-element + * array, with the keys 0, 1, + * key, and value. Elements + * 0 and key contain the key name of + * the array element, and 1 and value + * contain the data. + *

+ *

+ * If the internal pointer for the array points past the end of the + * array contents, each returns + * false. + * @deprecated 7.2 Use a foreach loop instead. + * @removed 8.0 + */ +#!---!# + +/** + * Sets which PHP errors are reported + * @link https://php.net/manual/en/function.error-reporting.php + * @param int $level [optional]

+ * The new error_reporting + * level. It takes on either a bitmask, or named constants. Using named + * constants is strongly encouraged to ensure compatibility for future + * versions. As error levels are added, the range of integers increases, + * so older integer-based error levels will not always behave as expected. + *

+ *

+ * The available error level constants and the actual + * meanings of these error levels are described in the + * predefined constants. + * + * error_reporting level constants and bit values + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
valueconstant
1 + * E_ERROR + *
2 + * E_WARNING + *
4 + * E_PARSE + *
8 + * E_NOTICE + *
16 + * E_CORE_ERROR + *
32 + * E_CORE_WARNING + *
64 + * E_COMPILE_ERROR + *
128 + * E_COMPILE_WARNING + *
256 + * E_USER_ERROR + *
512 + * E_USER_WARNING + *
1024 + * E_USER_NOTICE + *
32767 + * E_ALL + *
2048 + * E_STRICT + *
4096 + * E_RECOVERABLE_ERROR + *
8192 + * E_DEPRECATED + *
16384 + * E_USER_DEPRECATED + *
+ *

+ * @return int the old error_reporting + * level or the current level if no level parameter is + * given. + */ +#!---!# + +/** + * Defines a named constant + * @link https://php.net/manual/en/function.define.php + * @param string $name

+ * The name of the constant. + *

+ * @param mixed $value

+ * The value of the constant. + * In PHP 5, value must be a scalar value (integer, float, string, boolean, or null). + * In PHP 7, array values are also accepted. + * It is possible to define resource constants, + * however it is not recommended and may cause unpredictable behavior. + *

+ * @param bool $case_insensitive [optional]

+ * If set to true, the constant will be defined case-insensitive. + * The default behavior is case-sensitive; i.e. + * CONSTANT and Constant represent + * different values. + * Defining case-insensitive constants is deprecated as of PHP 7.3.0. + *

+ *

+ * Case-insensitive constants are stored as lower-case. + *

+ * @return bool true on success or false on failure. + */ +#!---!# + +/** + * Checks whether a given named constant exists + * @link https://php.net/manual/en/function.defined.php + * @param string $name

+ * The constant name. + *

+ * @return bool true if the named constant given by name + * has been defined, false otherwise. + */ +#!---!# + +/** + * Returns the name of the class of an object + * @link https://php.net/manual/en/function.get-class.php + * @param object $object [optional]

+ * The tested object. This parameter may be omitted when inside a class. + *

+ * @return string|false

The name of the class of which object is an + * instance. Returns false if object is not an + * object. + *

+ *

+ * If object is omitted when inside a class, the + * name of that class is returned. + */ +#!---!# + +/** + * the "Late Static Binding" class name + * @link https://php.net/manual/en/function.get-called-class.php + * @return string|false The class name. Returns false if called from outside a class. + */ +#!---!# + +/** + * Retrieves the parent class name for object or class + * @link https://php.net/manual/en/function.get-parent-class.php + * @param mixed $object [optional]

+ * The tested object or class name + *

+ * @return string|false

The name of the parent class of the class of which + * object is an instance or the name. + *

+ *

+ * If the object does not have a parent false will be returned. + *

+ *

+ * If called without parameter outside object, this function returns false. + */ +#!---!# + +/** + * Checks if the class method exists + * @link https://php.net/manual/en/function.method-exists.php + * @param mixed $object

+ * An object instance or a class name + *

+ * @param string $method_name

+ * The method name + *

+ * @return bool true if the method given by method_name + * has been defined for the given object, false + * otherwise. + */ +#!---!# + +/** + * Checks if the object or class has a property + * @link https://php.net/manual/en/function.property-exists.php + * @param mixed $class

+ * The class name or an object of the class to test for + *

+ * @param string $property

+ * The name of the property + *

+ * @return bool true if the property exists, false if it doesn't exist or + * null in case of an error. + */ +#!---!# + +/** + * Checks if the trait exists + * @param string $traitname Name of the trait to check + * @param bool $autoload [optional] Whether to autoload if not already loaded. + * @return bool Returns TRUE if trait exists, FALSE if not, NULL in case of an error. + * @link https://secure.php.net/manual/en/function.trait-exists.php + * @since 5.4 + */ +#!---!# + +/** + * Checks if the class has been defined + * @link https://php.net/manual/en/function.class-exists.php + * @param string $class_name

+ * The class name. The name is matched in a case-insensitive manner. + *

+ * @param bool $autoload [optional]

+ * Whether or not to call autoload by default. + *

+ * @return bool true if class_name is a defined class, + * false otherwise. + */ +#!---!# + +/** + * Checks if the interface has been defined + * @link https://php.net/manual/en/function.interface-exists.php + * @param string $interface_name

+ * The interface name + *

+ * @param bool $autoload [optional]

+ * Whether to call autoload or not by default. + *

+ * @return bool true if the interface given by + * interface_name has been defined, false otherwise. + * @since 5.0.2 + */ +#!---!# + +/** + * Return true if the given function has been defined + * @link https://php.net/manual/en/function.function-exists.php + * @param string $function_name

+ * The function name, as a string. + *

+ * @return bool true if function_name exists and is a + * function, false otherwise. + *

+ *

+ * This function will return false for constructs, such as + * include_once and echo. + */ +#!---!# + +/** + * Creates an alias for a class + * @link https://php.net/manual/en/function.class-alias.php + * @param string $original The original class. + * @param string $alias The alias name for the class. + * @param bool $autoload [optional] Whether to autoload if the original class is not found. + * @return bool true on success or false on failure. + */ +#!---!# + +/** + * Returns an array with the names of included or required files + * @link https://php.net/manual/en/function.get-included-files.php + * @return string[] an array of the names of all files. + *

+ *

+ * The script originally called is considered an "included file," so it will + * be listed together with the files referenced by + * include and family. + *

+ *

+ * Files that are included or required multiple times only show up once in + * the returned array. + */ +#!---!# + +/** + * Alias of get_included_files + * @link https://php.net/manual/en/function.get-required-files.php + * @return string[] + */ +#!---!# + +/** + * Checks if the object has this class as one of its parents + * @link https://php.net/manual/en/function.is-subclass-of.php + * @param mixed $object

+ * A class name or an object instance + *

+ * @param string $class_name

+ * The class name + *

+ * @param bool $allow_string [optional]

+ * If this parameter set to false, string class name as object is not allowed. + * This also prevents from calling autoloader if the class doesn't exist. + *

+ * @return bool This function returns true if the object object, + * belongs to a class which is a subclass of + * class_name, false otherwise. + */ +#!---!# + +/** + * Checks if the object is of this class or has this class as one of its parents + * @link https://php.net/manual/en/function.is-a.php + * @param object|string $object

+ * The tested object + *

+ * @param string $class_name

+ * The class name + *

+ * @param bool $allow_string [optional]

+ * If this parameter set to FALSE, string class name as object + * is not allowed. This also prevents from calling autoloader if the class doesn't exist. + *

+ * @return bool TRUE if the object is of this class or has this class as one of + * its parents, FALSE otherwise. + */ +#!---!# + +/** + * Get the default properties of the class + * @link https://php.net/manual/en/function.get-class-vars.php + * @param string $class_name

+ * The class name + *

+ * @return array an associative array of declared properties visible from the + * current scope, with their default value. + * The resulting array elements are in the form of + * varname => value. + */ +#!---!# + +/** + * Gets the properties of the given object + * @link https://php.net/manual/en/function.get-object-vars.php + * @param object $object

+ * An object instance. + *

+ * @return array an associative array of defined object accessible non-static properties + * for the specified object in scope. If a property have + * not been assigned a value, it will be returned with a null value. + */ +#!---!# + +/** + * Gets the class methods' names + * @link https://php.net/manual/en/function.get-class-methods.php + * @param mixed $class_name

+ * The class name or an object instance + *

+ * @return array an array of method names defined for the class specified by + * class_name. In case of an error, it returns null. + */ +#!---!# + +/** + * Generates a user-level error/warning/notice message + * @link https://php.net/manual/en/function.trigger-error.php + * @param string $error_msg

+ * The designated error message for this error. It's limited to 1024 + * characters in length. Any additional characters beyond 1024 will be + * truncated. + *

+ * @param int $error_type [optional]

+ * The designated error type for this error. It only works with the E_USER + * family of constants, and will default to E_USER_NOTICE. + *

+ * @return bool This function returns false if wrong error_type is + * specified, true otherwise. + */ +#!---!# + +/** + * Alias of trigger_error + * @link https://php.net/manual/en/function.user-error.php + * @param string $message + * @param int $error_type [optional] + * @return bool This function returns false if wrong error_type is + * specified, true otherwise. + */ +#!---!# + +/** + * Sets a user-defined error handler function + * @link https://php.net/manual/en/function.set-error-handler.php + * @param callable|null $error_handler

+ * The user function needs to accept two parameters: the error code, and a + * string describing the error. Then there are three optional parameters + * that may be supplied: the filename in which the error occurred, the + * line number in which the error occurred, and the context in which the + * error occurred (an array that points to the active symbol table at the + * point the error occurred). The function can be shown as: + *

+ *

+ * handler + * interrno + * stringerrstr + * stringerrfile + * interrline + * arrayerrcontext + * errno + * The first parameter, errno, contains the + * level of the error raised, as an integer. + * @param int $error_types [optional]

+ * Can be used to mask the triggering of the + * error_handler function just like the error_reporting ini setting + * controls which errors are shown. Without this mask set the + * error_handler will be called for every error + * regardless to the setting of the error_reporting setting. + *

+ * @return callable|null a string containing the previously defined error handler (if any). If + * the built-in error handler is used null is returned. null is also returned + * in case of an error such as an invalid callback. If the previous error handler + * was a class method, this function will return an indexed array with the class + * and the method name. + */ +#!---!# + +/** + * Restores the previous error handler function + * @link https://php.net/manual/en/function.restore-error-handler.php + * @return bool This function always returns true. + */ +#!---!# + +/** + * Sets a user-defined exception handler function + * @link https://php.net/manual/en/function.set-exception-handler.php + * @param callable|null $exception_handler

+ * Name of the function to be called when an uncaught exception occurs. + * This function must be defined before calling + * set_exception_handler. This handler function + * needs to accept one parameter, which will be the exception object that + * was thrown. + * NULL may be passed instead, to reset this handler to its default state. + *

+ * @return callable|null the name of the previously defined exception handler, or null on error. If + * no previous handler was defined, null is also returned. + */ +#!---!# + +/** + * Restores the previously defined exception handler function + * @link https://php.net/manual/en/function.restore-exception-handler.php + * @return bool This function always returns true. + */ +#!---!# + +/** + * Returns an array with the name of the defined classes + * @link https://php.net/manual/en/function.get-declared-classes.php + * @return array an array of the names of the declared classes in the current + * script. + *

+ *

+ * Note that depending on what extensions you have compiled or + * loaded into PHP, additional classes could be present. This means that + * you will not be able to define your own classes using these + * names. There is a list of predefined classes in the Predefined Classes section of + * the appendices. + */ +#!---!# + +/** + * Returns an array of all declared interfaces + * @link https://php.net/manual/en/function.get-declared-interfaces.php + * @return array an array of the names of the declared interfaces in the current + * script. + */ +#!---!# + +/** + * Returns an array of all declared traits + * @return array with names of all declared traits in values. Returns NULL in case of a failure. + * @link https://secure.php.net/manual/en/function.get-declared-traits.php + * @see class_uses() + * @since 5.4 + */ +#!---!# + +/** + * Returns an array of all defined functions + * @link https://php.net/manual/en/function.get-defined-functions.php + * @param bool $exclude_disabled [optional] Whether disabled functions should be excluded from the return value. + * @return array an multidimensional array containing a list of all defined + * functions, both built-in (internal) and user-defined. The internal + * functions will be accessible via $arr["internal"], and + * the user defined ones using $arr["user"] (see example + * below). + */ +#!---!# + +/** + * Returns an array of all defined variables + * @link https://php.net/manual/en/function.get-defined-vars.php + * @return array A multidimensional array with all the variables. + */ +#!---!# + +/** + * Create an anonymous (lambda-style) function + * @link https://php.net/manual/en/function.create-function.php + * @param string $args

+ * The function arguments. + *

+ * @param string $code

+ * The function code. + *

+ * @return string|false a unique function name as a string, or false on error. + * @deprecated 7.2 Use anonymous functions instead. + * @removed 8.0 + */ +#!---!# + +/** + * Returns the resource type + * @link https://php.net/manual/en/function.get-resource-type.php + * @param resource $handle

+ * The evaluated resource handle. + *

+ * @return string If the given handle is a resource, this function + * will return a string representing its type. If the type is not identified + * by this function, the return value will be the string + * Unknown. + *

+ *

+ * This function will return false and generate an error if + * handle is not a resource. + */ +#!---!# + +/** + * Returns an array with the names of all modules compiled and loaded + * @link https://php.net/manual/en/function.get-loaded-extensions.php + * @param bool $zend_extensions [optional]

+ * Only return Zend extensions, if not then regular extensions, like + * mysqli are listed. Defaults to false (return regular extensions). + *

+ * @return array an indexed array of all the modules names. + */ +#!---!# + +/** + * Find out whether an extension is loaded + * @link https://php.net/manual/en/function.extension-loaded.php + * @param string $name

+ * The extension name. + *

+ *

+ * You can see the names of various extensions by using + * phpinfo or if you're using the + * CGI or CLI version of + * PHP you can use the -m switch to + * list all available extensions: + *

+ * $ php -m
+ * [PHP Modules]
+ * xml
+ * tokenizer
+ * standard
+ * sockets
+ * session
+ * posix
+ * pcre
+ * overload
+ * mysql
+ * mbstring
+ * ctype
+ * [Zend Modules]
+ * 
+ *

+ * @return bool true if the extension identified by name + * is loaded, false otherwise. + */ +#!---!# + +/** + * Returns an array with the names of the functions of a module + * @link https://php.net/manual/en/function.get-extension-funcs.php + * @param string $module_name

+ * The module name. + *

+ *

+ * This parameter must be in lowercase. + *

+ * @return string[]|false an array with all the functions, or false if + * module_name is not a valid extension. + */ +#!---!# + +/** + * Returns an associative array with the names of all the constants and their values + * @link https://php.net/manual/en/function.get-defined-constants.php + * @param bool $categorize [optional]

+ * Causing this function to return a multi-dimensional + * array with categories in the keys of the first dimension and constants + * and their values in the second dimension. + * + * define("MY_CONSTANT", 1); + * print_r(get_defined_constants(true)); + * + * The above example will output something similar to: + *

+ * Array
+ * (
+ * [Core] => Array
+ * (
+ * [E_ERROR] => 1
+ * [E_WARNING] => 2
+ * [E_PARSE] => 4
+ * [E_NOTICE] => 8
+ * [E_CORE_ERROR] => 16
+ * [E_CORE_WARNING] => 32
+ * [E_COMPILE_ERROR] => 64
+ * [E_COMPILE_WARNING] => 128
+ * [E_USER_ERROR] => 256
+ * [E_USER_WARNING] => 512
+ * [E_USER_NOTICE] => 1024
+ * [E_STRICT] => 2048
+ * [E_RECOVERABLE_ERROR] => 4096
+ * [E_DEPRECATED] => 8192
+ * [E_USER_DEPRECATED] => 16384
+ * [E_ALL] => 32767
+ * [TRUE] => 1
+ * )
+ * [pcre] => Array
+ * (
+ * [PREG_PATTERN_ORDER] => 1
+ * [PREG_SET_ORDER] => 2
+ * [PREG_OFFSET_CAPTURE] => 256
+ * [PREG_SPLIT_NO_EMPTY] => 1
+ * [PREG_SPLIT_DELIM_CAPTURE] => 2
+ * [PREG_SPLIT_OFFSET_CAPTURE] => 4
+ * [PREG_GREP_INVERT] => 1
+ * )
+ * [user] => Array
+ * (
+ * [MY_CONSTANT] => 1
+ * )
+ * )
+ * 
+ *

+ * @return array + */ +#!---!# + +/** + * Generates a backtrace + * @link https://php.net/manual/en/function.debug-backtrace.php + * @param int $options [optional]

+ * As of 5.3.6, this parameter is a bitmask for the following options: + * + * debug_backtrace options + * + * + * + * + * + * + * + * + *
DEBUG_BACKTRACE_PROVIDE_OBJECT + * Whether or not to populate the "object" index. + *
DEBUG_BACKTRACE_IGNORE_ARGS + * Whether or not to omit the "args" index, and thus all the function/method arguments, + * to save memory. + *
+ * Before 5.3.6, the only values recognized are true or false, which are the same as + * setting or not setting the DEBUG_BACKTRACE_PROVIDE_OBJECT option respectively. + *

+ * @param int $limit [optional]

+ * As of 5.4.0, this parameter can be used to limit the number of stack frames returned. + * By default (limit=0) it returns all stack frames. + *

+ * @return array an array of associative arrays. The possible returned elements + * are as follows: + *

+ *

+ * + * Possible returned elements from debug_backtrace + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
&Name;&Type;Description
functionstring + * The current function name. See also + * __FUNCTION__. + *
lineinteger + * The current line number. See also + * __LINE__. + *
filestring + * The current file name. See also + * __FILE__. + *
classstring + * The current class name. See also + * __CLASS__ + *
objectobject + * The current object. + *
typestring + * The current call type. If a method call, "->" is returned. If a static + * method call, "::" is returned. If a function call, nothing is returned. + *
argsarray + * If inside a function, this lists the functions arguments. If + * inside an included file, this lists the included file name(s). + *
+ */ +#!---!# + +/** + * Prints a backtrace + * @link https://php.net/manual/en/function.debug-print-backtrace.php + * @param int $options [optional]

+ * As of 5.3.6, this parameter is a bitmask for the following options: + * + * debug_print_backtrace options + * + * + * + * + *
DEBUG_BACKTRACE_IGNORE_ARGS + * Whether or not to omit the "args" index, and thus all the function/method arguments, + * to save memory. + *
+ *

+ * @param int $limit [optional]

+ * As of 5.4.0, this parameter can be used to limit the number of stack frames printed. + * By default (limit=0) it prints all stack frames. + *

+ * @return void + */ +#!---!# + +/** + * Forces collection of any existing garbage cycles + * @link https://php.net/manual/en/function.gc-collect-cycles.php + * @return int number of collected cycles. + */ +#!---!# + +/** + * Returns status of the circular reference collector + * @link https://php.net/manual/en/function.gc-enabled.php + * @return bool true if the garbage collector is enabled, false otherwise. + */ +#!---!# + +/** + * Activates the circular reference collector + * @link https://php.net/manual/en/function.gc-enable.php + * @return void + */ +#!---!# + +/** + * Deactivates the circular reference collector + * @link https://php.net/manual/en/function.gc-disable.php + * @return void + */ +#!---!# + +/** + * Gets information about the garbage collector + * @link https://php.net/manual/en/function.gc-status.php + * @return array associative array with the following elements: + *
    + *
  • "runs"
  • + *
  • "collected"
  • + *
  • "threshold"
  • + *
  • "roots"
  • + *
+ * @since 7.3 + */ +#!---!# + +/** + * Reclaims memory used by the Zend Engine memory manager + * @link https://php.net/manual/en/function.gc-mem-caches.php + * @return int Returns the number of bytes freed. + * @since 7.0 + */ +#!---!# + +/** + * Returns active resources + * @link https://php.net/manual/en/function.get-resources.php + * @param string $type [optional]

+ * + * If defined, this will cause get_resources() to only return resources of the given type. A list of resource types is available. + * + * If the string Unknown is provided as the type, then only resources that are of an unknown type will be returned. + * + * If omitted, all resources will be returned. + *

+ * @return array Returns an array of currently active resources, indexed by resource number. + * @since 7.0 + */ +#!---!# diff --git a/tests/DocblockFactoryTest.php b/tests/DocblockFactoryTest.php deleted file mode 100644 index c893836c..00000000 --- a/tests/DocblockFactoryTest.php +++ /dev/null @@ -1,111 +0,0 @@ -create($docblock); - $this->assertEquals($expected->tags(), $docblock->tags()); - } - - public function provideCreate() - { - return [ - 'no tags' => [ - '/** */', - Docblock::fromTags([]), - ], - 'var single type' => [ - '** @var Foobar */', - Docblock::fromTags([ new VarTag(DocblockTypes::fromStringTypes([ 'Foobar' ])), ]), - ], - 'var multiple types' => [ - '/** @var Foobar|string|null */', - Docblock::fromTags([ new VarTag(DocblockTypes::fromStringTypes([ 'Foobar', 'string', 'null' ])) ]), - ], - 'var union types' => [ - '/** @var Foobar&string */', - Docblock::fromTags([ new VarTag(DocblockTypes::fromStringTypes([ 'Foobar', 'string' ])) ]), - ], - 'param single type' => [ - '/** @param Foobar $foobar */', - Docblock::fromTags([ new ParamTag(DocblockTypes::fromStringTypes([ 'Foobar' ]), '$foobar') ]), - ], - 'method single type' => [ - '/** @method Foobar foobar() */', - Docblock::fromTags([ new MethodTag(DocblockTypes::fromStringTypes([ 'Foobar' ]), 'foobar') ]), - ], - 'property' => [ - '/** @property string $foo */', - Docblock::fromTags([ new PropertyTag(DocblockTypes::fromStringTypes(['string']), 'foo') ]), - ], - - 'property no type' => [ - '/** @property Foo */', - Docblock::fromTags([ new PropertyTag(DocblockTypes::fromStringTypes(['Foo']), '') ]), - ], - - 'property with nothing' => [ - '/** @property */', - Docblock::fromTags([ new PropertyTag(DocblockTypes::empty(), '') ]), - ], - - 'return single type' => [ - '/** @return Foobar foobar() */', - Docblock::fromTags([ new ReturnTag(DocblockTypes::fromStringTypes([ 'Foobar' ])) ]), - ], - 'return single nullable type' => [ - '/** @return ?Foobar foobar() */', - Docblock::fromTags([ new ReturnTag(DocblockTypes::fromStringTypes([ 'Foobar' ])) ]), - ], - 'inheritdoc' => [ - '/** {@inheritDoc} */', - Docblock::fromTags([ new InheritTag() ]), - ], - - 'var no type' => [ - '/** @var */', - Docblock::fromTags([ new VarTag(DocblockTypes::empty()) ]), - ], - 'param no type' => [ - '/** @param */', - Docblock::fromTags([ new ParamTag(DocblockTypes::empty(), '') ]), - ], - 'method no type' => [ - '/** @method */', - Docblock::fromTags([ new MethodTag(DocblockTypes::empty(), '') ]), - ], - 'return no type' => [ - '/** @return */', - Docblock::fromTags([ new ReturnTag(DocblockTypes::empty()) ]), - ], - 'deprecated' => [ - '/** @deprecated This is deprecated */', - Docblock::fromTags([ new DeprecatedTag('This is deprecated') ]), - ], - 'mixin' => [ - '/** @mixin Foobar\\Barfoo */', - Docblock::fromTags([ new MixinTag('Foobar\\Barfoo') ]), - ], - ]; - } -} diff --git a/tests/DocblockTest.php b/tests/DocblockTest.php deleted file mode 100644 index 83a888ea..00000000 --- a/tests/DocblockTest.php +++ /dev/null @@ -1,44 +0,0 @@ -tag1 = $this->prophesize(Tag::class); - } - - public function testFromTags() - { - $docblock = Docblock::fromTags([ - $this->tag1->reveal() - ]); - - $this->assertEquals(Tags::fromArray([$this->tag1->reveal()]), $docblock->tags()); - } - - public function testFromProseAndTags() - { - $docblock = Docblock::fromProseAndTags( - 'Hello this is prose', - [ - $this->tag1->reveal() - ] - ); - - $this->assertEquals(Tags::fromArray([$this->tag1->reveal()]), $docblock->tags()); - $this->assertEquals('Hello this is prose', $docblock->prose()); - } -} diff --git a/tests/DocblockTypeTest.php b/tests/DocblockTypeTest.php deleted file mode 100755 index e46f7112..00000000 --- a/tests/DocblockTypeTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertTrue($type->isCollection()); - $this->assertFalse($type->isArray()); - $this->assertEquals('Foobar', $type->__toString()); - $this->assertEquals('Item', $type->iteratedType()); - } -} diff --git a/tests/Parser/MethodParserTest.php b/tests/Parser/MethodParserTest.php deleted file mode 100644 index bafc44ce..00000000 --- a/tests/Parser/MethodParserTest.php +++ /dev/null @@ -1,169 +0,0 @@ -assertEquals($expected, $parser->parseMethod($parts)); - } - - public function provideCreate() - { - return [ - 'no parts' => [ - [ ], - new MethodTag(DocblockTypes::empty(), ''), - ], - //'type only parts' => [ - // [ 'Foobar' ], - // new MethodTag(DocblockTypes::fromStringTypes(['Foobar']), ''), - //], - 'no parenthesis' => [ - [ 'Foobar', 'foobar' ], - new MethodTag(DocblockTypes::fromStringTypes([ 'Foobar' ]), 'foobar'), - ], - 'single type' => [ - [ 'Foobar', 'foobar()' ], - new MethodTag(DocblockTypes::fromStringTypes([ 'Foobar' ]), 'foobar'), - ], - 'with parameters' => [ - [ 'Foobar', 'foobar(Foobar $foobar, string $foo, $bar)' ], - new MethodTag( - DocblockTypes::fromStringTypes([ 'Foobar' ]), - 'foobar', - [ - new Parameter('foobar', DocblockTypes::fromDocblockTypes([ DocblockType::of('Foobar') ])), - new Parameter('foo', DocblockTypes::fromDocblockTypes([ DocblockType::of('string') ])), - new Parameter('bar', DocblockTypes::fromDocblockTypes([ ])), - ] - ), - ], - 'with parameters and default value' => [ - [ 'Foobar', 'foobar(string $foo = "hello", $bar)' ], - new MethodTag( - DocblockTypes::fromStringTypes([ 'Foobar' ]), - 'foobar', - [ - new Parameter( - 'foo', - DocblockTypes::fromDocblockTypes([ DocblockType::of('string') ]), - DefaultValue::ofValue('hello') - ), - new Parameter('bar', DocblockTypes::fromDocblockTypes([ ])), - ] - ), - ], - 'static method' => [ - [ 'static', 'Foobar', 'foobar()' ], - new MethodTag( - DocblockTypes::fromStringTypes([ 'Foobar' ]), - 'foobar', - [], - true - ), - ], - 'phpspec be constructed with' => [ - [ 'void', 'foobar(...$arguments)' ], - new MethodTag( - DocblockTypes::fromStringTypes(['void']), - 'foobar', - [ - new Parameter( - 'arguments', - DocblockTypes::fromDocblockTypes([]) - ), - ] - ), - ], - 'phpspec be constructed through' => [ - [ 'void', 'beConstructedThrough($factoryMethod, array $constructorArguments = array())' ], - new MethodTag( - DocblockTypes::fromStringTypes(['void']), - 'beConstructedThrough', - [ - new Parameter( - 'factoryMethod', - DocblockTypes::fromDocblockTypes([]) - ), - new Parameter( - 'constructorArguments', - DocblockTypes::fromDocblockTypes([ DocblockType::of('array') ]), - DefaultValue::none() - ), - ] - ), - ], - 'phpspec should have count' => [ - [ 'void', 'shouldHaveCount($count)' ], - new MethodTag( - DocblockTypes::fromStringTypes(['void']), - 'shouldHaveCount', - [ - new Parameter( - 'count', - DocblockTypes::empty() - ), - ] - ), - - ], - 'laravel db' => [ - [ 'static', '\\Illuminate\\Database\\Query\\Builder', 'table(string $table)' ], - new MethodTag( - DocblockTypes::fromDocblockTypes([DocblockType::fullyQualifiedNameOf('Illuminate\\Database\\Query\\Builder')]), - 'table', - [ - new Parameter( - 'table', - DocblockTypes::fromStringTypes(['string']) - ), - ], - true - ), - - ], - 'laravel route' => [ - [ - 'static', - '\\Illuminate\\Routing\\Route', - 'get(string $uri, \\Closure|array|string|callable|null $action = null)' - ], - new MethodTag( - DocblockTypes::fromDocblockTypes([DocblockType::fullyQualifiedNameOf('Illuminate\\Routing\\Route')]), - 'get', - [ - new Parameter( - 'uri', - DocblockTypes::fromStringTypes(['string']) - ), - new Parameter( - 'action', - DocblockTypes::fromDocblockTypes([ - DocblockType::fullyQualifiedNameOf('Closure'), - DocblockType::of('array'), - DocblockType::of('string'), - DocblockType::of('callable'), - DocblockType::of('null'), - ]) - ), - ], - true - ) - ], - ]; - } -} diff --git a/tests/Parser/ParameterParserTest.php b/tests/Parser/ParameterParserTest.php deleted file mode 100644 index 18f8c9e5..00000000 --- a/tests/Parser/ParameterParserTest.php +++ /dev/null @@ -1,59 +0,0 @@ -assertEquals($expected, $parser->parse($paramString)); - } - - public function provideCreate() - { - return [ - 'no parts' => [ - '', - null - ], - 'lone variable' => [ - '$foobar', - new Parameter('foobar'), - ], - 'typed variable' => [ - 'Foobar $foobar', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar'])), - ], - 'typed variable with string default' => [ - 'Foobar $foobar = "foobar"', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar']), DefaultValue::ofValue('foobar')), - ], - 'typed variable with single quoted default string' => [ - 'Foobar $foobar = \'foobar\'', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar']), DefaultValue::ofValue('foobar')), - ], - 'typed variable with float' => [ - 'Foobar $foobar = 1.234', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar']), DefaultValue::ofValue(1.234)), - ], - 'typed variable with int' => [ - 'Foobar $foobar = 1234', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar']), DefaultValue::ofValue(1234)), - ], - 'typed variable with static call (not supported)' => [ - 'Foobar $foobar = Barfoo::FOOBAR', - new Parameter('foobar', DocblockTypes::fromStringTypes(['Foobar'])), - ], - ]; - } -} diff --git a/tests/Parser/TypesParserTest.php b/tests/Parser/TypesParserTest.php deleted file mode 100644 index 669371c0..00000000 --- a/tests/Parser/TypesParserTest.php +++ /dev/null @@ -1,54 +0,0 @@ -assertEquals($expected, $parser->parseTypes($types)); - } - - public function provideParseTypes() - { - return [ - [ - 'Foobar', - DocblockTypes::fromStringTypes(['Foobar']), - ], - [ - 'Foobar[]', - DocblockTypes::fromDocblockTypes([ DocblockType::arrayOf('Foobar') ]), - ], - [ - 'Foobar', - DocblockTypes::fromDocblockTypes([ DocblockType::collectionOf('Foobar', 'Item') ]), - ], - [ - '\Foobar\Foobar', - DocblockTypes::fromDocblockTypes([ DocblockType::fullyQualifiedNameOf('Foobar\Foobar') ]), - ], - [ - '?Foobar', - DocblockTypes::fromStringTypes(['Foobar']), - ], - [ - '?Foobar[]', - DocblockTypes::fromDocblockTypes([ DocblockType::arrayOf('Foobar') ]), - ], - [ - 'Foobar', - DocblockTypes::fromDocblockTypes([ DocblockType::collectionOf('Foobar', 'Item') ]), - ], - ]; - } -} diff --git a/tests/ParserTest.php b/tests/ParserTest.php deleted file mode 100644 index 7a911617..00000000 --- a/tests/ParserTest.php +++ /dev/null @@ -1,140 +0,0 @@ -parse($docblock); - $this->assertEquals($expected, $tags); - } - - public function provideParseTags() - { - yield [ - '/** @var Foobar */', - [ 'var' => [ [ 'Foobar' ] ] ], - ]; - - yield [ - '/** @var Foobar[] */', - [ 'var' => [ [ 'Foobar[]' ] ] ], - ]; - - yield 'for collection' => [ - '/** @var Foobar */', - [ 'var' => [ [ 'Foobar' ] ] ], - ]; - - yield [ - '/** @var Foobar $foobar */', - [ 'var' => [ [ 'Foobar', '$foobar' ] ] ], - ]; - - yield 'named var with irregular spacing' => [ - '/** @var Foobar $foobar */', - [ 'var' => [ [ 'Foobar', '$foobar' ] ] ], - ]; - - yield [ - <<<'EOT' -/** - * @var Foobar $foobar - * @var Barfoo $barfoo - **/ -EOT - , - ['var' => [ - [ 'Foobar', '$foobar' ], - [ 'Barfoo', '$barfoo' ] - ]], - ]; - - yield [ - <<<'EOT' -/** - * @var Foobar $foobar Hello this is description - **/ -EOT - , - ['var' => [ - [ 'Foobar', '$foobar', 'Hello', 'this', 'is', 'description' ], - ]], - ]; - - yield 'method with fully qualified type' => [ - <<<'EOT' -/** - * @method \Foobar\Barfoo foobar() - **/ -EOT - , - ['method' => [ - [ '\Foobar\Barfoo', 'foobar()' ], - ]], - ]; - - yield 'method with parameters' => [ - '/** @method \Barfoo foobar($foobar, string $foo) */', - [ 'method' => [ [ - '\Barfoo', - 'foobar($foobar,', 'string', '$foo)' - ] ] ], - ]; - - yield 'method with array type' => [ - '/** @method Foobar[] */', - [ 'method' => [ [ 'Foobar[]' ] ] ], - ]; - - yield 'phpspec should have count' => [ - '* @method void shouldHaveCount($count)', - [ 'method' => [ [ 'void', 'shouldHaveCount($count)' ] ] ], - ]; - - yield 'argument with default value' => [ - '* @method void shouldHaveCount($count = 5)', - [ 'method' => [ [ - 'void', - 'shouldHaveCount($count', '=', '5)' - ] ] ], - ]; - } - - /** - * @dataProvider provideParseProse - */ - public function testParseProse($docblock, $expected) - { - $parser = new Parser(); - list($prose, $tags) = $parser->parse($docblock); - $this->assertEquals($expected, $prose); - } - - public function provideParseProse() - { - return [ - [ - <<<'EOT' -/** - * Hello - * - * This is a description - * - * @return Foo - */ -EOT - , - [ 'Hello', '', 'This is a description', '' ], - ], - ]; - } -} diff --git a/tests/Printer/PrinterTest.php b/tests/Printer/PrinterTest.php new file mode 100644 index 00000000..3e2073ac --- /dev/null +++ b/tests/Printer/PrinterTest.php @@ -0,0 +1,56 @@ +markTestIncomplete(sprintf('No example given for "%s"', $path)); + return; + } + + $tokens = (new Lexer())->lex($parts[0]); + $node = (new Parser())->parse($tokens); + $rendered = (new TestPrinter())->print($node); + + /** + * @phpstan-ignore-next-line + */ + if (!isset($parts[1]) || $update) { + file_put_contents($path, implode("---\n", [$parts[0], $rendered])); + $this->markTestSkipped('Generated output'); + return; + } + + self::assertEquals(trim($parts[1]), trim($rendered)); + } + + /** + * @return Generator + */ + public function provideExamples(): Generator + { + foreach ((array)glob(__DIR__ . '/examples/*.test') as $path) { + yield [ + $path + ]; + } + } +} diff --git a/tests/Printer/examples/classname1.test b/tests/Printer/examples/classname1.test new file mode 100644 index 00000000..e107e06e --- /dev/null +++ b/tests/Printer/examples/classname1.test @@ -0,0 +1,10 @@ +/** + * @var Foobar\Barfoo + */ +--- +Docblock: = + ElementList: = /** + * + VarTag: = @var + ClassNode: = Foobar\Barfoo + */ diff --git a/tests/Printer/examples/classname2.test b/tests/Printer/examples/classname2.test new file mode 100644 index 00000000..3dab2b6b --- /dev/null +++ b/tests/Printer/examples/classname2.test @@ -0,0 +1,10 @@ +/** + * @var \foo_bar\bar_foo + */ +--- +Docblock: = + ElementList: = /** + * + VarTag: = @var + ClassNode: = \foo_bar\bar_foo + */ diff --git a/tests/Printer/examples/deprecated1.test b/tests/Printer/examples/deprecated1.test new file mode 100644 index 00000000..2189e884 --- /dev/null +++ b/tests/Printer/examples/deprecated1.test @@ -0,0 +1,9 @@ +/** + * @deprecated + */ +--- +Docblock: = + ElementList: = /** + * + DeprecatedTag: = @deprecated + */ diff --git a/tests/Printer/examples/deprecated2.test b/tests/Printer/examples/deprecated2.test new file mode 100644 index 00000000..721db036 --- /dev/null +++ b/tests/Printer/examples/deprecated2.test @@ -0,0 +1,10 @@ +/** + * @deprecated This is because + */ +--- +Docblock: = + ElementList: = /** + * + DeprecatedTag: = @deprecated + TextNode: = This is because + */ diff --git a/tests/Printer/examples/generic1.test b/tests/Printer/examples/generic1.test new file mode 100644 index 00000000..3fd85b39 --- /dev/null +++ b/tests/Printer/examples/generic1.test @@ -0,0 +1,15 @@ +/** + * @param Foobar $foobar + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + GenericNode: = + ClassNode: = Foobar< + TypeList: = + ListNode: = + ClassNode: = Barfoo[]> + VariableNode: = $foobar + */ diff --git a/tests/Printer/examples/generic2.test b/tests/Printer/examples/generic2.test new file mode 100644 index 00000000..60b522ec --- /dev/null +++ b/tests/Printer/examples/generic2.test @@ -0,0 +1,16 @@ +/** + * @param Foobar $foobar + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + GenericNode: = + ClassNode: = Foobar< + TypeList: = + ListNode: = + ClassNode: = Barfoo[], + ScalarNode: = string> + VariableNode: = $foobar + */ diff --git a/tests/Printer/examples/generic3.test b/tests/Printer/examples/generic3.test new file mode 100644 index 00000000..5b2addde --- /dev/null +++ b/tests/Printer/examples/generic3.test @@ -0,0 +1,19 @@ +/** + * @param Foobar,string> $foobar + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + GenericNode: = + ClassNode: = Foobar< + TypeList: = + GenericNode: = + ClassNode: = Barfoo< + TypeList: = + ScalarNode: = int, + ScalarNode: = string>, + ScalarNode: = string> + VariableNode: = $foobar + */ diff --git a/tests/Printer/examples/generic4.test b/tests/Printer/examples/generic4.test new file mode 100644 index 00000000..97a8ef56 --- /dev/null +++ b/tests/Printer/examples/generic4.test @@ -0,0 +1,22 @@ +/** + * @param Foobar,string, Baz> $foobar + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + GenericNode: = + ClassNode: = Foobar< + TypeList: = + GenericNode: = + ClassNode: = Barfoo< + TypeList: = + ListNode: = + ScalarNode: = int[], + ListNode: = + ScalarNode: = int[]>, + ScalarNode: = string, + ClassNode: = Baz> + VariableNode: = $foobar + */ diff --git a/tests/Printer/examples/list1.test b/tests/Printer/examples/list1.test new file mode 100644 index 00000000..9ee9cb00 --- /dev/null +++ b/tests/Printer/examples/list1.test @@ -0,0 +1,18 @@ +/** + * @param Foobar[] $foobar + * @param string[] $strings + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ListNode: = + ClassNode: = Foobar[] + VariableNode: = $foobar + * + ParamTag: = @param + ListNode: = + ScalarNode: = string[] + VariableNode: = $strings + */ diff --git a/tests/Printer/examples/method1.test b/tests/Printer/examples/method1.test new file mode 100644 index 00000000..f85a3223 --- /dev/null +++ b/tests/Printer/examples/method1.test @@ -0,0 +1,10 @@ +/** + * @method Foobar foobar() + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @method + ClassNode: = Foobarfoobar() + */ diff --git a/tests/Printer/examples/method2.test b/tests/Printer/examples/method2.test new file mode 100644 index 00000000..4a7a21e6 --- /dev/null +++ b/tests/Printer/examples/method2.test @@ -0,0 +1,10 @@ +/** + * @method static Foobar foobar() + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @methodstatic + ClassNode: = Foobarfoobar() + */ diff --git a/tests/Printer/examples/method3.test b/tests/Printer/examples/method3.test new file mode 100644 index 00000000..ef4e61d5 --- /dev/null +++ b/tests/Printer/examples/method3.test @@ -0,0 +1,15 @@ +/** + * @method static bool allAlnum(mixed $value) Assert that value is alphanumeric for all values. + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @methodstatic + ScalarNode: = boolallAlnum( + ParameterList: = + ParameterTag: = + ScalarNode: = mixed + VariableNode: = $value) + TextNode: = Assert that value is alphanumeric for all values. + */ diff --git a/tests/Printer/examples/method4.test b/tests/Printer/examples/method4.test new file mode 100644 index 00000000..c2876fec --- /dev/null +++ b/tests/Printer/examples/method4.test @@ -0,0 +1,15 @@ +/** + * @method bool is(string $value = null) + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @method + ScalarNode: = boolis( + ParameterList: = + ParameterTag: = + ScalarNode: = string + VariableNode: = $value + NullValue: = ) + */ diff --git a/tests/Printer/examples/method5.test b/tests/Printer/examples/method5.test new file mode 100644 index 00000000..a27e6a65 --- /dev/null +++ b/tests/Printer/examples/method5.test @@ -0,0 +1,26 @@ +/** + * @method static bool allAlnum(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric for all values. + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @methodstatic + ScalarNode: = boolallAlnum( + ParameterList: = + ParameterTag: = + ScalarNode: = mixed + VariableNode: = $value, + ParameterTag: = + UnionNode: = + TypeList: = + ScalarNode: = string| + ScalarNode: = callable + VariableNode: = $message + NullValue: = , + ParameterTag: = + ScalarNode: = string + VariableNode: = $propertyPath + NullValue: = ) + TextNode: = Assert that value is alphanumeric for all values. + */ diff --git a/tests/Printer/examples/method6.test b/tests/Printer/examples/method6.test new file mode 100644 index 00000000..9a301be1 --- /dev/null +++ b/tests/Printer/examples/method6.test @@ -0,0 +1,30 @@ +/** + * @method static bool allIpv4(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address for all values. + */ +--- +Docblock: = + ElementList: = /** + * + MethodTag: = @methodstatic + ScalarNode: = boolallIpv4( + ParameterList: = + ParameterTag: = + ScalarNode: = string + VariableNode: = $value, + ParameterTag: = + ScalarNode: = int + VariableNode: = $flag + NullValue: = , + ParameterTag: = + UnionNode: = + TypeList: = + ScalarNode: = string| + ScalarNode: = callable + VariableNode: = $message + NullValue: = , + ParameterTag: = + ScalarNode: = string + VariableNode: = $propertyPath + NullValue: = ) + TextNode: = Assert that value is an IPv4 address for all values. + */ diff --git a/tests/Printer/examples/mixin1.test b/tests/Printer/examples/mixin1.test new file mode 100644 index 00000000..a2fde0b2 --- /dev/null +++ b/tests/Printer/examples/mixin1.test @@ -0,0 +1,10 @@ +/** + * @mixin Foobar + */ +--- +Docblock: = + ElementList: = /** + * + MixinTag: = @mixin + ClassNode: = Foobar + */ diff --git a/tests/Printer/examples/nullable1.test b/tests/Printer/examples/nullable1.test new file mode 100644 index 00000000..806112b9 --- /dev/null +++ b/tests/Printer/examples/nullable1.test @@ -0,0 +1,11 @@ +/** + * @var ?Foo + */ +--- +Docblock: = + ElementList: = /** + * + VarTag: = @var + NullableNode: = ? + ClassNode: = Foo + */ diff --git a/tests/Printer/examples/param1.test b/tests/Printer/examples/param1.test new file mode 100644 index 00000000..971f3a7e --- /dev/null +++ b/tests/Printer/examples/param1.test @@ -0,0 +1,11 @@ +/** + * @param Foobar $foobar + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ClassNode: = Foobar + VariableNode: = $foobar + */ diff --git a/tests/Printer/examples/param2.test b/tests/Printer/examples/param2.test new file mode 100644 index 00000000..25e0bf36 --- /dev/null +++ b/tests/Printer/examples/param2.test @@ -0,0 +1,16 @@ +/** + * @param Foobar $foobar + * @param string $barfoo + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ClassNode: = Foobar + VariableNode: = $foobar + * + ParamTag: = @param + ScalarNode: = string + VariableNode: = $barfoo + */ diff --git a/tests/Printer/examples/param3.test b/tests/Printer/examples/param3.test new file mode 100644 index 00000000..45cb617b --- /dev/null +++ b/tests/Printer/examples/param3.test @@ -0,0 +1,29 @@ +/** + * Hello World + * + * @param Foobar $foobar + * + * @param string $barfoo + * + * @param bool $bool + */ +--- +Docblock: = + ElementList: = /** + * Hello World + * + * + ParamTag: = @param + ClassNode: = Foobar + VariableNode: = $foobar + * + * + ParamTag: = @param + ScalarNode: = string + VariableNode: = $barfoo + * + * + ParamTag: = @param + ScalarNode: = bool + VariableNode: = $bool + */ diff --git a/tests/Printer/examples/param4.test b/tests/Printer/examples/param4.test new file mode 100644 index 00000000..bb1afcd6 --- /dev/null +++ b/tests/Printer/examples/param4.test @@ -0,0 +1,10 @@ +/** + * @param bool + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ScalarNode: = bool + */ diff --git a/tests/Printer/examples/param5.test b/tests/Printer/examples/param5.test new file mode 100644 index 00000000..bf093d8a --- /dev/null +++ b/tests/Printer/examples/param5.test @@ -0,0 +1,12 @@ +/** + * @param bool $bool This is a boolean + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ScalarNode: = bool + VariableNode: = $bool + TextNode: = This is a boolean + */ diff --git a/tests/Printer/examples/param6.test b/tests/Printer/examples/param6.test new file mode 100644 index 00000000..2a0ff792 --- /dev/null +++ b/tests/Printer/examples/param6.test @@ -0,0 +1,20 @@ +/** + * @param bool $bool This is a boolean + * multiline comments not currently supported + * @param bool $bool This is a boolean + */ +--- +Docblock: = + ElementList: = /** + * + ParamTag: = @param + ScalarNode: = bool + VariableNode: = $bool + TextNode: = This is a boolean + * multiline comments not currently supported + * + ParamTag: = @param + ScalarNode: = bool + VariableNode: = $bool + TextNode: = This is a boolean + */ diff --git a/tests/Printer/examples/php_core1.test b/tests/Printer/examples/php_core1.test new file mode 100644 index 00000000..cdd3916a --- /dev/null +++ b/tests/Printer/examples/php_core1.test @@ -0,0 +1,71 @@ +/** + * Sets a user-defined error handler function + * @link https://php.net/manual/en/function.set-error-handler.php + * @param callable|null $error_handler

+ * The user function needs to accept two parameters... + *

+ *

+ * handler + * arrayerrcontext + * errno + * The first parameter, errno, contains the + * level of the error raised, as an integer. + * @param int $error_types [optional]

+ * Can be used to mask the triggering of the + * error_handler function just like the error_reporting ini setting + * controls which errors are shown. Without this mask set the + * error_handler will be called for every error + * regardless to the setting of the error_reporting setting. + *

+ * @return callable|null a string containing the previously defined error handler (if any). If + * the built-in error handler is used null is returned. null is also returned + * in case of an error such as an invalid callback. If the previous error handler + * was a class method, this function will return an indexed array with the class + * and the method name. + */ + --- +Docblock: = + ElementList: = /** + * Sets a user-defined error handler function + * + UnknownTag: = https://php.net/manual/en/function.set-error-handler.php + * + ParamTag: = @param + UnionNode: = + TypeList: = + ScalarNode: = callable| + NullNode: = null + VariableNode: = $error_handler + TextNode: =

+ * The user function needs to accept two parameters... + *

+ *

+ * handler + * arrayerrcontext + * errno + * The first parameter, errno, contains the + * level of the error raised, as an integer. + * + ParamTag: = @param + ScalarNode: = int + VariableNode: = $error_types + TextNode: = [optional]

+ * Can be used to mask the triggering of the + * error_handler function just like the error_reporting ini setting + * controls which errors are shown. Without this mask set the + * error_handler will be called for every error + * regardless to the setting of the error_reporting setting. + *

+ * + ReturnTag: = @return + UnionNode: = + TypeList: = + ScalarNode: = callable| + NullNode: = null + TextNode: = a string containing the previously defined error handler (if any). If + * the built-in error handler is used null is returned. null is also returned + * in case of an error such as an invalid callback. If the previous error handler + * was a class method, this function will return an indexed array with the class + * and the method name. + */ + \ No newline at end of file diff --git a/tests/Printer/examples/property1.test b/tests/Printer/examples/property1.test new file mode 100644 index 00000000..8842aa05 --- /dev/null +++ b/tests/Printer/examples/property1.test @@ -0,0 +1,10 @@ +/** + * @property string $foo + */ +--- +Docblock: = + ElementList: = /** + * + PropertyTag: = @property + ScalarNode: = string$foo + */ diff --git a/tests/Printer/examples/return1.test b/tests/Printer/examples/return1.test new file mode 100644 index 00000000..573dc13e --- /dev/null +++ b/tests/Printer/examples/return1.test @@ -0,0 +1,10 @@ +/** + * @return Foobar + */ +--- +Docblock: = + ElementList: = /** + * + ReturnTag: = @return + ClassNode: = Foobar + */ diff --git a/tests/Printer/examples/return2.test b/tests/Printer/examples/return2.test new file mode 100644 index 00000000..2e64713a --- /dev/null +++ b/tests/Printer/examples/return2.test @@ -0,0 +1,10 @@ +/** + * @return $this + */ +--- +Docblock: = + ElementList: = /** + * + ReturnTag: = @return + ThisNode: = $this + */ diff --git a/tests/Printer/examples/text1.test b/tests/Printer/examples/text1.test new file mode 100644 index 00000000..b87fca2c --- /dev/null +++ b/tests/Printer/examples/text1.test @@ -0,0 +1,12 @@ +/** + * Hello World + * + * This is some text + */ +--- +Docblock: = + ElementList: = /** + * Hello World + * + * This is some text + */ diff --git a/tests/Printer/examples/union1.test b/tests/Printer/examples/union1.test new file mode 100644 index 00000000..3e648291 --- /dev/null +++ b/tests/Printer/examples/union1.test @@ -0,0 +1,11 @@ +/** @var string|bool|?Bar */ +--- +Docblock: = + ElementList: = /** + VarTag: = @var + UnionNode: = + TypeList: = + ScalarNode: = string| + ScalarNode: = bool| + NullableNode: = ? + ClassNode: = Bar */ diff --git a/tests/Printer/examples/var1.test b/tests/Printer/examples/var1.test new file mode 100644 index 00000000..52dbf287 --- /dev/null +++ b/tests/Printer/examples/var1.test @@ -0,0 +1,11 @@ +/** + * @var string[] + */ +--- +Docblock: = + ElementList: = /** + * + VarTag: = @var + ListNode: = + ScalarNode: = string[] + */ diff --git a/tests/Printer/examples/var2.test b/tests/Printer/examples/var2.test new file mode 100644 index 00000000..63e6b43b --- /dev/null +++ b/tests/Printer/examples/var2.test @@ -0,0 +1,7 @@ +/** @var string $foobar */ +--- +Docblock: = + ElementList: = /** + VarTag: = @var + ScalarNode: = string + VariableNode: = $foobar */ diff --git a/tests/Printer/examples/var3.test b/tests/Printer/examples/var3.test new file mode 100644 index 00000000..63e6b43b --- /dev/null +++ b/tests/Printer/examples/var3.test @@ -0,0 +1,7 @@ +/** @var string $foobar */ +--- +Docblock: = + ElementList: = /** + VarTag: = @var + ScalarNode: = string + VariableNode: = $foobar */ diff --git a/tests/Tag/MethodTagTest.php b/tests/Tag/MethodTagTest.php deleted file mode 100644 index 2f663016..00000000 --- a/tests/Tag/MethodTagTest.php +++ /dev/null @@ -1,17 +0,0 @@ -assertEquals('foobar', $tag->methodName()); - $this->assertEquals(DocblockTypes::fromStringTypes([ 'Foobar' ]), $tag->types()); - } -} diff --git a/tests/Tag/PropertyTagTest.php b/tests/Tag/PropertyTagTest.php deleted file mode 100644 index c4f41faa..00000000 --- a/tests/Tag/PropertyTagTest.php +++ /dev/null @@ -1,17 +0,0 @@ -assertEquals('foobar', $tag->propertyName()); - $this->assertEquals(DocblockTypes::fromStringTypes([ 'Foobar' ]), $tag->types()); - } -} diff --git a/tests/Tag/VarTagTest.php b/tests/Tag/VarTagTest.php deleted file mode 100644 index c8e92620..00000000 --- a/tests/Tag/VarTagTest.php +++ /dev/null @@ -1,19 +0,0 @@ -assertEquals(DocblockTypes::fromStringTypes(['Foobar']), $tag->types()); - - $tag = new VarTag(DocblockTypes::fromStringTypes([ 'Foobar' ]), '$foobar'); - $this->assertEquals('$foobar', $tag->varName()); - } -} diff --git a/tests/TagsTest.php b/tests/TagsTest.php deleted file mode 100644 index 38cc1ee7..00000000 --- a/tests/TagsTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals($expected, $original->byName('foobar')); - } -} diff --git a/tests/Unit/Ast/NodeTest.php b/tests/Unit/Ast/NodeTest.php new file mode 100644 index 00000000..6e5d88da --- /dev/null +++ b/tests/Unit/Ast/NodeTest.php @@ -0,0 +1,151 @@ + + */ + public function provideNode(): Generator + { + yield from $this->provideApiTest(); + yield from $this->provideDocblock(); + yield from $this->provideTags(); + yield from $this->provideTypes(); + } + + /** + * @return Generator + */ + private function provideApiTest(): Generator + { + yield [ + '@method static Baz\Bar bar(string $boo, string $baz)', + function (MethodTag $methodNode): void { + self::assertTrue($methodNode->hasChild(ClassNode::class)); + self::assertFalse($methodNode->hasChild(MethodTag::class)); + self::assertCount(7, iterator_to_array($methodNode->children())); + self::assertCount(1, iterator_to_array($methodNode->children(ClassNode::class))); + self::assertTrue($methodNode->hasDescendant(ScalarNode::class)); + self::assertFalse($methodNode->hasDescendant(MethodNode::class)); + self::assertCount(2, iterator_to_array($methodNode->descendantElements(ScalarNode::class))); + self::assertInstanceOf(ScalarNode::class, $methodNode->firstDescendant(ScalarNode::class)); + } + ]; + } + + /** + * @return Generator + */ + private function provideTags() + { + yield [ + '@method static Baz\Bar bar(string $boo, string $baz)', + function (MethodTag $methodNode): void { + self::assertEquals('@method static Baz\Bar bar(string $boo, string $baz)', $methodNode->toString()); + self::assertEquals('string $boo, string $baz', $methodNode->parameters->toString()); + self::assertEquals('static', $methodNode->static->value); + self::assertEquals('Baz\Bar', $methodNode->type->toString()); + self::assertEquals('bar', $methodNode->name->toString()); + self::assertEquals('(', $methodNode->parenOpen->toString()); + self::assertEquals(')', $methodNode->parenClose->toString()); + self::assertTrue($methodNode->hasChild(ClassNode::class)); + self::assertFalse($methodNode->hasChild(MethodTag::class)); + } + ]; + yield [ + '@property Baz\Bar $foobar', + function (PropertyTag $property): void { + self::assertEquals('$foobar', $property->name->toString()); + } + ]; + + yield [ '@deprecated This is deprecated']; + yield 'deprecated' => [ + '/** @deprecated This is deprecated */', + function (Docblock $block) { + self::assertTrue($block->hasTag(DeprecatedTag::class)); + } + ]; + + yield [ '/** This is docblock @deprecated Foo */']; + yield [ '@mixin Foo\Bar']; + yield [ '@param string $foo This is a parameter']; + yield ['@param Baz\Bar $foobar This is a parameter']; + yield ['@var Baz\Bar $foobar']; + yield ['@return Baz\Bar']; + yield ['@return $this']; + } + + /** + * @return Generator + */ + private function provideTypes(): Generator + { + yield 'scalar' => ['string']; + yield 'union' => [ + '@return string|int|bool|float|mixed', + function (ReturnTag $return): void { + $type = $return->type; + assert($type instanceof UnionNode); + self::assertInstanceOf(UnionNode::class, $type); + self::assertEquals('string', $type->types->types()->first()->toString()); + self::assertCount(5, $type->types->types()); + } + ]; + yield 'list' => [ + '@return Foo[]', + function (ReturnTag $return): void { + self::assertInstanceOf(ListNode::class, $return->type); + } + ]; + yield 'generic' => [ + '@return Foo, Baz|Bar>', + function (ReturnTag $return): void { + self::assertInstanceOf(GenericNode::class, $return->type); + } + ]; + } + + private function provideDocblock() + { + yield 'docblock' => [ + <<<'EOT' +/** + * This is a docblock + * With some text - + * and maybe some + * ``` + * Markdown + * ``` + * @param This $should not be included + */ +EOT + , function (Docblock $docblock): void { + self::assertEquals(<<<'EOT' +This is a docblock +With some text - +and maybe some +``` +Markdown +``` +EOT +, $docblock->prose()); + } + ]; + } +} diff --git a/tests/Unit/Ast/NodeTestCase.php b/tests/Unit/Ast/NodeTestCase.php new file mode 100644 index 00000000..85d36fe5 --- /dev/null +++ b/tests/Unit/Ast/NodeTestCase.php @@ -0,0 +1,59 @@ +parse($doc); + $nodes = iterator_to_array($node->selfAndDescendantElements(), false); + self::assertIsIterable($nodes); + self::assertEquals(0, $node->start(), 'Start offset'); + self::assertEquals(strlen($doc), $node->end(), 'End offset'); + + if ($assertion) { + $assertion($node); + } + } + + /** + * @dataProvider provideNode + */ + public function testPartialParse(string $doc): void + { + $node = $this->parse($doc); + $partial = []; + foreach ($node->children() as $child) { + $partial[] = $child->toString(); + $node = $this->parse(implode(' ', $partial)); + self::assertInstanceOf(Element::class, $node); + } + } + + /** + * @dataProvider provideNode + */ + public function testIsomorphism(string $doc): void + { + $one = $this->parse($doc); + $two = $this->parse($one->toString()); + self::assertEquals($one, $two, $one->toString()); + } + + private function parse(string $doc): Node + { + $node = (new Parser())->parse((new Lexer())->lex($doc)); + return $node; + } +} diff --git a/tests/Unit/LexerTest.php b/tests/Unit/LexerTest.php new file mode 100644 index 00000000..86943555 --- /dev/null +++ b/tests/Unit/LexerTest.php @@ -0,0 +1,105 @@ + $expectedTokens + */ + public function testLex(string $lex, array $expectedTokens): void + { + $tokens = (new Lexer())->lex($lex)->toArray(); + + self::assertCount(count($expectedTokens), $tokens, 'Expected number of tokens'); + + foreach ($tokens as $index => $token) { + [$type, $value] = $expectedTokens[$index]; + $expectedToken = new Token($token->byteOffset, $type, $value); + self::assertEquals($expectedToken, $token); + } + } + + /** + * @return Generator + */ + public function provideLex(): Generator + { + yield [ '', [] ]; + yield [ + <<<'EOT' + /** + * Hello this is + * Multi + */ + EOT + + ,[ + [Token::T_PHPDOC_OPEN, '/**'], + [Token::T_WHITESPACE, "\n"], + [Token::T_PHPDOC_LEADING, ' * '], + [Token::T_LABEL, 'Hello'], + [Token::T_WHITESPACE, ' '], + [Token::T_LABEL, 'this'], + [Token::T_WHITESPACE, ' '], + [Token::T_LABEL, 'is'], + [Token::T_WHITESPACE, "\n"], + [Token::T_PHPDOC_LEADING, ' * '], + [Token::T_LABEL, 'Multi'], + [Token::T_WHITESPACE, "\n"], + [Token::T_WHITESPACE, " "], + [Token::T_PHPDOC_CLOSE, '*/'], + ] + ]; + + yield [ + 'Foobar', + [ + [Token::T_LABEL, 'Foobar'], + ] + ]; + yield [ + 'Foobar[]', + [ + [Token::T_LABEL, 'Foobar'], + [Token::T_LIST, '[]'], + ] + ]; + yield [ + 'Foobar', + [ + [Token::T_LABEL, 'Foobar'], + [Token::T_BRACKET_ANGLE_OPEN, '<'], + [Token::T_LABEL, 'Barfoo'], + [Token::T_BRACKET_ANGLE_CLOSE, '>'], + ] + ]; + yield [ + 'Foobar', + [ + [Token::T_LABEL, 'Foobar'], + [Token::T_BRACKET_ANGLE_OPEN, '<'], + [Token::T_LABEL, 'Barfoo'], + [Token::T_BRACKET_ANGLE_CLOSE, '>'], + ] + ]; + yield [ + 'Foobar{Barfoo, Foobar}', + [ + [Token::T_LABEL, 'Foobar'], + [Token::T_BRACKET_CURLY_OPEN, '{'], + [Token::T_LABEL, 'Barfoo'], + [Token::T_COMMA, ','], + [Token::T_WHITESPACE, ' '], + [Token::T_LABEL, 'Foobar'], + [Token::T_BRACKET_CURLY_CLOSE, '}'], + ] + ]; + } +} diff --git a/tests/Unit/ParserTest.php b/tests/Unit/ParserTest.php new file mode 100644 index 00000000..ae68a0e0 --- /dev/null +++ b/tests/Unit/ParserTest.php @@ -0,0 +1,48 @@ +parse((new Lexer())->lex($text)); + self::assertEquals($expected, $node); + } + + /** + * @return Generator + */ + public function provideParse(): Generator + { + yield [ + '/** */', + new Docblock([ + new Token(0, Token::T_PHPDOC_OPEN, '/**'), + new Token(3, Token::T_WHITESPACE, ' '), + new Token(4, Token::T_PHPDOC_CLOSE, '*/'), + ]) + ]; + yield [ + '/** Hello */', + new Docblock([ + new Token(0, Token::T_PHPDOC_OPEN, '/**'), + new Token(3, Token::T_WHITESPACE, ' '), + new Token(4, Token::T_LABEL, 'Hello'), + new Token(9, Token::T_WHITESPACE, ' '), + new Token(10, Token::T_PHPDOC_CLOSE, '*/'), + ]) + ]; + } +}