OLD | NEW |
---|---|
1 # Clang Tool Refactoring | 1 # Clang Tool Refactoring |
2 | 2 |
3 [TOC] | 3 [TOC] |
4 | 4 |
5 ## Introduction | 5 ## Introduction |
6 | 6 |
7 Clang tools can help with global refactorings of Chromium code. Clang tools can | 7 Clang tools can help with global refactorings of Chromium code. Clang tools can |
8 take advantage of clang's AST to perform refactorings that would be impossible | 8 take advantage of clang's AST to perform refactorings that would be impossible |
9 with a traditional find-and-replace regexp: | 9 with a traditional find-and-replace regexp: |
10 | 10 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 ... | 62 ... |
63 | 63 |
64 ==== END EDITS ==== | 64 ==== END EDITS ==== |
65 ``` | 65 ``` |
66 | 66 |
67 The header and footer are required. Each line between the header and footer | 67 The header and footer are required. Each line between the header and footer |
68 represents one edit. Fields are separated by `:::`, and the first field must | 68 represents one edit. Fields are separated by `:::`, and the first field must |
69 be `r` (for replacement). In the future, this may be extended to handle header | 69 be `r` (for replacement). In the future, this may be extended to handle header |
70 insertion/removal. A deletion is an edit with no replacement text. | 70 insertion/removal. A deletion is an edit with no replacement text. |
71 | 71 |
72 The edits are applied by [`run_tool.py`](#Running), which understands certain | 72 The edits are applied by [`apply_edits.py`](#Running), which understands certain |
73 conventions: | 73 conventions: |
74 | 74 |
75 * The tool should munge newlines in replacement text to `\0`. The script | 75 * The tool should munge newlines in replacement text to `\0`. The script |
76 knows to translate `\0` back to newlines when applying edits. | 76 knows to translate `\0` back to newlines when applying edits. |
77 * When removing an element from a 'list' (e.g. function parameters, | 77 * When removing an element from a 'list' (e.g. function parameters, |
78 initializers), the tool should emit a deletion for just the element. The | 78 initializers), the tool should emit a deletion for just the element. The |
79 script understands how to extend the deletion to remove commas, etc. as | 79 script understands how to extend the deletion to remove commas, etc. as |
80 needed. | 80 needed. |
81 | 81 |
82 TODO: Document more about `SourceLocation` and how spelling loc differs from | 82 TODO: Document more about `SourceLocation` and how spelling loc differs from |
(...skipping 28 matching lines...) Expand all Loading... | |
111 It is important to use --bootstrap as there appear to be [bugs](https://crbug.co m/580745) | 111 It is important to use --bootstrap as there appear to be [bugs](https://crbug.co m/580745) |
112 in the clang library this script produces if you build it with gcc, which is the default. | 112 in the clang library this script produces if you build it with gcc, which is the default. |
113 | 113 |
114 ## Running | 114 ## Running |
115 First, build all Chromium targets to avoid failures due to missing dependencies | 115 First, build all Chromium targets to avoid failures due to missing dependencies |
116 that are generated as part of the build: | 116 that are generated as part of the build: |
117 | 117 |
118 ```shell | 118 ```shell |
119 ninja -C out/Debug # For non-Windows | 119 ninja -C out/Debug # For non-Windows |
120 ninja -d keeprsp -C out/Debug # For Windows | 120 ninja -d keeprsp -C out/Debug # For Windows |
121 | |
122 # experimental alternative: | |
123 $gen_targets = $(ninja -C out/gn -t targets all \ | |
124 | grep '^gen/[^: ]*\.[ch][pc]*:' \ | |
125 | cut -f 1 -d :`) | |
126 ninja -C out/Debug $gen_targets | |
121 ``` | 127 ``` |
122 | 128 |
123 On Windows, generate the compile DB first, and after making any source changes. | 129 On Windows, generate the compile DB first, and after making any source changes. |
124 Then omit the `--generate-compdb` in later steps. | 130 Then omit the `--generate-compdb` in later steps. |
125 | 131 |
126 ```shell | 132 ```shell |
127 tools/clang/scripts/generate_win_compdb.py out/Debug | 133 tools/clang/scripts/generate_win_compdb.py out/Debug |
128 ``` | 134 ``` |
129 | 135 |
130 Then run the actual tool: | 136 Then run the actual clang tool to generate a list of edits: |
131 | 137 |
132 ```shell | 138 ```shell |
133 tools/clang/scripts/run_tool.py <toolname> \ | 139 tools/clang/scripts/run_tool.py <toolname> \ |
134 --generate-compdb | 140 --generate-compdb |
135 out/Debug <path 1> <path 2> ... | 141 out/Debug <path 1> <path 2> ... >/tmp/list-of-edits.debug |
136 ``` | 142 ``` |
137 | 143 |
138 `--generate-compdb` can be omitted if the compile DB was already generated and | 144 `--generate-compdb` can be omitted if the compile DB was already generated and |
139 the list of build flags and source files has not changed since generation. | 145 the list of build flags and source files has not changed since generation. |
140 | 146 |
141 `<path 1>`, `<path 2>`, etc are optional arguments to filter the files to run | 147 `<path 1>`, `<path 2>`, etc are optional arguments to filter the files to run |
142 the tool across. This is helpful when sharding global refactorings into smaller | 148 the tool against. This is helpful when sharding global refactorings into smaller |
143 chunks. For example, the following command will run the `empty_string` tool | 149 chunks. For example, the following command will run the `empty_string` tool |
144 across just the files in `//base`: | 150 against just the `.c`, `.cc`, `.cpp`, `.m`, `.mm` files in `//net`. Note that |
151 the filtering is not applied to the *output* of the tool - the tool can emit | |
152 edits that apply to files outside of `//cc` (i.e. edits that apply to headers | |
153 from `//base` that got included by source files in `//cc`). | |
154 | |
155 Note that some header files might only be included from generated files | |
156 (e.g. from only from some `.cpp` files under out/Debug/gen). To make sure | |
157 that contents of such header files are processed by the tool, the tool | |
dcheng
2016/12/28 19:01:36
the tool => run_tool.py (there's too many differen
Łukasz Anforowicz
2016/12/28 19:33:07
Done (but I think it is more correct to say "clang
| |
158 needs to be run against the generated files. The only way to accomplish this | |
159 today is to pass `--all` switch to `run_tool.py` - this will run the tool | |
160 against all the sources from the compilation database. | |
145 | 161 |
146 ```shell | 162 ```shell |
147 tools/clang/scripts/run_tool.py empty_string \ | 163 tools/clang/scripts/run_tool.py empty_string \ |
148 --generated-compdb \ | 164 --generated-compdb \ |
149 out/Debug base | 165 out/Debug net >/tmp/list-of-edits.debug |
150 ``` | 166 ``` |
151 | 167 |
168 Finally, apply the edits as follows: | |
169 | |
170 ```shell | |
171 cat /tmp/list-of-edits.debug \ | |
172 | tools/clang/scripts/extract_edits.py \ | |
173 | tools/clang/scripts/apply_edits.py out/Debug <path 1> <path 2> ... | |
174 ``` | |
175 | |
176 The tool will only apply edits to files actually under control of `git`. | |
dcheng
2016/12/28 19:01:36
The tool => apply_edits.py
Łukasz Anforowicz
2016/12/28 19:33:07
Done.
| |
177 `<path 1>`, `<path 2>`, etc are optional arguments to further filter the files | |
178 that the edits are applied to. Note that semantics of these filters is | |
179 distinctly different from the arguments of `run_tool.py` filters - one set of | |
180 filters controls which files are edited, the other set of filters controls which | |
181 files the clang tool is run against. | |
182 | |
152 ## Debugging | 183 ## Debugging |
153 Dumping the AST for a file: | 184 Dumping the AST for a file: |
154 | 185 |
155 ```shell | 186 ```shell |
156 clang++ -cc1 -ast-dump foo.cc | 187 clang++ -cc1 -ast-dump foo.cc |
157 ``` | 188 ``` |
158 | 189 |
159 Using `clang-query` to dynamically test matchers (requires checking out | 190 Using `clang-query` to dynamically test matchers (requires checking out |
160 and building [clang-tools-extras](https://github.com/llvm-mirror/clang-tools-ext ra)): | 191 and building [clang-tools-extras](https://github.com/llvm-mirror/clang-tools-ext ra)): |
161 | 192 |
(...skipping 18 matching lines...) Expand all Loading... | |
180 | 211 |
181 ```shell | 212 ```shell |
182 tools/clang/scripts/test_tool.py <tool name> | 213 tools/clang/scripts/test_tool.py <tool name> |
183 ``` | 214 ``` |
184 | 215 |
185 The name of the tool binary and the subdirectory for the tool in | 216 The name of the tool binary and the subdirectory for the tool in |
186 `//tools/clang` must match. The test runner finds all files that match the | 217 `//tools/clang` must match. The test runner finds all files that match the |
187 pattern `//tools/clang/<tool name>/tests/*-original.cc`, runs the tool across | 218 pattern `//tools/clang/<tool name>/tests/*-original.cc`, runs the tool across |
188 those files, and compared it to the `*-expected.cc` version. If there is a | 219 those files, and compared it to the `*-expected.cc` version. If there is a |
189 mismatch, the result is saved in `*-actual.cc`. | 220 mismatch, the result is saved in `*-actual.cc`. |
OLD | NEW |