| 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 "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 | /// 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>> ; |
| 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>> ; |
| 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>> ; |
| 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>> ; |
| 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>> ; |
| 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 | |