MaskRay / ccls

C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting
Apache License 2.0
3.73k stars 255 forks source link

Editing a header file breaks ccls indexing for the file #833

Open zhangzhang10 opened 2 years ago

zhangzhang10 commented 2 years ago

Observed behavior

I have a very simple project that is comprised of just two header files (.h), and one source file (.cpp). The project is set up using both compile_commands.json (created by cmake) and .ccls. In .ccls I use %compile_commands.json. Anytime I insert or delete a line from a header file and then save the file, all code below the modified line is no longer indexed properly by ccls. Features such as finding definitions, xref, semantic highlighting, etc. do not work for the code below the modified line. However, they still work for code above the modified line. It looks as if ccls is keeping a stale index cache for the header file after the change. This behavior only applies to header files. I don't have this problem with source files.

Expected behavior

All ccls features that work properly before a header file is modified should continue to work properly after the modification.

Steps to reproduce

  1. Create a simple project with at least 1 header file (.h) and one source file (.cpp). The header files are named with a different prefix than the cpp file. For example, test.h and main.cpp.

  2. Build the project with cmake and export a compile_commands.json file.

  3. Create a .ccls file at the top level that contains the following lines: %compile_commands.json %cpp -std=c++14 %h -x %h c++-header

  4. Insert one line of code (e.g. std::cout << "hello") in the middle of the header file, save.

  5. Perform a typical ccls function like finding a definition for a symbol below the modified line.

System information

Thanks.

madscientist commented 2 years ago

I wasn't able to reproduce this, but I'm pretty sure this is not right:

%h -x
%h c++-header

According to the Clang documentation the argument to -x is supposed to be immediately after it, not separated by a space. Based on https://clang.llvm.org/docs/ClangCommandLineReference.html it seems any of these would be valid:

%h -xc++-header

or

%h --language
%h c++-header

or

%h --language=c++-header
zhangzhang10 commented 2 years ago

@madscientist Thanks for looking into this issue. This .ccls syntax below is documented in the wiki. I simply followed the instructions.

%h -x
%h c++-header

Nevertheless, I changed to your suggestions. It didn't make a difference.

Then, I figured out what's going on. I had index.multiVersion set to 1. This caused multiple versions of the index of the header file to exist at the time. When one version changed, the other versions stayed behind. This gives a hell lot of confusion to ccls. By setting index.multiVersion to 0 (default value), I can work around the issue. But there emerge new problems; dependence lookup and xref occasionally don't work for some symbols in the header file.

madscientist commented 2 years ago

I guess that Clang is more forgiving in this instance than its documentation implies. I know for sure there are other Clang options where you cannot add the space between the option and its argument, or it will fail.