1 #pragma once
2 
3 #include "position.h"
4 
5 #include <clang-c/Index.h>
6 #include <optional.h>
7 
8 #include <array>
9 #include <string>
10 #include <vector>
11 
12 using Usr = uint64_t;
13 
14 Range ResolveCXSourceRange(const CXSourceRange& range,
15                            CXFile* cx_file = nullptr);
16 
17 class ClangCursor;
18 
19 class ClangType {
20  public:
21   ClangType();
22   ClangType(const CXType& other);
23 
24   bool operator==(const ClangType& rhs) const;
25 
26   // Returns true if this is a fundamental type like int.
is_builtin()27   bool is_builtin() const {
28     // NOTE: This will return false for pointed types. Should we call
29     //       strip_qualifiers for the user?
30     return cx_type.kind >= CXType_FirstBuiltin &&
31            cx_type.kind <= CXType_LastBuiltin;
32   }
33 
34   ClangCursor get_declaration() const;
35   std::string get_usr() const;
36   Usr get_usr_hash() const;
37   std::string get_spell_name() const;
38   ClangType get_canonical() const;
39 
40   // Try to resolve this type and remove qualifies, ie, Foo* will become Foo
41   ClangType strip_qualifiers() const;
42 
43   ClangType get_return_type() const;
44   std::vector<ClangType> get_arguments() const;
45   std::vector<ClangType> get_template_arguments() const;
46 
47   CXType cx_type;
48 };
49 
50 class ClangCursor {
51  public:
52   ClangCursor();
53   ClangCursor(const CXCursor& other);
54 
55   explicit operator bool() const;
56   bool operator==(const ClangCursor& rhs) const;
57   bool operator!=(const ClangCursor& rhs) const;
58 
59   CXCursorKind get_kind() const;
60   ClangType get_type() const;
61   std::string get_spell_name() const;
62   Range get_spell(CXFile* cx_file = nullptr) const;
63   Range get_extent() const;
64   std::string get_display_name() const;
65   std::string get_usr() const;
66   Usr get_usr_hash() const;
67   optional<Usr> get_opt_usr_hash() const;
68 
69   bool is_definition() const;
70 
71   // If the given cursor points to a template specialization, this
72   // will return the cursor pointing to the template definition.
73   // If the given cursor is not a template specialization, this will
74   // just return the same cursor.
75   //
76   // This means it is always safe to call this method.
77   ClangCursor template_specialization_to_template_definition() const;
78 
79   ClangCursor get_referenced() const;
80   ClangCursor get_canonical() const;
81   ClangCursor get_definition() const;
82   ClangCursor get_lexical_parent() const;
83   ClangCursor get_semantic_parent() const;
84   std::vector<ClangCursor> get_arguments() const;
85   bool is_valid_kind() const;
86 
87   std::string get_type_description() const;
88   std::string get_comments() const;
89 
90   std::string ToString() const;
91 
92   enum class VisitResult { Break, Continue, Recurse };
93 
94   template <typename TClientData>
95   using Visitor = VisitResult (*)(ClangCursor cursor,
96                                   ClangCursor parent,
97                                   TClientData* client_data);
98 
99   template <typename TClientData>
VisitChildren(Visitor<TClientData> visitor,TClientData * client_data)100   void VisitChildren(Visitor<TClientData> visitor,
101                      TClientData* client_data) const {
102     clang_visitChildren(cx_cursor, reinterpret_cast<CXCursorVisitor>(visitor),
103                         client_data);
104   }
105 
106   CXCursor cx_cursor;
107 };
108 
109 namespace std {
110 template <>
111 struct hash<ClangCursor> {
112   size_t operator()(const ClangCursor& x) const {
113     return clang_hashCursor(x.cx_cursor);
114   }
115 };
116 }  // namespace std
117