forked from standardese/cppast
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp_entity.hpp
More file actions
236 lines (197 loc) · 8.11 KB
/
Copy pathcpp_entity.hpp
File metadata and controls
236 lines (197 loc) · 8.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// Copyright (C) 2017-2018 Jonathan Müller <[email protected]>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.
#ifndef CPPAST_CPP_ENTITY_HPP_INCLUDED
#define CPPAST_CPP_ENTITY_HPP_INCLUDED
#include <atomic>
#include <string>
#include <type_safe/optional_ref.hpp>
#include <cppast/cpp_attribute.hpp>
#include <cppast/cpp_token.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast
{
class cpp_entity;
enum class cpp_entity_kind;
class cpp_entity_index;
struct cpp_entity_id;
class cpp_template_parameter;
class cpp_template;
/// The name of a scope.
///
/// It is a combination of a name and optional template parameters.
class cpp_scope_name
{
public:
/// \effects Creates a scope out of a given entity.
cpp_scope_name(type_safe::object_ref<const cpp_entity> entity);
/// \returns The name of the scope.
const std::string& name() const noexcept;
/// \returns Whether or not the scope is templated.
bool is_templated() const noexcept
{
return templ_.has_value();
}
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities
/// of the scope. \requires The scope is templated.
detail::iteratable_intrusive_list<cpp_template_parameter> template_parameters() const noexcept;
private:
type_safe::object_ref<const cpp_entity> entity_;
type_safe::optional_ref<const cpp_template> templ_;
};
/// The base class for all entities in the C++ AST.
class cpp_entity : detail::intrusive_list_node<cpp_entity>
{
public:
cpp_entity(const cpp_entity&) = delete;
cpp_entity& operator=(const cpp_entity&) = delete;
virtual ~cpp_entity() noexcept = default;
/// \returns The kind of the entity.
cpp_entity_kind kind() const noexcept
{
return do_get_entity_kind();
}
/// \returns The name of the entity.
/// The name is the string associated with the entity's declaration.
const std::string& name() const noexcept
{
return name_;
}
/// \returns The name of the new scope created by the entity,
/// if there is any.
type_safe::optional<cpp_scope_name> scope_name() const
{
return do_get_scope_name();
}
/// \returns A [ts::optional_ref]() to the parent entity in the AST.
type_safe::optional_ref<const cpp_entity> parent() const noexcept
{
return parent_;
}
/// \returns The documentation comment associated with that entity, if any.
/// \notes A documentation comment can have three forms:
///
/// * A C style doc comment. It is a C style comment starting with an additional `*`, i.e.
/// `/**`. One space after the leading sequence will be skipped. It ends either with `*/` or
/// `**/`. After a newline all whitespace is skipped, as well as an optional `*` followed by
/// another optional space, as well as trailing whitespace on each line. I.e. `/** a\n * b
/// */` yields the text `a\nb`.
/// * A C++ style doc comment. It is a C++ style comment starting with an additional `/` or '!`,
/// i.e. `///` or `//!`.
/// One space character after the leading sequence will be skipped,
/// as well as any trailing whitespace.
/// Two C++ style doc comments on two adjacent lines will be merged.
/// * An end of line doc comment. It is a C++ style comment starting with an '<', i.e. `//<`.
/// One space character after the leading sequence will be skipped,
/// as well as any trailing whitespace.
/// If the next line is a C++ style doc comment, it will be merged with that one.
///
/// A documentation comment is associated with an entity,
/// if for C and C++ style doc comments, the entity declaration begins
/// on the line after the last line of the comment,
/// and if for an end of line comment, the entity declaration ends
/// on the same line as the end of line comment.
///
/// This comment system is also used by [standardese](https://standardese.foonathan.net).
type_safe::optional_ref<const std::string> comment() const noexcept
{
return comment_.empty() ? nullptr : type_safe::opt_ref(&comment_);
}
/// \effects Sets the associated comment.
/// \requires The comment must not be empty, if there is one.
void set_comment(type_safe::optional<std::string> comment) noexcept
{
comment_ = comment.value_or("");
}
/// \returns The list of attributes that are specified for that entity.
const cpp_attribute_list& attributes() const noexcept
{
return attributes_;
}
/// \effects Adds an attribute for that entity.
void add_attribute(cpp_attribute attr) noexcept
{
attributes_.push_back(std::move(attr));
}
/// \effects Adds multiple arguments for that entity.
void add_attribute(const cpp_attribute_list& list) noexcept
{
attributes_.insert(attributes_.end(), list.begin(), list.end());
}
/// \returns The specified user data.
void* user_data() const noexcept
{
return user_data_.load();
}
/// \effects Sets some kind of user data.
///
/// User data is just some kind of pointer, there are no requirements.
/// The class will do no lifetime management.
///
/// User data is useful if you need to store additional data for an entity without the need to
/// maintain a registry.
void set_user_data(void* data) const noexcept
{
user_data_ = data;
}
protected:
/// \effects Creates it giving it the the name.
cpp_entity(std::string name) : name_(std::move(name)), user_data_(nullptr) {}
private:
/// \returns The kind of the entity.
virtual cpp_entity_kind do_get_entity_kind() const noexcept = 0;
/// \returns The name of the new scope created by the entity, if any.
/// By default, there is no scope created.
virtual type_safe::optional<cpp_scope_name> do_get_scope_name() const
{
return type_safe::nullopt;
}
void on_insert(const cpp_entity& parent) noexcept
{
parent_ = type_safe::ref(parent);
}
std::string name_;
std::string comment_;
cpp_attribute_list attributes_;
type_safe::optional_ref<const cpp_entity> parent_;
mutable std::atomic<void*> user_data_;
template <typename T>
friend struct detail::intrusive_list_access;
friend detail::intrusive_list_node<cpp_entity>;
};
/// A [cppast::cpp_entity]() that isn't exposed directly.
///
/// The only information available is the raw source code.
class cpp_unexposed_entity final : public cpp_entity
{
public:
static cpp_entity_kind kind() noexcept;
/// \returns A newly built and registered unexposed entity.
/// \notes It will be registered as a declaration.
static std::unique_ptr<cpp_entity> build(const cpp_entity_index& index, cpp_entity_id id,
std::string name, cpp_token_string spelling);
/// \returns A newly built unnamed unexposed entity.
/// It will not be registered.
static std::unique_ptr<cpp_entity> build(cpp_token_string spelling);
/// \returns The spelling of that entity.
const cpp_token_string& spelling() const noexcept
{
return spelling_;
}
private:
cpp_unexposed_entity(std::string name, cpp_token_string spelling)
: cpp_entity(std::move(name)), spelling_(std::move(spelling))
{}
cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_token_string spelling_;
};
/// \returns Whether or not the entity is templated.
/// If this function returns `true` that means the entity is not the "real" entity,
/// but contains just the information for the template which is the parent entity.
/// \notes Do not use this entity other to read information from the template entity.
bool is_templated(const cpp_entity& e) noexcept;
/// \returns Whether or not the given entity is "friended",
/// that is, its declaration exists as part of a [cppast::cpp_friend]() declaration.
bool is_friended(const cpp_entity& e) noexcept;
} // namespace cppast
#endif // CPPAST_CPP_ENTITY_HPP_INCLUDED