Giter Site home page Giter Site logo

felixfbecker / php-language-server Goto Github PK

View Code? Open in Web Editor NEW
1.1K 30.0 185.0 1.97 MB

PHP Implementation of the VS Code Language Server Protocol ๐Ÿ†šโ†”๐Ÿ–ฅ

License: ISC License

PHP 99.87% Dockerfile 0.13% Hack 0.01%
language-server php symbols intellisense autocomplete ide language-server-protocol static-analysis code-analysis intelligence

php-language-server's Introduction

PHP Language Server

Version Linux Build Status Windows Build status Coverage semantic-release Minimum PHP Version License Gitter

A pure PHP implementation of the open Language Server Protocol. Provides static code analysis for PHP for any IDE.

Uses the great Tolerant PHP Parser, phpDocumentor's DocBlock reflection and an event loop for concurrency.

Table of Contents

Features

Completion search demo

Signature help demo

Go To Definition demo

Find References demo

Hover class demo

Hover parameter demo

A hover request returns a declaration line (marked with language php) and the summary of the docblock. For Parameters, it will return the @param tag.

Document Symbols demo

Workspace Symbols demo

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.

Error reporting through Publish Diagnostics

Error reporting demo

PHP parse errors are reported as errors, parse errors of docblocks are reported as warnings. Errors/Warnings from the vendor directory are ignored.

Stubs for PHP built-ins

Completion, type resolval etc. will use the standard PHP library and common extensions.

What is considered a definition?

Globally searchable definitions are:

  • classes
  • interfaces
  • traits
  • properties
  • methods
  • class constants
  • constants with const keyword

Definitions resolved just-in-time when needed:

  • variable assignments
  • parameters
  • closure use statements

Not supported yet:

  • constants with define()

Namespaces are not considerd a declaration by design because they only make up a part of the fully qualified name and don't map to one unique declaration.

What is considered a reference?

Definitions/references/hover currently work for

  • class instantiations
  • static method calls
  • class constant access
  • static property access
  • parameter type hints
  • return type hints
  • method calls, if the variable was assigned to a new object in the same scope
  • property access, if the variable was assigned to a new object in the same scope
  • variables
  • parameters
  • imported closure variables (use)
  • use statements for classes, constants and functions
  • class-like after implements/extends
  • function calls
  • constant access
  • instanceof checks
  • Reassigned variables
  • Nested access/calls on return values, properties, array access

Protocol Extensions

This language server implements the files protocol extension. If the client expresses support through ClientCapabilities.xfilesProvider and ClientCapabilities.xcontentProvider, the server will request files in the workspace and file contents through requests from the client and never access the file system directly. This allows the server to operate in an isolated environment like a container, on a remote workspace or any a different protocol than file://.

Performance

Upon initialization, the server will recursively scan the project directory for PHP files, parse them and add all definitions and references to an in-memory index. The time this takes depends on the project size. At the time of writing, this project contains 78 files + 1560 files in dependencies which take 97s to parse and consume 76 MB on a Surface Pro 3. The language server is fully operational while indexing and can respond to requests with the definitions already indexed. Follow-up requests will be almost instant because the index is kept in memory.

Having XDebug enabled heavily impacts performance and can even crash the server if the max_nesting_level setting is too low.

Versioning

This project follows semver for the protocol communication and command line parameters, e.g. a major version increase of the LSP will result in a major version increase of the PHP LS. New features like request implementations will result in a new minor version. Everything else will be a patch release. All classes are considered internal and are not subject to semver.

Installation

The recommended installation method is through Composer. Simply run

composer require felixfbecker/language-server

and you will get the latest stable release and all dependencies.
Running composer update will update the server to the latest non-breaking version.

After installing the language server and its dependencies, you must parse the stubs for standard PHP symbols and save the index for fast initialization.

 composer run-script --working-dir=vendor/felixfbecker/language-server parse-stubs

Running

Start the language server with

php vendor/felixfbecker/language-server/bin/php-language-server.php

Command line arguments

--tcp=host:port (optional)

Causes the server to use a tcp connection for communicating with the language client instead of using STDIN/STDOUT. The server will try to connect to the specified address. Strongly recommended on Windows because of blocking STDIO.

Example:

php bin/php-language-server.php --tcp=127.0.0.1:12345

--tcp-server=host:port (optional)

Causes the server to use a tcp connection for communicating with the language client instead of using STDIN/STDOUT. The server will listen on the given address for a connection. If PCNTL is available, will fork a child process for every connection. If not, will only accept one connection and the connection cannot be reestablished once closed, spawn a new process instead.

Example:

php bin/php-language-server.php --tcp-server=127.0.0.1:12345

--memory-limit=integer (optional)

Sets memory limit for language server. Equivalent to memory-limit php.ini directive. The default is 4GB (which is way more than needed).

Example:

php bin/php-language-server.php --memory-limit=256M

Used by

Contributing

You need at least PHP 7.0 and Composer installed. Clone the repository and run

composer install

to install dependencies.

Run the tests with

composer test

Lint with

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

PHPLS_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).

php-language-server's People

Contributors

cweagans avatar d0x2f avatar dantleech avatar declspeck avatar exploide avatar felixfbecker avatar haringsrob avatar jens1o avatar jjk96 avatar jkblume avatar john-nguyen09 avatar kaloyan-raev avatar lgabeskiria avatar maartenstaa avatar michaelbelgium avatar mousetraps avatar muglug avatar nateeag avatar netjan avatar phil-nelson avatar roblourens avatar roxma avatar soren121 avatar staabm avatar sunverwerth avatar talv avatar tysonandre avatar vakata avatar vinkla avatar wulftone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-language-server's Issues

Catch parser errors for indexing

Indexing is done async so it crashes the process if parsing throws an exception (instead of returning an error response). We need to catch the exception and log it through logMessage instead.

Add command line parameter for memory limit

One of the conclusions from #57 is that it would be nice to add command line param to configure PHP memory limit. I think it shouldn't be a problem to add parameter like --memory-limit and use it with ini_set in php-language-server.php. Similar to existing --tcp parameter.

Completion

Should suggest:

  • global symbols (classes, interfaces, traits, functions)
  • local variables
  • local parameters
  • variables imported with use
  • not the variables outside of the function scope
  • properties and methods of classes if the cursor is behind a ->
    • it should resolve the variable to a class type and get the members
  • namespaces and classes when the cursor is inside a use statement
  • built-in PHP functions, classes and globals
    • how to get them? Is there a machine-parseble version of the docs?

It should:

  • follow PSR autoloading rules defined in composer.json
  • parse docblocks for type annotations of parameters and properties

Improvements for file indexing

I would like to propose two changes in actual indexing implementation:

  • keep source file content only for opened files. Content should be assigned after opening file and removed on close. This should give substantial memory saving.
  • Similar to previous, send publishDiagnostics notification also only for opened file. This is just minor optimization but sending lots of events that will be not used in client is just wasting resources.

If there will be no objections I will prepare PR.

Implemented methods

  • intialize
  • documentSymbols needs tests
  • formatDocument easy
  • provideCompletion epic

Debug

Is it possible to debug language server with vscode?

Global symbol search

First off, great work! I am using your extension during daily development and it works very well.

A feature still missing is global symbol search. (ctrll+p, #)
I started working on a feature branch and it already does the job.

Parsing the whole php-language-server project takes about 10 seconds on my machine.
The php-cli process takes up about 180MB of ram with all symbol information parsed.

Changes made:

  • Added support for client:window/* commands
  • Added support for server:workspace/* commands
  • Refactored symbol database into own set of classes. (Was in Server/TextDocument before)
  • Disabled memory limit
  • ProtocolStreamReader was blocking the event loop, made non-blocking
  • Find all .php files on startup and start parsing one at a time with Loop/nextTick

To do:

  • Fix old tests
  • Add new tests
  • Reduce memory usage. Most of it is the AST, maybe we can throw it away after parsing,
  • Figure out solution for blocking STDIN. The current one is a hack. This is a windows limitation, see https://bugs.php.net/bug.php?id=34972

Please let me know what you think about it and if you want any changes made. I can then open a pull request.

Resolve types recursively

From #49:

Go To Definition currently works for

  • class instantiations
  • static method calls
  • class constant access
  • static property access
  • parameter type hints
  • return type hints
  • method calls, if the variable was assigned to a new object in the same scope
  • property access, if the variable was assigned to a new object in the same scope
  • variables
  • parameters
  • imported closure variables (use)
  • use statements that import a class-like
  • class-like after implements/extends
  • function calls
  • constant access

What does not work yet:

$x = new Whatever();
$y = $x;
$y->myMethod(); // cannot get definition for myMethod

$x = new Whatever();
$x->property->myMethod(); // cannot get definition for myMethod
$x->myMethod()->anotherMethod(); // cannot get definition for anotherMethod

$this->myMethod(); // cannot get definition for myMethod, $this is not resolved to the class

trait MyTrait {}
class MyClass {
  use MyTrait; // cannot get definition for MyTrait
}
  • Method/property access on a return value needs to be resolved recursively
  • Variable reassignments need to be resolved recursively
  • DocBlocks need to be parsed

Use error handler

I would like to convert all errors into ErrorExceptions and ensure all errors are logged to STDERR.

SymbolInformation ranges are not accurate

It looks like the end position of the ranges is shifted one character left than desired.

The start position for class members does not cover the access modifier.

The problem is not visible in VS Code, because it highlights the entire lines covered by the range.

But it is clearly visible in Eclipse Che which highlight the exact range. See the animation below.

che-php-symbols

Indexing became extremely slow

After recent changes indexing performance decreased and memory consumption increased extremely. After indexing 3k-4k files slow down is more visible.

Result for magento (24k files) project:
All PHP files parsed in 2904 seconds. 6123 MiB allocated.
Previous those values were about 100s and 600MiB.

Connection to server got closed. Server will not be restarted.

Hi there,

I have upgraded my VS CODE to v1.5.3 and soon later I realized that the PHP language server is not working anymore. I saw these messages from the output window:

[Info - 11:53:23 AM] Connection to server got closed. Server will restart.
[Info - 11:53:29 AM] Connection to server got closed. Server will restart.
[Info - 11:53:35 AM] Connection to server got closed. Server will restart.
[Info - 11:53:41 AM] Connection to server got closed. Server will restart.
[Error - 11:53:47 AM] Connection to server got closed. Server will not be restarted.

I'm no longer able to search for symbol using '@' command in the Command Palette.

I then tried the tests command, and I got

vendor/bin/phpunit --bootstrap vendor/autoload.php tests
PHPUnit 5.6.1 by Sebastian Bergmann and contributors.

................ 16 / 16 (100%)

Time: 1.57 seconds, Memory: 14.00MB

OK (16 tests, 28 assertions)

Strange enough, could anyone helps? Thanks.

Indexing finished with fatal error

I was trying to open magento2 in VSCode. After longer time output was filled with fatal error:

PHP Fatal error:  Maximum function nesting level of '256' reached, aborting! in /home/wywrzal/git/vscode-php-intellisense/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php on line 75
PHP Stack trace:
PHP   1. {main}() /home/wywrzal/git/vscode-php-intellisense/vendor/felixfbecker/language-server/bin/php-language-server.php:0
PHP   2. Sabre\Event\Loop\run() /home/wywrzal/git/vscode-php-intellisense/vendor/felixfbecker/language-server/bin/php-language-server.php:33
PHP   3. Sabre\Event\Loop\Loop->run() /home/wywrzal/git/vscode-php-intellisense/vendor/sabre/event/lib/Loop/functions.php:122
PHP   4. Sabre\Event\Loop\Loop->tick($block = *uninitialized*) /home/wywrzal/git/vscode-php-intellisense/vendor/sabre/event/lib/Loop/Loop.php:194
PHP   5. Sabre\Event\Loop\Loop->runTimers() /home/wywrzal/git/vscode-php-intellisense/vendor/sabre/event/lib/Loop/Loop.php:216
PHP   6. LanguageServer\LanguageServer->LanguageServer\{closure}() /home/wywrzal/git/vscode-php-intellisense/vendor/sabre/event/lib/Loop/Loop.php:280
PHP   7. LanguageServer\PhpDocument->updateContent($content = *uninitialized*) /home/wywrzal/git/php-language-server/src/LanguageServer.php:153
PHP   8. LanguageServer\PhpDocument->parse() /home/wywrzal/git/php-language-server/src/PhpDocument.php:61
PHP   9. PhpParser\NodeTraverser->traverse($nodes = *uninitialized*) /home/wywrzal/git/php-language-server/src/PhpDocument.php:106
PHP  10. PhpParser\NodeTraverser->traverseArray($nodes = *uninitialized*) /home/wywrzal/git/vscode-php-intellisense/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:64
PHP  11. PhpParser\NodeTraverser->traverseNode($node = *uninitialized*) /home/wywrzal/git/vscode-php-intellisense/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:135
...

Exceptions vs returning null

We currently return null or empty arrays in many places if an action could not be performed. Examples:

  • Definition for a position that could not be mapped to a Node
  • Definition for a node we couldn't find the definition for
  • Any request for a document that is not parsed yet / invalid ($stmts is not available)

This results in a lot of repeated if checks, not covered branches, possible NullPointers, and potential violation of the protocol (when null is not allowed as a return value for result)

An Exception would bubble and get turned into an ErrorResponse, which probably results in an error message in the editor. I would like to find out how other language servers do this. We could still catch exceptions and return null in the method handler.

Opinions?

Undefined index error

If I run the language server with PHP installation that has E_ALL error reporting, it fails with the following error:

PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\ContextErrorException: Notice: Undefined index: tcp in /home/kraev/git/php-language-server/bin/php-language-server.php:22
Stack trace:
#0 /home/kraev/git/php-language-server/bin/php-language-server.php(22): Symfony\Component\Debug\ErrorHandler->handleError(8, 'Undefined index...', '/home/kraev/git...', 22, Array)
#1 {main}
  thrown in /home/kraev/git/php-language-server/bin/php-language-server.php on line 22

Searching for workspace symbols is super slow

This is when calling Ctrl+T (Show All Symbols) in VS Code.

I remember it used to return a result in a couple of seconds, but now it keeps searching for a minutes and goes on. I see high CPU usage during this time. Eventually, it may finish, but I haven't got the patient to wait for it.

Add license file

Please, add an explicit LICENSE file to the repo that states the license of this project.

I see composer.json has a "license": "ISC" declaration, but please confirm it in a LICENSE file too.

Cache indexing result

Currently the project index is rebuilt from scratch every time the workspace is opened.
This can take a long time during which features might not work properly.

We need a file system cache for the results of the indexing process.

Test is failing on my machine

It looks that new tests are 'order sensitive'. I'm using Fedora 24 (64bit).

PHPUnit output:

There was 1 failure:

1) LanguageServer\Tests\Utils\RecursiveFileSearchTest::testFilesAreFound
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => '/home/wywrzal/git/php-language-server/fixtures/recursive/a.txt'
+    0 => '/home/wywrzal/git/php-language-server/fixtures/recursive/search/here/c.txt'
     1 => '/home/wywrzal/git/php-languag.../b.txt'
-    2 => '/home/wywrzal/git/php-language-server/fixtures/recursive/search/here/c.txt'
+    2 => '/home/wywrzal/git/php-language-server/fixtures/recursive/a.txt'
 )

/home/wywrzal/git/php-language-server/tests/Utils/RecursiveFileSearchTest.php:18

phpconfig.json

We need to create phpconfig.json file with some configurable options (php target version, autloload.php path, etc...) per project.

Add linting

I don't know what is the best linter for PHP and how to configure it?
Needs to be integrated in CI

PHP 5 runtime support

We would lose the following features:

  • scalar type hinting
  • return type annotations
  • group use statements
  • anonymous classes
  • ?? operator

Is there anything like BabelJS for PHP that transpiles it?

Add size limit for processed PHP file

Very large files can consume disproportionate huge amount of memory. Composer project contains file LargeClass.php and this one file is bumping memory consumption from 18MiB to 542MiB. Such large files are not real life production code (mostly fixtures) and does not make sense to process them. I believe that limit around 0.5MB will be good enough.

Example of such file:
https://github.com/composer/composer/blob/master/tests/Composer/Test/Autoload/Fixtures/classmap/LargeClass.php

How to make the VSCode extension work

Hi,

I just downloaded the extension for VSCode, but it does not seem to work. For example, i cant find symbols (it says "unfortunately we have no symbol information for the file") or format code (the option doesn't appear on the context menu).

I'm using Linux Mint 18, the latest version of VSCode, and installed PHP 7 using sudo apt-get install php.

Is there something else i'm supposed to do?

Thank you.

Updated document isn't removing not existing FQN

Simple example:

<?php
namespace Test2;

function fooFunction(){   
}

This file after processing (indexing) will add FQN in definitions 'Test2\fooFunction()'. When file will be opened in editor and namespace 'Test2' will be removed then new FQN will be added 'fooFunction()' but first one is not removed. Now we have two elements in definitions array. I'm not sure maybe similar problem is affecting references.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.