xref: /llvm-project/clang-tools-extra/clangd/ConfigFragment.h (revision 1f90797f6a9d91d61e0f66b465b0467e4c66d0e0)
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 
43 namespace clang {
44 namespace clangd {
45 namespace config {
46 
47 /// An entity written in config along, with its optional location in the file.
48 template <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 
58 private:
59   T Value;
60 };
61 
62 /// A chunk of configuration obtained from a config file, LSP, or elsewhere.
63 struct 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   CompileFlagsBlock CompileFlags;
175 
176   /// Controls how clangd understands code outside the current file.
177   /// clangd's indexes provide information about symbols that isn't available
178   /// to clang's parser, such as incoming references.
179   struct IndexBlock {
180     /// Whether files are built in the background to produce a project index.
181     /// This is checked for translation units only, not headers they include.
182     /// Legal values are "Build" or "Skip".
183     std::optional<Located<std::string>> Background;
184     /// An external index uses data source outside of clangd itself. This is
185     /// usually prepared using clangd-indexer.
186     /// Exactly one source (File/Server) should be configured.
187     struct ExternalBlock {
188       /// Whether the block is explicitly set to `None`. Can be used to clear
189       /// any external index specified before.
190       Located<bool> IsNone = false;
191       /// Path to an index file generated by clangd-indexer. Relative paths may
192       /// be used, if config fragment is associated with a directory.
193       std::optional<Located<std::string>> File;
194       /// Address and port number for a clangd-index-server. e.g.
195       /// `123.1.1.1:13337`.
196       std::optional<Located<std::string>> Server;
197       /// Source root governed by this index. Default is the directory
198       /// associated with the config fragment. Absolute in case of user config
199       /// and relative otherwise. Should always use forward-slashes.
200       std::optional<Located<std::string>> MountPoint;
201     };
202     std::optional<Located<ExternalBlock>> External;
203     // Whether the standard library visible from this file should be indexed.
204     // This makes all standard library symbols available, included or not.
205     std::optional<Located<bool>> StandardLibrary;
206   };
207   IndexBlock Index;
208 
209   /// Controls behavior of diagnostics (errors and warnings).
210   struct DiagnosticsBlock {
211     /// Diagnostic codes that should be suppressed.
212     ///
213     /// Valid values are:
214     /// - *, to disable all diagnostics
215     /// - diagnostic codes exposed by clangd (e.g unknown_type, -Wunused-result)
216     /// - clang internal diagnostic codes (e.g. err_unknown_type)
217     /// - warning categories (e.g. unused-result)
218     /// - clang-tidy check names (e.g. bugprone-narrowing-conversions)
219     ///
220     /// This is a simple filter. Diagnostics can be controlled in other ways
221     /// (e.g. by disabling a clang-tidy check, or the -Wunused compile flag).
222     /// This often has other advantages, such as skipping some analysis.
223     std::vector<Located<std::string>> Suppress;
224 
225     /// Controls how clangd will correct "unnecessary" #include directives.
226     /// clangd can warn if a header is `#include`d but not used, and suggest
227     /// removing it.
228     //
229     /// Strict means a header is unused if it does not *directly* provide any
230     /// symbol used in the file. Removing it may still break compilation if it
231     /// transitively includes headers that are used. This should be fixed by
232     /// including those headers directly.
233     ///
234     /// Valid values are:
235     /// - Strict
236     /// - std::nullopt
237     std::optional<Located<std::string>> UnusedIncludes;
238 
239     /// Controls if clangd should analyze missing #include directives.
240     /// clangd will warn if no header providing a symbol is `#include`d
241     /// (missing) directly, and suggest adding it.
242     ///
243     /// Strict means a header providing a symbol is missing if it is not
244     /// *directly #include'd. The file might still compile if the header is
245     /// included transitively.
246     ///
247     /// Valid values are:
248     /// - Strict
249     /// - std::nullopt
250     std::optional<Located<std::string>> MissingIncludes;
251 
252     /// Controls IncludeCleaner diagnostics.
253     struct IncludesBlock {
254       /// Regexes that will be used to avoid diagnosing certain includes as
255       /// unused or missing. These can match any suffix of the header file in
256       /// question.
257       std::vector<Located<std::string>> IgnoreHeader;
258 
259       /// If false (default), unused system headers will be ignored.
260       /// Standard library headers are analyzed regardless of this option.
261       std::optional<Located<bool>> AnalyzeAngledIncludes;
262     };
263     IncludesBlock Includes;
264 
265     /// Controls how clang-tidy will run over the code base.
266     ///
267     /// The settings are merged with any settings found in .clang-tidy
268     /// configuration files with these ones taking precedence.
269     struct ClangTidyBlock {
270       std::vector<Located<std::string>> Add;
271       /// List of checks to disable.
272       /// Takes precedence over Add. To enable all llvm checks except include
273       /// order:
274       ///   Add: llvm-*
275       ///   Remove: llvm-include-order
276       std::vector<Located<std::string>> Remove;
277 
278       /// A Key-Value pair list of options to pass to clang-tidy checks
279       /// These take precedence over options specified in clang-tidy
280       /// configuration files. Example:
281       ///   CheckOptions:
282       ///     readability-braces-around-statements.ShortStatementLines: 2
283       std::vector<std::pair<Located<std::string>, Located<std::string>>>
284           CheckOptions;
285 
286       /// Whether to run checks that may slow down clangd.
287       ///   Strict: Run only checks measured to be fast. (Default)
288       ///           This excludes recently-added checks we have not timed yet.
289       ///   Loose: Run checks unless they are known to be slow.
290       ///   None: Run checks regardless of their speed.
291       std::optional<Located<std::string>> FastCheckFilter;
292     };
293     ClangTidyBlock ClangTidy;
294   };
295   DiagnosticsBlock Diagnostics;
296 
297   // Describes the style of the codebase, beyond formatting.
298   struct StyleBlock {
299     // Namespaces that should always be fully qualified, meaning no "using"
300     // declarations, always spell out the whole name (with or without leading
301     // ::). All nested namespaces are affected as well.
302     // Affects availability of the AddUsing tweak.
303     std::vector<Located<std::string>> FullyQualifiedNamespaces;
304 
305     /// List of regexes for headers that should always be included with a
306     /// ""-style include. By default, and in case of a conflict with
307     /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
308     /// AngledHeaders), system headers use <> and non-system headers use "".
309     /// These can match any suffix of the header file in question.
310     /// Matching is performed against the header text, not its absolute path
311     /// within the project.
312     std::vector<Located<std::string>> QuotedHeaders;
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>> AngledHeaders;
321   };
322   StyleBlock Style;
323 
324   /// Describes code completion preferences.
325   struct CompletionBlock {
326     /// Whether code completion should include suggestions from scopes that are
327     /// not visible. The required scope prefix will be inserted.
328     std::optional<Located<bool>> AllScopes;
329     /// How to present the argument list between '()' and '<>':
330     /// valid values are enum Config::ArgumentListsPolicy values:
331     ///   None: Nothing at all
332     ///   OpenDelimiter: only opening delimiter "(" or "<"
333     ///   Delimiters: empty pair of delimiters "()" or "<>"
334     ///   FullPlaceholders: full name of both type and parameter
335     std::optional<Located<std::string>> ArgumentLists;
336   };
337   CompletionBlock Completion;
338 
339   /// Describes hover preferences.
340   struct HoverBlock {
341     /// Whether hover show a.k.a type.
342     std::optional<Located<bool>> ShowAKA;
343   };
344   HoverBlock Hover;
345 
346   /// Configures labels shown inline with the code.
347   struct InlayHintsBlock {
348     /// Enables/disables the inlay-hints feature.
349     std::optional<Located<bool>> Enabled;
350 
351     /// Show parameter names before function arguments.
352     std::optional<Located<bool>> ParameterNames;
353     /// Show deduced types for `auto`.
354     std::optional<Located<bool>> DeducedTypes;
355     /// Show designators in aggregate initialization.
356     std::optional<Located<bool>> Designators;
357     /// Show defined symbol names at the end of a definition block.
358     std::optional<Located<bool>> BlockEnd;
359     /// Show parameter names and default values of default arguments after all
360     /// of the explicit arguments.
361     std::optional<Located<bool>> DefaultArguments;
362     /// Limit the length of type name hints. (0 means no limit)
363     std::optional<Located<uint32_t>> TypeNameLimit;
364   };
365   InlayHintsBlock InlayHints;
366 
367   /// Configures semantic tokens that are produced by clangd.
368   struct SemanticTokensBlock {
369     /// Disables clangd to produce semantic tokens for the given kinds.
370     std::vector<Located<std::string>> DisabledKinds;
371     /// Disables clangd to assign semantic tokens with the given modifiers.
372     std::vector<Located<std::string>> DisabledModifiers;
373   };
374   SemanticTokensBlock SemanticTokens;
375 };
376 
377 } // namespace config
378 } // namespace clangd
379 } // namespace clang
380 
381 #endif
382