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
+ *
+ * value |
+ * constant |
+ *
+ *
+ * 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 |
+ *
+ *
+ * function |
+ * string |
+ *
+ * The current function name. See also
+ * __FUNCTION__.
+ * |
+ *
+ *
+ * line |
+ * integer |
+ *
+ * The current line number. See also
+ * __LINE__.
+ * |
+ *
+ *
+ * file |
+ * string |
+ *
+ * The current file name. See also
+ * __FILE__.
+ * |
+ *
+ *
+ * class |
+ * string |
+ *
+ * The current class name. See also
+ * __CLASS__
+ * |
+ *
+ *
+ * object |
+ * object |
+ *
+ * The current object.
+ * |
+ *
+ *
+ * type |
+ * string |
+ *
+ * The current call type. If a method call, "->" is returned. If a static
+ * method call, "::" is returned. If a function call, nothing is returned.
+ * |
+ *
+ *
+ * args |
+ * array |
+ *
+ * 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, '*/'),
+ ])
+ ];
+ }
+}