Question

I know that it is possible to use Ctrl+] to jump to a definition in Vim and this can work in conjunction whith either ctags or Cscope. I am looking for a more accurate alternative to both ctags and Cscope when working PHP. Sometimes there are multiple possible results to choose from or false positives. I only want to jump to the actual definition of whatever is under the cursor. Ideally this should work for variables, functions, constants, and classes.

I don't see why this can't be done by analyzing the files. I have finally overcome just about every other annoyance/misunderstanding I have with Vim by learning and customizing, so if I could nail this one it would be awesome.

Also, do other's agree that Cscope and ctags are not accurate enough for PHP or am I doing something wrong?

UPDATE

4 years later, I am still using Vim with PHP, and still having this problem. I have tried eclim, ctags, exubarant-ctags, universal-ctags, and cscope. I have tried passing various arguments to these programs to get them to generate better tags. The experience is very poor for all of these options.

But I understand the problem much better now. There might be nothing wrong with the tags generated by these programs. The problem seems to be that when you press Ctrl + ] in Vim or Neovim, it just looks for a tag by that name. It is not looking at the context of the file you are editing to see which tag by that name it should use. It does not even understand what language you are editing, and look for tags from code in that language.

Is there a way to make vim search through the tags file more intelligently, based on the context, and then jump to the most likely location? You know, like what would happen inside a good IDE?

Was it helpful?

Solution 6

LanguageServer-php-neovim is a Neovim plugin that is great for code definition lookups. It even works well for variables! It basically allows you to use the php-language-server plugin, that was originally designed for VS Code, inside Neovim via the LanguageClient-neovim plugin. This is all possible because php-language-server was designed to use the VS Code Language Server Protocol, which is an open protocol created by Microsoft that is now supported by many editors for many languages. Some people are interested in getting the language server protocol to be have native support in Neovim without the need for a plugin just to support that protocol. I would not be surprised if that happens soonish since there is already a work in progress pull request for it. If Neovim starts supporting this, you would only need a single plugin for the language.

If you don't want to or can't set that up to work correctly for you project, and you are determined to stick with tags, it is important to understand the limitations of tags. A tags file is typically just a file with keywords that appear in your code, and where they are in your code. It would take quite a lot of work, customization, and ingenuity to use something like that in an editor or IDE to provide either code completion or jump to features that are as smart as other tools that are designed to have more insight about your code. That being said, if you really want to stick with tags, I personally think my project-tags plugin is the best experience you will get inside Vim, as I made it to fill this need and to do what I wished the other tags plugins did.

Argh, forget it. Language servers are way too problematic. I posted my question 5 years ago, and 5 years later still no good solution. I give up! I'm giving up on PHP, and giving up on Vim and Neovim. I'm switching to Kotlin and the InjelliJ IDE. Even while I still have to use PHP for now I'm switching to PhpStorm. I will still use a Vim plugin. Vim and Noevim are great editors, but trying to wrangle a bunch of intelligent tools to work inside them as if they were all designed to run together to provide a good experience is just not working for me, and I have been trying for many years. I will always have these tools to fall back on as needed, and they are great for when you have to ssh into a server and do some simple editing. But for hard core development you want language aware, productivity boosting tools that are all finely crafted to work together in a synergistic way to provide a singular experience. Or in other words, you want an integrated development environment.

OTHER TIPS

As a C++ developer I had similar issues for a long time. Until, that is, I reorganized my approach to using tag files under Vim a few years ago. The trick that made it work for me was to generate separate tag files for different slices of code: my project, various external code libraries, etc... I then had to set the 'tags' option to look for the files in a priority order, with my local code project files coming first and then working outward from there with the system header files being LAST.

In my case, I had separate tag files for each of these and listed in this order in the 'tags' option:

  1. My local project
  2. Any other project that this project uses
  3. System-bundled libraries (boost)
  4. System-bundled libraries (WxWidgets)
  5. System libraries (C++ standard libraries)
  6. System libraries (all else)

I'm not a PHP developer, but again the main mistake I made for a long time was just generating a single tags file FOR EVERYTHING. I'd have upwards of 30 tags to search through many times (using the :tag command). If you generate multiple tags files you have much more control over the search order of tags and thus what tags in which files are found.

See if that works for you. It did for me.

To improve ctags for PHP, you could create tags file like this:

#!/bin/bash
cd /path/to/framework/library
exec ctags-exuberant -f ~/.vim/mytags/framework \
-h ".php" -R \
--exclude="\.svn" \
--totals=yes \
--tag-relative=yes \
--PHP-kinds=+cf \
--regex-PHP='/abstract class ([^ ]*)/\1/c/' \
--regex-PHP='/interface ([^ ]*)/\1/c/' \
--regex-PHP='/(public |static |abstract |protected |private )+function ([^ (]*)/\2/f/'

then load the tags

:set tags=~/.vim/mytags/framework

taken from my blog post

You may also wanna take a look at eclim.

This could utilize eclipse's completion feature, and it should work fine for PHP (I haven't tried).

Struggled with the same problem for a long time until I found the LanguageServer for PHP.

It provides features like GoToDefinition, ShowReferences, Tags at current document etc. It is integrating okay with fzf right out of the box.

Things I don't like about it:

  1. autocompletion is slow compared to other frameworks like padawan
  2. it doesn't cache (yet) your project's index, which means, it has to reindex when you open neovim. Nevertheless, you can use the GoToDefinition functionality while it's still indexing.

Quick setup for vim-plug:

Plug 'autozimu/LanguageClient-neovim', { 'do': ':UpdateRemotePlugins' }

Plug 'roxma/LanguageServer-php-neovim', {'do': 'composer install && composer run-script parse-stubs'}

autocmd FileType php LanguageClientStart

nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>

nnoremap <silent> gr :call LanguageClient_textDocument_references()<CR>

Best solution I've found so far.

More of a workaround, but if you press g CTRL+[ instead of just CTRL+', you get a list of all the tags of that name, and you can select which one to jump to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top