From 5835bd314b7f2eae775501d9545681e148b63c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2018 21:35:05 +0100 Subject: [PATCH 1/6] [PR] Intellisense autocomplete also suggests private or protected method and properties Checking the visibility and the context from where the node is: inside a method declaration or after an instantiation --- src/CompletionProvider.php | 6 ++++-- src/Definition.php | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 44cf5b8e..2dba3735 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -246,8 +246,10 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon // Collect all definitions that match any of the prefixes foreach ($this->index->getDefinitions() as $fqn => $def) { foreach ($prefixes as $prefix) { - if (substr($fqn, 0, strlen($prefix)) === $prefix && $def->isMember) { - $list->items[] = CompletionItemFactory::fromDefinition($def); + if (substr($fqn, 0, strlen($prefix)) === $prefix && + $def->isMember && + $def->isVisible($prefix, $prefixes[0], $node)) { + $list->items[] = CompletionItem::fromDefinition($def); } } } diff --git a/src/Definition.php b/src/Definition.php index 9ea27f9c..4b6239db 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -133,4 +133,33 @@ public function getAncestorDefinitions(ReadableIndex $index, bool $includeSelf = } } } + + /** + * Checks the definition's visibility. + * @return bool + */ + public function isVisible(string $match, string $caller, \Microsoft\PhpParser\Node $node): bool + { + $ancestor = $node->getFirstAncestor(\Microsoft\PhpParser\Node\MethodDeclaration::class); + + if ($ancestor) { + if ($match !== $caller && $this->isPrivate()) { + return false; + } + } else if ($this->isProtected() || $this->isPrivate()) { + return false; + } + + return true; + } + + private function isPrivate(): bool + { + return 'private' === substr($this->declarationLine, 0, 7); + } + + private function isProtected(): bool + { + return 'protected' === substr($this->declarationLine, 0, 9); + } } From a54fcf9d14f1584e553c49e3742ce56e8cea0d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Sat, 10 Nov 2018 13:14:51 +0100 Subject: [PATCH 2/6] Adding netbeans config to gitignore --- .gitignore | 1 + src/CompletionProvider.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6476dbe1..a7c04f14 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ composer.lock stubs *.ast node_modules/ +/nbproject/ \ No newline at end of file diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2dba3735..fa6d54f3 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -236,7 +236,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon $fqns = FqnUtilities\getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) ); - + $start = microtime(true); // Add the object access operator to only get members of all parents $prefixes = []; foreach ($this->expandParentFqns($fqns) as $prefix) { @@ -253,7 +253,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon } } } - + echo microtime(true) - $start; } elseif ( ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression || ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression From d1bdcbd173ac2dd83b9429a4cd5ef82f7b0d255a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Sat, 10 Nov 2018 13:40:55 +0100 Subject: [PATCH 3/6] Resolving node ancestor in the CompletionProvider, so it's resolved outside the loop --- src/CompletionProvider.php | 5 +++-- src/Definition.php | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index fa6d54f3..4a87f1d6 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -237,6 +237,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) ); $start = microtime(true); + $isInMethodDeclaration = null !== $node->getFirstAncestor(\Microsoft\PhpParser\Node\MethodDeclaration::class); // Add the object access operator to only get members of all parents $prefixes = []; foreach ($this->expandParentFqns($fqns) as $prefix) { @@ -248,8 +249,8 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon foreach ($prefixes as $prefix) { if (substr($fqn, 0, strlen($prefix)) === $prefix && $def->isMember && - $def->isVisible($prefix, $prefixes[0], $node)) { - $list->items[] = CompletionItem::fromDefinition($def); + $def->isVisible($prefix, $prefixes[0], $isInMethodDeclaration)) { + $list->items[] = CompletionItemFactory::fromDefinition($def); } } } diff --git a/src/Definition.php b/src/Definition.php index 4b6239db..39636bb4 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -136,13 +136,15 @@ public function getAncestorDefinitions(ReadableIndex $index, bool $includeSelf = /** * Checks the definition's visibility. + * @param string $match Owner of the FQNS + * @param string $caller Descendant of the FQNS owner + * @param bool $isInMethodDeclaration checking if the call is from inside a + * method * @return bool */ - public function isVisible(string $match, string $caller, \Microsoft\PhpParser\Node $node): bool - { - $ancestor = $node->getFirstAncestor(\Microsoft\PhpParser\Node\MethodDeclaration::class); - - if ($ancestor) { + public function isVisible(string $match, string $caller, bool $isInMethodDeclaration): bool + { + if ($isInMethodDeclaration) { if ($match !== $caller && $this->isPrivate()) { return false; } From b808e3c365a5226cf6b7cd32a2512d9431f0ba01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Sat, 10 Nov 2018 13:46:40 +0100 Subject: [PATCH 4/6] Update .gitignore Ignoting Netbeans conf --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6476dbe1..a7c04f14 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ composer.lock stubs *.ast node_modules/ +/nbproject/ \ No newline at end of file From 88bb2eaf177edf9dfab245cf1c663a22fd494019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Sat, 10 Nov 2018 13:52:16 +0100 Subject: [PATCH 5/6] Minor changes --- src/CompletionProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 4a87f1d6..2461031b 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -236,7 +236,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon $fqns = FqnUtilities\getFqnsFromType( $this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression) ); - $start = microtime(true); + $isInMethodDeclaration = null !== $node->getFirstAncestor(\Microsoft\PhpParser\Node\MethodDeclaration::class); // Add the object access operator to only get members of all parents $prefixes = []; @@ -254,7 +254,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon } } } - echo microtime(true) - $start; + } elseif ( ($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression || ($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression From df898ec633eb4a2a4fd95ac49c13699993d5e846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20No=C3=A9=20Gonz=C3=A1lez?= Date: Sat, 10 Nov 2018 14:22:55 +0100 Subject: [PATCH 6/6] Merging with master --- src/CompletionProvider.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2461031b..ff640f0b 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -272,7 +272,7 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon $fqns = FqnUtilities\getFqnsFromType( $classType = $this->definitionResolver->resolveExpressionNodeToType($scoped->scopeResolutionQualifier) ); - + $isInMethodDeclaration = null !== $node->getFirstAncestor(\Microsoft\PhpParser\Node\MethodDeclaration::class); // Append :: operator to only get static members of all parents $prefixes = []; foreach ($this->expandParentFqns($fqns) as $prefix) { @@ -282,7 +282,9 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon // Collect all definitions that match any of the prefixes foreach ($this->index->getDefinitions() as $fqn => $def) { foreach ($prefixes as $prefix) { - if (substr(strtolower($fqn), 0, strlen($prefix)) === strtolower($prefix) && $def->isMember) { + if (substr(strtolower($fqn), 0, strlen($prefix)) === strtolower($prefix) && + $def->isMember && + $def->isVisible($prefix, $prefixes[0], $isInMethodDeclaration)) { $list->items[] = CompletionItemFactory::fromDefinition($def); } }