256 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- 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;
 | 
						|
  };
 | 
						|
  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 {
 | 
						|
      /// 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
 |