# Save and load `Model` from/to Neo4j base.
#
# Nit models are composed by MEntities.
-# This module creates NeoNode for each MEntity found in a `Model` and save them into Neo4j database.
+# This module creates NeoNode for each MEntity found in a `Model` and save them
+# into Neo4j database.
#
# see `Neo4jClient`.
#
#
# Structure of the nit `Model` in base:
#
+# Note : Any null or empty attribute will not be saved in the database.
+#
# For any `MEntity` (in addition to specific data):
#
-# * Generic labels: model name (`model_name`) and `MEntity`.
+# * labels: model name (`model_name`) and `MEntity`.
# * `name`: short (unqualified) name.
# * `mdoc`: JSON array representing the associated Markdown documentation
-# (one item by line). Does not exist if there is no associated documentation.
+# (one item by line).
#
-# Note : All nodes in the model are `MEntity`.
+# Note : All nodes described here are MEntities.
#
# `MProject`
#
-# * Specific label: `MProject`
+# * labels: `MProject`, `model_name` and `MEntity`.
# * `(:MProject)-[:ROOT]->(:MGroup)`: root of the group tree.
#
# `MGroup`
#
-# * Specific label: `MGroup`
+# * labels: `MGroup`, `model_name` and `MEntity`.
# * `full_name`: fully qualified name.
# * `(:MGroup)-[:PROJECT]->(:MProject)`: associated project.
-# * `(:MGroup)-[:PARENT]->(:MGroup)`: parent group. Does not exist for the root group.
-# * `(:MGroup)-[:DECLARES]->(:MModule)`: modules that are direct children of this group.
-# * `(:MGroup)-[:NESTS]->(:MGroup)`: subgroups that are direct children of this group.
+# * `(:MGroup)-[:PARENT]->(:MGroup)`: parent group. Does not exist for the root
+# group.
+# * `(:MGroup)-[:DECLARES]->(:MModule)`: modules that are direct children of
+# this group.
+# * `(:MGroup)-[:NESTS]->(:MGroup)`: nested groups that are direct children of
+# this group.
#
# `MModule`
#
-# * Specific label: `MModule`
+# * labels: `MModule`, `model_name` and `MEntity`.
# * `full_name`: fully qualified name.
-# * `location`: origin of the definition. See `Location.to_s`.
+# * `location`: origin of the definition. SEE: `Location.to_s`
# * `(:MModule)-[:IMPORTS]->(:MModule)`: modules that are imported directly.
-# * `(:MModule)-[:INTRODUCES]->(:MClass)`: all by classes introduced by this module.
-# * `(:MModule)-[:DEFINES]->(:MClassDef)`: all class definitons contained in this module.
+# * `(:MModule)-[:INTRODUCES]->(:MClass)`: all by classes introduced by this
+# module.
+# * `(:MModule)-[:DEFINES]->(:MClassDef)`: all class definitons contained in
+# this module.
#
# `MClass`
#
-# * Specific label: `MClass`
+# * labels: `MClass`, `model_name` and `MEntity`.
# * `full_name`: fully qualified name.
# * `arity`: number of generic formal parameters. 0 if the class is not generic.
# * `kind`: kind of the class (`interface`, `abstract class`, etc.)
# * `visibility`: visibility of the class.
-# * `(:MClass)-[:CLASSTYPE]->(:MClassType)`: principal static type of the class.
+# * `(:MClass)-[:CLASSTYPE]->(:MClassType)`: SEE: `MClass.mclass_type`
+#
+# Arguments in the `CLASSTYPE` are named following the `parameter_names`
+# attribute of the `MClassDef` that introduces the class. A class definition
+# introduces a class if and only if it has this class as `MCLASS` and
+# has `is_intro` set to `true`.
#
# `MClassDef`
#
-# * Specific label: `MClassDef`
-# * `is_intro`: indicates if this definition introduces the class.
-# * `location`: origin of the definition. See `Location.to_s`.
+# * labels: `MClassDef`, `model_name` and `MEntity`.
+# * `is_intro`: Does this definition introduce the class?
+# * `location`: origin of the definition. SEE: `Location.to_s`
# * `parameter_names`: JSON array listing the name of each formal generic
-# parameter (in order of declaration). Does not exist if there is no formal
-# generic parameter.
-# * `(:MClassDef)-[:BOUNDTYPE]->(:MClassType)`: bounded type associated to the classdef.
+# parameter (in order of declaration).
+# * `(:MClassDef)-[:BOUNDTYPE]->(:MClassType)`: bounded type associated to the
+# classdef.
# * `(:MClassDef)-[:MCLASS]->(:MClass)`: associated `MClass`.
-# * `(:MClassDef)-[:INTRODUCES]->(:MProperty)`: all properties introduced by the classdef.
-# * `(:MClassDef)-[:DECLARES]->(:MPropDef)`: all property definitions in the classdef (introductions and redefinitions).
+# * `(:MClassDef)-[:INTRODUCES]->(:MProperty)`: all properties introduced by
+# the classdef.
+# * `(:MClassDef)-[:DECLARES]->(:MPropDef)`: all property definitions in the
+# classdef (introductions and redefinitions).
# * `(:MClassDef)-[:INHERITS]->(:MClassType)`: all declared super-types
#
# `MProperty`
#
-# * Specific label: `MProperty`. Must also have `MMethod`, `MAttribute` or
-# `MVirtualTypeProp`, depending on the class of the represented entity.
+# * labels: `MProperty`, `model_name` and `MEntity`. Must also have `MMethod`,
+# `MAttribute` or `MVirtualTypeProp`, depending on the class of the represented
+# entity.
# * `full_name`: fully qualified name.
# * `visibility`: visibility of the property.
-# * `is_init`: Indicates if the property is a constructor. Exists only if the node is a `MMethod`.
-# * `(:MProperty)-[:INTRO_CLASSDEF]->(:MClassDef)`: classdef that introduce the property.
+# * `is_init`: Indicates if the property is a constructor. Exists only if the
+# node is a `MMethod`.
+# * `(:MProperty)-[:INTRO_CLASSDEF]->(:MClassDef)`: classdef that introduces
+# the property.
#
# `MPropDef`
#
-# * Specific label: `MPropDef`. Must also have `MMethodDef`, `MAttributeDef` or
-# `MVirtualTypeDef`, depending on the class of the represented entity.
-# * `is_intro`: indicates if this definition introduces the property.
-# * `location`: origin of the definition. See `Location.to_s`.
+# * labels: `MPropDef`, `model_name` and `MEntity`. Must also have `MMethodDef`,
+# `MAttributeDef` or `MVirtualTypeDef`, depending on the class of the
+# represented entity.
+# * `is_intro`: Does this definition introduce the property?
+# * `location`: origin of the definition. SEE: `Location.to_s`.
# * `(:MPropDef)-[:DEFINES]->(:MProperty)`: associated property.
#
# Additional attributes and relationship for `MMethodDef`:
# * `is_abstract`: Is the method definition abstract?
# * `is_intern`: Is the method definition intern?
# * `is_extern`: Is the method definition extern?
-# * `(:MMethodDef)-[:SIGNATURE]->(:MSignature)`: signature attached to the property definition.
+# * `(:MMethodDef)-[:SIGNATURE]->(:MSignature)`: signature attached to the
+# property definition.
#
# Additional relationship for `MVirtualTypeDef`:
#
#
# `MType`
#
-# * Specific label: `MType`. Must also have `MClassType`, `MNullableType`,
-# `MVirtualType` or `MSignature`, depending on the class of the represented
-# entity.
+# * labels: `MType`, `model_name` and `MEntity`. Must also have `MClassType`,
+# `MNullableType`, `MVirtualType` or `MSignature`, depending on the class of
+# the represented entity.
#
# Additional label and relationships for `MClassType`:
#
-# * If it is a `MGenericType`, has also the `MGenericType` label.
-# * `(:MClassType)-[:CLASS]->(:MClass)`: class.
+# * If it is a `MGenericType`, also has the `MGenericType` label.
+# * `(:MClassType)-[:CLASS]->(:MClass)`: SEE: `MClassType.mclass`
# * `(:MClassType)-[:ARGUMENT]->(:MType)`: type arguments.
#
+# Arguments are named following the `parameter_names` attribute of the
+# `MClassDef` that introduces the class referred by `CLASS`.
+#
# Additional relationship for `MVirtualType`:
#
# * `(:MVirtualType)-[:PROPERTY]->(:MProperty)`: associated property that
# Additional attribute and relationship for `MParameterType`:
#
# * `rank`: position of the parameter (0 for the first parameter).
-# * `(:MParameterType)-[:CLASS]->(:MClass)`: generic class where the parameter belong.
+# * `(:MParameterType)-[:CLASS]->(:MClass)`: generic class where the parameter
+# belong.
#
# Additional relationship for `MNullableType`:
#
# * `(:MSignature)-[:RETURNTYPE]->(:MType)`: return type. Does not exist for
# procedures.
#
-# In order to maintain the correct parameters order, each `MSignature` node contains
-# an array of parameter names corresponding to the parameter order in the signature.
+# In order to maintain the correct parameters order, each `MSignature` node
+# contains an array of parameter names corresponding to the parameter order in
+# the signature.
#
# For example, if the source code contains:
#
# fun foo(a: A, b: B, c: C)
#
-# The `MSignature` node will contain a property `parameter_names = ["a", "b", "c"]` so
-# the MSignature can be reconstructed with the parameters in the correct order.
+# The `MSignature` node will contain a property
+# `parameter_names = ["a", "b", "c"]` so the MSignature can be reconstructed
+# with the parameters in the correct order.
#
# `MParameter`
#
-# * Specific label: `MParameter`
+# * labels: `MParameter`, `model_name` and `MEntity`.
# * `is_vararg`: Is the parameter a vararg?
# * `rank`: position of the parameter (0 for the first parameter).
# * `(:MParameter)-[:TYPE]->(:MType)`: static type of the parameter.
node.labels.add "MModule"
node["full_name"] = mmodule.full_name
node["location"] = mmodule.location.to_s
- var mgroup = mmodule.mgroup
for parent in mmodule.in_importation.direct_greaters do
node.out_edges.add(new NeoEdge(node, "IMPORTS", to_node(parent)))
end
private fun mclass_node(mclass: MClass): NeoNode do
var node = make_node(mclass)
node.labels.add "MClass"
- node["arity"] = mclass.arity
node["full_name"] = mclass.full_name
node["kind"] = mclass.kind.to_s
node["visibility"] = mclass.visibility.to_s
+ if not mclass.mparameters.is_empty then
+ var parameter_names = new Array[String]
+ for p in mclass.mparameters do parameter_names.add(p.name)
+ node["parameter_names"] = new JsonArray.from(parameter_names)
+ end
node.out_edges.add(new NeoEdge(node, "CLASSTYPE", to_node(mclass.mclass_type)))
return node
end
assert node.labels.has("MClass")
var mmodule = to_mmodule(model, node.in_nodes("INTRODUCES").first)
var name = node["name"].to_s
- var arity = node["arity"].to_s.to_i
var kind = to_kind(node["kind"].to_s)
var visibility = to_visibility(node["visibility"].to_s)
- var mclass = new MClass(mmodule, name, arity, kind, visibility)
+ var parameter_names = new Array[String]
+ if node.has_key("parameter_names") then
+ for e in node["parameter_names"].as(JsonArray) do
+ parameter_names.add e.to_s
+ end
+ end
+ var mclass = new MClass(mmodule, name, parameter_names, kind, visibility)
mentities[node] = mclass
set_doc(node, mclass)
return mclass
node.labels.add "MClassDef"
node["is_intro"] = mclassdef.is_intro
node["location"] = mclassdef.location.to_s
- if not mclassdef.parameter_names.is_empty then
- node["parameter_names"] = new JsonArray.from(mclassdef.parameter_names)
- end
node.out_edges.add(new NeoEdge(node, "BOUNDTYPE", to_node(mclassdef.bound_mtype)))
node.out_edges.add(new NeoEdge(node, "MCLASS", to_node(mclassdef.mclass)))
for mproperty in mclassdef.intro_mproperties do
var mmodule = to_mmodule(model, node.in_nodes("DEFINES").first)
var mtype = to_mtype(model, node.out_nodes("BOUNDTYPE").first).as(MClassType)
var location = to_location(node["location"].to_s)
- var parameter_names = new Array[String]
- if node.has_key("parameter_names") then
- for e in node["parameter_names"].as(JsonArray) do
- parameter_names.add e.to_s
- end
- end
- var mclassdef = new MClassDef(mmodule, mtype, location, parameter_names)
+ var mclassdef = new MClassDef(mmodule, mtype, location)
mentities[node] = mclassdef
set_doc(node, mclassdef)
var supertypes = new Array[MClassType]
else if node.labels.has("MParameterType") then
var mclass = to_mclass(model, node.out_nodes("CLASS").first)
var rank = node["rank"].to_s.to_i
- var mtype = new MParameterType(mclass, rank)
+ var mtype = mclass.mparameters[rank]
mentities[node] = mtype
return mtype
else if node.labels.has("MNullableType") then
var intype = to_mtype(model, node.out_nodes("TYPE").first)
- var mtype = new MNullableType(intype)
+ var mtype = intype.as_nullable
mentities[node] = mtype
return mtype
else if node.labels.has("MVirtualType") then
var mproperty = to_mproperty(model, node.out_nodes("PROPERTY").first)
- var mtype = new MVirtualType(mproperty)
+ assert mproperty isa MVirtualTypeProp
+ var mtype = mproperty.mvirtualtype
mentities[node] = mtype
return mtype
else if node.labels.has("MSignature") then