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 |
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(args: Subject, args: Predicate, args: Object) == |
39 | std::tie(args: Other.Subject, args: Other.Predicate, args: Other.Object); |
40 | } |
41 | // SPO order |
42 | bool operator<(const Relation &Other) const { |
43 | return std::tie(args: Subject, args: Predicate, args: Object) < |
44 | std::tie(args: Other.Subject, args: Other.Predicate, args: 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 | |
60 | const_iterator begin() const { return Relations.begin(); } |
61 | const_iterator end() const { return Relations.end(); } |
62 | size_t size() const { return Relations.size(); } |
63 | bool empty() const { return Relations.empty(); } |
64 | |
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. |
78 | void insert(const Relation &R) { Relations.push_back(x: 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: |
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 | |