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