1 //===--- Relation.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_RELATION_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_RELATION_H 11 12 #include "index/SymbolID.h" 13 #include "llvm/ADT/iterator_range.h" 14 #include <cstdint> 15 #include <utility> 16 17 namespace clang { 18 namespace clangd { 19 20 enum class RelationKind : uint8_t { 21 BaseOf, 22 OverriddenBy, 23 }; 24 25 /// Represents a relation between two symbols. 26 /// For an example: 27 /// - "A is a base class of B" is represented as 28 /// { Subject = A, Predicate = BaseOf, Object = B }. 29 /// - "Derived::Foo overrides Base::Foo" is represented as 30 /// { Subject = Base::Foo, Predicate = OverriddenBy, Object = Derived::Foo 31 /// }. 32 struct Relation { 33 SymbolID Subject; 34 RelationKind Predicate; 35 SymbolID Object; 36 37 bool operator==(const Relation &Other) const { 38 return std::tie(Subject, Predicate, Object) == 39 std::tie(Other.Subject, Other.Predicate, Other.Object); 40 } 41 // SPO order 42 bool operator<(const Relation &Other) const { 43 return std::tie(Subject, Predicate, Object) < 44 std::tie(Other.Subject, Other.Predicate, Other.Object); 45 } 46 }; 47 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const RelationKind R); 48 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Relation &R); 49 50 class RelationSlab { 51 public: 52 using value_type = Relation; 53 using const_iterator = std::vector<value_type>::const_iterator; 54 using iterator = const_iterator; 55 56 RelationSlab() = default; 57 RelationSlab(RelationSlab &&Slab) = default; 58 RelationSlab &operator=(RelationSlab &&RHS) = default; 59 begin()60 const_iterator begin() const { return Relations.begin(); } end()61 const_iterator end() const { return Relations.end(); } size()62 size_t size() const { return Relations.size(); } empty()63 bool empty() const { return Relations.empty(); } 64 bytes()65 size_t bytes() const { 66 return sizeof(*this) + sizeof(value_type) * Relations.capacity(); 67 } 68 69 /// Lookup all relations matching the given subject and predicate. 70 llvm::iterator_range<iterator> lookup(const SymbolID &Subject, 71 RelationKind Predicate) const; 72 73 /// RelationSlab::Builder is a mutable container that can 'freeze' to 74 /// RelationSlab. 75 class Builder { 76 public: 77 /// Adds a relation to the slab. insert(const Relation & R)78 void insert(const Relation &R) { Relations.push_back(R); } 79 80 /// Consumes the builder to finalize the slab. 81 RelationSlab build() &&; 82 83 private: 84 std::vector<Relation> Relations; 85 }; 86 87 private: RelationSlab(std::vector<Relation> Relations)88 RelationSlab(std::vector<Relation> Relations) 89 : Relations(std::move(Relations)) {} 90 91 std::vector<Relation> Relations; 92 }; 93 94 } // namespace clangd 95 } // namespace clang 96 97 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_RELATION_H 98