neo_doxygen: Quiet warning about the old-style `init`.
[nit.git] / contrib / neo_doxygen / src / model / graph.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 # Graphs and basic entities.
16 module model::graph
17
18 import neo4j
19 import location
20
21 # A Neo4j graph.
22 class NeoGraph
23 # All the nodes in the graph.
24 var all_nodes: SimpleCollection[NeoNode] = new Array[NeoNode]
25
26 # All the edges in the graph.
27 var all_edges: SimpleCollection[NeoEdge] = new Array[NeoEdge]
28
29 # Add a relationship between two nodes.
30 #
31 # Parameters are the same than for the constructor of `NeoEdge`.
32 fun add_edge(from: NeoNode, rel_type: String, to: NeoNode) do
33 all_edges.add(new NeoEdge(from, rel_type, to))
34 end
35 end
36
37 # A project’s graph.
38 class ProjectGraph
39 super NeoGraph
40
41 # The project’s name.
42 var project_name: String
43
44 # The node reperesenting the project.
45 #
46 # Once the project’s graph is initialized, this node must not be edited.
47 var project = new NeoNode
48
49 # Entities by `model_id`.
50 var by_id: Map[String, Entity] = new HashMap[String, Entity]
51
52 # Initialize a new project graph using the specified project name.
53 #
54 # The specified name will label all nodes of the project’s graph.
55 init do
56 project.labels.add(project_name)
57 project.labels.add("MEntity")
58 project.labels.add("MProject")
59 project["name"] = project_name
60 all_nodes.add(project)
61
62 var root = new RootNamespace(self)
63 root.put_in_graph
64 by_id[""] = root
65 end
66
67 # Request to all nodes in the graph to add their related edges.
68 fun put_edges do
69 all_edges.clear
70 add_edge(project, "ROOT", by_id[""])
71 for n in all_nodes do
72 if n isa Entity then
73 n.put_edges
74 end
75 end
76 end
77 end
78
79 # A model’s entity.
80 #
81 # In practice, this is the base class of every node in a `ProjectGraph`.
82 abstract class Entity
83 super NeoNode
84
85 # Graph that will embed the entity.
86 var graph: ProjectGraph
87
88 # ID of the entity in the model.
89 #
90 # Is empty for entities without an ID.
91 var model_id: String = "" is writable
92
93 # Associated documentation.
94 var doc = new JsonArray is writable
95
96 init do
97 self.labels.add(graph.project_name)
98 self.labels.add("MEntity")
99 end
100
101 # The short (unqualified) name.
102 #
103 # May be also set by `full_name=`.
104 fun name=(name: String) do
105 self["name"] = name
106 end
107
108 # The short (unqualified) name.
109 fun name: String do
110 var name = self["name"]
111 assert name isa String
112 return name
113 end
114
115 # Include the documentation of `self` in the graph.
116 protected fun set_mdoc do
117 self["mdoc"] = doc
118 end
119
120 # The namespace separator of Nit/C++.
121 fun ns_separator: String do return "::"
122
123 # The name separator used when calling `full_name=`.
124 fun name_separator: String do return ns_separator
125
126 # The full (qualified) name.
127 #
128 # Also set `name` using `name_separator`.
129 fun full_name=(full_name: String) do
130 var m: nullable Match = full_name.search_last(name_separator)
131
132 self["full_name"] = full_name
133 if m == null then
134 name = full_name
135 else
136 name = full_name.substring_from(m.after)
137 end
138 end
139
140 # The full (qualified) name.
141 fun full_name: String do
142 var full_name = self["full_name"]
143 assert full_name isa String
144 return full_name
145 end
146
147 # Set the full name using the current name and the specified parent name.
148 fun parent_name=(parent_name: String) do
149 self["full_name"] = parent_name + name_separator + self["name"].as(not null).to_s
150 end
151
152 # Set the location of the entity in the source code.
153 fun location=(location: nullable Location) do
154 self["location"] = location
155 end
156
157 # Put the entity in the graph.
158 #
159 # Called by the loader when it has finished to read the entity.
160 fun put_in_graph do
161 if doc.length > 0 then
162 set_mdoc
163 end
164 graph.all_nodes.add(self)
165 if model_id != "" then graph.by_id[model_id] = self
166 end
167
168 # Put the related edges in the graph.
169 #
170 # This method is called on each node by `ProjectGraph.put_edges`.
171 #
172 # Note: Even at this step, the entity may modify its own attributes and
173 # inner entities’ ones because some values are only known once the entity
174 # know its relationships with the rest of the graph.
175 fun put_edges do end
176 end
177
178 # An entity whose the location is mandatory.
179 abstract class CodeBlock
180 super Entity
181
182 init do
183 self["location"] = new Location
184 end
185
186 redef fun location=(location: nullable Location) do
187 if location == null then
188 super(new Location)
189 else
190 super
191 end
192 end
193 end
194
195 # A compound.
196 #
197 # Usually corresponds to a `<compounddef>` element in of the XML output of
198 # Doxygen.
199 abstract class Compound
200 super Entity
201
202 # Set the declared visibility (the proctection) of the compound.
203 fun visibility=(visibility: String) do
204 self["visibility"] = visibility
205 end
206
207 # Set the specific kind of the compound.
208 fun kind=(kind: String) do
209 self["kind"] = kind
210 end
211
212 # Declare an inner namespace.
213 #
214 # Note: Althought Doxygen indicates that the name is optional,
215 # declarations with an empty name are not supported yet.
216 #
217 # Parameters:
218 #
219 # * `id`: `model_id` of the inner namespace. May be empty.
220 # * `full_name`: qualified name of the inner namespace.
221 fun declare_namespace(id: String, full_name: String) do end
222
223 # Declare an inner class.
224 #
225 # Note: Althought Doxygen indicates that both arguments are optional,
226 # declarations with either an empty name or an empty ID are not
227 # supported yet.
228 #
229 # Parameters:
230 #
231 # * `id`: `model_id` of the inner class.
232 # * `full_name`: qualified name of the inner class.
233 fun declare_class(id: String, full_name: String) do end
234
235 # Declare a base compound (usually, a base class).
236 #
237 # Parameters:
238 #
239 # * `id`: `model_id` of the base compound. May be empty.
240 # * `full_name`: qualified name of the base compound. May be empty.
241 # * `prot`: visibility (proctection) of the relationship.
242 # * `virt`: level of virtuality of the relationship.
243 fun declare_super(id: String, full_name: String, prot: String,
244 virt: String) do end
245 end
246
247 # An unrecognized compound.
248 #
249 # Used to simplify the handling of ignored entities.
250 class UnknownCompound
251 super Compound
252
253 redef fun put_in_graph do end
254 redef fun put_edges do end
255 end
256
257 # A namespace.
258 #
259 # Corresponds to a group in Nit.
260 class Namespace
261 super Compound
262
263 # Inner namespaces (IDs).
264 #
265 # Left empty for the root namespace.
266 var inner_namespaces: SimpleCollection[String] = new Array[String]
267
268 init do
269 super
270 self.labels.add("MGroup")
271 end
272
273 redef fun declare_namespace(id: String, name: String) do
274 inner_namespaces.add(id)
275 end
276
277 redef fun put_edges do
278 super
279 graph.add_edge(self, "PROJECT", graph.project)
280 if self["name"] == self["full_name"] and self["full_name"] != "" then
281 # The root namespace does not know its children.
282 var root = graph.by_id[""]
283 graph.add_edge(self, "PARENT", root)
284 graph.add_edge(root, "NESTS", self)
285 end
286 for ns in inner_namespaces do
287 var node = graph.by_id[ns]
288 graph.add_edge(node, "PARENT", self)
289 graph.add_edge(self, "NESTS", node)
290 end
291 end
292 end
293
294 # The root namespace of a `ProjectGraph`.
295 #
296 # This the only entity in the graph whose `model_id` is really `""`.
297 # Added automatically at the initialization of a `ProjectGraph`.
298 class RootNamespace
299 super Namespace
300
301 init do
302 super
303 self["full_name"] = ""
304 self["name"] = graph.project["name"]
305 end
306
307 redef fun declare_namespace(id: String, name: String) do end
308 end