neo_doxygen: Generalize the concept of “member”.
[nit.git] / contrib / neo_doxygen / src / model / class_compound.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 # Nodes for classes.
16 module model::class_compound
17
18 import graph
19 import member
20 import type_entity
21
22 # A class.
23 class ClassCompound
24 super Compound
25
26 # The corresponding type.
27 #
28 # In the case of a generic class, defines bounds for type parameters.
29 var class_type: ClassType is noinit
30
31 # The definition.
32 var class_def: ClassDef is noinit
33
34 init do
35 super
36 class_type = new ClassType(graph)
37 class_type.class_compound = self
38 class_def = new ClassDef(graph, self)
39 self.labels.add("MClass")
40 kind = "class"
41 visibility = "public"
42 end
43
44 # Return the number of type parameters.
45 fun arity: Int do return class_type.arity
46
47 redef fun name=(name: String) do
48 super
49 class_type.name = name
50 class_def.name = name
51 end
52
53 redef fun full_name=(full_name: String) do
54 super
55 class_type.full_name = full_name
56 class_def.full_name = full_name
57 end
58
59 redef fun parent_name=(parent_name: String) do
60 super
61 class_type.parent_name = parent_name
62 class_def.parent_name = parent_name
63 end
64
65 redef fun location=(location: nullable Location) do
66 super
67 class_def.location = location
68 end
69
70 redef fun set_mdoc do
71 super
72 class_def["mdoc"] = doc
73 end
74
75 redef fun declare_super(id: String, full_name: String, prot: String, virt: String) do
76 class_def.declare_super(id, full_name, prot, virt)
77 end
78
79 redef fun declare_member(member: Member) do
80 class_def.declare_member(member)
81 end
82
83 # Append the specified type parameter.
84 fun add_type_parameter(parameter: TypeParameter) do
85 class_type.arguments.add(parameter)
86 end
87
88 redef fun put_in_graph do
89 super
90 class_type.put_in_graph
91 class_def.put_in_graph
92 end
93
94 redef fun put_edges do
95 super
96 graph.add_edge(self, "CLASSTYPE", class_type)
97 if arity > 0 then
98 var names = new JsonArray
99
100 for p in class_type.arguments do
101 names.add(p.name)
102 end
103 self["parameter_names"] = names
104 end
105 end
106 end
107
108 # The `MClassDef` node of a class.
109 class ClassDef
110 super CodeBlock
111
112 # The defined class.
113 var class_compound: ClassCompound
114
115 # The `model_id` of the base classes.
116 var supers: SimpleCollection[String] = new Array[String]
117
118 # The set of the introduced/redefined members.
119 #
120 # Includes inner classes.
121 #
122 # To ensure that the `full_name` of each member is correctly set,
123 # `declare_member` or `declare_class` should be used to add each member.
124 #
125 # Note: `declare_class` is defined by the `inner_class` module.
126 var members: SimpleCollection[MemberOrInner] = new Array[MemberOrInner]
127
128 init do
129 super
130 self.labels.add("MClassDef")
131 self["is_intro"] = true
132 end
133
134 # Declare a base compound (usually, a base class).
135 #
136 # Parameters:
137 #
138 # * `id`: `model_id` of the base compound. May be empty.
139 # * `full_name`: qualified name of the base compound. May be empty.
140 # * `prot`: visibility (proctection) of the relationship.
141 # * `virt`: level of virtuality of the relationship.
142 fun declare_super(id: String, full_name: String, prot: String,
143 virt: String) do
144 # TODO prot, virt, full_name
145 if "" != id then
146 supers.add(id)
147 end
148 end
149
150 # Append the specified member.
151 fun declare_member(member: Member) do
152 var full_name = self["full_name"]
153
154 if full_name != null then
155 member.parent_name = full_name.to_s
156 end
157 members.add(member)
158 end
159
160 redef fun full_name=(full_name: String) do
161 super
162 for m in members do
163 m.parent_name = full_name
164 end
165 end
166
167 redef fun parent_name=(parent_name: String) do
168 super
169 for m in members do
170 m.parent_name = full_name
171 end
172 end
173
174 redef fun put_edges do
175 super
176 graph.add_edge(self, "BOUNDTYPE", class_compound.class_type)
177 graph.add_edge(self, "MCLASS", class_compound)
178 for s in supers do
179 graph.add_edge(self, "INHERITS", graph.by_id[s].as(ClassCompound).class_type)
180 end
181 for m in members do
182 if m.is_intro then
183 var intro = m.introducer.as(not null)
184 graph.add_edge(self, "INTRODUCES", intro)
185 graph.add_edge(intro, "INTRO_CLASSDEF", self)
186 end
187 graph.add_edge(self, "DECLARES", m)
188 end
189 end
190 end
191
192 # A type defined by a class.
193 class ClassType
194 super TypeEntity
195
196 # The associated class.
197 #
198 # You may use this attribute or `class_compound_id` to specify the class.
199 var class_compound: nullable ClassCompound = null is writable
200
201 # The `model_id` of the associated class.
202 #
203 # You may use this attribute or `class_compound` to specify the class.
204 var class_compound_id: String = "" is writable
205
206 # The type arguments or the type parameters.
207 var arguments = new Array[TypeEntity]
208
209 init do
210 super
211 self.labels.add("MClassType")
212 end
213
214 # Return the number of arguments.
215 fun arity: Int do return arguments.length
216
217 # Is the class generic?
218 fun is_generic: Bool do return arity > 0
219
220 redef fun put_in_graph do
221 super
222 if is_generic then
223 self.labels.add("MGenericType")
224 else
225 var i = self.labels.index_of("MGenericType")
226 if i >= 0 then self.labels.remove_at(i)
227 end
228 end
229
230 redef fun put_edges do
231 var cls = class_compound
232
233 if cls == null and class_compound_id != "" then
234 cls = graph.by_id[class_compound_id].as(ClassCompound)
235 end
236 assert cls != null
237
238 super
239 graph.add_edge(self, "CLASS", cls)
240 assert cls.arity == self.arity
241 for i in [0..arguments.length[ do
242 var a = arguments[i]
243 if cls.class_type != self then
244 a.name = cls.class_type.arguments[i].name
245 end
246 if a isa TypeParameter then
247 a.rank = i
248 graph.add_edge(a, "CLASS", cls)
249 end
250 graph.add_edge(self, "ARGUMENT", a)
251 end
252 end
253 end