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 "ConfigProvider.h" 36 #include "llvm/ADT/Optional.h" 37 #include "llvm/Support/SMLoc.h" 38 #include "llvm/Support/SourceMgr.h" 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 = {}) RangeLocated49 : 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 llvm::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_comands.json etc). 167 /// 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 /// - None: do not use a compilation database, just default flags. 171 llvm::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 llvm::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 llvm::Optional<Located<std::string>> File; 193 /// Address and port number for a clangd-index-server. e.g. 194 /// `123.1.1.1:13337`. 195 llvm::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 llvm::Optional<Located<std::string>> MountPoint; 200 }; 201 llvm::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 llvm::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 /// - None 236 llvm::Optional<Located<std::string>> UnusedIncludes; 237 238 /// Controls IncludeCleaner diagnostics. 239 struct IncludesBlock { 240 /// Regexes that will be used to avoid diagnosing certain includes as 241 /// unused or missing. These can match any suffix of the header file in 242 /// question. 243 std::vector<Located<std::string>> IgnoreHeader; 244 }; 245 IncludesBlock Includes; 246 247 /// Controls how clang-tidy will run over the code base. 248 /// 249 /// The settings are merged with any settings found in .clang-tidy 250 /// configuration files with these ones taking precedence. 251 struct ClangTidyBlock { 252 std::vector<Located<std::string>> Add; 253 /// List of checks to disable. 254 /// Takes precedence over Add. To enable all llvm checks except include 255 /// order: 256 /// Add: llvm-* 257 /// Remove: llvm-include-order 258 std::vector<Located<std::string>> Remove; 259 260 /// A Key-Value pair list of options to pass to clang-tidy checks 261 /// These take precedence over options specified in clang-tidy 262 /// configuration files. Example: 263 /// CheckOptions: 264 /// readability-braces-around-statements.ShortStatementLines: 2 265 std::vector<std::pair<Located<std::string>, Located<std::string>>> 266 CheckOptions; 267 }; 268 ClangTidyBlock ClangTidy; 269 }; 270 DiagnosticsBlock Diagnostics; 271 272 // Describes the style of the codebase, beyond formatting. 273 struct StyleBlock { 274 // Namespaces that should always be fully qualified, meaning no "using" 275 // declarations, always spell out the whole name (with or without leading 276 // ::). All nested namespaces are affected as well. 277 // Affects availability of the AddUsing tweak. 278 std::vector<Located<std::string>> FullyQualifiedNamespaces; 279 }; 280 StyleBlock Style; 281 282 /// Describes code completion preferences. 283 struct CompletionBlock { 284 /// Whether code completion should include suggestions from scopes that are 285 /// not visible. The required scope prefix will be inserted. 286 llvm::Optional<Located<bool>> AllScopes; 287 }; 288 CompletionBlock Completion; 289 290 /// Describes hover preferences. 291 struct HoverBlock { 292 /// Whether hover show a.k.a type. 293 llvm::Optional<Located<bool>> ShowAKA; 294 }; 295 HoverBlock Hover; 296 297 /// Configures labels shown inline with the code. 298 struct InlayHintsBlock { 299 /// Enables/disables the inlay-hints feature. 300 llvm::Optional<Located<bool>> Enabled; 301 302 /// Show parameter names before function arguments. 303 llvm::Optional<Located<bool>> ParameterNames; 304 /// Show deduced types for `auto`. 305 llvm::Optional<Located<bool>> DeducedTypes; 306 /// Show designators in aggregate initialization. 307 llvm::Optional<Located<bool>> Designators; 308 }; 309 InlayHintsBlock InlayHints; 310 }; 311 312 } // namespace config 313 } // namespace clangd 314 } // namespace clang 315 316 #endif 317