neo_doxygen: Generalize the concept of “member”.
[nit.git] / contrib / neo_doxygen / src / model / member.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Members.
16 module model::member
17
18 import graph
19 import type_entity
20
21 # A member or an inner class.
22 abstract class MemberOrInner
23 super CodeBlock
24
25 # The type of the introducer.
26 type INTRODUCER_TYPE: MemberIntroducer
27
28 # The node used to represent the `MProperty` node.
29 #
30 # Only defined if `self` is at the root of a reimplementation graph, and
31 # only once `put_in_graph` is called.
32 var introducer: nullable INTRODUCER_TYPE = null
33
34 init do
35 super
36 self.labels.add("MPropDef")
37 end
38
39 # Does this member introduce the property?
40 fun is_intro: Bool is abstract
41
42 redef fun put_in_graph do
43 super
44 self["is_intro"] = is_intro
45 if is_intro then
46 var visibility = self["visibility"]
47 var full_name = self["full_name"]
48 var name = self["name"]
49
50 introducer = create_introducer
51 if full_name isa String then
52 introducer.full_name = full_name
53 else if name isa String then
54 introducer.name = name
55 end
56 if visibility isa String then
57 introducer.visibility = visibility
58 end
59 introducer.put_in_graph
60 end
61 end
62
63 redef fun put_edges do
64 super
65 var intro = resolve_introducer
66
67 assert intro != null
68 graph.add_edge(self, "DEFINES", intro)
69 end
70
71 # Set the visibility.
72 fun visibility=(visibility: String) do
73 self["visibility"] = visibility
74 if introducer != null then
75 introducer.as(not null).visibility = visibility
76 end
77 end
78
79 # Get the visibility.
80 #
81 # Return `""` by default.
82 fun visibility: String do
83 var visibility = self["visibility"]
84 if visibility isa String then return visibility
85 return ""
86 end
87
88 redef fun name=(name: String) do
89 super
90 if introducer != null then
91 introducer.as(not null).name = name
92 end
93 end
94
95 redef fun full_name=(full_name: String) do
96 super
97 if introducer != null then
98 introducer.as(not null).full_name = full_name
99 end
100 end
101
102 redef fun parent_name=(parent_name: String) do
103 super
104 if introducer != null then
105 introducer.as(not null).parent_name = parent_name
106 end
107 end
108
109 # Create an instance of `MemberIntroducer` that will be linked to `self`.
110 protected fun create_introducer: INTRODUCER_TYPE is abstract
111
112 # Find the nearest reimplementation root.
113 fun resolve_introducer: nullable INTRODUCER_TYPE is abstract
114 end
115
116 # A member.
117 abstract class Member
118 super MemberOrInner
119
120 # Members that this member redefines/reimplements.
121 var reimplemented: SimpleCollection[String] = new Array[String]
122
123 # Set the static type.
124 fun static_type=(static_type: nullable TypeEntity) is abstract
125
126 # Get the static type.
127 fun static_type: nullable TypeEntity is abstract
128
129 # Append the specified parameter to the signature.
130 fun add_parameter(parameter: MemberParameter) do end
131
132 # Append a member that is reimplemeneted by `self`.
133 fun reimplement(parent: String) do
134 reimplemented.add(parent)
135 end
136
137 redef fun is_intro do return reimplemented.length <= 0
138
139 # Is the member abstract?
140 fun is_abstract=(is_abstract: Bool) do
141 self["is_abstract"] = is_abstract
142 end
143
144 # Find the nearest reimplementation root.
145 #
146 # var g = new ProjectGraph("foo")
147 # var m1 = new Attribute(g)
148 # var m2 = new Attribute(g)
149 # var m3 = new Attribute(g)
150 # #
151 # m1.model_id = "1"
152 # m1.put_in_graph
153 # m2.reimplement("1")
154 # m2.put_in_graph
155 # assert m1.resolve_introducer == m1.introducer
156 # assert m2.resolve_introducer == m1.introducer
157 # #
158 # m3.model_id = "3"
159 # m3.reimplement("3")
160 # m3.put_in_graph
161 # assert m3.resolve_introducer == null
162 redef fun resolve_introducer do
163 if introducer == null then
164 var member_queue = new List[String]
165 var visited = new HashSet[Member]
166 var member: Member
167
168 member_queue.add_all(reimplemented)
169 while not member_queue.is_empty do
170 member = graph.by_id[member_queue.shift].as(Member)
171 if visited.has(member) then
172 return null
173 else if member.is_intro then
174 return member.introducer
175 else
176 visited.add(member)
177 member_queue.add_all(member.reimplemented)
178 end
179 end
180 return null
181 else
182 return introducer
183 end
184 end
185 end
186
187 # An unrecognized member.
188 #
189 # Used to simplify the handling of ignored entities.
190 class UnknownMember
191 super Member
192
193 redef fun put_in_graph do end
194 redef fun put_edges do end
195 end
196
197 # A local definition of a method.
198 class Method
199 super Member
200
201 redef type INTRODUCER_TYPE: MethodIntroducer
202
203 # The method’s signature.
204 var signature: Signature is noinit, writable
205
206 init do
207 super
208 self.labels.add("MMethodDef")
209 self["is_intern"] = false # TODO
210 self["is_extern"] = false # TODO
211 signature = new Signature(graph)
212 is_abstract = false
213 end
214
215 # Set the return type.
216 redef fun static_type=(static_type: nullable TypeEntity) do
217 signature.return_type = static_type
218 end
219
220 # Get the return type.
221 redef fun static_type: nullable TypeEntity do return signature.return_type
222
223 redef fun add_parameter(parameter: MemberParameter) do
224 signature.parameters.add(parameter)
225 end
226
227 redef fun create_introducer do return new MethodIntroducer(graph)
228
229 redef fun put_in_graph do
230 super
231 signature.put_in_graph
232 end
233
234 redef fun put_edges do
235 super
236 graph.add_edge(self, "SIGNATURE", signature)
237 end
238 end
239
240 # A local definition of an attribute.
241 class Attribute
242 super Member
243
244 redef type INTRODUCER_TYPE: AttributeIntroducer
245
246 # The declared type.
247 redef var static_type: nullable TypeEntity = null is writable
248
249 init do
250 super
251 self.labels.add("MAttributeDef")
252 end
253
254 redef fun create_introducer do return new AttributeIntroducer(graph)
255
256 redef fun put_in_graph do
257 super
258 if static_type != null then
259 static_type.as(not null).put_in_graph
260 end
261 end
262
263 redef fun put_edges do
264 super
265 if static_type != null then
266 graph.add_edge(self, "TYPE", static_type.as(not null))
267 end
268 end
269 end
270
271 # The `MProperty` node of a root of a reimplementation graph.
272 abstract class MemberIntroducer
273 super Entity
274
275 init do
276 super
277 self.labels.add("MProperty")
278 self["visibility"] = "public"
279 end
280
281 # Set the visibility.
282 fun visibility=(visibility: String) do
283 self["visibility"] = visibility
284 end
285
286 # Get the visibility.
287 #
288 # Return `""` by default.
289 fun visibility: String do
290 var visibility = self["visibility"]
291 if visibility isa String then return visibility
292 return ""
293 end
294 end
295
296 # A `MProperty` node for a method.
297 class MethodIntroducer
298 super MemberIntroducer
299
300 init do
301 super
302 self.labels.add("MMethod")
303 self["is_init"] = false # TODO
304 end
305 end
306
307 # A `MProperty` node for an attribute.
308 class AttributeIntroducer
309 super MemberIntroducer
310
311 init do
312 super
313 self.labels.add("MAttribute")
314 end
315 end
316
317 redef class Compound
318 # Append the specified member.
319 fun declare_member(member: Member) do end
320 end