clang-tools  11.0.0
ConfigFragment.h
Go to the documentation of this file.
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/ADT/STLExtras.h"
38 #include "llvm/Support/Error.h"
39 #include "llvm/Support/SMLoc.h"
40 #include "llvm/Support/SourceMgr.h"
41 #include <string>
42 #include <vector>
43 
44 namespace clang {
45 namespace clangd {
46 namespace config {
47 
48 /// An entity written in config along, with its optional location in the file.
49 template <typename T> struct Located {
50  Located(T Value, llvm::SMRange Range = {})
51  : Range(Range), Value(std::move(Value)) {}
52 
53  llvm::SMRange Range;
54  T &operator->() { return Value; }
55  const T &operator->() const { return Value; }
56  T &operator*() { return Value; }
57  const T &operator*() const { return Value; }
58 
59 private:
60  T Value;
61 };
62 
63 /// A chunk of configuration obtained from a config file, LSP, or elsewhere.
64 struct Fragment {
65  /// Parses fragments from a YAML file (one from each --- delimited document).
66  /// Documents that contained fatal errors are omitted from the results.
67  /// BufferName is used for the SourceMgr and diagnostics.
68  static std::vector<Fragment> parseYAML(llvm::StringRef YAML,
69  llvm::StringRef BufferName,
71 
72  /// Analyzes and consumes this fragment, possibly yielding more diagnostics.
73  /// This always produces a usable result (errors are recovered).
74  ///
75  /// Typically, providers will compile a Fragment once when it's first loaded,
76  /// caching the result for reuse.
77  /// Like a compiled program, this is good for performance and also encourages
78  /// errors to be reported early and only once.
79  ///
80  /// The returned function is a cheap-copyable wrapper of refcounted internals.
82 
83  /// These fields are not part of the user-specified configuration, but
84  /// instead are populated by the parser to describe the configuration source.
85  struct SourceInfo {
86  /// Retains a buffer of the original source this fragment was parsed from.
87  /// Locations within Located<T> objects point into this SourceMgr.
88  /// Shared because multiple fragments are often parsed from one (YAML) file.
89  /// May be null, then all locations should be ignored.
90  std::shared_ptr<llvm::SourceMgr> Manager;
91  /// The start of the original source for this fragment.
92  /// Only valid if SourceManager is set.
93  llvm::SMLoc Location;
94  };
96 
97  /// Conditions in the If block restrict when a Fragment applies.
98  ///
99  /// Each separate condition must match (combined with AND).
100  /// When one condition has multiple values, any may match (combined with OR).
101  /// e.g. `PathMatch: [foo/.*, bar/.*]` matches files in either directory.
102  ///
103  /// Conditions based on a file's path use the following form:
104  /// - if the fragment came from a project directory, the path is relative
105  /// - if the fragment is global (e.g. user config), the path is absolute
106  /// - paths always use forward-slashes (UNIX-style)
107  /// If no file is being processed, these conditions will not match.
108  struct IfBlock {
109  /// The file being processed must fully match a regular expression.
110  std::vector<Located<std::string>> PathMatch;
111  /// The file being processed must *not* fully match a regular expression.
112  std::vector<Located<std::string>> PathExclude;
113 
114  /// An unrecognized key was found while parsing the condition.
115  /// The condition will evaluate to false.
117  };
119 
120  /// Conditions in the CompileFlags block affect how a file is parsed.
121  ///
122  /// clangd emulates how clang would interpret a file.
123  /// By default, it behaves roughly like `clang $FILENAME`, but real projects
124  /// usually require setting the include path (with the `-I` flag), defining
125  /// preprocessor symbols, configuring warnings etc.
126  /// Often, a compilation database specifies these compile commands. clangd
127  /// searches for compile_commands.json in parents of the source file.
128  ///
129  /// This section modifies how the compile command is constructed.
131  /// List of flags to append to the compile command.
132  std::vector<Located<std::string>> Add;
133  /// List of flags to remove from the compile command.
134  ///
135  /// - If the value is a recognized clang flag (like "-I") then it will be
136  /// removed along with any arguments. Synonyms like --include-dir= will
137  /// also be removed.
138  /// - Otherwise, if the value ends in * (like "-DFOO=*") then any argument
139  /// with the prefix will be removed.
140  /// - Otherwise any argument exactly matching the value is removed.
141  ///
142  /// In all cases, -Xclang is also removed where needed.
143  ///
144  /// Example:
145  /// Command: clang++ --include-directory=/usr/include -DFOO=42 foo.cc
146  /// Remove: [-I, -DFOO=*]
147  /// Result: clang++ foo.cc
148  ///
149  /// Flags added by the same CompileFlags entry will not be removed.
150  std::vector<Located<std::string>> Remove;
151  };
153 
154  /// Controls how clangd understands code outside the current file.
155  /// clangd's indexes provide information about symbols that isn't available
156  /// to clang's parser, such as incoming references.
157  struct IndexBlock {
158  /// Whether files are built in the background to produce a project index.
159  /// This is checked for translation units only, not headers they include.
160  /// Legal values are "Build" or "Skip".
161  llvm::Optional<Located<std::string>> Background;
162  };
164 };
165 
166 } // namespace config
167 } // namespace clangd
168 } // namespace clang
169 
170 #endif
clang::clangd::config::Fragment::SourceInfo::Location
llvm::SMLoc Location
The start of the original source for this fragment.
Definition: ConfigFragment.h:93
clang::clangd::IndexFileFormat::YAML
clang::clangd::config::Fragment::parseYAML
static std::vector< Fragment > parseYAML(llvm::StringRef YAML, llvm::StringRef BufferName, DiagnosticCallback)
Parses fragments from a YAML file (one from each — delimited document).
Definition: ConfigYAML.cpp:198
clang::clangd::config::Fragment::CompileFlags
CompileFlagsBlock CompileFlags
Definition: ConfigFragment.h:152
clang::clangd::config::Fragment::CompileFlagsBlock
Conditions in the CompileFlags block affect how a file is parsed.
Definition: ConfigFragment.h:130
clang::clangd::config::Fragment::IndexBlock
Controls how clangd understands code outside the current file.
Definition: ConfigFragment.h:157
clang::clangd::config::Fragment::IndexBlock::Background
llvm::Optional< Located< std::string > > Background
Whether files are built in the background to produce a project index.
Definition: ConfigFragment.h:161
ConfigProvider.h
clang::clangd::config::Fragment::compile
CompiledFragment compile(DiagnosticCallback) &&
Analyzes and consumes this fragment, possibly yielding more diagnostics.
Definition: ConfigCompile.cpp:225
clang::clangd::config::Fragment::IfBlock::PathMatch
std::vector< Located< std::string > > PathMatch
The file being processed must fully match a regular expression.
Definition: ConfigFragment.h:110
clang::clangd::config::Located::operator*
const T & operator*() const
Definition: ConfigFragment.h:57
clang::clangd::config::Located::Range
llvm::SMRange Range
Definition: ConfigFragment.h:53
clang::clangd::config::Fragment::IfBlock
Conditions in the If block restrict when a Fragment applies.
Definition: ConfigFragment.h:108
clang::clangd::config::Located
An entity written in config along, with its optional location in the file.
Definition: ConfigFragment.h:49
clang::clangd::config::Located::Located
Located(T Value, llvm::SMRange Range={})
Definition: ConfigFragment.h:50
clang::clangd::config::Located::operator->
T & operator->()
Definition: ConfigFragment.h:54
clang::clangd::config::Located::operator->
const T & operator->() const
Definition: ConfigFragment.h:55
clang::clangd::config::Fragment::Source
SourceInfo Source
Definition: ConfigFragment.h:95
clang::clangd::config::Fragment::Index
IndexBlock Index
Definition: ConfigFragment.h:163
clang::clangd::config::Located::operator*
T & operator*()
Definition: ConfigFragment.h:56
clang::clangd::config::CompiledFragment
std::function< bool(const Params &, Config &)> CompiledFragment
A chunk of configuration that has been fully analyzed and is ready to apply.
Definition: ConfigProvider.h:54
clang::clangd::config::Fragment::SourceInfo::Manager
std::shared_ptr< llvm::SourceMgr > Manager
Retains a buffer of the original source this fragment was parsed from.
Definition: ConfigFragment.h:90
clang::clangd::Range
Definition: Protocol.h:173
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::config::Fragment::IfBlock::HasUnrecognizedCondition
bool HasUnrecognizedCondition
An unrecognized key was found while parsing the condition.
Definition: ConfigFragment.h:116
clang::clangd::config::Fragment::SourceInfo
These fields are not part of the user-specified configuration, but instead are populated by the parse...
Definition: ConfigFragment.h:85
clang::clangd::config::Fragment::IfBlock::PathExclude
std::vector< Located< std::string > > PathExclude
The file being processed must not fully match a regular expression.
Definition: ConfigFragment.h:112
clang::clangd::config::Fragment
A chunk of configuration obtained from a config file, LSP, or elsewhere.
Definition: ConfigFragment.h:64
clang::clangd::config::Fragment::If
IfBlock If
Definition: ConfigFragment.h:118
clang::clangd::config::Fragment::CompileFlagsBlock::Remove
std::vector< Located< std::string > > Remove
List of flags to remove from the compile command.
Definition: ConfigFragment.h:150
clang::clangd::config::Fragment::CompileFlagsBlock::Add
std::vector< Located< std::string > > Add
List of flags to append to the compile command.
Definition: ConfigFragment.h:132
clang::clangd::config::DiagnosticCallback
llvm::function_ref< void(const llvm::SMDiagnostic &)> DiagnosticCallback
Used to report problems in parsing or interpreting a config.
Definition: ConfigProvider.h:47