Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
fb48c70ce2 | |
|
3fc105717d | |
|
9dc1656592 | |
|
7303143a60 | |
|
1705583e32 | |
|
1da3328bc2 | |
|
450116e2f3 | |
|
b1cc565d7e |
|
@ -10,6 +10,7 @@
|
||||||
/.gitignore export-ignore
|
/.gitignore export-ignore
|
||||||
/.gitmodules export-ignore
|
/.gitmodules export-ignore
|
||||||
/.npmrc export-ignore
|
/.npmrc export-ignore
|
||||||
|
/.phan export-ignore
|
||||||
/.travis.yml export-ignore
|
/.travis.yml export-ignore
|
||||||
/appveyor.yml export-ignore
|
/appveyor.yml export-ignore
|
||||||
/codecov.yml export-ignore
|
/codecov.yml export-ignore
|
||||||
|
|
|
@ -0,0 +1,308 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Phan\Issue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This configuration file was automatically generated by 'phan --init --init-level=1'
|
||||||
|
*
|
||||||
|
* TODOs (added by 'phan --init'):
|
||||||
|
*
|
||||||
|
* - Go through this file and verify that there are no missing/unnecessary files/directories.
|
||||||
|
* (E.g. this only includes direct composer dependencies - You may have to manually add indirect composer dependencies to 'directory_list')
|
||||||
|
* - Look at 'plugins' and add or remove plugins if appropriate (see https://github.com/phan/phan/tree/master/.phan/plugins#plugins)
|
||||||
|
* - Add global suppressions for pre-existing issues to suppress_issue_types (https://github.com/phan/phan/wiki/Tutorial-for-Analyzing-a-Large-Sloppy-Code-Base)
|
||||||
|
*
|
||||||
|
* This configuration will be read and overlayed on top of the
|
||||||
|
* default configuration. Command line arguments will be applied
|
||||||
|
* after this file is read.
|
||||||
|
*
|
||||||
|
* @see src/Phan/Config.php
|
||||||
|
* See Config for all configurable options.
|
||||||
|
*
|
||||||
|
* A Note About Paths
|
||||||
|
* ==================
|
||||||
|
*
|
||||||
|
* Files referenced from this file should be defined as
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Config::projectPath('relative_path/to/file')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* where the relative path is relative to the root of the
|
||||||
|
* project which is defined as either the working directory
|
||||||
|
* of the phan executable or a path passed in via the CLI
|
||||||
|
* '-d' flag.
|
||||||
|
*/
|
||||||
|
return [
|
||||||
|
|
||||||
|
// Supported values: '7.0', '7.1', '7.2', null.
|
||||||
|
// If this is set to null,
|
||||||
|
// then Phan assumes the PHP version which is closest to the minor version
|
||||||
|
// of the php executable used to execute phan.
|
||||||
|
// Automatically inferred from composer.json requirement for "php" of "^7.0"
|
||||||
|
'target_php_version' => '7.0',
|
||||||
|
|
||||||
|
// If enabled, missing properties will be created when
|
||||||
|
// they are first seen. If false, we'll report an
|
||||||
|
// error message if there is an attempt to write
|
||||||
|
// to a class property that wasn't explicitly
|
||||||
|
// defined.
|
||||||
|
'allow_missing_properties' => false,
|
||||||
|
|
||||||
|
// If enabled, null can be cast as any type and any
|
||||||
|
// type can be cast to null. Setting this to true
|
||||||
|
// will cut down on false positives.
|
||||||
|
'null_casts_as_any_type' => false,
|
||||||
|
|
||||||
|
// If enabled, allow null to be cast as any array-like type.
|
||||||
|
// This is an incremental step in migrating away from null_casts_as_any_type.
|
||||||
|
// If null_casts_as_any_type is true, this has no effect.
|
||||||
|
'null_casts_as_array' => false,
|
||||||
|
|
||||||
|
// If enabled, allow any array-like type to be cast to null.
|
||||||
|
// This is an incremental step in migrating away from null_casts_as_any_type.
|
||||||
|
// If null_casts_as_any_type is true, this has no effect.
|
||||||
|
'array_casts_as_null' => false,
|
||||||
|
|
||||||
|
// If enabled, scalars (int, float, bool, string, null)
|
||||||
|
// are treated as if they can cast to each other.
|
||||||
|
// This does not affect checks of array keys. See scalar_array_key_cast.
|
||||||
|
'scalar_implicit_cast' => false,
|
||||||
|
|
||||||
|
// If enabled, any scalar array keys (int, string)
|
||||||
|
// are treated as if they can cast to each other.
|
||||||
|
// E.g. array<int,stdClass> can cast to array<string,stdClass> and vice versa.
|
||||||
|
// Normally, a scalar type such as int could only cast to/from int and mixed.
|
||||||
|
'scalar_array_key_cast' => false,
|
||||||
|
|
||||||
|
// If this has entries, scalars (int, float, bool, string, null)
|
||||||
|
// are allowed to perform the casts listed.
|
||||||
|
// E.g. ['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']]
|
||||||
|
// allows casting null to a string, but not vice versa.
|
||||||
|
// (subset of scalar_implicit_cast)
|
||||||
|
'scalar_implicit_partial' => [],
|
||||||
|
|
||||||
|
// If true, seemingly undeclared variables in the global
|
||||||
|
// scope will be ignored. This is useful for projects
|
||||||
|
// with complicated cross-file globals that you have no
|
||||||
|
// hope of fixing.
|
||||||
|
'ignore_undeclared_variables_in_global_scope' => false,
|
||||||
|
|
||||||
|
// Backwards Compatibility Checking. This is slow
|
||||||
|
// and expensive, but you should consider running
|
||||||
|
// it before upgrading your version of PHP to a
|
||||||
|
// new version that has backward compatibility
|
||||||
|
// breaks.
|
||||||
|
'backward_compatibility_checks' => false,
|
||||||
|
|
||||||
|
// If true, check to make sure the return type declared
|
||||||
|
// in the doc-block (if any) matches the return type
|
||||||
|
// declared in the method signature.
|
||||||
|
'check_docblock_signature_return_type_match' => true,
|
||||||
|
|
||||||
|
// (*Requires check_docblock_signature_param_type_match to be true*)
|
||||||
|
// If true, make narrowed types from phpdoc params override
|
||||||
|
// the real types from the signature, when real types exist.
|
||||||
|
// (E.g. allows specifying desired lists of subclasses,
|
||||||
|
// or to indicate a preference for non-nullable types over nullable types)
|
||||||
|
// Affects analysis of the body of the method and the param types passed in by callers.
|
||||||
|
'prefer_narrowed_phpdoc_param_type' => true,
|
||||||
|
|
||||||
|
// (*Requires check_docblock_signature_return_type_match to be true*)
|
||||||
|
// If true, make narrowed types from phpdoc returns override
|
||||||
|
// the real types from the signature, when real types exist.
|
||||||
|
// (E.g. allows specifying desired lists of subclasses,
|
||||||
|
// or to indicate a preference for non-nullable types over nullable types)
|
||||||
|
// Affects analysis of return statements in the body of the method and the return types passed in by callers.
|
||||||
|
'prefer_narrowed_phpdoc_return_type' => true,
|
||||||
|
|
||||||
|
'ensure_signature_compatibility' => true,
|
||||||
|
|
||||||
|
// Set to true in order to attempt to detect dead
|
||||||
|
// (unreferenced) code. Keep in mind that the
|
||||||
|
// results will only be a guess given that classes,
|
||||||
|
// properties, constants and methods can be referenced
|
||||||
|
// as variables (like `$class->$property` or
|
||||||
|
// `$class->$method()`) in ways that we're unable
|
||||||
|
// to make sense of.
|
||||||
|
'dead_code_detection' => false,
|
||||||
|
|
||||||
|
// If true, this run a quick version of checks that takes less
|
||||||
|
// time at the cost of not running as thorough
|
||||||
|
// an analysis. You should consider setting this
|
||||||
|
// to true only when you wish you had more **undiagnosed** issues
|
||||||
|
// to fix in your code base.
|
||||||
|
//
|
||||||
|
// In quick-mode the scanner doesn't rescan a function
|
||||||
|
// or a method's code block every time a call is seen.
|
||||||
|
// This means that the problem here won't be detected:
|
||||||
|
//
|
||||||
|
// ```php
|
||||||
|
// <?php
|
||||||
|
// function test($arg):int {
|
||||||
|
// return $arg;
|
||||||
|
// }
|
||||||
|
// test("abc");
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// This would normally generate:
|
||||||
|
//
|
||||||
|
// ```sh
|
||||||
|
// test.php:3 TypeError return string but `test()` is declared to return int
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The initial scan of the function's code block has no
|
||||||
|
// type information for `$arg`. It isn't until we see
|
||||||
|
// the call and rescan test()'s code block that we can
|
||||||
|
// detect that it is actually returning the passed in
|
||||||
|
// `string` instead of an `int` as declared.
|
||||||
|
'quick_mode' => false,
|
||||||
|
|
||||||
|
// If true, then before analysis, try to simplify AST into a form
|
||||||
|
// which improves Phan's type inference in edge cases.
|
||||||
|
//
|
||||||
|
// This may conflict with 'dead_code_detection'.
|
||||||
|
// When this is true, this slows down analysis slightly.
|
||||||
|
//
|
||||||
|
// E.g. rewrites `if ($a = value() && $a > 0) {...}`
|
||||||
|
// into $a = value(); if ($a) { if ($a > 0) {...}}`
|
||||||
|
'simplify_ast' => true,
|
||||||
|
|
||||||
|
// Enable or disable support for generic templated
|
||||||
|
// class types.
|
||||||
|
'generic_types_enabled' => true,
|
||||||
|
|
||||||
|
// Override to hardcode existence and types of (non-builtin) globals in the global scope.
|
||||||
|
// Class names should be prefixed with '\\'.
|
||||||
|
// (E.g. ['_FOO' => '\\FooClass', 'page' => '\\PageClass', 'userId' => 'int'])
|
||||||
|
'globals_type_map' => [],
|
||||||
|
|
||||||
|
// The minimum severity level to report on. This can be
|
||||||
|
// set to Issue::SEVERITY_LOW, Issue::SEVERITY_NORMAL or
|
||||||
|
// Issue::SEVERITY_CRITICAL. Setting it to only
|
||||||
|
// critical issues is a good place to start on a big
|
||||||
|
// sloppy mature code base.
|
||||||
|
'minimum_severity' => Issue::SEVERITY_LOW,
|
||||||
|
|
||||||
|
// Add any issue types (such as 'PhanUndeclaredMethod')
|
||||||
|
// to this black-list to inhibit them from being reported.
|
||||||
|
'suppress_issue_types' => [
|
||||||
|
'PhanTypeMismatchDeclaredParamNullable',
|
||||||
|
'PhanUndeclaredProperty', // 66 occurence(s) (e.g. not being specific enough about the subclass)
|
||||||
|
'PhanUndeclaredMethod', // 32 occurence(s) (e.g. not being specific enough about the subclass of Node)
|
||||||
|
'PhanTypeMismatchArgument', // 21 occurence(s)
|
||||||
|
'PhanTypeMismatchProperty', // 13 occurence(s)
|
||||||
|
'PhanUnreferencedUseNormal', // 10 occurence(s) TODO: Fix
|
||||||
|
'PhanTypeMismatchDeclaredReturn', // 8 occurence(s)
|
||||||
|
'PhanUndeclaredTypeProperty', // 7 occurence(s)
|
||||||
|
'PhanTypeMismatchReturn', // 6 occurence(s)
|
||||||
|
'PhanUndeclaredVariable', // 4 occurence(s)
|
||||||
|
'PhanUndeclaredTypeReturnType', // 4 occurence(s)
|
||||||
|
'PhanParamTooMany', // 3 occurence(s)
|
||||||
|
'PhanUndeclaredTypeParameter', // 2 occurence(s)
|
||||||
|
'PhanUndeclaredClassProperty', // 2 occurence(s)
|
||||||
|
'PhanTypeSuspiciousStringExpression', // 2 occurence(s)
|
||||||
|
'PhanTypeMismatchArgumentInternal', // 2 occurence(s)
|
||||||
|
'PhanUnextractableAnnotationElementName', // 1 occurence(s)
|
||||||
|
'PhanUndeclaredClassMethod', // 1 occurence(s)
|
||||||
|
'PhanUndeclaredClassInstanceof', // 1 occurence(s)
|
||||||
|
'PhanTypeSuspiciousNonTraversableForeach', // 1 occurence(s)
|
||||||
|
'PhanTypeMismatchDimAssignment', // 1 occurence(s)
|
||||||
|
'PhanTypeMismatchDeclaredParam', // 1 occurence(s)
|
||||||
|
'PhanTypeInvalidDimOffset', // 1 occurence(s)
|
||||||
|
],
|
||||||
|
|
||||||
|
// A regular expression to match files to be excluded
|
||||||
|
// from parsing and analysis and will not be read at all.
|
||||||
|
//
|
||||||
|
// This is useful for excluding groups of test or example
|
||||||
|
// directories/files, unanalyzable files, or files that
|
||||||
|
// can't be removed for whatever reason.
|
||||||
|
// (e.g. '@Test\.php$@', or '@vendor/.*/(tests|Tests)/@')
|
||||||
|
'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@',
|
||||||
|
|
||||||
|
// A file list that defines files that will be excluded
|
||||||
|
// from parsing and analysis and will not be read at all.
|
||||||
|
//
|
||||||
|
// This is useful for excluding hopelessly unanalyzable
|
||||||
|
// files that can't be removed for whatever reason.
|
||||||
|
'exclude_file_list' => [],
|
||||||
|
|
||||||
|
// A directory list that defines files that will be excluded
|
||||||
|
// from static analysis, but whose class and method
|
||||||
|
// information should be included.
|
||||||
|
//
|
||||||
|
// Generally, you'll want to include the directories for
|
||||||
|
// third-party code (such as "vendor/") in this list.
|
||||||
|
//
|
||||||
|
// n.b.: If you'd like to parse but not analyze 3rd
|
||||||
|
// party code, directories containing that code
|
||||||
|
// should be added to the `directory_list` as
|
||||||
|
// to `excluce_analysis_directory_list`.
|
||||||
|
'exclude_analysis_directory_list' => [
|
||||||
|
'vendor/',
|
||||||
|
],
|
||||||
|
|
||||||
|
// The number of processes to fork off during the analysis
|
||||||
|
// phase.
|
||||||
|
'processes' => 1,
|
||||||
|
|
||||||
|
// List of case-insensitive file extensions supported by Phan.
|
||||||
|
// (e.g. php, html, htm)
|
||||||
|
'analyzed_file_extensions' => [
|
||||||
|
'php',
|
||||||
|
],
|
||||||
|
|
||||||
|
// You can put paths to stubs of internal extensions in this config option.
|
||||||
|
// If the corresponding extension is **not** loaded, then phan will use the stubs instead.
|
||||||
|
// Phan will continue using its detailed type annotations,
|
||||||
|
// but load the constants, classes, functions, and classes (and their Reflection types)
|
||||||
|
// from these stub files (doubling as valid php files).
|
||||||
|
// Use a different extension from php to avoid accidentally loading these.
|
||||||
|
// The 'tools/make_stubs' script can be used to generate your own stubs (compatible with php 7.0+ right now)
|
||||||
|
'autoload_internal_extension_signatures' => [],
|
||||||
|
|
||||||
|
// A list of plugin files to execute
|
||||||
|
// Plugins which are bundled with Phan can be added here by providing their name (e.g. 'AlwaysReturnPlugin')
|
||||||
|
// Alternately, you can pass in the full path to a PHP file with the plugin's implementation (e.g. 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php')
|
||||||
|
'plugins' => [
|
||||||
|
'AlwaysReturnPlugin',
|
||||||
|
'DollarDollarPlugin',
|
||||||
|
'DuplicateArrayKeyPlugin',
|
||||||
|
'PregRegexCheckerPlugin',
|
||||||
|
'PrintfCheckerPlugin',
|
||||||
|
'UnreachableCodePlugin',
|
||||||
|
],
|
||||||
|
|
||||||
|
// A list of directories that should be parsed for class and
|
||||||
|
// method information. After excluding the directories
|
||||||
|
// defined in exclude_analysis_directory_list, the remaining
|
||||||
|
// files will be statically analyzed for errors.
|
||||||
|
//
|
||||||
|
// Thus, both first-party and third-party code being used by
|
||||||
|
// your application should be included in this list.
|
||||||
|
'directory_list' => [
|
||||||
|
'src',
|
||||||
|
'vendor/composer/xdebug-handler/src',
|
||||||
|
'vendor/felixfbecker/advanced-json-rpc/lib',
|
||||||
|
'vendor/felixfbecker/language-server-protocol/src/',
|
||||||
|
'vendor/microsoft/tolerant-php-parser/src',
|
||||||
|
'vendor/netresearch/jsonmapper/src',
|
||||||
|
'vendor/phpdocumentor/reflection-common/src',
|
||||||
|
'vendor/phpdocumentor/reflection-docblock/src',
|
||||||
|
'vendor/phpdocumentor/type-resolver/src',
|
||||||
|
'vendor/phpunit/phpunit/src',
|
||||||
|
'vendor/psr/log/Psr',
|
||||||
|
'vendor/sabre/event/lib',
|
||||||
|
'vendor/sabre/uri/lib',
|
||||||
|
'vendor/webmozart/glob/src',
|
||||||
|
'vendor/webmozart/path-util/src',
|
||||||
|
],
|
||||||
|
|
||||||
|
// A list of individual files to include in analysis
|
||||||
|
// with a path relative to the root directory of the
|
||||||
|
// project
|
||||||
|
'file_list' => [
|
||||||
|
'bin/php-language-server.php',
|
||||||
|
],
|
||||||
|
];
|
|
@ -16,8 +16,11 @@ cache:
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- composer install --prefer-dist --no-interaction
|
- composer install --prefer-dist --no-interaction
|
||||||
|
- pecl install ast-1.0.0
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- vendor/bin/phpcs -n
|
- vendor/bin/phpcs -n
|
||||||
|
- vendor/bin/phan
|
||||||
- vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always
|
- vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,17 +1,19 @@
|
||||||
|
|
||||||
# Running this container will start a language server that listens for TCP connections on port 2088
|
# Running this container will start a language server that listens for TCP connections on port 2088
|
||||||
# Every connection will be run in a forked child process
|
# Every connection will be run in a forked child process
|
||||||
|
|
||||||
# Please note that before building the image, you have to install dependencies with `composer install`
|
FROM composer AS builder
|
||||||
|
|
||||||
|
COPY ./ /app
|
||||||
|
RUN composer install
|
||||||
|
|
||||||
FROM php:7-cli
|
FROM php:7-cli
|
||||||
MAINTAINER Felix Becker <felix.b@outlook.com>
|
LABEL maintainer="Felix Becker <felix.b@outlook.com>"
|
||||||
|
|
||||||
RUN docker-php-ext-configure pcntl --enable-pcntl
|
RUN docker-php-ext-configure pcntl --enable-pcntl
|
||||||
RUN docker-php-ext-install pcntl
|
RUN docker-php-ext-install pcntl
|
||||||
COPY ./php.ini /usr/local/etc/php/conf.d/
|
COPY ./php.ini /usr/local/etc/php/conf.d/
|
||||||
|
|
||||||
COPY ./ /srv/phpls
|
COPY --from=builder /app /srv/phpls
|
||||||
|
|
||||||
WORKDIR /srv/phpls
|
WORKDIR /srv/phpls
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "felixfbecker/language-server",
|
"name": "icedream/language-server",
|
||||||
"description": "PHP Implementation of the Visual Studio Code Language Server Protocol",
|
"description": "PHP Implementation of the Visual Studio Code Language Server Protocol",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
@ -37,8 +37,12 @@
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^6.3",
|
"phpunit/phpunit": "^6.3",
|
||||||
|
"phan/phan": "1.1.4",
|
||||||
"squizlabs/php_codesniffer": "^3.1"
|
"squizlabs/php_codesniffer": "^3.1"
|
||||||
},
|
},
|
||||||
|
"replace": {
|
||||||
|
"felixfbecker/language-server": "self.version"
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"LanguageServer\\": "src/"
|
"LanguageServer\\": "src/"
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"prepare": [
|
"prepare": [
|
||||||
{
|
{
|
||||||
"path": "@semantic-release/exec",
|
"path": "@semantic-release/exec",
|
||||||
"cmd": "composer install --prefer-dist --no-interaction && docker build -t felixfbecker/php-language-server ."
|
"cmd": "docker build -t felixfbecker/php-language-server ."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"publish": [
|
"publish": [
|
||||||
|
|
|
@ -11,6 +11,11 @@ use Sabre\Event\Promise;
|
||||||
*/
|
*/
|
||||||
class ClientCache implements Cache
|
class ClientCache implements Cache
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var LanguageClient
|
||||||
|
*/
|
||||||
|
public $client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param LanguageClient $client
|
* @param LanguageClient $client
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types = 1);
|
||||||
namespace LanguageServer\Client;
|
namespace LanguageServer\Client;
|
||||||
|
|
||||||
use LanguageServer\ClientHandler;
|
use LanguageServer\ClientHandler;
|
||||||
use LanguageServerProtocol\{TextDocumentItem, TextDocumentIdentifier};
|
use LanguageServerProtocol\{Diagnostic, TextDocumentItem, TextDocumentIdentifier};
|
||||||
use Sabre\Event\Promise;
|
use Sabre\Event\Promise;
|
||||||
use JsonMapper;
|
use JsonMapper;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types = 1);
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
use LanguageServer\Index\ReadableIndex;
|
use LanguageServer\Index\ReadableIndex;
|
||||||
use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver};
|
use phpDocumentor\Reflection\{Types, Type, TypeResolver};
|
||||||
use LanguageServerProtocol\SymbolInformation;
|
use LanguageServerProtocol\SymbolInformation;
|
||||||
use Generator;
|
use Generator;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ class Definition
|
||||||
* Can also be a compound type.
|
* 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
|
* @var Type|null
|
||||||
*/
|
*/
|
||||||
public $type;
|
public $type;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ declare(strict_types = 1);
|
||||||
|
|
||||||
namespace LanguageServer\FilesFinder;
|
namespace LanguageServer\FilesFinder;
|
||||||
|
|
||||||
use Webmozart\Glob\Iterator\GlobIterator;
|
|
||||||
use Sabre\Event\Promise;
|
use Sabre\Event\Promise;
|
||||||
use function Sabre\Event\coroutine;
|
use function Sabre\Event\coroutine;
|
||||||
use function LanguageServer\{pathToUri, timeout};
|
use function LanguageServer\{pathToUri, timeout};
|
||||||
|
@ -23,7 +22,7 @@ class FileSystemFilesFinder implements FilesFinder
|
||||||
$uris = [];
|
$uris = [];
|
||||||
foreach (new GlobIterator($glob) as $path) {
|
foreach (new GlobIterator($glob) as $path) {
|
||||||
// Exclude any directories that also match the glob pattern
|
// Exclude any directories that also match the glob pattern
|
||||||
if (!is_dir($path)) {
|
if (!is_dir($path) || !is_readable($path)) {
|
||||||
$uris[] = pathToUri($path);
|
$uris[] = pathToUri($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace LanguageServer\FilesFinder;
|
||||||
|
|
||||||
|
use ArrayIterator;
|
||||||
|
use EmptyIterator;
|
||||||
|
use IteratorIterator;
|
||||||
|
use RecursiveIteratorIterator;
|
||||||
|
use Webmozart\Glob\Glob;
|
||||||
|
use Webmozart\Glob\Iterator\GlobFilterIterator;
|
||||||
|
use Webmozart\Glob\Iterator\RecursiveDirectoryIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns filesystem paths matching a glob.
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @see Glob
|
||||||
|
*/
|
||||||
|
class GlobIterator extends IteratorIterator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new iterator.
|
||||||
|
*
|
||||||
|
* @param string $glob The glob pattern.
|
||||||
|
* @param int $flags A bitwise combination of the flag constants in
|
||||||
|
* {@link Glob}.
|
||||||
|
*/
|
||||||
|
public function __construct($glob, $flags = 0)
|
||||||
|
{
|
||||||
|
$basePath = Glob::getBasePath($glob, $flags);
|
||||||
|
if (!Glob::isDynamic($glob) && file_exists($glob)) {
|
||||||
|
// If the glob is a file path, return that path
|
||||||
|
$innerIterator = new ArrayIterator(array($glob));
|
||||||
|
} elseif (is_dir($basePath)) {
|
||||||
|
// Use the system's much more efficient glob() function where we can
|
||||||
|
if (
|
||||||
|
// glob() does not support /**/
|
||||||
|
false === strpos($glob, '/**/') &&
|
||||||
|
// glob() does not support stream wrappers
|
||||||
|
false === strpos($glob, '://') &&
|
||||||
|
// glob() does not support [^...] on Windows
|
||||||
|
('\\' !== DIRECTORY_SEPARATOR || false === strpos($glob, '[^'))
|
||||||
|
) {
|
||||||
|
$results = glob($glob, GLOB_BRACE);
|
||||||
|
|
||||||
|
// $results may be empty or false if $glob is invalid
|
||||||
|
if (empty($results)) {
|
||||||
|
// Parse glob and provoke errors if invalid
|
||||||
|
Glob::toRegEx($glob);
|
||||||
|
|
||||||
|
// Otherwise return empty result set
|
||||||
|
$innerIterator = new EmptyIterator();
|
||||||
|
} else {
|
||||||
|
$innerIterator = new ArrayIterator($results);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise scan the glob's base directory for matches
|
||||||
|
$innerIterator = new GlobFilterIterator(
|
||||||
|
$glob,
|
||||||
|
new RecursiveIteratorIterator(
|
||||||
|
new RecursiveDirectoryIterator(
|
||||||
|
$basePath,
|
||||||
|
RecursiveDirectoryIterator::CURRENT_AS_PATHNAME,
|
||||||
|
RecursiveDirectoryIterator::SKIP_DOTS
|
||||||
|
),
|
||||||
|
RecursiveIteratorIterator::SELF_FIRST,
|
||||||
|
RecursiveIteratorIterator::CATCH_GET_CHILD
|
||||||
|
),
|
||||||
|
GlobFilterIterator::FILTER_VALUE,
|
||||||
|
$flags
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the glob's base directory does not exist, return nothing
|
||||||
|
$innerIterator = new EmptyIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct($innerIterator);
|
||||||
|
}
|
||||||
|
}
|
|
@ -274,7 +274,6 @@ class Index implements ReadableIndex, \Serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $serialized
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function serialize()
|
public function serialize()
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Indexer
|
||||||
/**
|
/**
|
||||||
* @var int The prefix for every cache item
|
* @var int The prefix for every cache item
|
||||||
*/
|
*/
|
||||||
const CACHE_VERSION = 2;
|
const CACHE_VERSION = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var FilesFinder
|
* @var FilesFinder
|
||||||
|
|
|
@ -167,7 +167,7 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
*/
|
*/
|
||||||
public function initialize(ClientCapabilities $capabilities, string $rootPath = null, int $processId = null, string $rootUri = null): Promise
|
public function initialize(ClientCapabilities $capabilities, string $rootPath = null, int $processId = null, string $rootUri = null): Promise
|
||||||
{
|
{
|
||||||
if ($rootPath === null) {
|
if ($rootPath === null && $rootUri !== null) {
|
||||||
$rootPath = uriToPath($rootUri);
|
$rootPath = uriToPath($rootUri);
|
||||||
}
|
}
|
||||||
return coroutine(function () use ($capabilities, $rootPath, $processId) {
|
return coroutine(function () use ($capabilities, $rootPath, $processId) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ class PhpDocument
|
||||||
/**
|
/**
|
||||||
* Map from fully qualified name (FQN) to Node
|
* Map from fully qualified name (FQN) to Node
|
||||||
*
|
*
|
||||||
* @var Node
|
* @var Node[]
|
||||||
*/
|
*/
|
||||||
private $definitionNodes;
|
private $definitionNodes;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ namespace LanguageServer;
|
||||||
use LanguageServer\Index\ReadableIndex;
|
use LanguageServer\Index\ReadableIndex;
|
||||||
use LanguageServerProtocol\{
|
use LanguageServerProtocol\{
|
||||||
Position,
|
Position,
|
||||||
SignatureHelp,
|
SignatureHelp
|
||||||
ParameterInformation
|
|
||||||
};
|
};
|
||||||
use Microsoft\PhpParser\Node;
|
use Microsoft\PhpParser\Node;
|
||||||
use Sabre\Event\Promise;
|
use Sabre\Event\Promise;
|
||||||
|
|
Loading…
Reference in New Issue