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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang-tools-extra/clangd/ConfigFragment.h