More accurate alternative/workaround to ctags/Cscope for PHP?
Asked Answered
M

6

15

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?

Mayday answered 1/12, 2011 at 23:6 Comment(1)
github.com/vim-php/phpctags looks like it could possibly make ctags work better for PHP. I will try it out some time.Mayday
M
1

PHP is not a well designed language, and it is not statically typed. As such, the foundation is just not there for any good tools of this kind to be made that would be practical to use in real world projects. IDEs, language servers, and Vim and Neovim plugins can only know as much about the code as the language allows. It is possible to write very consistent code in PHP with as much types as possible and that only utilizes a limited subset of the language, such that tools could understand it. However if your team is capable of writing that good of PHP code, they are good enough to rewrite the code in a more well designed language that can support even better tooling, something like Kotlin which also has great IDE support.

Mayday answered 1/8, 2016 at 15:12 Comment(0)
M
4

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.

Mogilev answered 10/3, 2015 at 16:30 Comment(3)
While your approach is definitely good as a pragmatic answer to the question, saying that generating a single index is "not good" is a fallacy. The real problem is that the index is not built using specific language semantics. Philosophically I often hate modifying my workflow when it has no real benefits (as opposed to artificial benefits) and especially when it's all because the tools I use have clear limitations. That said, in the grand scheme of things it's just another compromise, and we make many every day.Vex
Removed "NOT GOOD" as an approach for using a single tag file for everything and shifted the focus more to how using multiple tag files can help with searching through tags.Mogilev
This is helpful advice. It doesn't completely solve my problem, but it is a step forward.Mayday
R
3

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

Rainproof answered 21/12, 2011 at 10:1 Comment(2)
I tried this, but ctags is still pretty retarted after this. For example when trying to navigate to a function that exists in the current file, it takes me to a random line in that file.Mayday
OK, for some reason pressing g <C-]> is working more accurately as in not jumping to a random line as described above, even when this does not bring up a list of choices. For now I have mapped <C-]> to g<C-]> and will see how that goes...Mayday
N
2

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

Nealneala answered 15/2, 2012 at 12:50 Comment(5)
I have tried eclim before and found it quite lacking compared to real Vim. I doubt there is any Vim plugin or emulation mode for anything that I would be satisfied with.Mayday
Which part do you think eclim is lacking compared to Vim?Nealneala
You know what, it has been so long since I tried this that I don't remember anymore. I just looked at the eclim page again, and it seems it might be a good solution, especially since it is designed so that you could use Vim as your primary editor. Also I see it has remained under active development so this gives me hope. I have removed the downvote for now. I will try this out when I have some time.Mayday
I found eclim to work better than ctags but at the added expensive of depending on eclipse. It makes porting your vim configuration more of a pain but if you don't care about that I would give eclim a shot.Dalrymple
I finally tried out eclim. It is even worse than using tags. I don't understand this because when I used to use eclipse for PHP projects, the code definition lookup feature worked pretty well. But when I use the contextual php lookup under cursor command for eclim, it is not intelligent at all.Mayday
E
2

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.

Electronegative answered 23/6, 2017 at 13:48 Comment(0)
L
1

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.

Labor answered 2/12, 2011 at 19:49 Comment(1)
Actually this is what I am trying to avoid. The whole point is to jump to the definition, not manually search for it. It would be easier to just go to the definition myself than use this.Mayday
M
1

PHP is not a well designed language, and it is not statically typed. As such, the foundation is just not there for any good tools of this kind to be made that would be practical to use in real world projects. IDEs, language servers, and Vim and Neovim plugins can only know as much about the code as the language allows. It is possible to write very consistent code in PHP with as much types as possible and that only utilizes a limited subset of the language, such that tools could understand it. However if your team is capable of writing that good of PHP code, they are good enough to rewrite the code in a more well designed language that can support even better tooling, something like Kotlin which also has great IDE support.

Mayday answered 1/8, 2016 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.