diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 0000000..2fbed1a --- /dev/null +++ b/FAQ.md @@ -0,0 +1,161 @@ +### Some C/C++ headers are not recognized + +There are at least three sets of implicit include paths. They take effect without your `-I` option in `.ccls` or `compile_commands.json` + +```c++ +// a.cc +// system C header, usually in /usr/include +#include +// system C++ header. The location varies among distributions, e.g. /usr/include/c++/{6,7.2.1} +#include +// In Clang resource directory +#include +``` + +Put `a.cc` in some directory with `echo clang++ > .ccls`. Open the file, you should be able to jump to `stdio.h` `new` `stddef.h` when you trigger `textDocument/definition` on the include lines. + +Note that this might not work on Windows. To solve this, add the system include directories to compile_commands.json via your build system of choice using the INCLUDE environment variable (available after executing VsDevCmd.bat). + +For CMake this can be achieved in a single line: `target_include_directories( SYSTEM PRIVATE $ENV{INCLUDE})` + +#### If `-resource-dir` is correct + +If the [[initialization option|Initialization options]] `cacheDirectory` is `/tmp/ccls`, and the source file is `/tmp/c/a.cc`, `jq . < /tmp/ccls/@tmp@c/a.cc.json` to see if `-resource-dir` is correct, e.g. `"-resource-dir=/home/ray/Dev/Util/cquery/build/debug/lib/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04/lib/clang/5.0.1"` + +system C/C++ headers can be detected reliably. For Clang resource directory, there is logic in `wscript` to detect it when you run `./waf configure [OPTIONS]` + +* For `--bundled-clang=5.0.1`: `../lib/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04/lib/clang/5.0.1` which is relative to the `build/release/bin/ccls` executable. + The relative path of `build/release/bin/ccls` and `build/release/lib/` cannot change, otherwise libclang.so used by ccls cannot find the Clang resource directory. +* For `--use-system-clang`: it is recognized from `-resource-dir` option in the output of `clang++ '-###' -xc /dev/null`) + +```bash +./waf configure --prefix /tmp/opt && ./waf install +``` + +#### `-isystem` + +`-isystem` system include paths is usually unnecessary. But for cross compiling or on some bizarre system you may have to specify them. A simple approach other than trial and error (changing `.ccls` and restarting your editor) is to use `c-index-test` (if you use `--bundled-clang`, preferably the executable in the extracted tarball; if you link against system libclang, use something like `/usr/bin/c-index-test`) + +`build/debug/lib/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04/bin/c-index-test -index-file local /tmp/c/a.cc -isystem/usr/include/c++/7.3.0 -isystemyour_include_path2` + +Play with your `-isystem` options until you get a group of options that you can add to [`.ccls`](https://github.com/ccls-project/cquery/wiki/Getting-started#cquery) + +If you want the ccls binary at a specific location use a symlink - do not move the binary itself. + +### Project root detection + +For C++ projects, `compile_commands.json` is used by [emacs-ccls](https://github.com/ccls-project/emacs-cquery/) to mark the project root. This is usually a symlink to the real `compile_commands.json` in a build directory: + +``` +proj + build + gen + generated_file_in_build.cc + compile_commands.json + compile_commands.json -> build/compile_commands.json +``` + +In this example, the `:rootUri` of the generated C++ file is `proj/build/` because of `proj/build/compile_commands.json`. However, the user wants it to be `proj/`. Customize `ccls-project-root-matchers`. + +### Includes + +Here is an example. + +`include/a.h`: +```c +int bad; +``` + +`a.cc`: +```c +int main(){return bad;} +``` + +`.ccls`: +```text +%clang +%cpp -std=gnu++14 +-Iinclude +``` + +ccls will save a file in `cacheDirectory`: +`jq . < /tmp/ccls/@tmp@c/a.cc.json` +```json +15 +{ + "last_modification_time": 1520737513, + "language": 1, + "import_file": "/tmp/c/a.cc", + "args": [ + "clang++", + "-working-directory=/tmp/c", + "-std=gnu++14", + "-Iinclude", + "/tmp/c/a.cc", + "-resource-dir=/home/maskray/Dev/Util/ccls/build/debug/lib/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04/lib/clang/6.0.0", + "-Wno-unknown-warning-option", + "-fparse-all-comments" + ], + "includes": [ + { + "line": 0, + "resolved_path": "/tmp/c/include/a.h" + } + ], + "dependencies": [ + "/tmp/c/include/a.h" + ], + ... +``` + +### Definitions + +`textDocument/definition` can be used in many places. Some are current implementation details and may subject to change. + +* void foo(); A declaration jumps to the definition +* void foo() {} The definition lists all declarations +* A a; For variables of custom types, besides declarations of the variable, both the type and the variable jump to the declaration/definition of its type `A` +* class C { jumps to declarations (and constructors/destructors) +* a.field jumps to the member in the struct declaration +* #include <map> jumps to the header +* std::string a = "a"; takes you to the constructor. Many implicit constructors can also be jumped in this way. +* a == b `operator==` for user defined operators +* namespace ns { find original or extension namespaces +* // ns::foo in comments, it recognizes the identifier around the cursor, approximately finds the best matching symbol and jumps to it; on `ns`, it jumps to the namespace + +### References + +* #include <iostream> lists all `#include` lines in the project pointing to the included file +* [](){} lists all(?) lambda expressions thanks to implicit `std::function` move constructor +* extern int a; If `ReferenceContext.includeDeclaration` is true, the definition and declarations are also listed. + +### `$ccls/base` + +* struct A:B{void f()override;}; lists `B` or `B::f()` + +### `$ccls/derived` + +* struct B{virtual void f();}; derived classes or virtual function overrides + +### `$ccls/vars` + +* A a; lists all instances of user-defined `A`. +* int i; lists all instances of `int`. + +### [`$ccls/callHierarchy`](https://github.com/ccls-project/cquery/blob/master/src/messages/cquery_call_hierarchy.cc) + +```elisp +(ccls-call-hierarchy nil) ; caller hierarchy +(ccls-call-hierarchy t) ; callee hierarchy +``` + +### [`$ccls/inheritanceHierarchy`](https://github.com/ccls-project/cquery/blob/master/src/messages/cquery_inheritance_hierarchy.cc) + +```elisp +(ccls-inheritance-hierarchy nil) ; base hierarchy +(ccls-inheritance-hierarchy t) ; derived hierarchy +``` + +### [`$ccls/memberHierarchy`](https://github.com/ccls-project/cquery/blob/master/src/messages/cquery_member_hierarchy.cc) + +Recursively list members of a record type. 😂 nobody has implemented UI for the feature. Help wanted! \ No newline at end of file