diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 44cf5b8..2dba373 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -246,8 +246,10 @@ class CompletionProvider // 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 9ea27f9..4b6239d 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -133,4 +133,33 @@ class Definition } } } + + /** + * 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); + } }