brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.4 KiB · b62b15d Raw
245 lines · c
1//===--- Index.h -------------------------------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H11 12#include "index/Ref.h"13#include "index/Relation.h"14#include "index/Symbol.h"15#include "index/SymbolID.h"16#include "llvm/ADT/DenseSet.h"17#include "llvm/ADT/FunctionExtras.h"18#include "llvm/Support/JSON.h"19#include <mutex>20#include <optional>21#include <string>22 23namespace clang {24namespace clangd {25 26struct FuzzyFindRequest {27  /// A query string for the fuzzy find. This is matched against symbols'28  /// un-qualified identifiers and should not contain qualifiers like "::".29  std::string Query;30  /// If this is non-empty, symbols must be in at least one of the scopes31  /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::"32  /// is provided, the matched symbols must be defined in namespace xyz but not33  /// namespace xyz::abc.34  ///35  /// The global scope is "", a top level scope is "foo::", etc.36  std::vector<std::string> Scopes;37  /// If set to true, allow symbols from any scope. Scopes explicitly listed38  /// above will be ranked higher.39  bool AnyScope = false;40  /// The number of top candidates to return. The index may choose to41  /// return more than this, e.g. if it doesn't know which candidates are best.42  std::optional<uint32_t> Limit;43  /// If set to true, only symbols for completion support will be considered.44  bool RestrictForCodeCompletion = false;45  /// Contextually relevant files (e.g. the file we're code-completing in).46  /// Paths should be absolute.47  std::vector<std::string> ProximityPaths;48  /// Preferred types of symbols. These are raw representation of `OpaqueType`.49  std::vector<std::string> PreferredTypes;50 51  bool operator==(const FuzzyFindRequest &Req) const {52    return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,53                    ProximityPaths, PreferredTypes) ==54           std::tie(Req.Query, Req.Scopes, Req.Limit,55                    Req.RestrictForCodeCompletion, Req.ProximityPaths,56                    Req.PreferredTypes);57  }58  bool operator!=(const FuzzyFindRequest &Req) const { return !(*this == Req); }59};60bool fromJSON(const llvm::json::Value &Value, FuzzyFindRequest &Request,61              llvm::json::Path);62llvm::json::Value toJSON(const FuzzyFindRequest &Request);63 64struct LookupRequest {65  llvm::DenseSet<SymbolID> IDs;66};67 68struct RefsRequest {69  llvm::DenseSet<SymbolID> IDs;70  RefKind Filter = RefKind::All;71  /// If set, limit the number of refers returned from the index. The index may72  /// choose to return less than this, e.g. it tries to avoid returning stale73  /// results.74  std::optional<uint32_t> Limit;75  /// If set, populates the container of the reference.76  /// Index implementations may chose to populate containers no matter what.77  bool WantContainer = false;78};79 80struct ContainedRefsRequest {81  /// Note that RefKind::Call just restricts the matched SymbolKind to82  /// functions, not the form of the reference (e.g. address-of-function,83  /// which can indicate an indirect call, should still be caught).84  static const RefKind SupportedRefKinds = RefKind::Call;85 86  SymbolID ID;87  /// If set, limit the number of refers returned from the index. The index may88  /// choose to return less than this, e.g. it tries to avoid returning stale89  /// results.90  std::optional<uint32_t> Limit;91};92 93struct RelationsRequest {94  llvm::DenseSet<SymbolID> Subjects;95  RelationKind Predicate;96  /// If set, limit the number of relations returned from the index.97  std::optional<uint32_t> Limit;98};99 100struct ContainedRefsResult {101  /// The source location where the symbol is named.102  SymbolLocation Location;103  RefKind Kind = RefKind::Unknown;104  /// The ID of the symbol which is referred to105  SymbolID Symbol;106};107 108/// Describes what data is covered by an index.109///110/// Indexes may contain symbols but not references from a file, etc.111/// This affects merging: if a staler index contains a reference but a fresher112/// one does not, we want to trust the fresher index *only* if it actually113/// includes references in general.114enum class IndexContents : uint8_t {115  None = 0,116  Symbols = 1 << 1,117  References = 1 << 2,118  Relations = 1 << 3,119  All = Symbols | References | Relations120};121 122inline constexpr IndexContents operator&(IndexContents L, IndexContents R) {123  return static_cast<IndexContents>(static_cast<uint8_t>(L) &124                                    static_cast<uint8_t>(R));125}126 127inline constexpr IndexContents operator|(IndexContents L, IndexContents R) {128  return static_cast<IndexContents>(static_cast<uint8_t>(L) |129                                    static_cast<uint8_t>(R));130}131 132/// Interface for symbol indexes that can be used for searching or133/// matching symbols among a set of symbols based on names or unique IDs.134class SymbolIndex {135public:136  virtual ~SymbolIndex() = default;137 138  /// Matches symbols in the index fuzzily and applies \p Callback on139  /// each matched symbol before returning.140  /// If returned Symbols are used outside Callback, they must be deep-copied!141  ///142  /// Returns true if there may be more results (limited by Req.Limit).143  virtual bool144  fuzzyFind(const FuzzyFindRequest &Req,145            llvm::function_ref<void(const Symbol &)> Callback) const = 0;146 147  /// Looks up symbols with any of the given symbol IDs and applies \p Callback148  /// on each matched symbol.149  /// The returned symbol must be deep-copied if it's used outside Callback.150  virtual void151  lookup(const LookupRequest &Req,152         llvm::function_ref<void(const Symbol &)> Callback) const = 0;153 154  /// Finds all occurrences (e.g. references, declarations, definitions) of155  /// symbols and applies \p Callback on each result.156  ///157  /// Results should be returned in arbitrary order.158  /// The returned result must be deep-copied if it's used outside Callback.159  /// FIXME: there's no indication which result references which symbol.160  ///161  /// Returns true if there will be more results (limited by Req.Limit);162  virtual bool refs(const RefsRequest &Req,163                    llvm::function_ref<void(const Ref &)> Callback) const = 0;164 165  /// Find all symbols that are referenced by a symbol and apply166  /// \p Callback on each result.167  ///168  /// Results should be returned in arbitrary order.169  /// The returned result must be deep-copied if it's used outside Callback.170  ///171  /// Returns true if there will be more results (limited by Req.Limit);172  virtual bool containedRefs(173      const ContainedRefsRequest &Req,174      llvm::function_ref<void(const ContainedRefsResult &)> Callback) const = 0;175 176  /// Finds all relations (S, P, O) stored in the index such that S is among177  /// Req.Subjects and P is Req.Predicate, and invokes \p Callback for (S, O) in178  /// each.179  virtual void relations(180      const RelationsRequest &Req,181      llvm::function_ref<void(const SymbolID &Subject, const Symbol &Object)>182          Callback) const = 0;183 184  /// Finds all relations (O, P, S) stored in the index such that S is among185  /// Req.Subjects and P is Req.Predicate, and invokes \p Callback for (S, O) in186  /// each. Currently only allows the OverriddenBy relation.187  virtual void reverseRelations(188      const RelationsRequest &Req,189      llvm::function_ref<void(const SymbolID &Subject, const Symbol &Object)>190          Callback) const = 0;191 192  /// Returns function which checks if the specified file was used to build this193  /// index or not. The function must only be called while the index is alive.194  using IndexedFiles =195      llvm::unique_function<IndexContents(llvm::StringRef) const>;196  virtual IndexedFiles indexedFiles() const = 0;197 198  /// Returns estimated size of index (in bytes).199  virtual size_t estimateMemoryUsage() const = 0;200};201 202// Delegating implementation of SymbolIndex whose delegate can be swapped out.203class SwapIndex : public SymbolIndex {204public:205  // If an index is not provided, reset() must be called.206  SwapIndex(std::unique_ptr<SymbolIndex> Index = nullptr)207      : Index(std::move(Index)) {}208  void reset(std::unique_ptr<SymbolIndex>);209 210  // SymbolIndex methods delegate to the current index, which is kept alive211  // until the call returns (even if reset() is called).212  bool fuzzyFind(const FuzzyFindRequest &,213                 llvm::function_ref<void(const Symbol &)>) const override;214  void lookup(const LookupRequest &,215              llvm::function_ref<void(const Symbol &)>) const override;216  bool refs(const RefsRequest &,217            llvm::function_ref<void(const Ref &)>) const override;218  bool containedRefs(219      const ContainedRefsRequest &,220      llvm::function_ref<void(const ContainedRefsResult &)>) const override;221  void relations(const RelationsRequest &,222                 llvm::function_ref<void(const SymbolID &, const Symbol &)>)223      const override;224 225  void226  reverseRelations(const RelationsRequest &,227                   llvm::function_ref<void(const SymbolID &, const Symbol &)>)228      const override;229 230  llvm::unique_function<IndexContents(llvm::StringRef) const>231  indexedFiles() const override;232 233  size_t estimateMemoryUsage() const override;234 235private:236  std::shared_ptr<SymbolIndex> snapshot() const;237  mutable std::mutex Mutex;238  std::shared_ptr<SymbolIndex> Index;239};240 241} // namespace clangd242} // namespace clang243 244#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H245