Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 1 | =================== |
| 2 | Clang-Include-Fixer |
| 3 | =================== |
| 4 | |
| 5 | .. contents:: |
| 6 | |
| 7 | One of the major nuisances of C++ compared to other languages is the manual |
| 8 | management of ``#include`` directives in any file. |
| 9 | :program:`clang-include-fixer` addresses one aspect of this problem by providing |
| 10 | an automated way of adding ``#include`` directives for missing symbols in one |
| 11 | translation unit. |
| 12 | |
Haojian Wu | 499375c | 2016-07-27 13:17:16 +0000 | [diff] [blame] | 13 | While inserting missing ``#include``, :program:`clang-include-fixer` adds |
| 14 | missing namespace qualifiers to all instances of an unidentified symbol if |
| 15 | the symbol is missing some prefix namespace qualifiers. |
| 16 | |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 17 | Setup |
| 18 | ===== |
| 19 | |
| 20 | To use :program:`clang-include-fixer` two databases are required. Both can be |
| 21 | generated with existing tools. |
| 22 | |
| 23 | - Compilation database. Contains the compiler commands for any given file in a |
| 24 | project and can be generated by CMake, see `How To Setup Tooling For LLVM`_. |
Benjamin Kramer | a3d8233 | 2016-05-13 09:27:54 +0000 | [diff] [blame] | 25 | - Symbol index. Contains all symbol information in a project to match a given |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 26 | identifier to a header file. |
| 27 | |
| 28 | Ideally both databases (``compile_commands.json`` and |
| 29 | ``find_all_symbols_db.yaml``) are linked into the root of the source tree they |
| 30 | correspond to. Then the :program:`clang-include-fixer` can automatically pick |
| 31 | them up if called with a source file from that tree. Note that by default |
| 32 | ``compile_commands.json`` as generated by CMake does not include header files, |
| 33 | so only implementation files can be handled by tools. |
| 34 | |
| 35 | .. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html |
| 36 | |
Benjamin Kramer | a3d8233 | 2016-05-13 09:27:54 +0000 | [diff] [blame] | 37 | Creating a Symbol Index From a Compilation Database |
Haojian Wu | 499375c | 2016-07-27 13:17:16 +0000 | [diff] [blame] | 38 | --------------------------------------------------- |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 39 | |
| 40 | The include fixer contains :program:`find-all-symbols`, a tool to create a |
| 41 | symbol database in YAML format from a compilation database by parsing all |
| 42 | source files listed in it. The following list of commands shows how to set up a |
| 43 | database for LLVM, any project built by CMake should follow similar steps. |
| 44 | |
| 45 | .. code-block:: console |
| 46 | |
| 47 | $ cd path/to/llvm-build |
Haojian Wu | e64cee8 | 2016-06-07 07:50:48 +0000 | [diff] [blame] | 48 | $ ninja find-all-symbols // build find-all-symbols tool. |
| 49 | $ ninja clang-include-fixer // build clang-include-fixer tool. |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 50 | $ ls compile_commands.json # Make sure compile_commands.json exists. |
| 51 | compile_commands.json |
| 52 | $ path/to/llvm/source/tools/clang/tools/extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py |
| 53 | ... wait as clang indexes the code base ... |
| 54 | $ ln -s $PWD/find_all_symbols_db.yaml path/to/llvm/source/ # Link database into the source tree. |
| 55 | $ ln -s $PWD/compile_commands.json path/to/llvm/source/ # Also link compilation database if it's not there already. |
| 56 | $ cd path/to/llvm/source |
Haojian Wu | e64cee8 | 2016-06-07 07:50:48 +0000 | [diff] [blame] | 57 | $ /path/to/clang-include-fixer -db=yaml path/to/file/with/missing/include.cpp |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 58 | Added #include "foo.h" |
| 59 | |
Eric Liu | c7f3b10 | 2016-05-18 14:10:16 +0000 | [diff] [blame] | 60 | Integrate with Vim |
Haojian Wu | 499375c | 2016-07-27 13:17:16 +0000 | [diff] [blame] | 61 | ------------------ |
Eric Liu | c7f3b10 | 2016-05-18 14:10:16 +0000 | [diff] [blame] | 62 | To run `clang-include-fixer` on a potentially unsaved buffer in Vim. Add the |
| 63 | following key binding to your ``.vimrc``: |
| 64 | |
| 65 | .. code-block:: console |
| 66 | |
Kirill Bobyrev | c4018e2 | 2016-07-27 14:23:47 +0000 | [diff] [blame] | 67 | noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/clang-include-fixer.py<cr> |
Eric Liu | c7f3b10 | 2016-05-18 14:10:16 +0000 | [diff] [blame] | 68 | |
Kirill Bobyrev | c4018e2 | 2016-07-27 14:23:47 +0000 | [diff] [blame] | 69 | This enables `clang-include-fixer` for NORMAL and VISUAL mode. Change |
Alexander Kornienko | 053826f | 2016-08-02 20:29:47 +0000 | [diff] [blame^] | 70 | `<leader>cf` to another binding if you need clang-include-fixer on a different |
| 71 | key. The `<leader> key |
| 72 | <http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_3)#Map_leader>`_ |
Kirill Bobyrev | 5c339ec | 2016-07-27 14:26:03 +0000 | [diff] [blame] | 73 | is a reference to a specific key defined by the mapleader variable and is bound |
Kirill Bobyrev | c4018e2 | 2016-07-27 14:23:47 +0000 | [diff] [blame] | 74 | to backslash by default. |
Eric Liu | c7f3b10 | 2016-05-18 14:10:16 +0000 | [diff] [blame] | 75 | |
Haojian Wu | e64cee8 | 2016-06-07 07:50:48 +0000 | [diff] [blame] | 76 | Make sure vim can find :program:`clang-include-fixer`: |
| 77 | |
| 78 | - Add the path to :program:`clang-include-fixer` to the PATH environment variable. |
| 79 | - Or set ``g:clang_include_fixer_path`` in vimrc: ``let g:clang_include_fixer_path=path/to/clang-include-fixer`` |
| 80 | |
| 81 | You can customize the number of headers being shown by setting |
| 82 | ``let g:clang_include_fixer_maximum_suggested_headers=5`` |
| 83 | |
Eric Liu | c7f3b10 | 2016-05-18 14:10:16 +0000 | [diff] [blame] | 84 | See ``clang-include-fixer.py`` for more details. |
| 85 | |
Benjamin Kramer | 57d070e | 2016-07-27 10:11:06 +0000 | [diff] [blame] | 86 | Integrate with Emacs |
| 87 | -------------------- |
| 88 | To run `clang-include-fixer` on a potentially unsaved buffer in Emacs. |
| 89 | Ensure that Emacs finds ``clang-include-fixer.el`` by adding the directory containing the file to the ``load-path`` |
| 90 | and requiring the `clang-include-fixer` in your ```.emacs``: |
| 91 | |
| 92 | .. code-block:: console |
| 93 | |
| 94 | (add-to-list 'load-path "path/to/llvm/source/tools/clang/tools/extra/include-fixer/tool/" |
| 95 | (require 'clang-include-fixer) |
| 96 | |
| 97 | Within Emacs the tool can be invoked with the command ``M-x clang-include-fixer``. |
| 98 | |
| 99 | Make sure Emacs can find :program:`clang-include-fixer`: |
| 100 | |
| 101 | - Add the path to :program:`clang-include-fixer` to the PATH environment variable. |
| 102 | |
| 103 | See ``clang-include-fixer.el`` for more details. |
| 104 | |
Benjamin Kramer | bfcab59 | 2016-05-11 09:44:10 +0000 | [diff] [blame] | 105 | How it Works |
| 106 | ============ |
| 107 | |
| 108 | To get the most information out of clang at parse time, |
| 109 | :program:`clang-include-fixer` runs in tandem with the parse and receives |
| 110 | callbacks from Clang's semantic analysis. In particular it reuses the existing |
| 111 | support for typo corrections. Whenever Clang tries to correct a potential typo |
| 112 | it emits a callback to the include fixer which then looks for a corresponding |
| 113 | file. At this point rich lookup information is still available, which is not |
| 114 | available in the AST at a later stage. |
| 115 | |
| 116 | The identifier that should be typo corrected is then sent to the database, if a |
| 117 | header file is returned it is added as an include directive at the top of the |
| 118 | file. |
| 119 | |
| 120 | Currently :program:`clang-include-fixer` only inserts a single include at a |
| 121 | time to avoid getting caught in follow-up errors. If multiple `#include` |
| 122 | additions are desired the program can be rerun until a fix-point is reached. |