shawncplus / phpcomplete.vim

Improved PHP omnicompletion
http://www.vim.org/scripts/script.php?script_id=3171
595 stars 110 forks source link

PHP 5.3 namespace support #4

Closed lauris closed 10 years ago

lauris commented 12 years ago

It seems that it does not support PHP namespaces.

shawncplus commented 12 years ago

Truth. This is going to take some work...

lauris commented 12 years ago

Quick fix would be to allow \ in class name. However this does not solve cases when a class is called in current namespace, e.g. namespace app; $class = new controller();

shawncplus commented 12 years ago

Yeah, it also doesn't solve the situation of raw functions inside a namespace. Namespaces are a pretty big thing to tackle for completion because it's essentially an entirely new container construct that needs to be taken into account to search.

qstrahl commented 11 years ago

It's pretty necessary to have namespace support; it's good convention, and quickly becoming standard among most big frameworks.

stephpy commented 11 years ago

:+1:

qstrahl commented 11 years ago

@shawncplus I would like to tackle this problem (as well as detecting inheritance) but I don't have any experience; I am planning to just take the plunge and see what I can make of what is already there but if you have the time and patience to offer me some useful information on the subject, I would be greatly appreciative.

My understanding of ctags is that there is no support for PHP namespaces; does that make all this an impossibility (until I write support for it into ctags =P)?

shawncplus commented 11 years ago

I'm unfamiliar with the namespace support in ctags, if it doesn't have support then yes, it's impossible unless someone updates ctags or write another script that does namespace parsing and writes to a file in the same fiel format as ctags

qstrahl commented 11 years ago

I've confirmed that ctags lacks support for namespaces in PHP. I'll be back after I fix ctags. Wish me luck. =P

markwu commented 11 years ago

@qstrahl Did you try the patched ctags? Does it generate the correct namespace tags for ctags? I try it with my project, it seems generate namespace information by default (it seems correct, but don't know format is right or not):

Command laravel/vendor/Symfony/Component/Console/Command/Command.php    /^class Command$/;" c   namespace:Symfony\Component\Console\Command
CommandTester   laravel/vendor/Symfony/Component/Console/Tester/CommandTester.php   /^class CommandTester$/;"   c   namespace:Symfony\Component\Console\Tester

@complex857 Is this enough for phpcomplete.vim to implement class namespace? If not, maybe we can discuss with @techlivezheng to implement namespace in phpctags, too.

I compare patched ctags and phpctags, it seems phpctags generate more detail and correct tags information. The only one problem is phpctags is really slow.

complex857 commented 11 years ago

I've compiled a new ctags with the patch, running it against a vanilla Symfony with

time ~/ctags-trunk/ctags -R --fields=+aimsS ~/Symfony

took only 0m1.412s in my system with warm disk caches (this as thinkpad x200 from 2009, with it's original samsung spinning disk). Generates lines like this:

For classes:

Firewall    vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall.php /^class Firewall implements EventSubscriberInterface$/;"    c   namespace:Symfony\Component\Security\Http   inherits:EventSubscriberInterface

For methods:

abs vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php /^    public function abs($x)$/;"   f   class:Doctrine\ORM\Query::Expr  access:public   signature:($x)

For constants:

CASE_FIRST  vendor/symfony/symfony/src/Symfony/Component/Locale/Stub/StubCollator.php   /^    const CASE_FIRST = 2;$/;" d   class:Symfony\Component\Locale\Stub::StubCollator

For namespaces:

Psr\Log vendor/psr/log/Psr/Log/LoggerAwareTrait.php /^namespace Psr\\Log;$/;"   n

For attributes:

addedColumns    vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php /^    public $addedColumns;$/;" v   class:Doctrine\DBAL\Schema::TableDiff   access:public

These look absolutely fantastic, and should be much enough for many namespace related scenarios.

The fact that there are n kind for namespaces makes straightforward to implement completion for lines like namespace Psr\... or use \Psr.... To make classname contexts like $foo = new ... or Foo extends ... or just static invocations (when you start to type the class name and we can't tell if it's going to be a function or constant or anything else without a $) will have to have some parsing in the current file to get the active namespace (the first line with namesapce ... or the imported namespaces (lines like use \Foo or use \Foo as Bar). As @shawncplus wrote a year ago, it's going to take some work.

qstrahl commented 11 years ago

Yeah, the new patched PHP module for ctags makes this problem solvable. There's a lot to be done with regard to namespaces for phpcomplete, but I'm pretty sure I can manage it, so if somebody doesn't beat me to it, I'll take a crack at it soon.

markwu commented 11 years ago

I am playing with phpctags, too. I already have namespace in my local branch.

markwu commented 11 years ago

@qstrahl I just add namespace & inherits support(extends and implements) for phpctags and wait for merge. If you want to play with it, you can try my repository https://github.com/markwu/phpctags/tree/test

I have to mention, it is really slow when compare to ctags.

qstrahl commented 11 years ago

I'll be trying to implement support with the patched ctags, since it's the official solution for Vim. Nice job on using PHP-Parser, though; it won't be easy to get accuracy like that out of a non-native solution.

markwu commented 11 years ago

That's why I follow the patched ctags's format, that can make sure the tags generate by phpctags can used in future version with more precise tags information. :)

complex857 commented 11 years ago

I've started to work on namespace support. The first commit landed in the master branch, featuring support for use ... contexts, completing namespaces and classes from tags with support for built-in class name imports. To make this feature work properly you will have to have a tags file created with a patched ctags or other tags file generator that extracts namespaces with kind:'n' and add namespace field for classes.

I've wrote an installation guide in the wiki. Please test the code and the guide and report any difficulties or anything that could be improved. If someone could volunteer to write a homebrew formula (I don't have a mac) or create binaries for windows, linux that would be nice.

qstrahl commented 11 years ago

Awesome work! This is a huge step for PHP development in Vim. =)

complex857 commented 11 years ago

Added namespace awareness when completing class names after new and extends (currently you will have to type out namespace names at this moment). I've also made GetClassLocation and GetClassContents methods aware of namespaces. When completing class names the code will use the g:phpcomplete_min_num_of_chars_for_namespace_completion option so by default you will have to type out at least one character (not required for built-in classes though).

I myself doesn't use namespaces in my day-to-day work so I encourage everyone to test the functionality and report any bugs or scenarios where the code doesn't work.

complex857 commented 11 years ago

Added namespace awareness to the general completion case (this is the case when we don't have anything object related, not specifically looking for a class or namespace name, and not a variable). The completion now will list namespaces and understand when something starts with a \. The last main missing puzzle piece is supporting the imported and possibly aliased classes, interfaces, and other namespaces (the use ... as .... lines).

complex857 commented 11 years ago

Pushed support for imported class and namespace names. These imports touch many part of the completion. Support now includes completing renamed class names in various contexts, the plugin understands renamed class names and maps them to their original when completing properties and methods.

With this patch the namespace support is pretty much complete, all the major moving parts are in place. @everyone, please try the code in real life projects and report errors and limitations.

complex857 commented 11 years ago

I've realized that GetClassName() was blissfully ignorant about the current namespace, even trough it changes every class name's meaning. Now this have been fixed.

complex857 commented 10 years ago

The namespace support is generally implemented in every part of the plugin. I'll close this issue. New issues with errors in detection or namespace handling are always welcome.