1 #include "cursor.hpp"
2 #include "utility.hpp"
3
get_spelling() const4 std::string clangmm::Cursor::Type::get_spelling() const {
5 return to_string(clang_getTypeSpelling(cx_type));
6 }
7
get_result() const8 clangmm::Cursor::Type clangmm::Cursor::Type::get_result() const {
9 return Type(clang_getResultType(cx_type));
10 }
11
get_cursor() const12 clangmm::Cursor clangmm::Cursor::Type::get_cursor() const {
13 return Cursor(clang_getTypeDeclaration(cx_type));
14 }
15
operator ==(const Cursor::Type & rhs) const16 bool clangmm::Cursor::Type::operator==(const Cursor::Type &rhs) const {
17 return clang_equalTypes(cx_type, rhs.cx_type);
18 }
19
get_kind() const20 clangmm::Cursor::Kind clangmm::Cursor::get_kind() const {
21 return static_cast<Kind>(clang_getCursorKind(cx_cursor));
22 }
23
get_kind_spelling() const24 std::string clangmm::Cursor::get_kind_spelling() const {
25 return to_string(clang_getCursorKindSpelling(clang_getCursorKind(cx_cursor)));
26 }
27
is_similar_kind(Kind kind,Kind other_kind)28 bool clangmm::Cursor::is_similar_kind(Kind kind, Kind other_kind) {
29 auto is_function_or_method = [](Kind kind) {
30 if(kind == Kind::FunctionDecl || kind == Kind::CXXMethod || kind == Kind::FunctionTemplate)
31 return true;
32 return false;
33 };
34 auto is_class_or_struct = [](Kind kind) {
35 if(kind == Kind::ClassDecl || kind == Kind::StructDecl || kind == Kind::ClassTemplate ||
36 kind == Cursor::Kind::Constructor || kind == Cursor::Kind::Destructor || kind == Cursor::Kind::FunctionTemplate)
37 return true;
38 return false;
39 };
40 if(kind == Kind::FunctionTemplate)
41 return is_function_or_method(other_kind) || is_class_or_struct(other_kind);
42 if(is_function_or_method(kind))
43 return is_function_or_method(other_kind);
44 if(is_class_or_struct(kind))
45 return is_class_or_struct(other_kind);
46 return kind == other_kind;
47 }
48
get_type() const49 clangmm::Cursor::Type clangmm::Cursor::get_type() const {
50 return Type(clang_getCursorType(cx_cursor));
51 }
52
get_source_location() const53 clangmm::SourceLocation clangmm::Cursor::get_source_location() const {
54 return SourceLocation(clang_getCursorLocation(cx_cursor));
55 }
56
get_source_range() const57 clangmm::SourceRange clangmm::Cursor::get_source_range() const {
58 return SourceRange(clang_getCursorExtent(cx_cursor));
59 }
60
get_spelling() const61 std::string clangmm::Cursor::get_spelling() const {
62 return to_string(clang_getCursorSpelling(cx_cursor));
63 }
64
get_display_name() const65 std::string clangmm::Cursor::get_display_name() const {
66 return to_string(clang_getCursorDisplayName(cx_cursor));
67 }
68
get_token_spelling() const69 std::string clangmm::Cursor::get_token_spelling() const {
70 auto spelling = get_spelling();
71 for(size_t i = 0; i < spelling.size(); ++i) {
72 if(spelling[i] == '<' || spelling[i] == '(') {
73 if(i > 0 && spelling[0] == '~')
74 return spelling.substr(1, i - 1);
75 return spelling.substr(0, i);
76 }
77 }
78 if(!spelling.empty() && spelling[0] == '~')
79 return spelling.substr(1);
80 return spelling;
81 }
82
get_usr() const83 std::string clangmm::Cursor::get_usr() const {
84 return to_string(clang_getCursorUSR(cx_cursor));
85 }
86
get_usr_extended() const87 std::string clangmm::Cursor::get_usr_extended() const {
88 if(!is_valid_kind())
89 return std::string();
90
91 auto cursor = *this;
92 auto kind = cursor.get_kind();
93 // If constructor, destructor or function template, and the token spelling is equal, set cursor to parent
94 if(kind == Cursor::Kind::Constructor || kind == Cursor::Kind::Destructor ||
95 kind == Cursor::Kind::FunctionTemplate) {
96 auto parent = cursor.get_semantic_parent();
97 auto parent_kind = parent.get_kind();
98 if((parent_kind == Cursor::Kind::ClassDecl || parent_kind == Cursor::Kind::StructDecl || parent_kind == Cursor::Kind::ClassTemplate) &&
99 cursor.get_token_spelling() == parent.get_token_spelling())
100 cursor = parent;
101 }
102
103 std::string usr = cursor.get_token_spelling();
104 auto parent = cursor.get_semantic_parent();
105 while((kind = parent.get_kind()) != Kind::TranslationUnit && parent.is_valid_kind()) {
106 if(kind == Kind::CXXMethod || kind == Kind::FunctionDecl || kind == Kind::FunctionTemplate ||
107 kind == Kind::Constructor || kind == Kind::Destructor) {
108 auto canonical = cursor.get_canonical();
109 auto location = canonical.get_source_location();
110 auto offset = location.get_offset();
111 return std::to_string(offset.line) + ':' + std::to_string(offset.index) + ':' + location.get_path();
112 }
113 usr += ':' + parent.get_token_spelling();
114 parent = parent.get_semantic_parent();
115 }
116 return usr;
117 }
118
get_all_usr_extended() const119 std::unordered_set<std::string> clangmm::Cursor::get_all_usr_extended() const {
120 std::unordered_set<std::string> usrs;
121 if(get_kind() == Kind::CXXMethod) {
122 class Recursive {
123 public:
124 static void overridden(std::unordered_set<std::string> &usrs, const Cursor &cursor) {
125 usrs.emplace(cursor.get_usr_extended());
126 CXCursor *cursors;
127 unsigned size;
128 clang_getOverriddenCursors(cursor.cx_cursor, &cursors, &size);
129 for(unsigned c = 0; c < size; ++c)
130 overridden(usrs, cursors[c]);
131 clang_disposeOverriddenCursors(cursors);
132 }
133 };
134 Recursive::overridden(usrs, *this);
135 return usrs;
136 }
137 else {
138 usrs.emplace(get_usr_extended());
139 return usrs;
140 }
141 }
142
get_referenced() const143 clangmm::Cursor clangmm::Cursor::get_referenced() const {
144 return Cursor(clang_getCursorReferenced(cx_cursor));
145 }
146
get_canonical() const147 clangmm::Cursor clangmm::Cursor::get_canonical() const {
148 return Cursor(clang_getCanonicalCursor(cx_cursor));
149 }
150
get_definition() const151 clangmm::Cursor clangmm::Cursor::get_definition() const {
152 return Cursor(clang_getCursorDefinition(cx_cursor));
153 }
154
get_semantic_parent() const155 clangmm::Cursor clangmm::Cursor::get_semantic_parent() const {
156 return Cursor(clang_getCursorSemanticParent(cx_cursor));
157 }
158
get_children() const159 std::vector<clangmm::Cursor> clangmm::Cursor::get_children() const {
160 std::vector<Cursor> result;
161 clang_visitChildren(cx_cursor, [](CXCursor cur, CXCursor /*parent*/, CXClientData data) {
162 static_cast<std::vector<Cursor> *>(data)->emplace_back(cur);
163 return CXChildVisit_Continue;
164 }, &result);
165 return result;
166 }
167
get_arguments() const168 std::vector<clangmm::Cursor> clangmm::Cursor::get_arguments() const {
169 std::vector<Cursor> cursors;
170 auto size = clang_Cursor_getNumArguments(cx_cursor);
171 for(int c = 0; c < size; ++c)
172 cursors.emplace_back(clang_Cursor_getArgument(cx_cursor, c));
173 return cursors;
174 }
175
get_all_overridden_cursors() const176 std::vector<clangmm::Cursor> clangmm::Cursor::get_all_overridden_cursors() const {
177 std::vector<Cursor> result;
178 if(get_kind() != Kind::CXXMethod)
179 return result;
180
181 class Recursive {
182 public:
183 static void overridden(std::vector<Cursor> &result, const Cursor &cursor, int depth) {
184 if(depth > 0)
185 result.emplace_back(cursor);
186 CXCursor *cursors;
187 unsigned size;
188 clang_getOverriddenCursors(cursor.cx_cursor, &cursors, &size);
189 for(unsigned c = 0; c < size; ++c)
190 overridden(result, cursors[c], depth + 1);
191 clang_disposeOverriddenCursors(cursors);
192 }
193 };
194 Recursive::overridden(result, *this, 0);
195 return result;
196 }
197
operator bool() const198 clangmm::Cursor::operator bool() const {
199 return !clang_Cursor_isNull(cx_cursor);
200 }
201
operator ==(const Cursor & rhs) const202 bool clangmm::Cursor::operator==(const Cursor &rhs) const {
203 return clang_equalCursors(cx_cursor, rhs.cx_cursor);
204 }
205
hash() const206 unsigned clangmm::Cursor::hash() const {
207 return clang_hashCursor(cx_cursor);
208 }
209
is_valid_kind() const210 bool clangmm::Cursor::is_valid_kind() const {
211 auto referenced = clang_getCursorReferenced(cx_cursor);
212 if(clang_Cursor_isNull(referenced))
213 return false;
214 auto kind = get_kind();
215 return kind > Kind::UnexposedDecl && (kind < Kind::FirstInvalid || kind > Kind::LastInvalid);
216 }
217
get_type_description() const218 std::string clangmm::Cursor::get_type_description() const {
219 auto type = clang_getCursorType(cx_cursor);
220 if(type.kind != CXTypeKind::CXType_Invalid && type.kind != CXTypeKind::CXType_Unexposed)
221 return to_string(clang_getTypeSpelling(type));
222
223 auto referenced = clang_getCursorReferenced(cx_cursor);
224 if(!clang_Cursor_isNull(referenced)) {
225 auto type = clang_getCursorType(referenced);
226 if(type.kind != CXTypeKind::CXType_Invalid)
227 return to_string(clang_getTypeSpelling(type));
228 }
229
230 return get_spelling();
231 }
232
get_brief_comments() const233 std::string clangmm::Cursor::get_brief_comments() const {
234 std::string comment_string;
235 auto referenced = get_referenced();
236 if(referenced) {
237 comment_string = to_string(clang_Cursor_getBriefCommentText(referenced.cx_cursor));
238 }
239 return comment_string;
240 }
241