niosus / EasyClangComplete

:boom: Robust C/C++ code completion for Sublime Text 3/4

Home Page:https://niosus.github.io/EasyClangComplete/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improve automatic header_to_source_mapping

jdumas opened this issue · comments

System info:

  • Sublime Text version: 3.2.2
  • Which system are you on: macOS
  • Clang version: AppleClang 11.0.3

What happens:

I am working on a project which relies heavily on templates and is mostly header-only. Thus, using EasyClangComplete on those header files is a pain, because there isn't always a matching translation unit in the compile_commands.json where to get compilation flags from. It's been an open issue in CMake for 3 years now, and I don't think anyone has a good solution yet.

In the meantime, here are some suggestions for an automatic "fallback" that would help my situation:

  1. Look through the compile_commands.json for a translation unit compiled with a -I<path> where <path> contains the header file currently being edited in Sublime. Typically even in a header-only library, there will be unit tests or example files that are actually compiled, so we can get compilation flags from them.

  2. Maybe ask cmake-server for information about targets with include directories matching the file being edited? And retrieve compilation flags from that? Idk if that's possible.

  3. Have an option to generate an error when a source cannot be matched from a header file. This would help debugging and diagnose such situations instead of getting garbage errors due to incorrect compilation flags.

  4. Finally, as a last resort it would also be useful to be able to map "all unknown files" under a certain directory to a specific .cpp file. E.g. if I have the following project structure:

    src/foo
    
    src/foo/include
    src/foo/include/bar.h
    src/foo/include/subdir/baz.h
    
    src/foo/tests
    src/foo/tests/main.cpp
    

    Then I'd want to map bar.h and subdir/baz.h to use the same flags as tests/main.cpp. But if I have other modules (src/foo, src/moo), I would like to map each module to their respective tests/main.cpp (for example).

Of course it would be best if CMake/compile_commands.json would support header files properly, because right now I'm having a real pain developing any header-only templated code.

EDIT: Actually I also found out about compdb, which seems to be able to complete an existing compile_command.json to include header files. Maybe EasyClangComplete could call that automatically under the hood? It seems that https://clangd.llvm.org/ would also be a better alternative than libclang going forward. It's supported by LSP which seems to be a competing plugin for C++ completion. Maybe it can give some ideas...

As you probably know there is already a setting:

"header_to_source_mapping": [
    "./",
    "../src/",
    "../src/*",
    "$project_path/default_file.cpp"
  ]

This will force the plugin to search for files related to headers in the order provided in the setting. In this example, it will try to match exactly the same file name with source extensions in the same folder, then in ../src/ folder, then it would try to match any source file in ../src/ folder regardless of the name and finally if nothing has worked still, it will take the flags from the provided default file.

It is not exactly what you asked for, but it works for me when I work in header-heavy codebases.

As for your suggestions:

  1. Probably infeasible. Although I should give it another thought some time.
  2. Could be possible. I did not think about that. Will have a look at some point.
  3. Definitely a good idea. At least we should not pollute the header with garbage. Probably a better option is to show something like an [X] in the status as opposed to the usual tick.
  4. Probably addressed above?

As for clangd yes, I've been looking at it for some time now, but as it is very different and I don't have as much time as before now, it probably won't happen while this plugin works for me. When it stops, I will be forced to switch to something else, and probably will write some clangd-based tooling.

Unfortunately I don't think the header_to_source_mapping setting is working very well for me. I have a project with multiple modules under src/ (src/foo, src/bar), each with their own set of include, and often no associated source files (only unit tests). I don't feel that header_to_source_mapping allows me to easily map different subfolder to a different of reference source file.

I have tried to run compdb manually and it actually works pretty well. Do you think that's something EasyClangComplete could integrate? The only thing compdb does is generate a new compile_commands.json with header files included, and it's a python-based package, so it should be easy to integrate within EasyClangComplete I think (clangd still needs someone to complete the compile_commands.json for header files anyway).

As for header to source mapping, what I tend to do is just point in it to the tests folder usually. Not ideal but worked quite well in practice.

As for compd, sure, sounds like it could be added as an optional intermediate step. I did not try it and don't know how the configuration is done there, but I am open to it. The main issue is, again, time. 🤷‍♂️

Yes, except that I have multiple test folders per project (one per module), and they don't have the same set of dependencies.

Running compd from the command-line is pretty easy, as one just needs to do:

compdb -p build/ list > compile_commands.json

To generate a completed compilation database from the build folder generated by cmake. But yeah I understand that time is a premium for all of us. Let me know if you ever get around to look into it.

I believe that even in your case you could still use the tests folders as the project still probably follows some structure right? In the header to source mapping you can always use relative paths. Or am I missing something?

Also, I will have a look into the compdb approach, but not sure when I will have the time to properly integrate this.

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Just comment here to prevent this from happening.

commented

The issue has been automatically closed due to lack of activity. Feel free to reopen the issue if it is still relevant.