1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
//===--- ConfigFragment.h - Unit of user-specified configuration -*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Various clangd features have configurable behaviour (or can be disabled).
// The configuration system allows users to control this:
// - in a user config file, a project config file, via LSP, or via flags
// - specifying different settings for different files
//
// This file defines the config::Fragment structure which models one piece of
// configuration as obtained from a source like a file.
//
// This is distinct from how the config is interpreted (CompiledFragment),
// combined (Provider) and exposed to the rest of clangd (Config).
//
//===----------------------------------------------------------------------===//
//
// To add a new configuration option, you must:
// - add its syntactic form to Fragment
// - update ConfigYAML.cpp to parse it
// - add its semantic form to Config (in Config.h)
// - update ConfigCompile.cpp to map Fragment -> Config
// - make use of the option inside clangd
// - document the new option (config.md in the llvm/clangd-www repository)
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONFIGFRAGMENT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CONFIGFRAGMENT_H
#include "ConfigProvider.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include <string>
#include <vector>
namespace clang {
namespace clangd {
namespace config {
/// An entity written in config along, with its optional location in the file.
template <typename T> struct Located {
Located(T Value, llvm::SMRange Range = {})
: Range(Range), Value(std::move(Value)) {}
llvm::SMRange Range;
T *operator->() { return &Value; }
const T *operator->() const { return &Value; }
T &operator*() { return Value; }
const T &operator*() const { return Value; }
private:
T Value;
};
/// A chunk of configuration obtained from a config file, LSP, or elsewhere.
struct Fragment {
/// Parses fragments from a YAML file (one from each --- delimited document).
/// Documents that contained fatal errors are omitted from the results.
/// BufferName is used for the SourceMgr and diagnostics.
static std::vector<Fragment> parseYAML(llvm::StringRef YAML,
llvm::StringRef BufferName,
DiagnosticCallback);
/// Analyzes and consumes this fragment, possibly yielding more diagnostics.
/// This always produces a usable result (errors are recovered).
///
/// Typically, providers will compile a Fragment once when it's first loaded,
/// caching the result for reuse.
/// Like a compiled program, this is good for performance and also encourages
/// errors to be reported early and only once.
///
/// The returned function is a cheap-copyable wrapper of refcounted internals.
CompiledFragment compile(DiagnosticCallback) &&;
/// These fields are not part of the user-specified configuration, but
/// instead are populated by the parser to describe the configuration source.
struct SourceInfo {
/// Retains a buffer of the original source this fragment was parsed from.
/// Locations within Located<T> objects point into this SourceMgr.
/// Shared because multiple fragments are often parsed from one (YAML) file.
/// May be null, then all locations should be ignored.
std::shared_ptr<llvm::SourceMgr> Manager;
/// The start of the original source for this fragment.
/// Only valid if SourceManager is set.
llvm::SMLoc Location;
/// Absolute path to directory the fragment is associated with. Relative
/// paths mentioned in the fragment are resolved against this.
std::string Directory;
/// Whether this fragment is allowed to make critical security/privacy
/// decisions.
bool Trusted = false;
};
SourceInfo Source;
/// Conditions in the If block restrict when a Fragment applies.
///
/// Each separate condition must match (combined with AND).
/// When one condition has multiple values, any may match (combined with OR).
/// e.g. `PathMatch: [foo/.*, bar/.*]` matches files in either directory.
///
/// Conditions based on a file's path use the following form:
/// - if the fragment came from a project directory, the path is relative
/// - if the fragment is global (e.g. user config), the path is absolute
/// - paths always use forward-slashes (UNIX-style)
/// If no file is being processed, these conditions will not match.
struct IfBlock {
/// The file being processed must fully match a regular expression.
std::vector<Located<std::string>> PathMatch;
/// The file being processed must *not* fully match a regular expression.
std::vector<Located<std::string>> PathExclude;
/// An unrecognized key was found while parsing the condition.
/// The condition will evaluate to false.
bool HasUnrecognizedCondition = false;
};
IfBlock If;
/// Conditions in the CompileFlags block affect how a file is parsed.
///
/// clangd emulates how clang would interpret a file.
/// By default, it behaves roughly like `clang $FILENAME`, but real projects
/// usually require setting the include path (with the `-I` flag), defining
/// preprocessor symbols, configuring warnings etc.
/// Often, a compilation database specifies these compile commands. clangd
/// searches for compile_commands.json in parents of the source file.
///
/// This section modifies how the compile command is constructed.
struct CompileFlagsBlock {
/// List of flags to append to the compile command.
std::vector<Located<std::string>> Add;
/// List of flags to remove from the compile command.
///
/// - If the value is a recognized clang flag (like "-I") then it will be
/// removed along with any arguments. Synonyms like --include-dir= will
/// also be removed.
/// - Otherwise, if the value ends in * (like "-DFOO=*") then any argument
/// with the prefix will be removed.
/// - Otherwise any argument exactly matching the value is removed.
///
/// In all cases, -Xclang is also removed where needed.
///
/// Example:
/// Command: clang++ --include-directory=/usr/include -DFOO=42 foo.cc
/// Remove: [-I, -DFOO=*]
/// Result: clang++ foo.cc
///
/// Flags added by the same CompileFlags entry will not be removed.
std::vector<Located<std::string>> Remove;
/// Directory to search for compilation database (compile_comands.json etc).
/// Valid values are:
/// - A single path to a directory (absolute, or relative to the fragment)
/// - Ancestors: search all parent directories (the default)
/// - None: do not use a compilation database, just default flags.
llvm::Optional<Located<std::string>> CompilationDatabase;
};
CompileFlagsBlock CompileFlags;
/// Controls how clangd understands code outside the current file.
/// clangd's indexes provide information about symbols that isn't available
/// to clang's parser, such as incoming references.
struct IndexBlock {
/// Whether files are built in the background to produce a project index.
/// This is checked for translation units only, not headers they include.
/// Legal values are "Build" or "Skip".
llvm::Optional<Located<std::string>> Background;
/// An external index uses data source outside of clangd itself. This is
/// usually prepared using clangd-indexer.
/// Exactly one source (File/Server) should be configured.
struct ExternalBlock {
/// Whether the block is explicitly set to `None`. Can be used to clear
/// any external index specified before.
Located<bool> IsNone = false;
/// Path to an index file generated by clangd-indexer. Relative paths may
/// be used, if config fragment is associated with a directory.
llvm::Optional<Located<std::string>> File;
/// Address and port number for a clangd-index-server. e.g.
/// `123.1.1.1:13337`.
llvm::Optional<Located<std::string>> Server;
/// Source root governed by this index. Default is the directory
/// associated with the config fragment. Absolute in case of user config
/// and relative otherwise. Should always use forward-slashes.
llvm::Optional<Located<std::string>> MountPoint;
};
llvm::Optional<Located<ExternalBlock>> External;
};
IndexBlock Index;
/// Controls behavior of diagnostics (errors and warnings).
struct DiagnosticsBlock {
/// Diagnostic codes that should be suppressed.
///
/// Valid values are:
/// - *, to disable all diagnostics
/// - diagnostic codes exposed by clangd (e.g unknown_type, -Wunused-result)
/// - clang internal diagnostic codes (e.g. err_unknown_type)
/// - warning categories (e.g. unused-result)
/// - clang-tidy check names (e.g. bugprone-narrowing-conversions)
///
/// This is a simple filter. Diagnostics can be controlled in other ways
/// (e.g. by disabling a clang-tidy check, or the -Wunused compile flag).
/// This often has other advantages, such as skipping some analysis.
std::vector<Located<std::string>> Suppress;
/// Controls how clang-tidy will run over the code base.
///
/// The settings are merged with any settings found in .clang-tidy
/// configiration files with these ones taking precedence.
struct ClangTidyBlock {
std::vector<Located<std::string>> Add;
/// List of checks to disable.
/// Takes precedence over Add. To enable all llvm checks except include
/// order:
/// Add: llvm-*
/// Remove: llvm-include-onder
std::vector<Located<std::string>> Remove;
/// A Key-Value pair list of options to pass to clang-tidy checks
/// These take precedence over options specified in clang-tidy
/// configuration files. Example:
/// CheckOptions:
/// readability-braces-around-statements.ShortStatementLines: 2
std::vector<std::pair<Located<std::string>, Located<std::string>>>
CheckOptions;
};
ClangTidyBlock ClangTidy;
};
DiagnosticsBlock Diagnostics;
// Describes the style of the codebase, beyond formatting.
struct StyleBlock {
// Namespaces that should always be fully qualified, meaning no "using"
// declarations, always spell out the whole name (with or without leading
// ::). All nested namespaces are affected as well.
// Affects availability of the AddUsing tweak.
std::vector<Located<std::string>> FullyQualifiedNamespaces;
};
StyleBlock Style;
/// Describes code completion preferences.
struct CompletionBlock {
/// Whether code completion should include suggestions from scopes that are
/// not visible. The required scope prefix will be inserted.
llvm::Optional<Located<bool>> AllScopes;
};
CompletionBlock Completion;
};
} // namespace config
} // namespace clangd
} // namespace clang
#endif
|