diff --git a/.dockerignore b/.dockerignore index a839c69..29f27b6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,3 +7,4 @@ fixtures/ coverage/ coverage.xml images/ +node_modules/ diff --git a/.editorconfig b/.editorconfig index d162066..2954e68 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ trim_trailing_whitespace = true indent_style = space indent_size = 4 -[*.json,*.yml] +[*.{json,yml}] indent_size = 2 [composer.json] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..688e780 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +* text=auto + +/.vscode export-ignore +/fixtures export-ignore +/images export-ignore +/tests export-ignore +/validation export-ignore +/.dockerignore export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.gitmodules export-ignore +/.npmrc export-ignore +/.travis.yml export-ignore +/codecov.yml export-ignore +/dependencies.yml export-ignore +/Dockerfile export-ignore +/package.json export-ignore +/Performance.php export-ignore +/php.ini export-ignore +/phpcs.xml.dist export-ignore +/phpunit.xml.dist export-ignore +/release-docker.php export-ignore diff --git a/.gitignore b/.gitignore index f6b089b..6476dbe 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ vendor/ .phpls/ composer.lock stubs -*.ast \ No newline at end of file +*.ast +node_modules/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.travis.yml b/.travis.yml index 7fb9c9a..1301d4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,60 @@ + language: php php: - - '7.0' + - '7.0' + - '7.2.0RC5' -services: - - docker +git: + depth: 10 + submodules: false cache: directories: - - $HOME/.composer/cache + - $HOME/Library/Caches/Homebrew + - $HOME/.composer/cache + - $HOME/.npm install: - - composer install - - composer run-script parse-stubs - + - composer install --prefer-dist --no-interaction script: - - vendor/bin/phpcs -n - - vendor/bin/phpunit --coverage-clover=coverage.xml + - vendor/bin/phpcs -n + - vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always + - bash <(curl -s https://codecov.io/bash) -after_success: - - bash <(curl -s https://codecov.io/bash) - - | - if [[ $TRAVIS_TAG == v* ]]; then - docker build -t felixfbecker/php-language-server:${TRAVIS_TAG:1} . - docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" - docker push felixfbecker/php-language-server:${TRAVIS_TAG:1} - fi +jobs: + include: + - stage: test + os: osx + osx_image: xcode9.1 + language: generic + before_install: + # Fix ruby error https://github.com/Homebrew/brew/issues/3299 + - brew update + - brew tap homebrew/homebrew-php + - brew install php71 + - brew install homebrew/php/php71-xdebug + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - ln -s "`pwd`/composer.phar" /usr/local/bin/composer + - stage: release + php: '7.0' + services: + - docker + install: + - composer install --prefer-dist --no-interaction + - nvm install 8 + - nvm use 8 + - npm install + script: + - docker build -t felixfbecker/php-language-server . + - npm run semantic-release + +stages: + - test + - name: release + if: branch = master AND type = push AND fork = false + +branches: + except: + - /^v\d+\.\d+\.\d+$/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 0f77709..1e4b234 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,29 +1,27 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Listen for XDebug", - "type": "php", - "request": "launch", - "port": 9000 - }, - { - "name": "Launch currently open script", - "type": "php", - "request": "launch", - "program": "${file}", - "cwd": "${fileDirname}", - "port": 9000 - }, - { - "name": "PHPUnit", - "type": "php", - "request": "launch", - "program": "${workspaceRoot}/vendor/phpunit/phpunit/phpunit", - "cwd": "${workspaceRoot}", - "args": [ - // "--filter", "CompletionTest" - ] - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "PHPUnit", + "type": "php", + "request": "launch", + "program": "${workspaceRoot}/vendor/phpunit/phpunit/phpunit", + // "args": ["--filter", "testDefinitionForSelfKeyword"], + "cwd": "${workspaceRoot}" + }, + { + "name": "Listen for XDebug", + "type": "php", + "request": "launch", + "port": 9000 + }, + { + "name": "Launch currently open script", + "type": "php", + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "port": 9000 + } + ] } diff --git a/Dockerfile b/Dockerfile index f4291db..549a28f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,11 +7,6 @@ FROM php:7-cli MAINTAINER Felix Becker -RUN apt-get update \ - # Needed for CodeSniffer - && apt-get install -y libxml2 libxml2-dev \ - && rm -rf /var/lib/apt/lists/* - RUN docker-php-ext-configure pcntl --enable-pcntl RUN docker-php-ext-install pcntl COPY ./php.ini /usr/local/etc/php/conf.d/ diff --git a/README.md b/README.md index ef351ec..b25680e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # PHP Language Server [![Version](https://img.shields.io/packagist/v/felixfbecker/language-server.svg)](https://packagist.org/packages/felixfbecker/language-server) -[![Build Status](https://travis-ci.org/felixfbecker/php-language-server.svg?branch=master)](https://travis-ci.org/felixfbecker/php-language-server) +[![Linux Build Status](https://travis-ci.org/felixfbecker/php-language-server.svg?branch=master)](https://travis-ci.org/felixfbecker/php-language-server) +[![Windows Build status](https://ci.appveyor.com/api/projects/status/2sp5ll052wdjqmdm/branch/master?svg=true)](https://ci.appveyor.com/project/felixfbecker/php-language-server/branch/master) [![Coverage](https://codecov.io/gh/felixfbecker/php-language-server/branch/master/graph/badge.svg)](https://codecov.io/gh/felixfbecker/php-language-server) [![Dependency Status](https://gemnasium.com/badges/github.com/felixfbecker/php-language-server.svg)](https://gemnasium.com/github.com/felixfbecker/php-language-server) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.0-8892BF.svg)](https://php.net/) [![License](https://img.shields.io/packagist/l/felixfbecker/language-server.svg)](https://github.com/felixfbecker/php-language-server/blob/master/LICENSE.txt) [![Gitter](https://badges.gitter.im/felixfbecker/php-language-server.svg)](https://gitter.im/felixfbecker/php-language-server?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) @@ -40,9 +42,6 @@ For Parameters, it will return the `@param` tag. The query is matched case-insensitively against the fully qualified name of the symbol. Non-Standard: An empty query will return _all_ symbols found in the workspace. -### [Document Formatting](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#document-formatting-request) -![Document Formatting demo](images/formatDocument.gif) - ### Error reporting through [Publish Diagnostics](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#publishdiagnostics-notification) ![Error reporting demo](images/publishDiagnostics.png) @@ -190,14 +189,21 @@ Clone the repository and run composer install to install dependencies. -Then parse the stubs with - - composer run-script parse-stubs Run the tests with - vendor/bin/phpunit + composer test Lint with - vendor/bin/phpcs + composer lint + +The project parses PHPStorm's PHP stubs to get support for PHP builtins. It re-parses them as needed after Composer processes, but after some code changes (such as ones involving the index or parsing) you may have to explicitly re-parse them: + + composer run-script parse-stubs + +To debug with xDebug ensure that you have this set as an environment variable + + COMPOSER_ALLOW_XDEBUG=1 + +This tells the Language Server to not restart without XDebug if it detects that XDebug is enabled (XDebug has a high performance impact). diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..7d0525c --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,54 @@ +version: '{build}' + +image: Visual Studio 2017 +platform: + - x64 + +skip_tags: true +skip_branch_with_pr: true +clone_depth: 1 +max_jobs: 3 + +cache: + - '%LOCALAPPDATA%\Composer' + - '%LOCALAPPDATA%\Temp\Chocolatey' + +environment: + ANSICON: 121x90 (121x90) + matrix: + - { PHP_VERSION: '7.1.11', VC_VERSION: '14', XDEBUG_VERSION: '2.5.5' } + +install: + # Enable Windows Update service, needed to install vcredist2015 (dependency of php) + - ps: Set-Service wuauserv -StartupType Manual + - choco config set cacheLocation %LOCALAPPDATA%\Temp\Chocolatey + - choco install -y php --version %PHP_VERSION% + - choco install -y composer + - refreshenv + - composer install --no-interaction --no-progress --prefer-dist + # Install XDebug for code coverage + - ps: | + $client = New-Object System.Net.WebClient + $phpMinorVersion = $env:PHP_VERSION -replace '\.\d+$' + $xdebugUrl = "https://xdebug.org/files/php_xdebug-$env:XDEBUG_VERSION-$phpMinorVersion-vc14-nts-x86_64.dll" + $phpDir = (Get-Item (Get-Command php).Source).Directory.FullName + $xdebugPath = Join-Path $phpDir ext\xdebug.dll + $client.DownloadFile($xdebugUrl, $xdebugPath) + $phpIniPath = Join-Path $phpDir php.ini + Add-Content $phpIniPath @" + zend_extension=$xdebugPath + "@ + +build: off + +test_script: + - vendor\bin\phpunit --coverage-clover=coverage/coverage.xml + +after_test: + - ps: | + # Delete vendor because it causes problems with codecovs report search + # https://github.com/codecov/codecov-bash/issues/96 + Remove-Item -Recurse -Force vendor + $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH + Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh + bash codecov.sh -f 'coverage/coverage.xml' diff --git a/composer.json b/composer.json index 50f314b..a21535b 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,7 @@ { "name": "felixfbecker/language-server", "description": "PHP Implementation of the Visual Studio Code Language Server Protocol", - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], "license": "ISC", - "type": "library", "keywords": [ "php", "language", @@ -21,27 +14,29 @@ "autocompletion", "refactor" ], - "bin": ["bin/php-language-server.php"], - "scripts": { - "parse-stubs": "LanguageServer\\ComposerScripts::parseStubs", - "post-install-cmd": "@parse-stubs" - }, + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], "require": { - "php": ">=7.0", - "phpdocumentor/reflection-docblock": "~3.1.1", - "sabre/event": "^5.0", - "felixfbecker/advanced-json-rpc": "^2.0", - "squizlabs/php_codesniffer" : "3.0.0RC3", - "netresearch/jsonmapper": "^1.0", - "webmozart/path-util": "^2.3", - "webmozart/glob": "^4.1", - "sabre/uri": "^2.0", - "jetbrains/phpstorm-stubs": "dev-master", + "php": "^7.0", "composer/composer": "^1.3", - "Microsoft/tolerant-php-parser": "^0.0.4" + "felixfbecker/advanced-json-rpc": "^3.0.0", + "jetbrains/phpstorm-stubs": "dev-master", + "microsoft/tolerant-php-parser": "0.0.*", + "netresearch/jsonmapper": "^1.0", + "phpdocumentor/reflection-docblock": "^4.0.0", + "sabre/event": "^5.0", + "sabre/uri": "^2.0", + "webmozart/glob": "^4.1", + "webmozart/path-util": "^2.3" + }, + "require-dev": { + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.1" }, - "minimum-stability": "dev", - "prefer-stable": true, "autoload": { "psr-4": { "LanguageServer\\": "src/" @@ -57,8 +52,19 @@ "LanguageServer\\Tests\\": "tests/" } }, - "require-dev": { - "phpunit/phpunit": "^5.5", - "phpunit/php-code-coverage": "^4.0" - } + "bin": [ + "bin/php-language-server.php" + ], + "scripts": { + "parse-stubs": "LanguageServer\\ComposerScripts::parseStubs", + "post-install-cmd": "@parse-stubs", + "post-update-cmd": "@parse-stubs", + "test": "vendor/bin/phpunit", + "lint": "vendor/bin/phpcs" + }, + "config": { + "sort-packages": true + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/dependencies.yml b/dependencies.yml new file mode 100644 index 0000000..bf6bd77 --- /dev/null +++ b/dependencies.yml @@ -0,0 +1,20 @@ +collectors: + +# pull requests for new major versions +- type: php-composer + path: / + actors: + - type: php-composer + versions: "Y.0.0" + settings: + commit_message_prefix: "chore: " +- type: js-npm + path: / + settings: + dist_tags: + semantic-release: next + actors: + - type: js-npm + versions: "Y.0.0" + settings: + commit_message_prefix: "chore: " diff --git a/fixtures/completion/html_no_completion.php b/fixtures/completion/html_no_completion.php new file mode 100644 index 0000000..9318418 --- /dev/null +++ b/fixtures/completion/html_no_completion.php @@ -0,0 +1 @@ +< diff --git a/fixtures/diagnostics/baselines/this_in_method.php b/fixtures/diagnostics/baselines/this_in_method.php new file mode 100644 index 0000000..0463b79 --- /dev/null +++ b/fixtures/diagnostics/baselines/this_in_method.php @@ -0,0 +1,9 @@ + - + - ./tests + ./tests - - - ./src + + ./src diff --git a/src/ClientHandler.php b/src/ClientHandler.php index 7b5a702..9fe921b 100644 --- a/src/ClientHandler.php +++ b/src/ClientHandler.php @@ -71,7 +71,6 @@ class ClientHandler */ public function notify(string $method, $params): Promise { - $id = $this->idGenerator->generate(); return $this->protocolWriter->write( new Protocol\Message( new AdvancedJsonRpc\Notification($method, (object)$params) diff --git a/src/CompletionProvider.php b/src/CompletionProvider.php index 2414ead..d774423 100644 --- a/src/CompletionProvider.php +++ b/src/CompletionProvider.php @@ -10,7 +10,9 @@ use LanguageServer\Protocol\{ Position, CompletionList, CompletionItem, - CompletionItemKind + CompletionItemKind, + CompletionContext, + CompletionTriggerKind }; use Microsoft\PhpParser; use Microsoft\PhpParser\Node; @@ -122,9 +124,10 @@ class CompletionProvider * * @param PhpDocument $doc The opened document * @param Position $pos The cursor position + * @param CompletionContext $context The completion context * @return CompletionList */ - public function provideCompletion(PhpDocument $doc, Position $pos): CompletionList + public function provideCompletion(PhpDocument $doc, Position $pos, CompletionContext $context = null): CompletionList { // This can be made much more performant if the tree follows specific invariants. $node = $doc->getNodeAtPosition($pos); @@ -152,7 +155,21 @@ class CompletionProvider // Inspect the type of expression under the cursor - if ($node === null || $node instanceof Node\Statement\InlineHtml || $pos == new Position(0, 0)) { + $content = $doc->getContent(); + $offset = $pos->toOffset($content); + if ( + $node === null + || ( + $node instanceof Node\Statement\InlineHtml + && ( + $context === null + // Make sure to not suggest on the > trigger character in HTML + || $context->triggerKind === CompletionTriggerKind::INVOKED + || $context->triggerCharacter === '<' + ) + ) + || $pos == new Position(0, 0) + ) { // HTML, beginning of file // Inside HTML and at the beginning of the file, propose index->getDefinitions() as $fqn => $def) { foreach ($prefixes as $prefix) { - if (substr($fqn, 0, strlen($prefix)) === $prefix && !$def->isGlobal) { + if (substr($fqn, 0, strlen($prefix)) === $prefix && $def->isMember) { $list->items[] = CompletionItem::fromDefinition($def); } } @@ -243,7 +260,7 @@ class CompletionProvider // 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->isGlobal) { + if (substr(strtolower($fqn), 0, strlen($prefix)) === strtolower($prefix) && $def->isMember) { $list->items[] = CompletionItem::fromDefinition($def); } } @@ -316,7 +333,7 @@ class CompletionProvider if ( // Exclude methods, properties etc. - $def->isGlobal + !$def->isMember && ( !$prefix || ( @@ -415,7 +432,7 @@ class CompletionProvider // Walk the AST upwards until a scope boundary is met $level = $node; - while ($level && !ParserHelpers\isFunctionLike($level)) { + while ($level && !($level instanceof PhpParser\FunctionLike)) { // Walk siblings before the node $sibling = $level; while ($sibling = $sibling->getPreviousSibling()) { @@ -429,7 +446,7 @@ class CompletionProvider // If the traversal ended because a function was met, // also add its parameters and closure uses to the result list - if ($level && ParserHelpers\isFunctionLike($level) && $level->parameters !== null) { + if ($level && $level instanceof PhpParser\FunctionLike && $level->parameters !== null) { foreach ($level->parameters->getValues() as $param) { $paramName = $param->getName(); if (empty($namePrefix) || strpos($paramName, $namePrefix) !== false) { diff --git a/src/ComposerScripts.php b/src/ComposerScripts.php index 487c39d..2a584d2 100644 --- a/src/ComposerScripts.php +++ b/src/ComposerScripts.php @@ -56,7 +56,8 @@ class ComposerScripts $parts['scheme'] = 'phpstubs'; $uri = Uri\build($parts); - $document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); + // Create a new document and add it to $index + new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); } $index->setComplete(); diff --git a/src/Definition.php b/src/Definition.php index c03e852..c27f871 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -39,12 +39,13 @@ class Definition public $extends; /** - * Only true for classes, interfaces, traits, functions and non-class constants + * False for classes, interfaces, traits, functions and non-class constants + * True for methods, properties and class constants * This is so methods and properties are not suggested in the global scope * * @var bool */ - public $isGlobal; + public $isMember; /** * True if this definition is affected by global namespace fallback (global function or global constant) @@ -78,7 +79,7 @@ class Definition * For functions and methods, this is the return type. * For any other declaration it will be null. * Can also be a compound type. - * If it is unknown, will be Types\Mixed. + * If it is unknown, will be Types\Mixed_. * * @var \phpDocumentor\Type|null */ diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 51c5955..c9d1400 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -181,10 +181,8 @@ class DefinitionResolver ); // Interfaces, classes, traits, namespaces, functions, and global const elements - $def->isGlobal = ( - $node instanceof Node\Statement\InterfaceDeclaration || - $node instanceof Node\Statement\ClassDeclaration || - $node instanceof Node\Statement\TraitDeclaration || + $def->isMember = !( + $node instanceof PhpParser\ClassLike || ($node instanceof Node\Statement\NamespaceDefinition && $node->name !== null) || @@ -266,13 +264,38 @@ class DefinitionResolver // Other references are references to a global symbol that have an FQN // Find out the FQN $fqn = $this->resolveReferenceNodeToFqn($node); - if ($fqn === null) { + if (!$fqn) { return null; } + + if ($fqn === 'self' || $fqn === 'static') { + // Resolve self and static keywords to the containing class + // (This is not 100% correct for static but better than nothing) + $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class); + if (!$classNode) { + return; + } + $fqn = (string)$classNode->getNamespacedName(); + if (!$fqn) { + return; + } + } else if ($fqn === 'parent') { + // Resolve parent keyword to the base class FQN + $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class); + if (!$classNode || !$classNode->classBaseClause || !$classNode->classBaseClause->baseClass) { + return; + } + $fqn = (string)$classNode->classBaseClause->baseClass->getResolvedName(); + if (!$fqn) { + return; + } + } + // If the node is a function or constant, it could be namespaced, but PHP falls back to global // http://php.net/manual/en/language.namespaces.fallback.php // TODO - verify that this is not a method $globalFallback = ParserHelpers\isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression; + // Return the Definition object from the index index return $this->index->getDefinition($fqn, $globalFallback); } @@ -280,6 +303,7 @@ class DefinitionResolver /** * Given any node, returns the FQN of the symbol that is referenced * Returns null if the FQN could not be resolved or the reference node references a variable + * May also return "static", "self" or "parent" * * @param Node $node * @return string|null @@ -511,7 +535,7 @@ class DefinitionResolver // Traverse the AST up do { // If a function is met, check the parameters and use statements - if (ParserHelpers\isFunctionLike($n)) { + if ($n instanceof PhpParser\FunctionLike) { if ($n->parameters !== null) { foreach ($n->parameters->getElements() as $param) { if ($param->getName() === $name) { @@ -551,7 +575,7 @@ class DefinitionResolver /** * Given an expression node, resolves that expression recursively to a type. - * If the type could not be resolved, returns Types\Mixed. + * If the type could not be resolved, returns Types\Mixed_. * * @param Node\Expression $expr * @return \phpDocumentor\Reflection\Type|null @@ -567,7 +591,7 @@ class DefinitionResolver if ($expr == null || $expr instanceof PhpParser\MissingToken || $expr instanceof PhpParser\SkippedToken) { // TODO some members are null or Missing/SkippedToken // How do we handle this more generally? - return new Types\Mixed; + return new Types\Mixed_; } // VARIABLE @@ -597,7 +621,7 @@ class DefinitionResolver // Find the function definition if ($expr->callableExpression instanceof Node\Expression) { // Cannot get type for dynamic function call - return new Types\Mixed; + return new Types\Mixed_; } if ($expr->callableExpression instanceof Node\QualifiedName) { @@ -646,7 +670,7 @@ class DefinitionResolver // MEMBER ACCESS EXPRESSION if ($expr instanceof Node\Expression\MemberAccessExpression) { if ($expr->memberName instanceof Node\Expression) { - return new Types\Mixed; + return new Types\Mixed_; } $var = $expr->dereferencableExpression; @@ -659,10 +683,10 @@ class DefinitionResolver if ($t instanceof Types\This) { $classFqn = self::getContainingClassFqn($expr); if ($classFqn === null) { - return new Types\Mixed; + return new Types\Mixed_; } } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) { - return new Types\Mixed; + return new Types\Mixed_; } else { $classFqn = substr((string)$t->getFqsen(), 1); } @@ -689,7 +713,7 @@ class DefinitionResolver if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) { $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier); if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) { - return new Types\Mixed; + return new Types\Mixed_; } $fqn = substr((string)$classType->getFqsen(), 1) . '::'; @@ -701,7 +725,7 @@ class DefinitionResolver $def = $this->index->getDefinition($fqn); if ($def === null) { - return new Types\Mixed; + return new Types\Mixed_; } return $def->type; } @@ -888,7 +912,7 @@ class DefinitionResolver if ($expr instanceof Node\Expression\SubscriptExpression) { $varType = $this->resolveExpressionNodeToType($expr->postfixExpression); if (!($varType instanceof Types\Array_)) { - return new Types\Mixed; + return new Types\Mixed_; } return $varType->getValueType(); } @@ -897,14 +921,14 @@ class DefinitionResolver // include, require, include_once, require_once if ($expr instanceof Node\Expression\ScriptInclusionExpression) { // TODO: resolve path to PhpDocument and find return statement - return new Types\Mixed; + return new Types\Mixed_; } if ($expr instanceof Node\QualifiedName) { return $this->resolveClassNameToType($expr); } - return new Types\Mixed; + return new Types\Mixed_; } @@ -918,7 +942,7 @@ class DefinitionResolver public function resolveClassNameToType($class): Type { if ($class instanceof Node\Expression) { - return new Types\Mixed; + return new Types\Mixed_; } if ($class instanceof PhpParser\Token && $class->kind === PhpParser\TokenKind::ClassKeyword) { // Anonymous class @@ -958,7 +982,7 @@ class DefinitionResolver * For classes and interfaces, this is the class type (object). * For variables / assignments, this is the documented type or type the assignment resolves to. * Can also be a compound type. - * If it is unknown, will be Types\Mixed. + * If it is unknown, will be Types\Mixed_. * Returns null if the node does not have a type. * * @param Node $node @@ -1012,7 +1036,7 @@ class DefinitionResolver } $type = $defaultType; } - return $type ?? new Types\Mixed; + return $type ?? new Types\Mixed_; } // FUNCTIONS AND METHODS @@ -1020,7 +1044,7 @@ class DefinitionResolver // 1. doc block // 2. return type hint // 3. TODO: infer from return statements - if (ParserHelpers\isFunctionLike($node)) { + if ($node instanceof PhpParser\FunctionLike) { // Functions/methods $docBlock = $this->getDocBlock($node); if ( @@ -1040,7 +1064,7 @@ class DefinitionResolver return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); } // Unknown return type - return new Types\Mixed; + return new Types\Mixed_; } // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS @@ -1077,7 +1101,7 @@ class DefinitionResolver // TODO: read @property tags of class // TODO: Try to infer the type from default value / constant value // Unknown - return new Types\Mixed; + return new Types\Mixed_; } // The node does not have a type @@ -1101,9 +1125,7 @@ class DefinitionResolver // interface C { } A\B\C // trait C { } A\B\C if ( - $node instanceof Node\Statement\ClassDeclaration || - $node instanceof Node\Statement\InterfaceDeclaration || - $node instanceof Node\Statement\TraitDeclaration + $node instanceof PhpParser\ClassLike ) { return (string) $node->getNamespacedName(); } @@ -1134,9 +1156,7 @@ class DefinitionResolver // Class method: use ClassName->methodName() as name $class = $node->getFirstAncestor( Node\Expression\ObjectCreationExpression::class, - Node\Statement\ClassDeclaration::class, - Node\Statement\InterfaceDeclaration::class, - Node\Statement\TraitDeclaration::class + PhpParser\ClassLike::class ); if (!isset($class->name)) { // Ignore anonymous classes @@ -1160,9 +1180,7 @@ class DefinitionResolver ($classDeclaration = $node->getFirstAncestor( Node\Expression\ObjectCreationExpression::class, - Node\Statement\ClassDeclaration::class, - Node\Statement\InterfaceDeclaration::class, - Node\Statement\TraitDeclaration::class + PhpParser\ClassLike::class ) ) !== null && isset($classDeclaration->name)) { $name = $node->getName(); @@ -1190,9 +1208,7 @@ class DefinitionResolver // Class constant: use ClassName::CONSTANT_NAME as name $classDeclaration = $constDeclaration->getFirstAncestor( Node\Expression\ObjectCreationExpression::class, - Node\Statement\ClassDeclaration::class, - Node\Statement\InterfaceDeclaration::class, - Node\Statement\TraitDeclaration::class + PhpParser\ClassLike::class ); if (!isset($classDeclaration->name)) { diff --git a/src/Formatter.php b/src/Formatter.php deleted file mode 100644 index 2787cb7..0000000 --- a/src/Formatter.php +++ /dev/null @@ -1,107 +0,0 @@ -standards = self::findConfiguration($path); - - // Autoload class to set up a bunch of PHP_CodeSniffer-specific token type constants - spl_autoload_call(Tokens::class); - - $file = new DummyFile($content, new Ruleset($config), $config); - $file->process(); - $fixed = $file->fixer->fixFile(); - if (!$fixed && $file->getErrorCount() > 0) { - throw new Exception('Unable to format file'); - } - - $new = $file->fixer->getContents(); - if ($content === $new) { - return []; - } - return [new TextEdit(new Range(new Position(0, 0), self::calculateEndPosition($content)), $new)]; - } - - /** - * Calculate position of last character. - * - * @param string $content document as string - * - * @return \LanguageServer\Protocol\Position - */ - private static function calculateEndPosition(string $content): Position - { - $lines = explode("\n", $content); - return new Position(count($lines) - 1, strlen(end($lines))); - } - - /** - * Search for PHP_CodeSniffer configuration file at given directory or its parents. - * If no configuration found then PSR2 standard is loaded by default. - * - * @param string $path path to file or directory - * @return string[] - */ - private static function findConfiguration(string $path) - { - if (is_dir($path)) { - $currentDir = $path; - } else { - $currentDir = dirname($path); - } - do { - $default = $currentDir . DIRECTORY_SEPARATOR . 'phpcs.xml'; - if (is_file($default)) { - return [$default]; - } - - $default = $currentDir . DIRECTORY_SEPARATOR . 'phpcs.xml.dist'; - if (is_file($default)) { - return [$default]; - } - - $lastDir = $currentDir; - $currentDir = dirname($currentDir); - } while ($currentDir !== '.' && $currentDir !== $lastDir); - - $standard = Config::getConfigData('default_standard') ?? 'PSR2'; - return explode(',', $standard); - } -} diff --git a/src/FqnUtilities.php b/src/FqnUtilities.php index a3aab05..b5d01a9 100644 --- a/src/FqnUtilities.php +++ b/src/FqnUtilities.php @@ -22,7 +22,7 @@ function getFqnsFromType($type): array } if ($type instanceof Types\Compound) { for ($i = 0; $t = $type->get($i); $i++) { - foreach (getFqnsFromType($type) as $fqn) { + foreach (getFqnsFromType($t) as $fqn) { $fqns[] = $fqn; } } diff --git a/src/Indexer.php b/src/Indexer.php index 9f8749d..2618d43 100644 --- a/src/Indexer.php +++ b/src/Indexer.php @@ -16,9 +16,9 @@ use function Sabre\Event\coroutine; class Indexer { /** - * @var The prefix for every cache item + * @var int The prefix for every cache item */ - const CACHE_VERSION = 1; + const CACHE_VERSION = 2; /** * @var FilesFinder diff --git a/src/LanguageServer.php b/src/LanguageServer.php index 4e783ad..46281f5 100644 --- a/src/LanguageServer.php +++ b/src/LanguageServer.php @@ -266,8 +266,6 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher $serverCapabilities->documentSymbolProvider = true; // Support "Find all symbols in workspace" $serverCapabilities->workspaceSymbolProvider = true; - // Support "Format Code" - $serverCapabilities->documentFormattingProvider = true; // Support "Go to definition" $serverCapabilities->definitionProvider = true; // Support "Find all references" diff --git a/src/ParserHelpers.php b/src/ParserHelpers.php index 0ea210a..f20fb1f 100644 --- a/src/ParserHelpers.php +++ b/src/ParserHelpers.php @@ -25,7 +25,7 @@ function isConstantFetch(Node $node) : bool $parent instanceof Node\Expression\CallExpression || $parent instanceof Node\Expression\ObjectCreationExpression || $parent instanceof Node\Expression\ScopedPropertyAccessExpression || - isFunctionLike($parent) || + $parent instanceof PhpParser\FunctionLike || ( $parent instanceof Node\Expression\BinaryExpression && $parent->operator->kind === PhpParser\TokenKind::InstanceOfKeyword @@ -38,14 +38,6 @@ function getFunctionLikeDeclarationFromParameter(Node\Parameter $node) return $node->parent->parent; } -function isFunctionLike(Node $node) -{ - return - $node instanceof Node\Statement\FunctionDeclaration || - $node instanceof Node\MethodDeclaration || - $node instanceof Node\Expression\AnonymousFunctionCreationExpression; -} - function isBooleanExpression($expression) : bool { if (!($expression instanceof Node\Expression\BinaryExpression)) { diff --git a/src/PhpDocument.php b/src/PhpDocument.php index ff3cf8b..0ac8421 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -166,19 +166,6 @@ class PhpDocument $this->sourceFileNode = $treeAnalyzer->getSourceFileNode(); } - /** - * Returns array of TextEdit changes to format this document. - * - * @return \LanguageServer\Protocol\TextEdit[] - */ - public function getFormattedText() - { - if (empty($this->getContent())) { - return []; - } - return Formatter::format($this->getContent(), $this->uri); - } - /** * Returns this document's text content. * diff --git a/src/Protocol/CompletionContext.php b/src/Protocol/CompletionContext.php new file mode 100644 index 0000000..ff18bd1 --- /dev/null +++ b/src/Protocol/CompletionContext.php @@ -0,0 +1,30 @@ +triggerKind = $triggerKind; + $this->triggerCharacter = $triggerCharacter; + } +} diff --git a/src/Protocol/CompletionTriggerKind.php b/src/Protocol/CompletionTriggerKind.php new file mode 100644 index 0000000..d36129d --- /dev/null +++ b/src/Protocol/CompletionTriggerKind.php @@ -0,0 +1,16 @@ +documentLoader->close($textDocument->uri); } - /** - * The document formatting request is sent from the server to the client to format a whole document. - * - * @param TextDocumentIdentifier $textDocument The document to format - * @param FormattingOptions $options The format options - * @return Promise - */ - public function formatting(TextDocumentIdentifier $textDocument, FormattingOptions $options) - { - return $this->documentLoader->getOrLoad($textDocument->uri)->then(function (PhpDocument $document) { - return $document->getFormattedText(); - }); - } - /** * The references request is sent from the client to the server to resolve project-wide references for the symbol * denoted by the given text document position. @@ -372,13 +359,14 @@ class TextDocument * * @param TextDocumentIdentifier The text document * @param Position $position The position + * @param CompletionContext|null $context The completion context * @return Promise */ - public function completion(TextDocumentIdentifier $textDocument, Position $position): Promise + public function completion(TextDocumentIdentifier $textDocument, Position $position, CompletionContext $context = null): Promise { - return coroutine(function () use ($textDocument, $position) { + return coroutine(function () use ($textDocument, $position, $context) { $document = yield $this->documentLoader->getOrLoad($textDocument->uri); - return $this->completionProvider->provideCompletion($document, $position); + return $this->completionProvider->provideCompletion($document, $position, $context); }); } diff --git a/src/Server/Workspace.php b/src/Server/Workspace.php index 61db068..fe1dda6 100644 --- a/src/Server/Workspace.php +++ b/src/Server/Workspace.php @@ -123,6 +123,7 @@ class Workspace */ public function xreferences($query, array $files = null): Promise { + // TODO: $files is unused in the coroutine return coroutine(function () use ($query, $files) { if ($this->composerLock === null) { return []; diff --git a/src/TreeAnalyzer.php b/src/TreeAnalyzer.php index 2e34aa6..465f5bb 100644 --- a/src/TreeAnalyzer.php +++ b/src/TreeAnalyzer.php @@ -9,12 +9,19 @@ use phpDocumentor\Reflection\DocBlockFactory; use Sabre\Uri; use Microsoft\PhpParser; use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\Token; class TreeAnalyzer { /** @var PhpParser\Parser */ private $parser; + /** @var DocBlockFactory */ + private $docBlockFactory; + + /** @var DefinitionResolver */ + private $definitionResolver; + /** @var Node\SourceFileNode */ private $sourceFileNode; @@ -49,40 +56,53 @@ class TreeAnalyzer // TODO - docblock errors - $this->collectDefinitionsAndReferences($this->sourceFileNode); + $this->traverse($this->sourceFileNode); } - private function collectDefinitionsAndReferences(Node $sourceFileNode) + /** + * Collects Parser diagnostic messages for the Node/Token + * and transforms them into LSP Format + * + * @param Node|Token $node + * @return void + */ + private function collectDiagnostics($node) { - foreach ($sourceFileNode::CHILD_NAMES as $name) { - $node = $sourceFileNode->$name; + // Get errors from the parser. + if (($error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { + $range = PhpParser\PositionUtilities::getRangeFromPosition($error->start, $error->length, $this->sourceFileNode->fileContents); - if ($node === null) { - continue; + switch ($error->kind) { + case PhpParser\DiagnosticKind::Error: + $severity = DiagnosticSeverity::ERROR; + break; + case PhpParser\DiagnosticKind::Warning: + default: + $severity = DiagnosticSeverity::WARNING; + break; } - if (\is_array($node)) { - foreach ($node as $child) { - if ($child instanceof Node) { - $this->update($child); - } - } - continue; - } - - if ($node instanceof Node) { - $this->update($node); - } - - if (($error = PhpParser\DiagnosticsProvider::checkDiagnostics($node)) !== null) { - $range = PhpParser\PositionUtilities::getRangeFromPosition($error->start, $error->length, $this->sourceFileNode->fileContents); + $this->diagnostics[] = new Diagnostic( + $error->message, + new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->start->character) + ), + null, + $severity, + 'php' + ); + } + // Check for invalid usage of $this. + if ($node instanceof Node\Expression\Variable && $node->getName() === 'this') { + // Find the first ancestor that's a class method. Return an error + // if there is none, or if the method is static. + $method = $node->getFirstAncestor(Node\MethodDeclaration::class); + if ($method && $method->isStatic()) { $this->diagnostics[] = new Diagnostic( - $error->message, - new Range( - new Position($range->start->line, $range->start->character), - new Position($range->end->line, $range->start->character) - ), + "\$this can not be used in static methods.", + Range::fromNode($node), null, DiagnosticSeverity::ERROR, 'php' @@ -91,12 +111,45 @@ class TreeAnalyzer } } + /** + * Recursive AST traversal to collect definitions/references and diagnostics + * + * @param Node|Token $currentNode The node/token to process + */ + private function traverse($currentNode) + { + $this->collectDiagnostics($currentNode); + + // Only update/descend into Nodes, Tokens are leaves + if ($currentNode instanceof Node) { + $this->collectDefinitionsAndReferences($currentNode); + + foreach ($currentNode::CHILD_NAMES as $name) { + $child = $currentNode->$name; + + if ($child === null) { + continue; + } + + if (\is_array($child)) { + foreach ($child as $actualChild) { + if ($actualChild !== null) { + $this->traverse($actualChild); + } + } + } else { + $this->traverse($child); + } + } + } + } + /** * Collect definitions and references for the given node * * @param Node $node */ - private function update(Node $node) + private function collectDefinitionsAndReferences(Node $node) { $fqn = ($this->definitionResolver)::getDefinedFqn($node); // Only index definitions with an FQN (no variables) @@ -104,8 +157,9 @@ class TreeAnalyzer $this->definitionNodes[$fqn] = $node; $this->definitions[$fqn] = $this->definitionResolver->createDefinitionFromNode($node, $fqn); } else { + $parent = $node->parent; - if (!( + if ( ( // $node->parent instanceof Node\Expression\ScopedPropertyAccessExpression || ($node instanceof Node\Expression\ScopedPropertyAccessExpression || @@ -114,45 +168,71 @@ class TreeAnalyzer $node->parent instanceof Node\Expression\CallExpression || $node->memberName instanceof PhpParser\Token )) - || ($parent instanceof Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart())) + || ($parent instanceof Node\Statement\NamespaceDefinition && $parent->name !== null && $parent->name->getStart() === $node->getStart()) ) { - $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); - if ($fqn !== null) { - $this->addReference($fqn, $node); + return; + } - if ( - $node instanceof Node\QualifiedName - && ($node->isQualifiedName() || $node->parent instanceof Node\NamespaceUseClause) - && !($parent instanceof Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() - ) - ) { - // Add references for each referenced namespace - $ns = $fqn; - while (($pos = strrpos($ns, '\\')) !== false) { - $ns = substr($ns, 0, $pos); - $this->addReference($ns, $node); - } - } + $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node); + if (!$fqn) { + return; + } - // Namespaced constant access and function calls also need to register a reference - // to the global version because PHP falls back to global at runtime - // http://php.net/manual/en/language.namespaces.fallback.php - if (ParserHelpers\isConstantFetch($node) || - ($parent instanceof Node\Expression\CallExpression - && !( - $node instanceof Node\Expression\ScopedPropertyAccessExpression || - $node instanceof Node\Expression\MemberAccessExpression - ))) { - $parts = explode('\\', $fqn); - if (count($parts) > 1) { - $globalFqn = end($parts); - $this->addReference($globalFqn, $node); - } - } + if ($fqn === 'self' || $fqn === 'static') { + // Resolve self and static keywords to the containing class + // (This is not 100% correct for static but better than nothing) + $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class); + if (!$classNode) { + return; + } + $fqn = (string)$classNode->getNamespacedName(); + if (!$fqn) { + return; + } + } else if ($fqn === 'parent') { + // Resolve parent keyword to the base class FQN + $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class); + if (!$classNode || !$classNode->classBaseClause || !$classNode->classBaseClause->baseClass) { + return; + } + $fqn = (string)$classNode->classBaseClause->baseClass->getResolvedName(); + if (!$fqn) { + return; + } + } + + $this->addReference($fqn, $node); + + if ( + $node instanceof Node\QualifiedName + && ($node->isQualifiedName() || $node->parent instanceof Node\NamespaceUseClause) + && !($parent instanceof Node\Statement\NamespaceDefinition && $parent->name->getStart() === $node->getStart() + ) + ) { + // Add references for each referenced namespace + $ns = $fqn; + while (($pos = strrpos($ns, '\\')) !== false) { + $ns = substr($ns, 0, $pos); + $this->addReference($ns, $node); + } + } + + // Namespaced constant access and function calls also need to register a reference + // to the global version because PHP falls back to global at runtime + // http://php.net/manual/en/language.namespaces.fallback.php + if (ParserHelpers\isConstantFetch($node) || + ($parent instanceof Node\Expression\CallExpression + && !( + $node instanceof Node\Expression\ScopedPropertyAccessExpression || + $node instanceof Node\Expression\MemberAccessExpression + ))) { + $parts = explode('\\', $fqn); + if (count($parts) > 1) { + $globalFqn = end($parts); + $this->addReference($globalFqn, $node); } } } - $this->collectDefinitionsAndReferences($node); } /** @@ -175,7 +255,7 @@ class TreeAnalyzer } /** - * @return Definition + * @return Definition[] */ public function getDefinitions() { diff --git a/src/utils.php b/src/utils.php index 636b41e..97e091d 100644 --- a/src/utils.php +++ b/src/utils.php @@ -148,9 +148,8 @@ function isVendored(PhpDocument $document, \stdClass $composerJson = null): bool * Check a given URI against the composer.json to see if it * is a vendored URI * - * @param \stdClass|null $composerJson * @param string $uri - * @param array $matches + * @param \stdClass|null $composerJson * @return string|null */ function getPackageName(string $uri, \stdClass $composerJson = null) diff --git a/tests/Diagnostics/InvalidThisUsageTest.php b/tests/Diagnostics/InvalidThisUsageTest.php new file mode 100644 index 0000000..b7e8196 --- /dev/null +++ b/tests/Diagnostics/InvalidThisUsageTest.php @@ -0,0 +1,82 @@ +getDiagnostics(); + } + + /** + * Assertions about a diagnostic. + * + * @param Diagnostic|null $diagnostic + * @param int $message + * @param string $severity + * @param Range $range + */ + private function assertDiagnostic($diagnostic, $message, $severity, $range) + { + $this->assertInstanceOf(Diagnostic::class, $diagnostic); + $this->assertEquals($message, $diagnostic->message); + $this->assertEquals($severity, $diagnostic->severity); + $this->assertEquals($range, $diagnostic->range); + } + + public function testThisInStaticMethodProducesError() + { + $diagnostics = $this->collectDiagnostics( + __DIR__ . '/../../fixtures/diagnostics/errors/this_in_static_method.php' + ); + + $this->assertCount(1, $diagnostics); + $this->assertDiagnostic( + $diagnostics[0], + '$this can not be used in static methods.', + DiagnosticSeverity::ERROR, + new Range( + new Position(6, 15), + new Position(6, 20) + ) + ); + } + + public function testThisInMethodProducesNoError() + { + $diagnostics = $this->collectDiagnostics( + __DIR__ . '/../../fixtures/diagnostics/baselines/this_in_method.php' + ); + + $this->assertCount(0, $diagnostics); + } +} diff --git a/tests/FormatterTest.php b/tests/FormatterTest.php deleted file mode 100644 index a46f2ec..0000000 --- a/tests/FormatterTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame($output, $edits[0]->newText); - } - - public function testFormatNoChange() - { - $expected = file_get_contents(__DIR__ . '/../fixtures/format_expected.php'); - - $edits = Formatter::format($expected, 'file:///whatever'); - $this->assertSame([], $edits); - } -} diff --git a/tests/Index/IndexTest.php b/tests/Index/IndexTest.php new file mode 100644 index 0000000..8236f8d --- /dev/null +++ b/tests/Index/IndexTest.php @@ -0,0 +1,30 @@ +setDefinition('SomeNamespace\SomeClass', new Definition); + $methodDefinition = new Definition; + $methodFqn = 'SomeNamespace\SomeClass->someMethod()'; + $index->setDefinition($methodFqn, $methodDefinition); + $index->setDefinition('SomeNamespace\SomeClass->someProperty', new Definition); + $this->assertSame($methodDefinition, $index->getDefinition($methodFqn)); + } + + public function testGetSetClassDefinition() + { + $index = new Index; + $definition = new Definition; + $fqn = 'SomeNamespace\SomeClass'; + $index->setDefinition($fqn, $definition); + $this->assertSame($definition, $index->getDefinition($fqn)); + } +} diff --git a/tests/LanguageServerTest.php b/tests/LanguageServerTest.php index 5d03451..5d58172 100644 --- a/tests/LanguageServerTest.php +++ b/tests/LanguageServerTest.php @@ -34,7 +34,6 @@ class LanguageServerTest extends TestCase $serverCapabilities->textDocumentSync = TextDocumentSyncKind::FULL; $serverCapabilities->documentSymbolProvider = true; $serverCapabilities->workspaceSymbolProvider = true; - $serverCapabilities->documentFormattingProvider = true; $serverCapabilities->definitionProvider = true; $serverCapabilities->referencesProvider = true; $serverCapabilities->hoverProvider = true; diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 04e5976..45d949f 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -122,15 +122,16 @@ abstract class ServerTestCase extends TestCase 0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15))) ], 'TestNamespace\\TestClass' => [ - 0 => new Location($symbolsUri , new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {} - 1 => new Location($referencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); - 2 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); - 3 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; - 4 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; - 5 => new Location($referencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) - 6 => new Location($referencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass - 7 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; - 8 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass; + 0 => new Location($symbolsUri, new Range(new Position(48, 13), new Position(48, 17))), // echo self::TEST_CLASS_CONST; + 1 => new Location($symbolsUri , new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {} + 2 => new Location($referencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); + 3 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); + 4 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; + 5 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; + 6 => new Location($referencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) + 7 => new Location($referencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass + 8 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; + 9 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass; ], 'TestNamespace\\TestChild' => [ 0 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 25))), // echo $child->testProperty; @@ -176,14 +177,15 @@ abstract class ServerTestCase extends TestCase 1 => new Location($globalReferencesUri, new Range(new Position(29, 5), new Position(29, 15))) ], 'TestClass' => [ - 0 => new Location($globalSymbolsUri, new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {} - 1 => new Location($globalReferencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); - 2 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); - 3 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; - 4 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; - 5 => new Location($globalReferencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) - 6 => new Location($globalReferencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass - 7 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; + 0 => new Location($globalSymbolsUri, new Range(new Position(48, 13), new Position(48, 17))), // echo self::TEST_CLASS_CONST; + 1 => new Location($globalSymbolsUri, new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {} + 2 => new Location($globalReferencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass(); + 3 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod(); + 4 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty; + 5 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST; + 6 => new Location($globalReferencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param) + 7 => new Location($globalReferencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass + 8 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty; ], 'TestChild' => [ 0 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 25))), // echo $child->testProperty; diff --git a/tests/Server/TextDocument/CompletionTest.php b/tests/Server/TextDocument/CompletionTest.php index 0d68ec3..424dc3c 100644 --- a/tests/Server/TextDocument/CompletionTest.php +++ b/tests/Server/TextDocument/CompletionTest.php @@ -17,7 +17,9 @@ use LanguageServer\Protocol\{ Position, CompletionList, CompletionItem, - CompletionItemKind + CompletionItemKind, + CompletionContext, + CompletionTriggerKind }; use function LanguageServer\pathToUri; @@ -464,6 +466,41 @@ class CompletionTest extends TestCase ], true), $items); } + public function testHtmlPrefixShouldNotTriggerCompletion() + { + $completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php'); + $this->loader->open($completionUri, file_get_contents($completionUri)); + $items = $this->textDocument->completion( + new TextDocumentIdentifier($completionUri), + new Position(0, 1), + new CompletionContext(CompletionTriggerKind::TRIGGER_CHARACTER, '>') + )->wait(); + $this->assertEquals(new CompletionList([], true), $items); + } + + public function testHtmlPrefixShouldTriggerCompletionIfManuallyInvoked() + { + $completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php'); + $this->loader->open($completionUri, file_get_contents($completionUri)); + $items = $this->textDocument->completion( + new TextDocumentIdentifier($completionUri), + new Position(0, 1), + new CompletionContext(CompletionTriggerKind::INVOKED) + )->wait(); + $this->assertEquals(new CompletionList([ + new CompletionItem( + 'assertEquals([], $result); } + public function testDefinitionForSelfKeyword() + { + // echo self::TEST_CLASS_CONST; + // Get definition for self + $reference = $this->getReferenceLocations('TestClass')[0]; + $result = $this->textDocument->definition( + new TextDocumentIdentifier($reference->uri), + $reference->range->start + )->wait(); + $this->assertEquals($this->getDefinitionLocation('TestClass'), $result); + } + public function testDefinitionForClassLike() { // $obj = new TestClass(); // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[0]; + $reference = $this->getReferenceLocations('TestClass')[1]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -45,7 +57,7 @@ class GlobalTest extends ServerTestCase { // TestClass::staticTestMethod(); // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[1]; + $reference = $this->getReferenceLocations('TestClass')[2]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -57,7 +69,7 @@ class GlobalTest extends ServerTestCase { // echo TestClass::$staticTestProperty; // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[2]; + $reference = $this->getReferenceLocations('TestClass')[3]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -69,7 +81,7 @@ class GlobalTest extends ServerTestCase { // TestClass::TEST_CLASS_CONST; // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[3]; + $reference = $this->getReferenceLocations('TestClass')[4]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -213,7 +225,7 @@ class GlobalTest extends ServerTestCase { // function whatever(TestClass $param) { // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[4]; + $reference = $this->getReferenceLocations('TestClass')[5]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -225,7 +237,7 @@ class GlobalTest extends ServerTestCase { // function whatever(TestClass $param): TestClass { // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[5]; + $reference = $this->getReferenceLocations('TestClass')[6]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start diff --git a/tests/Server/TextDocument/Definition/NamespacedTest.php b/tests/Server/TextDocument/Definition/NamespacedTest.php index ef66624..395881b 100644 --- a/tests/Server/TextDocument/Definition/NamespacedTest.php +++ b/tests/Server/TextDocument/Definition/NamespacedTest.php @@ -34,7 +34,7 @@ class NamespacedTest extends GlobalTest { // use TestNamespace\TestClass; // Get definition for TestClass - $reference = $this->getReferenceLocations('TestClass')[6]; + $reference = $this->getReferenceLocations('TestClass')[7]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start @@ -46,7 +46,7 @@ class NamespacedTest extends GlobalTest { // use TestNamespace\{TestTrait, TestInterface}; // Get definition for TestInterface - $reference = $this->getReferenceLocations('TestClass')[0]; + $reference = $this->getReferenceLocations('TestClass')[1]; $result = $this->textDocument->definition( new TextDocumentIdentifier($reference->uri), $reference->range->start diff --git a/tests/Server/TextDocument/FormattingTest.php b/tests/Server/TextDocument/FormattingTest.php deleted file mode 100644 index 1844891..0000000 --- a/tests/Server/TextDocument/FormattingTest.php +++ /dev/null @@ -1,50 +0,0 @@ -uri = $uri; - $textDocumentItem->languageId = 'php'; - $textDocumentItem->version = 1; - $textDocumentItem->text = file_get_contents($path); - $textDocument->didOpen($textDocumentItem); - - // how code should look after formatting - $expected = file_get_contents(__DIR__ . '/../../../fixtures/format_expected.php'); - // Request formatting - $result = $textDocument->formatting(new TextDocumentIdentifier($uri), new FormattingOptions())->wait(); - $this->assertEquals([new TextEdit(new Range(new Position(0, 0), new Position(20, 0)), $expected)], $result); - } -} diff --git a/tests/Server/TextDocument/HoverTest.php b/tests/Server/TextDocument/HoverTest.php index 5010360..2ba49e1 100644 --- a/tests/Server/TextDocument/HoverTest.php +++ b/tests/Server/TextDocument/HoverTest.php @@ -15,7 +15,7 @@ class HoverTest extends ServerTestCase { // $obj = new TestClass(); // Get hover for TestClass - $reference = $this->getReferenceLocations('TestClass')[0]; + $reference = $this->getReferenceLocations('TestClass')[1]; $result = $this->textDocument->hover( new TextDocumentIdentifier($reference->uri), $reference->range->start diff --git a/tests/Server/TextDocument/References/GlobalTest.php b/tests/Server/TextDocument/References/GlobalTest.php index fcb6e71..105dfef 100644 --- a/tests/Server/TextDocument/References/GlobalTest.php +++ b/tests/Server/TextDocument/References/GlobalTest.php @@ -151,7 +151,7 @@ class GlobalTest extends ServerTestCase { // $obj = new TestClass(); // Get references for TestClass - $reference = $this->getReferenceLocations('TestClass')[0]; + $reference = $this->getReferenceLocations('TestClass')[1]; $result = $this->textDocument->references( new ReferenceContext, new TextDocumentIdentifier($reference->uri), diff --git a/tests/Validation/ValidationTest.php b/tests/Validation/ValidationTest.php index 3fc7429..9057c9d 100644 --- a/tests/Validation/ValidationTest.php +++ b/tests/Validation/ValidationTest.php @@ -96,7 +96,9 @@ class ValidationTest extends TestCase $testCasesDir = realpath(__DIR__ . '/cases'); foreach ($refsAndDefs['references'] as $key => $list) { $fixedPathRefs = array_map(function ($ref) use ($testCasesDir) { - return str_replace($testCasesDir, '.', $ref); + $ref = str_replace($testCasesDir, '.', $ref); + $ref = str_replace(DIRECTORY_SEPARATOR, '/', $ref); + return $ref; }, $list); $refsAndDefs['references']->$key = $fixedPathRefs; @@ -107,6 +109,7 @@ class ValidationTest extends TestCase if ($def !== null && $def->symbolInformation !== null && $def->symbolInformation->location !== null && $def->symbolInformation->location->uri !== null) { $def->symbolInformation->location->uri = str_replace($testCasesDir, '.', $def->symbolInformation->location->uri); + $def->symbolInformation->location->uri = str_replace(DIRECTORY_SEPARATOR, '/', $def->symbolInformation->location->uri); } } diff --git a/tests/Validation/cases/WithReturnTypehints.php.expected.json b/tests/Validation/cases/WithReturnTypehints.php.expected.json index 26b00e2..8c6b092 100644 --- a/tests/Validation/cases/WithReturnTypehints.php.expected.json +++ b/tests/Validation/cases/WithReturnTypehints.php.expected.json @@ -3,7 +3,7 @@ "Fixtures\\Prophecy\\EmptyClass": [ "./WithReturnTypehints.php" ], - "self": [ + "Fixtures\\Prophecy\\WithReturnTypehints": [ "./WithReturnTypehints.php" ], "Fixtures\\Prophecy\\__CLASS__": [ @@ -11,16 +11,13 @@ ], "__CLASS__": [ "./WithReturnTypehints.php" - ], - "parent": [ - "./WithReturnTypehints.php" ] }, "definitions": { "Fixtures\\Prophecy": { "fqn": "Fixtures\\Prophecy", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -41,7 +38,7 @@ "extends": [ "Fixtures\\Prophecy\\EmptyClass" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -60,7 +57,7 @@ "Fixtures\\Prophecy\\WithReturnTypehints->getSelf()": { "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getSelf()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -80,7 +77,7 @@ "Fixtures\\Prophecy\\WithReturnTypehints->getName()": { "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getName()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -100,7 +97,7 @@ "Fixtures\\Prophecy\\WithReturnTypehints->getParent()": { "fqn": "Fixtures\\Prophecy\\WithReturnTypehints->getParent()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json index b0625d7..51343f1 100644 --- a/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json +++ b/tests/Validation/cases/anonymousClassMembersShouldNotBeSymbols.php.expected.json @@ -4,7 +4,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json b/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json index d58986d..107877e 100644 --- a/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json +++ b/tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json @@ -4,7 +4,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +23,7 @@ "A->foo": { "fqn": "A->foo", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/caseStatement1.php.expected.json b/tests/Validation/cases/caseStatement1.php.expected.json index 573dd17..9746749 100644 --- a/tests/Validation/cases/caseStatement1.php.expected.json +++ b/tests/Validation/cases/caseStatement1.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/classDefinition1.php.expected.json b/tests/Validation/cases/classDefinition1.php.expected.json index 6c418b7..670b5de 100644 --- a/tests/Validation/cases/classDefinition1.php.expected.json +++ b/tests/Validation/cases/classDefinition1.php.expected.json @@ -11,7 +11,7 @@ "TestNamespace": { "fqn": "TestNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "TestNamespace\\A": { "fqn": "TestNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "TestNamespace\\A->a": { "fqn": "TestNamespace\\A->a", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/classProperty1.php.expected.json b/tests/Validation/cases/classProperty1.php.expected.json index e00107e..921bf0b 100644 --- a/tests/Validation/cases/classProperty1.php.expected.json +++ b/tests/Validation/cases/classProperty1.php.expected.json @@ -11,7 +11,7 @@ "TestNamespace": { "fqn": "TestNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "TestNamespace\\TestClass": { "fqn": "TestNamespace\\TestClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "TestNamespace\\TestClass->testProperty": { "fqn": "TestNamespace\\TestClass->testProperty", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -69,7 +69,7 @@ "TestNamespace\\TestClass->testMethod()": { "fqn": "TestNamespace\\TestClass->testMethod()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constants.php.expected.json b/tests/Validation/cases/constants.php.expected.json index d629870..a76c059 100644 --- a/tests/Validation/cases/constants.php.expected.json +++ b/tests/Validation/cases/constants.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::suite()": { "fqn": "MyNamespace\\A::suite()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constants2.php.expected.json b/tests/Validation/cases/constants2.php.expected.json index 66c678f..ae5a2ce 100644 --- a/tests/Validation/cases/constants2.php.expected.json +++ b/tests/Validation/cases/constants2.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::suite()": { "fqn": "MyNamespace\\A::suite()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constants3.php.expected.json b/tests/Validation/cases/constants3.php.expected.json index 03f00ba..c6ad922 100644 --- a/tests/Validation/cases/constants3.php.expected.json +++ b/tests/Validation/cases/constants3.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::suite()": { "fqn": "MyNamespace\\A::suite()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constants4.php.expected.json b/tests/Validation/cases/constants4.php.expected.json index 62ce430..bc46cf1 100644 --- a/tests/Validation/cases/constants4.php.expected.json +++ b/tests/Validation/cases/constants4.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A->suite()": { "fqn": "MyNamespace\\A->suite()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constants5.php.expected.json b/tests/Validation/cases/constants5.php.expected.json index bb441c8..6bd7b8e 100644 --- a/tests/Validation/cases/constants5.php.expected.json +++ b/tests/Validation/cases/constants5.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "MyNamespace\\Mbstring": { "fqn": "MyNamespace\\Mbstring", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -46,7 +46,7 @@ "MyNamespace\\Mbstring::MB_CASE_FOLD": { "fqn": "MyNamespace\\Mbstring::MB_CASE_FOLD", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json b/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json index 8f9a212..b49f5a9 100644 --- a/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json +++ b/tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json @@ -8,7 +8,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "A->b()": { "fqn": "A->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json index 73f6bee..dd1737a 100644 --- a/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json +++ b/tests/Validation/cases/docBlocksOnNamespaceDefinition.php.expected.json @@ -4,7 +4,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/exceptions1.php.expected.json b/tests/Validation/cases/exceptions1.php.expected.json index a4a71d1..c1ee1bd 100644 --- a/tests/Validation/cases/exceptions1.php.expected.json +++ b/tests/Validation/cases/exceptions1.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/ifStatement1.php.expected.json b/tests/Validation/cases/ifStatement1.php.expected.json index 18efe9f..98e6572 100644 --- a/tests/Validation/cases/ifStatement1.php.expected.json +++ b/tests/Validation/cases/ifStatement1.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/interfaceProperty.php.expected.json b/tests/Validation/cases/interfaceProperty.php.expected.json index 178834d..10c49f0 100644 --- a/tests/Validation/cases/interfaceProperty.php.expected.json +++ b/tests/Validation/cases/interfaceProperty.php.expected.json @@ -4,7 +4,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json b/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json index f62d214..a9c2162 100644 --- a/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json +++ b/tests/Validation/cases/magicConstantsShouldBeGlobal.php.expected.json @@ -11,7 +11,7 @@ "B": { "fqn": "B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/magicConsts.php.expected.json b/tests/Validation/cases/magicConsts.php.expected.json index a37791b..6f863b9 100644 --- a/tests/Validation/cases/magicConsts.php.expected.json +++ b/tests/Validation/cases/magicConsts.php.expected.json @@ -8,7 +8,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -27,7 +27,7 @@ "A::$deprecationsTriggered": { "fqn": "A::$deprecationsTriggered", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberAccess1.php.expected.json b/tests/Validation/cases/memberAccess1.php.expected.json index 7f9630a..c039e5e 100644 --- a/tests/Validation/cases/memberAccess1.php.expected.json +++ b/tests/Validation/cases/memberAccess1.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::a()": { "fqn": "MyNamespace\\A::a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberAccess2.php.expected.json b/tests/Validation/cases/memberAccess2.php.expected.json index 7b3ce1d..50902a1 100644 --- a/tests/Validation/cases/memberAccess2.php.expected.json +++ b/tests/Validation/cases/memberAccess2.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::a()": { "fqn": "MyNamespace\\A::a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberAccess3.php.expected.json b/tests/Validation/cases/memberAccess3.php.expected.json index 520dae8..d91b27d 100644 --- a/tests/Validation/cases/memberAccess3.php.expected.json +++ b/tests/Validation/cases/memberAccess3.php.expected.json @@ -26,7 +26,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -45,7 +45,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -64,7 +64,7 @@ "MyNamespace\\A::getInitializer()": { "fqn": "MyNamespace\\A::getInitializer()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberAccess4.php.expected.json b/tests/Validation/cases/memberAccess4.php.expected.json index 1d51b85..0b7e1bf 100644 --- a/tests/Validation/cases/memberAccess4.php.expected.json +++ b/tests/Validation/cases/memberAccess4.php.expected.json @@ -17,7 +17,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -36,7 +36,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -55,7 +55,7 @@ "MyNamespace\\A->testRequest()": { "fqn": "MyNamespace\\A->testRequest()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberAccess5.php.expected.json b/tests/Validation/cases/memberAccess5.php.expected.json index 57aca0a..050cf3b 100644 --- a/tests/Validation/cases/memberAccess5.php.expected.json +++ b/tests/Validation/cases/memberAccess5.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "MyNamespace\\ParseErrorsTest": { "fqn": "MyNamespace\\ParseErrorsTest", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -46,7 +46,7 @@ "MyNamespace\\ParseErrorsTest->setUp()": { "fqn": "MyNamespace\\ParseErrorsTest->setUp()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/memberCall1.php.expected.json b/tests/Validation/cases/memberCall1.php.expected.json index 416a705..d02d7e3 100644 --- a/tests/Validation/cases/memberCall1.php.expected.json +++ b/tests/Validation/cases/memberCall1.php.expected.json @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\ParseErrorsTest": { "fqn": "MyNamespace\\ParseErrorsTest", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\ParseErrorsTest->setAccount()": { "fqn": "MyNamespace\\ParseErrorsTest->setAccount()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/methodReturnType.php.expected.json b/tests/Validation/cases/methodReturnType.php.expected.json index 54d79d6..2c89994 100644 --- a/tests/Validation/cases/methodReturnType.php.expected.json +++ b/tests/Validation/cases/methodReturnType.php.expected.json @@ -8,7 +8,7 @@ "FooClass": { "fqn": "FooClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -27,7 +27,7 @@ "FooClass->foo()": { "fqn": "FooClass->foo()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/multipleNamespaces.php.expected.json b/tests/Validation/cases/multipleNamespaces.php.expected.json index 30fe596..fa51f2d 100644 --- a/tests/Validation/cases/multipleNamespaces.php.expected.json +++ b/tests/Validation/cases/multipleNamespaces.php.expected.json @@ -17,7 +17,7 @@ "MyNamespace1": { "fqn": "MyNamespace1", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -36,7 +36,7 @@ "MyNamespace1\\B": { "fqn": "MyNamespace1\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -55,7 +55,7 @@ "MyNamespace1\\B->b()": { "fqn": "MyNamespace1\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -75,7 +75,7 @@ "MyNamespace2": { "fqn": "MyNamespace2", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -96,7 +96,7 @@ "extends": [ "MyNamespace2\\MyNamespace1\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -115,7 +115,7 @@ "MyNamespace2\\A->a()": { "fqn": "MyNamespace2\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/multiplePreceedingComments.php.expected.json b/tests/Validation/cases/multiplePreceedingComments.php.expected.json index 5ca3dd7..96cbb4a 100644 --- a/tests/Validation/cases/multiplePreceedingComments.php.expected.json +++ b/tests/Validation/cases/multiplePreceedingComments.php.expected.json @@ -4,7 +4,7 @@ "Foo": { "fqn": "Foo", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +23,7 @@ "Foo->fn()": { "fqn": "Foo->fn()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/nameToken.php.expected.json b/tests/Validation/cases/nameToken.php.expected.json index 0ecd53f..37cb4ca 100644 --- a/tests/Validation/cases/nameToken.php.expected.json +++ b/tests/Validation/cases/nameToken.php.expected.json @@ -1,10 +1,14 @@ { - "references": [], + "references": { + "A": [ + "./nameToken.php" + ] + }, "definitions": { "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +27,7 @@ "A->b()": { "fqn": "A->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/namespaces2.php.expected.json b/tests/Validation/cases/namespaces2.php.expected.json index 42243e5..0dffc9f 100644 --- a/tests/Validation/cases/namespaces2.php.expected.json +++ b/tests/Validation/cases/namespaces2.php.expected.json @@ -17,7 +17,7 @@ "MyNamespace1": { "fqn": "MyNamespace1", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/namespaces5.php.expected.json b/tests/Validation/cases/namespaces5.php.expected.json index 5ffe02d..e609ca2 100644 --- a/tests/Validation/cases/namespaces5.php.expected.json +++ b/tests/Validation/cases/namespaces5.php.expected.json @@ -26,7 +26,7 @@ "B": { "fqn": "B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/namespaces6.php.expected.json b/tests/Validation/cases/namespaces6.php.expected.json index 1657f28..bf5a045 100644 --- a/tests/Validation/cases/namespaces6.php.expected.json +++ b/tests/Validation/cases/namespaces6.php.expected.json @@ -4,7 +4,7 @@ "A\\B": { "fqn": "A\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/namespaces8.php.expected.json b/tests/Validation/cases/namespaces8.php.expected.json index 71017d9..d303647 100644 --- a/tests/Validation/cases/namespaces8.php.expected.json +++ b/tests/Validation/cases/namespaces8.php.expected.json @@ -14,7 +14,7 @@ "LanguageServer\\Tests\\Utils": { "fqn": "LanguageServer\\Tests\\Utils", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/objectCreation.php.expected.json b/tests/Validation/cases/objectCreation.php.expected.json index a8fce0f..8fec38f 100644 --- a/tests/Validation/cases/objectCreation.php.expected.json +++ b/tests/Validation/cases/objectCreation.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -46,7 +46,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/objectCreation2.php.expected.json b/tests/Validation/cases/objectCreation2.php.expected.json index 2ec8314..e546528 100644 --- a/tests/Validation/cases/objectCreation2.php.expected.json +++ b/tests/Validation/cases/objectCreation2.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -68,7 +68,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/objectCreation3.php.expected.json b/tests/Validation/cases/objectCreation3.php.expected.json index f0cc31a..d2d3e2f 100644 --- a/tests/Validation/cases/objectCreation3.php.expected.json +++ b/tests/Validation/cases/objectCreation3.php.expected.json @@ -8,7 +8,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -27,7 +27,7 @@ "A->a()": { "fqn": "A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/param1.php.expected.json b/tests/Validation/cases/param1.php.expected.json index 33c99db..40cfbd1 100644 --- a/tests/Validation/cases/param1.php.expected.json +++ b/tests/Validation/cases/param1.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "MyNamespace\\init()": { "fqn": "MyNamespace\\init()", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/parent1.php.expected.json b/tests/Validation/cases/parent1.php.expected.json index eab232e..56d7e61 100644 --- a/tests/Validation/cases/parent1.php.expected.json +++ b/tests/Validation/cases/parent1.php.expected.json @@ -2,16 +2,13 @@ "references": { "MyNamespace\\B": [ "./parent1.php" - ], - "parent": [ - "./parent1.php" ] }, "definitions": { "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +27,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +46,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -71,7 +68,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -90,7 +87,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/parent3.php.expected.json b/tests/Validation/cases/parent3.php.expected.json index aedb4b2..3954754 100644 --- a/tests/Validation/cases/parent3.php.expected.json +++ b/tests/Validation/cases/parent3.php.expected.json @@ -5,16 +5,13 @@ ], "MyNamespace\\B->b()": [ "./parent3.php" - ], - "parent": [ - "./parent3.php" ] }, "definitions": { "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +30,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +49,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +71,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +90,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/propertyName1.php.expected.json b/tests/Validation/cases/propertyName1.php.expected.json index 42b2ee9..cc31ed6 100644 --- a/tests/Validation/cases/propertyName1.php.expected.json +++ b/tests/Validation/cases/propertyName1.php.expected.json @@ -4,7 +4,7 @@ "MyClass": { "fqn": "MyClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +23,7 @@ "MyClass->mainPropertyName": { "fqn": "MyClass->mainPropertyName", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/propertyName2.php.expected.json b/tests/Validation/cases/propertyName2.php.expected.json index 5a5c914..d4efb42 100644 --- a/tests/Validation/cases/propertyName2.php.expected.json +++ b/tests/Validation/cases/propertyName2.php.expected.json @@ -4,7 +4,7 @@ "MyClass": { "fqn": "MyClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +23,7 @@ "MyClass->mainPropertyName": { "fqn": "MyClass->mainPropertyName", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/returnType.php.expected.json b/tests/Validation/cases/returnType.php.expected.json index cf9cc63..20cdadf 100644 --- a/tests/Validation/cases/returnType.php.expected.json +++ b/tests/Validation/cases/returnType.php.expected.json @@ -11,7 +11,7 @@ "TestNamespace": { "fqn": "TestNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "TestNamespace\\whatever()": { "fqn": "TestNamespace\\whatever()", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/scopedPropertyAccess.php.expected.json b/tests/Validation/cases/scopedPropertyAccess.php.expected.json index 52b6e7a..ec50c7a 100644 --- a/tests/Validation/cases/scopedPropertyAccess.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess.php.expected.json @@ -11,7 +11,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -30,7 +30,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -49,7 +49,7 @@ "MyNamespace\\A::a()": { "fqn": "MyNamespace\\A::a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/scopedPropertyAccess2.php.expected.json b/tests/Validation/cases/scopedPropertyAccess2.php.expected.json index e5f6850..e1712cd 100644 --- a/tests/Validation/cases/scopedPropertyAccess2.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess2.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/scopedPropertyAccess3.php.expected.json b/tests/Validation/cases/scopedPropertyAccess3.php.expected.json index aa508bc..913721b 100644 --- a/tests/Validation/cases/scopedPropertyAccess3.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess3.php.expected.json @@ -11,7 +11,7 @@ "A": { "fqn": "A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -30,7 +30,7 @@ "A::$a": { "fqn": "A::$a", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/scopedPropertyAccess5.php.expected.json b/tests/Validation/cases/scopedPropertyAccess5.php.expected.json index bd4ee70..7e56123 100644 --- a/tests/Validation/cases/scopedPropertyAccess5.php.expected.json +++ b/tests/Validation/cases/scopedPropertyAccess5.php.expected.json @@ -17,7 +17,7 @@ "TestClass": { "fqn": "TestClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -36,7 +36,7 @@ "TestClass::$testProperty": { "fqn": "TestClass::$testProperty", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/self1.php.expected.json b/tests/Validation/cases/self1.php.expected.json index eb37fc7..fe2bc63 100644 --- a/tests/Validation/cases/self1.php.expected.json +++ b/tests/Validation/cases/self1.php.expected.json @@ -6,7 +6,7 @@ "MyNamespace\\A::b()": [ "./self1.php" ], - "self": [ + "MyNamespace\\A": [ "./self1.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/self2.php.expected.json b/tests/Validation/cases/self2.php.expected.json index 2280b1a..60ab062 100644 --- a/tests/Validation/cases/self2.php.expected.json +++ b/tests/Validation/cases/self2.php.expected.json @@ -6,7 +6,7 @@ "MyNamespace\\A::b()": [ "./self2.php" ], - "self": [ + "MyNamespace\\A": [ "./self2.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/self3.php.expected.json b/tests/Validation/cases/self3.php.expected.json index 3f69299..7d66c2b 100644 --- a/tests/Validation/cases/self3.php.expected.json +++ b/tests/Validation/cases/self3.php.expected.json @@ -6,7 +6,7 @@ "MyNamespace\\A->b()": [ "./self3.php" ], - "self": [ + "MyNamespace\\A": [ "./self3.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/self4.php.expected.json b/tests/Validation/cases/self4.php.expected.json index ec3ae07..64765b7 100644 --- a/tests/Validation/cases/self4.php.expected.json +++ b/tests/Validation/cases/self4.php.expected.json @@ -1,6 +1,6 @@ { "references": { - "self": [ + "MyNamespace\\A": [ "./self4.php" ], "MyNamespace\\A->addTestFile()": [ @@ -23,7 +23,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -42,7 +42,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -61,7 +61,7 @@ "MyNamespace\\A::suite()": { "fqn": "MyNamespace\\A::suite()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, diff --git a/tests/Validation/cases/self5.php.expected.json b/tests/Validation/cases/self5.php.expected.json index 6727689..eb41832 100644 --- a/tests/Validation/cases/self5.php.expected.json +++ b/tests/Validation/cases/self5.php.expected.json @@ -8,7 +8,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -27,7 +27,7 @@ "MyNamespace\\A": { "fqn": "MyNamespace\\A", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -46,7 +46,7 @@ "MyNamespace\\A->typesProvider()": { "fqn": "MyNamespace\\A->typesProvider()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/static1.php.expected.json b/tests/Validation/cases/static1.php.expected.json index 69f8de0..db1a0d2 100644 --- a/tests/Validation/cases/static1.php.expected.json +++ b/tests/Validation/cases/static1.php.expected.json @@ -6,7 +6,7 @@ "MyNamespace\\A::b()": [ "./static1.php" ], - "static": [ + "MyNamespace\\A": [ "./static1.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/static2.php.expected.json b/tests/Validation/cases/static2.php.expected.json index 17f9a66..bb662cb 100644 --- a/tests/Validation/cases/static2.php.expected.json +++ b/tests/Validation/cases/static2.php.expected.json @@ -6,7 +6,7 @@ "MyNamespace\\A::b()": [ "./static2.php" ], - "static": [ + "MyNamespace\\A": [ "./static2.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/static3.php.expected.json b/tests/Validation/cases/static3.php.expected.json index f6e5189..34d3851 100644 --- a/tests/Validation/cases/static3.php.expected.json +++ b/tests/Validation/cases/static3.php.expected.json @@ -3,10 +3,10 @@ "MyNamespace\\B": [ "./static3.php" ], - "MyNamespace\\b()": [ + "static->b()": [ "./static3.php" ], - "b()": [ + "MyNamespace\\A": [ "./static3.php" ] }, @@ -14,7 +14,7 @@ "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -33,7 +33,7 @@ "MyNamespace\\B": { "fqn": "MyNamespace\\B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -52,7 +52,7 @@ "MyNamespace\\B->b()": { "fqn": "MyNamespace\\B->b()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -74,7 +74,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -93,7 +93,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/static4.php.expected.json b/tests/Validation/cases/static4.php.expected.json index 3d05ede..de71d41 100644 --- a/tests/Validation/cases/static4.php.expected.json +++ b/tests/Validation/cases/static4.php.expected.json @@ -2,13 +2,16 @@ "references": { "MyNamespace\\B": [ "./static4.php" + ], + "MyNamespace\\A": [ + "./static4.php" ] }, "definitions": { "MyNamespace": { "fqn": "MyNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -29,7 +32,7 @@ "extends": [ "MyNamespace\\B" ], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -48,7 +51,7 @@ "MyNamespace\\A->a()": { "fqn": "MyNamespace\\A->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/staticMethodReturnType.php.expected.json b/tests/Validation/cases/staticMethodReturnType.php.expected.json index c178f0a..e6661ec 100644 --- a/tests/Validation/cases/staticMethodReturnType.php.expected.json +++ b/tests/Validation/cases/staticMethodReturnType.php.expected.json @@ -8,7 +8,7 @@ "FooClass": { "fqn": "FooClass", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -27,7 +27,7 @@ "FooClass::staticFoo()": { "fqn": "FooClass::staticFoo()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": true, "canBeInstantiated": false, @@ -47,7 +47,7 @@ "FooClass->bar()": { "fqn": "FooClass->bar()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/stringVariable.php.expected.json b/tests/Validation/cases/stringVariable.php.expected.json index 61669c8..1d4c7e3 100644 --- a/tests/Validation/cases/stringVariable.php.expected.json +++ b/tests/Validation/cases/stringVariable.php.expected.json @@ -1,10 +1,14 @@ { - "references": [], + "references": { + "B->hi": [ + "./stringVariable.php" + ] + }, "definitions": { "B": { "fqn": "B", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -23,7 +27,7 @@ "B->hi": { "fqn": "B->hi", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -43,7 +47,7 @@ "B->a()": { "fqn": "B->a()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json index f686093..509907c 100644 --- a/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json +++ b/tests/Validation/cases/testQualifiedNameOutsideOfNamespace.php.expected.json @@ -8,7 +8,7 @@ "SomeNamespace": { "fqn": "SomeNamespace", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": false, diff --git a/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json b/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json index f6851bf..662a7ed 100644 --- a/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json +++ b/tests/Validation/cases/verifyFqsenOnClassProperty.php.expected.json @@ -11,7 +11,7 @@ "Foo": { "fqn": "Foo", "extends": [], - "isGlobal": true, + "isMember": false, "roamed": false, "isStatic": false, "canBeInstantiated": true, @@ -30,7 +30,7 @@ "Foo->bar": { "fqn": "Foo->bar", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false, @@ -50,7 +50,7 @@ "Foo->foo()": { "fqn": "Foo->foo()", "extends": [], - "isGlobal": false, + "isMember": true, "roamed": false, "isStatic": false, "canBeInstantiated": false,