1 | //===--- ConfigFragment.h - Unit of user-specified configuration -*- C++-*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Various clangd features have configurable behaviour (or can be disabled). |
10 | // The configuration system allows users to control this: |
11 | // - in a user config file, a project config file, via LSP, or via flags |
12 | // - specifying different settings for different files |
13 | // |
14 | // This file defines the config::Fragment structure which models one piece of |
15 | // configuration as obtained from a source like a file. |
16 | // |
17 | // This is distinct from how the config is interpreted (CompiledFragment), |
18 | // combined (Provider) and exposed to the rest of clangd (Config). |
19 | // |
20 | //===----------------------------------------------------------------------===// |
21 | // |
22 | // To add a new configuration option, you must: |
23 | // - add its syntactic form to Fragment |
24 | // - update ConfigYAML.cpp to parse it |
25 | // - add its semantic form to Config (in Config.h) |
26 | // - update ConfigCompile.cpp to map Fragment -> Config |
27 | // - make use of the option inside clangd |
28 | // - document the new option (config.md in the llvm/clangd-www repository) |
29 | // |
30 | //===----------------------------------------------------------------------===// |
31 | |
32 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONFIGFRAGMENT_H |
33 | #define |
34 | |
35 | #include "ConfigProvider.h" |
36 | #include "llvm/Support/SMLoc.h" |
37 | #include "llvm/Support/SourceMgr.h" |
38 | #include <optional> |
39 | #include <string> |
40 | #include <vector> |
41 | |
42 | namespace clang { |
43 | namespace clangd { |
44 | namespace config { |
45 | |
46 | /// An entity written in config along, with its optional location in the file. |
47 | template <typename T> struct Located { |
48 | Located(T Value, llvm::SMRange Range = {}) |
49 | : Range(Range), Value(std::move(Value)) {} |
50 | |
51 | llvm::SMRange Range; |
52 | T *operator->() { return &Value; } |
53 | const T *operator->() const { return &Value; } |
54 | T &operator*() { return Value; } |
55 | const T &operator*() const { return Value; } |
56 | |
57 | private: |
58 | T Value; |
59 | }; |
60 | |
61 | /// A chunk of configuration obtained from a config file, LSP, or elsewhere. |
62 | struct Fragment { |
63 | /// Parses fragments from a YAML file (one from each --- delimited document). |
64 | /// Documents that contained fatal errors are omitted from the results. |
65 | /// BufferName is used for the SourceMgr and diagnostics. |
66 | static std::vector<Fragment> parseYAML(llvm::StringRef YAML, |
67 | llvm::StringRef BufferName, |
68 | DiagnosticCallback); |
69 | |
70 | /// Analyzes and consumes this fragment, possibly yielding more diagnostics. |
71 | /// This always produces a usable result (errors are recovered). |
72 | /// |
73 | /// Typically, providers will compile a Fragment once when it's first loaded, |
74 | /// caching the result for reuse. |
75 | /// Like a compiled program, this is good for performance and also encourages |
76 | /// errors to be reported early and only once. |
77 | /// |
78 | /// The returned function is a cheap-copyable wrapper of refcounted internals. |
79 | CompiledFragment compile(DiagnosticCallback) &&; |
80 | |
81 | /// These fields are not part of the user-specified configuration, but |
82 | /// instead are populated by the parser to describe the configuration source. |
83 | struct SourceInfo { |
84 | /// Retains a buffer of the original source this fragment was parsed from. |
85 | /// Locations within Located<T> objects point into this SourceMgr. |
86 | /// Shared because multiple fragments are often parsed from one (YAML) file. |
87 | /// May be null, then all locations should be ignored. |
88 | std::shared_ptr<llvm::SourceMgr> Manager; |
89 | /// The start of the original source for this fragment. |
90 | /// Only valid if SourceManager is set. |
91 | llvm::SMLoc Location; |
92 | /// Absolute path to directory the fragment is associated with. Relative |
93 | /// paths mentioned in the fragment are resolved against this. |
94 | std::string Directory; |
95 | /// Whether this fragment is allowed to make critical security/privacy |
96 | /// decisions. |
97 | bool Trusted = false; |
98 | }; |
99 | SourceInfo Source; |
100 | |
101 | /// Conditions in the If block restrict when a Fragment applies. |
102 | /// |
103 | /// Each separate condition must match (combined with AND). |
104 | /// When one condition has multiple values, any may match (combined with OR). |
105 | /// e.g. `PathMatch: [foo/.*, bar/.*]` matches files in either directory. |
106 | /// |
107 | /// Conditions based on a file's path use the following form: |
108 | /// - if the fragment came from a project directory, the path is relative |
109 | /// - if the fragment is global (e.g. user config), the path is absolute |
110 | /// - paths always use forward-slashes (UNIX-style) |
111 | /// If no file is being processed, these conditions will not match. |
112 | struct IfBlock { |
113 | /// The file being processed must fully match a regular expression. |
114 | std::vector<Located<std::string>> PathMatch; |
115 | /// The file being processed must *not* fully match a regular expression. |
116 | std::vector<Located<std::string>> PathExclude; |
117 | |
118 | /// An unrecognized key was found while parsing the condition. |
119 | /// The condition will evaluate to false. |
120 | bool HasUnrecognizedCondition = false; |
121 | }; |
122 | IfBlock If; |
123 | |
124 | /// Conditions in the CompileFlags block affect how a file is parsed. |
125 | /// |
126 | /// clangd emulates how clang would interpret a file. |
127 | /// By default, it behaves roughly like `clang $FILENAME`, but real projects |
128 | /// usually require setting the include path (with the `-I` flag), defining |
129 | /// preprocessor symbols, configuring warnings etc. |
130 | /// Often, a compilation database specifies these compile commands. clangd |
131 | /// searches for compile_commands.json in parents of the source file. |
132 | /// |
133 | /// This section modifies how the compile command is constructed. |
134 | struct CompileFlagsBlock { |
135 | /// Override the compiler executable name to simulate. |
136 | /// |
137 | /// The name can affect how flags are parsed (clang++ vs clang). |
138 | /// If the executable name is in the --query-driver allowlist, then it will |
139 | /// be invoked to extract include paths. |
140 | /// |
141 | /// (That this simply replaces argv[0], and may mangle commands that use |
142 | /// more complicated drivers like ccache). |
143 | std::optional<Located<std::string>> Compiler; |
144 | |
145 | /// List of flags to append to the compile command. |
146 | std::vector<Located<std::string>> Add; |
147 | /// List of flags to remove from the compile command. |
148 | /// |
149 | /// - If the value is a recognized clang flag (like "-I") then it will be |
150 | /// removed along with any arguments. Synonyms like --include-dir= will |
151 | /// also be removed. |
152 | /// - Otherwise, if the value ends in * (like "-DFOO=*") then any argument |
153 | /// with the prefix will be removed. |
154 | /// - Otherwise any argument exactly matching the value is removed. |
155 | /// |
156 | /// In all cases, -Xclang is also removed where needed. |
157 | /// |
158 | /// Example: |
159 | /// Command: clang++ --include-directory=/usr/include -DFOO=42 foo.cc |
160 | /// Remove: [-I, -DFOO=*] |
161 | /// Result: clang++ foo.cc |
162 | /// |
163 | /// Flags added by the same CompileFlags entry will not be removed. |
164 | std::vector<Located<std::string>> Remove; |
165 | |
166 | /// Directory to search for compilation database (compile_commands.json |
167 | /// etc). Valid values are: |
168 | /// - A single path to a directory (absolute, or relative to the fragment) |
169 | /// - Ancestors: search all parent directories (the default) |
170 | /// - std::nullopt: do not use a compilation database, just default flags. |
171 | std::optional<Located<std::string>> CompilationDatabase; |
172 | }; |
173 | CompileFlagsBlock CompileFlags; |
174 | |
175 | /// Controls how clangd understands code outside the current file. |
176 | /// clangd's indexes provide information about symbols that isn't available |
177 | /// to clang's parser, such as incoming references. |
178 | struct IndexBlock { |
179 | /// Whether files are built in the background to produce a project index. |
180 | /// This is checked for translation units only, not headers they include. |
181 | /// Legal values are "Build" or "Skip". |
182 | std::optional<Located<std::string>> Background; |
183 | /// An external index uses data source outside of clangd itself. This is |
184 | /// usually prepared using clangd-indexer. |
185 | /// Exactly one source (File/Server) should be configured. |
186 | struct ExternalBlock { |
187 | /// Whether the block is explicitly set to `None`. Can be used to clear |
188 | /// any external index specified before. |
189 | Located<bool> IsNone = false; |
190 | /// Path to an index file generated by clangd-indexer. Relative paths may |
191 | /// be used, if config fragment is associated with a directory. |
192 | std::optional<Located<std::string>> File; |
193 | /// Address and port number for a clangd-index-server. e.g. |
194 | /// `123.1.1.1:13337`. |
195 | std::optional<Located<std::string>> Server; |
196 | /// Source root governed by this index. Default is the directory |
197 | /// associated with the config fragment. Absolute in case of user config |
198 | /// and relative otherwise. Should always use forward-slashes. |
199 | std::optional<Located<std::string>> MountPoint; |
200 | }; |
201 | std::optional<Located<ExternalBlock>> External; |
202 | // Whether the standard library visible from this file should be indexed. |
203 | // This makes all standard library symbols available, included or not. |
204 | std::optional<Located<bool>> StandardLibrary; |
205 | }; |
206 | IndexBlock Index; |
207 | |
208 | /// Controls behavior of diagnostics (errors and warnings). |
209 | struct DiagnosticsBlock { |
210 | /// Diagnostic codes that should be suppressed. |
211 | /// |
212 | /// Valid values are: |
213 | /// - *, to disable all diagnostics |
214 | /// - diagnostic codes exposed by clangd (e.g unknown_type, -Wunused-result) |
215 | /// - clang internal diagnostic codes (e.g. err_unknown_type) |
216 | /// - warning categories (e.g. unused-result) |
217 | /// - clang-tidy check names (e.g. bugprone-narrowing-conversions) |
218 | /// |
219 | /// This is a simple filter. Diagnostics can be controlled in other ways |
220 | /// (e.g. by disabling a clang-tidy check, or the -Wunused compile flag). |
221 | /// This often has other advantages, such as skipping some analysis. |
222 | std::vector<Located<std::string>> Suppress; |
223 | |
224 | /// Controls how clangd will correct "unnecessary" #include directives. |
225 | /// clangd can warn if a header is `#include`d but not used, and suggest |
226 | /// removing it. |
227 | // |
228 | /// Strict means a header is unused if it does not *directly* provide any |
229 | /// symbol used in the file. Removing it may still break compilation if it |
230 | /// transitively includes headers that are used. This should be fixed by |
231 | /// including those headers directly. |
232 | /// |
233 | /// Valid values are: |
234 | /// - Strict |
235 | /// - std::nullopt |
236 | std::optional<Located<std::string>> UnusedIncludes; |
237 | |
238 | /// Controls if clangd should analyze missing #include directives. |
239 | /// clangd will warn if no header providing a symbol is `#include`d |
240 | /// (missing) directly, and suggest adding it. |
241 | /// |
242 | /// Strict means a header providing a symbol is missing if it is not |
243 | /// *directly #include'd. The file might still compile if the header is |
244 | /// included transitively. |
245 | /// |
246 | /// Valid values are: |
247 | /// - Strict |
248 | /// - std::nullopt |
249 | std::optional<Located<std::string>> MissingIncludes; |
250 | |
251 | /// Controls IncludeCleaner diagnostics. |
252 | struct IncludesBlock { |
253 | /// Regexes that will be used to avoid diagnosing certain includes as |
254 | /// unused or missing. These can match any suffix of the header file in |
255 | /// question. |
256 | std::vector<Located<std::string>> ; |
257 | }; |
258 | IncludesBlock Includes; |
259 | |
260 | /// Controls how clang-tidy will run over the code base. |
261 | /// |
262 | /// The settings are merged with any settings found in .clang-tidy |
263 | /// configuration files with these ones taking precedence. |
264 | struct ClangTidyBlock { |
265 | std::vector<Located<std::string>> Add; |
266 | /// List of checks to disable. |
267 | /// Takes precedence over Add. To enable all llvm checks except include |
268 | /// order: |
269 | /// Add: llvm-* |
270 | /// Remove: llvm-include-order |
271 | std::vector<Located<std::string>> Remove; |
272 | |
273 | /// A Key-Value pair list of options to pass to clang-tidy checks |
274 | /// These take precedence over options specified in clang-tidy |
275 | /// configuration files. Example: |
276 | /// CheckOptions: |
277 | /// readability-braces-around-statements.ShortStatementLines: 2 |
278 | std::vector<std::pair<Located<std::string>, Located<std::string>>> |
279 | CheckOptions; |
280 | |
281 | /// Whether to run checks that may slow down clangd. |
282 | /// Strict: Run only checks measured to be fast. (Default) |
283 | /// This excludes recently-added checks we have not timed yet. |
284 | /// Loose: Run checks unless they are known to be slow. |
285 | /// None: Run checks regardless of their speed. |
286 | std::optional<Located<std::string>> FastCheckFilter; |
287 | }; |
288 | ClangTidyBlock ClangTidy; |
289 | }; |
290 | DiagnosticsBlock Diagnostics; |
291 | |
292 | // Describes the style of the codebase, beyond formatting. |
293 | struct StyleBlock { |
294 | // Namespaces that should always be fully qualified, meaning no "using" |
295 | // declarations, always spell out the whole name (with or without leading |
296 | // ::). All nested namespaces are affected as well. |
297 | // Affects availability of the AddUsing tweak. |
298 | std::vector<Located<std::string>> FullyQualifiedNamespaces; |
299 | }; |
300 | StyleBlock Style; |
301 | |
302 | /// Describes code completion preferences. |
303 | struct CompletionBlock { |
304 | /// Whether code completion should include suggestions from scopes that are |
305 | /// not visible. The required scope prefix will be inserted. |
306 | std::optional<Located<bool>> AllScopes; |
307 | }; |
308 | CompletionBlock Completion; |
309 | |
310 | /// Describes hover preferences. |
311 | struct HoverBlock { |
312 | /// Whether hover show a.k.a type. |
313 | std::optional<Located<bool>> ShowAKA; |
314 | }; |
315 | HoverBlock Hover; |
316 | |
317 | /// Configures labels shown inline with the code. |
318 | struct InlayHintsBlock { |
319 | /// Enables/disables the inlay-hints feature. |
320 | std::optional<Located<bool>> Enabled; |
321 | |
322 | /// Show parameter names before function arguments. |
323 | std::optional<Located<bool>> ParameterNames; |
324 | /// Show deduced types for `auto`. |
325 | std::optional<Located<bool>> DeducedTypes; |
326 | /// Show designators in aggregate initialization. |
327 | std::optional<Located<bool>> Designators; |
328 | /// Show defined symbol names at the end of a definition block. |
329 | std::optional<Located<bool>> BlockEnd; |
330 | /// Limit the length of type name hints. (0 means no limit) |
331 | std::optional<Located<uint32_t>> TypeNameLimit; |
332 | }; |
333 | InlayHintsBlock InlayHints; |
334 | |
335 | /// Configures semantic tokens that are produced by clangd. |
336 | struct SemanticTokensBlock { |
337 | /// Disables clangd to produce semantic tokens for the given kinds. |
338 | std::vector<Located<std::string>> DisabledKinds; |
339 | /// Disables clangd to assign semantic tokens with the given modifiers. |
340 | std::vector<Located<std::string>> DisabledModifiers; |
341 | }; |
342 | SemanticTokensBlock SemanticTokens; |
343 | }; |
344 | |
345 | } // namespace config |
346 | } // namespace clangd |
347 | } // namespace clang |
348 | |
349 | #endif |
350 | |