#
# Note : All nodes described here are MEntities.
#
-# `MProject`
+# `MPackage`
#
-# * labels: `MProject`, `model_name` and `MEntity`.
-# * `(:MProject)-[:ROOT]->(:MGroup)`: root of the group tree.
+# * labels: `MPackage`, `model_name` and `MEntity`.
+# * `(:MPackage)-[:ROOT]->(:MGroup)`: root of the group tree.
#
# `MGroup`
#
# * labels: `MGroup`, `model_name` and `MEntity`.
-# * `full_name`: fully qualified name.
-# * `(:MGroup)-[:PROJECT]->(:MProject)`: associated project.
+# * `(:MGroup)-[:PROJECT]->(:MPackage)`: associated package.
# * `(:MGroup)-[:PARENT]->(:MGroup)`: parent group. Does not exist for the root
# group.
# * `(:MGroup)-[:DECLARES]->(:MModule)`: modules that are direct children of
# `MModule`
#
# * labels: `MModule`, `model_name` and `MEntity`.
-# * `full_name`: fully qualified name.
# * `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
# `MClass`
#
# * labels: `MClass`, `model_name` and `MEntity`.
-# * `full_name`: fully qualified name.
# * `kind`: kind of the class (`interface`, `abstract class`, etc.)
# * `visibility`: visibility of the class.
# * `parameter_names`: JSON array listing the name of each formal generic
# `MProperty`
#
# * 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.
+# `MAttribute` `MVirtualTypeProp` or `MInnerClass`, depending on the class of
+# the represented entity.
# * `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 introduces
# the property.
#
+# Additional relationship for `MInnerClass`:
+#
+# * `(:MInnerClassDef)-[:NESTS]->(:MClass)`: actual inner class.
+#
# `MPropDef`
#
# * labels: `MPropDef`, `model_name` and `MEntity`. Must also have `MMethodDef`,
-# `MAttributeDef` or `MVirtualTypeDef`, depending on the class of the
-# represented entity.
+# `MAttributeDef`, `MVirtualTypeDef` or `MInnerClassDef`, depending on the
+# class of the represented entity.
# * `location`: origin of the definition. SEE: `Location.to_s`.
# * `(:MPropDef)-[:DEFINES]->(:MProperty)`: associated property.
#
# is bound in this definition. Exists only if this definition bound the virtual
# type to an effective type.
#
+# Additional relationship for `MInnerClassDef`:
+#
+# * `(:MInnerClassDef)-[:NESTS]->(:MClassDef)`: actual inner class'
+# definition.
+#
# `MType`
#
# * labels: `MType`, `model_name` and `MEntity`. Must also have `MClassType`,
-# `MNullableType`, `MVirtualType` or `MSignature`, depending on the class of
-# the represented entity.
+# `MNullableType`, `MVirtualType`, `MRawType` or `MSignature`, depending on the
+# class of the represented entity.
#
# Additional label and relationships for `MClassType`:
#
#
# * `(:MNullableType)-[:TYPE]->(:MType)`: base type of the nullable type.
#
+# Additional attribute and relationship for `MRawType`:
+#
+# * `text`: JSON array of the parts’ text.
+# * `(:MRawType)-[:LINK]->(:MTypePart)`: the parts that link to another entity.
+#
# Additional attribute and relationships for `MSignature`:
#
# * `parameter_names`: JSON array representing the list of the parameter names.
#
# For example, if the source code contains:
#
+# ~~~nitish
# 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
#
# MParameters are also ranked by their position in the corresponding signature.
# Rank 0 for the first parameter, 1 for the next one and etc.
+#
+# `MTypePart`
+#
+# * labels: `MTypePart`, `model_name` and `MEntity`.
+# * `rank`: position in the `MRawType`.
+# * `(:MTypePart)-[:TARGET]->(:MEntity)`: the target of the link.
module neo
-import model
+import doc::model_ext
import neo4j
import toolcontext
fun load(model: Model): Model do
var nodes: Array[NeoNode]
- toolcontext.info("Loading project node...", 1)
- nodes = client.nodes_with_labels([model_name, "MProject"])
- for node in nodes do to_mproject(model, node)
+ toolcontext.info("Loading package node...", 1)
+ nodes = client.nodes_with_labels([model_name, "MPackage"])
+ for node in nodes do to_mpackage(model, node)
toolcontext.info("Loading groups...", 1)
nodes = client.nodes_with_labels([model_name, "MGroup"])
for node in nodes do to_mgroup(model, node)
# Collect all nodes from the current `model`.
private fun collect_model_nodes(model: Model): Collection[NeoNode] do
- for mproject in model.mprojects do
- to_node(mproject)
- for mgroup in mproject.mgroups do to_node(mgroup)
+ for mpackage in model.mpackages do
+ mpackage.to_node(nodes, model_name)
+ for mgroup in mpackage.mgroups do mgroup.to_node(nodes, model_name)
end
return nodes.values
end
# Nodes associated with MEntities.
private var nodes = new HashMap[MEntity, NeoNode]
- # Get the `NeoNode` associated with `mentity`.
- # `mentities` are stored locally to avoid duplication.
- fun to_node(mentity: MEntity): NeoNode do
- if nodes.has_key(mentity) then return nodes[mentity]
- if mentity isa MProject then return mproject_node(mentity)
- if mentity isa MGroup then return mgroup_node(mentity)
- if mentity isa MModule then return mmodule_node(mentity)
- if mentity isa MClass then return mclass_node(mentity)
- if mentity isa MClassDef then return mclassdef_node(mentity)
- if mentity isa MProperty then return mproperty_node(mentity)
- if mentity isa MPropDef then return mpropdef_node(mentity)
- if mentity isa MType then return mtype_node(mentity)
- if mentity isa MParameter then return mparameter_node(mentity)
+ # Get the `MEntity` associated with `node`.
+ fun to_mentity(model: Model, node: NeoNode): MEntity do
+ if node.labels.has("MPackage") then return to_mpackage(model, node)
+ if node.labels.has("MGroup") then return to_mgroup(model, node)
+ if node.labels.has("MModule") then return to_mmodule(model, node)
+ if node.labels.has("MClass") then return to_mclass(model, node)
+ if node.labels.has("MClassDef") then return to_mclassdef(model, node)
+ if node.labels.has("MProperty") then return to_mproperty(model, node)
+ if node.labels.has("MPropDef") then return to_mpropdef(model, node)
+ if node.labels.has("MType") then return to_mtype(model, node)
+ if node.labels.has("MParameter") then return to_mparameter(model, node)
abort
end
- # Make a new `NeoNode` based on `mentity`.
- private fun make_node(mentity: MEntity): NeoNode do
- var node = new NeoNode
- nodes[mentity] = node
- node.labels.add "MEntity"
- node.labels.add model_name
- node["name"] = mentity.name
- if mentity.mdoc != null then node["mdoc"] = new JsonArray.from(mentity.mdoc.content)
- return node
- end
-
- # Build a `NeoNode` representing `mproject`.
- private fun mproject_node(mproject: MProject): NeoNode do
- var node = make_node(mproject)
- node.labels.add "MProject"
- var root = mproject.root
- if root != null then
- node.out_edges.add(new NeoEdge(node, "ROOT", to_node(root)))
- end
- return node
- end
-
- # Build a new `MProject` from a `node`.
+ # Build a new `MPackage` from a `node`.
#
- # REQUIRE `node.labels.has("MProject")`
- private fun to_mproject(model: Model, node: NeoNode): MProject do
+ # REQUIRE `node.labels.has("MPackage")`
+ private fun to_mpackage(model: Model, node: NeoNode): MPackage do
var m = mentities.get_or_null(node.id.as(Int))
- if m isa MProject then return m
-
- assert node.labels.has("MProject")
- var mproject = new MProject(node["name"].to_s, model)
- mentities[node.id.as(Int)] = mproject
- set_doc(node, mproject)
- mproject.root = to_mgroup(model, node.out_nodes("ROOT").first)
- return mproject
- end
-
- # Build a `NeoNode` representing `mgroup`.
- private fun mgroup_node(mgroup: MGroup): NeoNode do
- var node = make_node(mgroup)
- node.labels.add "MGroup"
- node["full_name"] = mgroup.full_name
- var parent = mgroup.parent
- node.out_edges.add(new NeoEdge(node, "PROJECT", to_node(mgroup.mproject)))
- if parent != null then
- node.out_edges.add(new NeoEdge(node, "PARENT", to_node(parent)))
- end
- for mmodule in mgroup.mmodules do
- node.out_edges.add(new NeoEdge(node, "DECLARES", to_node(mmodule)))
- end
- for subgroup in mgroup.in_nesting.direct_smallers do
- node.in_edges.add(new NeoEdge(node, "NESTS", to_node(subgroup)))
- end
- return node
+ if m isa MPackage then return m
+
+ assert node.labels.has("MPackage")
+ var location = to_location(node["location"].to_s)
+ var mpackage = new MPackage(node["name"].to_s, model, location)
+ mentities[node.id.as(Int)] = mpackage
+ set_doc(node, mpackage)
+ mpackage.root = to_mgroup(model, node.out_nodes("ROOT").first)
+ return mpackage
end
# Build a new `MGroup` from a `node`.
if m isa MGroup then return m
assert node.labels.has("MGroup")
- var mproject = to_mproject(model, node.out_nodes("PROJECT").first)
+ var location = to_location(node["location"].to_s)
+ var mpackage = to_mpackage(model, node.out_nodes("PROJECT").first)
var parent: nullable MGroup = null
var out = node.out_nodes("PARENT")
if not out.is_empty then
parent = to_mgroup(model, out.first)
end
- var mgroup = new MGroup(node["name"].to_s, mproject, parent)
+ var mgroup = new MGroup(node["name"].to_s, location, mpackage, parent)
mentities[node.id.as(Int)] = mgroup
set_doc(node, mgroup)
return mgroup
end
- # Build a `NeoNode` representing `mmodule`.
- private fun mmodule_node(mmodule: MModule): NeoNode do
- var node = make_node(mmodule)
- node.labels.add "MModule"
- node["full_name"] = mmodule.full_name
- node["location"] = mmodule.location.to_s
- for parent in mmodule.in_importation.direct_greaters do
- node.out_edges.add(new NeoEdge(node, "IMPORTS", to_node(parent)))
- end
- for mclass in mmodule.intro_mclasses do
- node.out_edges.add(new NeoEdge(node, "INTRODUCES", to_node(mclass)))
- end
- for mclassdef in mmodule.mclassdefs do
- node.out_edges.add(new NeoEdge(node, "DEFINES", to_node(mclassdef)))
- end
- return node
- end
-
# Build a new `MModule` from a `node`.
#
# REQUIRE `node.labels.has("MModule")`
return mmodule
end
- # Build a `NeoNode` representing `mclass`.
- private fun mclass_node(mclass: MClass): NeoNode do
- var node = make_node(mclass)
- node.labels.add "MClass"
- 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
-
# Build a new `MClass` from a `node`.
#
# REQUIRE `node.labels.has("MClass")`
assert node.labels.has("MClass")
var mmodule = to_mmodule(model, node.in_nodes("INTRODUCES").first)
var name = node["name"].to_s
+ var location = to_location(node["location"].to_s)
var kind = to_kind(node["kind"].to_s)
var visibility = to_visibility(node["visibility"].to_s)
var parameter_names = new Array[String]
parameter_names.add e.to_s
end
end
- var mclass = new MClass(mmodule, name, parameter_names, kind, visibility)
+ var mclass = new MClass(mmodule, name, location, parameter_names, kind, visibility)
mentities[node.id.as(Int)] = mclass
set_doc(node, mclass)
return mclass
end
- # Build a `NeoNode` representing `mclassdef`.
- private fun mclassdef_node(mclassdef: MClassDef): NeoNode do
- var node = make_node(mclassdef)
- node.labels.add "MClassDef"
- node["location"] = mclassdef.location.to_s
- 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
- node.out_edges.add(new NeoEdge(node, "INTRODUCES", to_node(mproperty)))
- end
- for mpropdef in mclassdef.mpropdefs do
- node.out_edges.add(new NeoEdge(node, "DECLARES", to_node(mpropdef)))
- end
- for sup in mclassdef.supertypes do
- node.out_edges.add(new NeoEdge(node, "INHERITS", to_node(sup)))
- end
- return node
- end
-
# Build a new `MClassDef` from a `node`.
#
# REQUIRE `node.labels.has("MClassDef")`
return mclassdef
end
- # Build a `NeoNode` representing `mproperty`.
- private fun mproperty_node(mproperty: MProperty): NeoNode do
- var node = make_node(mproperty)
- node.labels.add "MProperty"
- node["full_name"] = mproperty.full_name
- node["visibility"] = mproperty.visibility.to_s
- if mproperty isa MMethod then
- node.labels.add "MMethod"
- node["is_init"] = mproperty.is_init
- else if mproperty isa MAttribute then
- node.labels.add "MAttribute"
- else if mproperty isa MVirtualTypeProp then
- node.labels.add "MVirtualTypeProp"
- end
- node.out_edges.add(new NeoEdge(node, "INTRO_CLASSDEF", to_node(mproperty.intro_mclassdef)))
- return node
- end
-
# Build a new `MProperty` from a `node`.
#
# REQUIRE `node.labels.has("MProperty")`
assert node.labels.has("MProperty")
var intro_mclassdef = to_mclassdef(model, node.out_nodes("INTRO_CLASSDEF").first)
var name = node["name"].to_s
+ var location = to_location(node["location"].to_s)
var visibility = to_visibility(node["visibility"].to_s)
var mprop: nullable MProperty = null
if node.labels.has("MMethod") then
- mprop = new MMethod(intro_mclassdef, name, visibility)
+ mprop = new MMethod(intro_mclassdef, name, location, visibility)
mprop.is_init = node["is_init"].as(Bool)
else if node.labels.has("MAttribute") then
- mprop = new MAttribute(intro_mclassdef, name, visibility)
+ mprop = new MAttribute(intro_mclassdef, name, location, visibility)
else if node.labels.has("MVirtualTypeProp") then
- mprop = new MVirtualTypeProp(intro_mclassdef, name, visibility)
+ mprop = new MVirtualTypeProp(intro_mclassdef, name, location, visibility)
+ else if node.labels.has("MInnerClass") then
+ var inner = to_mclass(model, node.out_nodes("NESTS").first)
+ mprop = new MInnerClass(intro_mclassdef, name, location, visibility, inner)
end
if mprop == null then
print "not yet implemented to_mproperty for {node.labels.join(",")}"
return mprop
end
- # Build a `NeoNode` representing `mpropdef`.
- private fun mpropdef_node(mpropdef: MPropDef): NeoNode do
- var node = make_node(mpropdef)
- node.labels.add "MPropDef"
- node["location"] = mpropdef.location.to_s
- node.out_edges.add(new NeoEdge(node, "DEFINES", to_node(mpropdef.mproperty)))
- if mpropdef isa MMethodDef then
- node.labels.add "MMethodDef"
- node["is_abstract"] = mpropdef.is_abstract
- node["is_intern"] = mpropdef.is_intern
- node["is_extern"] = mpropdef.is_extern
- var msignature = mpropdef.msignature
- if msignature != null then
- node.out_edges.add(new NeoEdge(node, "SIGNATURE", to_node(msignature)))
- end
- else if mpropdef isa MAttributeDef then
- node.labels.add "MAttributeDef"
- var static_mtype = mpropdef.static_mtype
- if static_mtype != null then
- node.out_edges.add(new NeoEdge(node, "TYPE", to_node(static_mtype)))
- end
- else if mpropdef isa MVirtualTypeDef then
- node.labels.add "MVirtualTypeDef"
- var bound = mpropdef.bound
- if bound != null then
- node.out_edges.add(new NeoEdge(node, "BOUND", to_node(bound)))
- end
- end
- return node
- end
-
# Build a new `MPropDef` from a `node`.
#
# REQUIRE `node.labels.has("MPropDef")`
mentities[node.id.as(Int)] = mpropdef
var bound = node.out_nodes("BOUND")
if not bound.is_empty then mpropdef.bound = to_mtype(model, bound.first)
+ else if node.labels.has("MInnerClassDef") then
+ var inner = to_mclassdef(model, node.out_nodes("NESTS").first)
+ mpropdef = new MInnerClassDef(mclassdef,
+ mproperty.as(MInnerClass), location, inner)
+ mentities[node.id.as(Int)] = mpropdef
end
if mpropdef == null then
print "not yet implemented to_mpropdef for {node.labels.join(",")}"
return mpropdef
end
- # Build a `NeoNode` representing `mtype`.
- private fun mtype_node(mtype: MType): NeoNode do
- var node = make_node(mtype)
- node.labels.add "MType"
- if mtype isa MClassType then
- node.labels.add "MClassType"
- node.out_edges.add(new NeoEdge(node, "CLASS", to_node(mtype.mclass)))
- for arg in mtype.arguments do
- node.out_edges.add(new NeoEdge(node, "ARGUMENT", to_node(arg)))
- end
- if mtype isa MGenericType then
- node.labels.add "MGenericType"
- end
- else if mtype isa MVirtualType then
- node.labels.add "MVirtualType"
- node.out_edges.add(new NeoEdge(node, "PROPERTY", to_node(mtype.mproperty)))
- else if mtype isa MParameterType then
- node.labels.add "MParameterType"
- node["rank"] = mtype.rank
- node.out_edges.add(new NeoEdge(node, "CLASS", to_node(mtype.mclass)))
- else if mtype isa MNullableType then
- node.labels.add "MNullableType"
- node.out_edges.add(new NeoEdge(node, "TYPE", to_node(mtype.mtype)))
- else if mtype isa MSignature then
- node.labels.add "MSignature"
- var names = new JsonArray
- var rank = 0
- for mparameter in mtype.mparameters do
- names.add mparameter.name
- var pnode = to_node(mparameter)
- pnode["rank"] = rank
- node.out_edges.add(new NeoEdge(node, "PARAMETER", pnode))
- end
- if not names.is_empty then node["parameter_names"] = names
- var return_mtype = mtype.return_mtype
- if return_mtype != null then
- node.out_edges.add(new NeoEdge(node, "RETURNTYPE", to_node(return_mtype)))
- end
- end
- return node
- end
-
# Build a new `MType` from a `node`.
#
# REQUIRE `node.labels.has("MType")`
var mtype = new MSignature(mparameters, return_mtype)
mentities[node.id.as(Int)] = mtype
return mtype
+ else if node.labels.has("MRawType") then
+ var mtype = new MRawType(model)
+ var parts = node["text"]
+ if parts isa JsonArray then
+ for p in parts do
+ mtype.parts.add(new MTypePart(model, p.to_s, null))
+ end
+ for pnode in node.out_nodes("LINK") do
+ assert pnode.labels.has("MTypePart")
+ if not pnode.out_nodes("TARGET").is_empty then
+ var rank = pnode["rank"]
+ var target = to_mentity(model, pnode.out_nodes("TARGET").first)
+ assert rank isa Int
+ mtype.parts[rank] = mtype.parts[rank].link_to(target)
+ end
+ end
+ end
+ mentities[node.id.as(Int)] = mtype
+ return mtype
end
print "not yet implemented to_mtype for {node.labels.join(",")}"
abort
end
- # Build a `NeoNode` representing `mparameter`.
- private fun mparameter_node(mparameter: MParameter): NeoNode do
- var node = make_node(mparameter)
- node.labels.add "MParameter"
- node["name"] = mparameter.name
- node["is_vararg"] = mparameter.is_vararg
- node.out_edges.add(new NeoEdge(node, "TYPE", to_node(mparameter.mtype)))
- return node
- end
-
# Build a new `MParameter` from `node`.
#
# REQUIRE `node.labels.has("MParameter")`
end
# Get a `Location` from its string representation.
- private fun to_location(loc: String): Location do
- #TODO filepath
- var parts = loc.split_with(":")
- var file = new SourceFile.from_string(parts[0], "")
- var pos = parts[1].split_with("--")
- var pos1 = pos[0].split_with(",")
- var pos2 = pos[1].split_with(",")
- var line_s = pos1[0].to_i
- var line_e = pos2[0].to_i
- var column_s = pos1[1].to_i
- var column_e = 0
- if pos2.length == 2 then pos2[1].to_i
- return new Location(file, line_s, line_e, column_s, column_e)
+ private fun to_location(loc: String): nitc::Location do
+ return new nitc::Location.from_string(loc)
end
# Get a `MVisibility` from its string representation.
return protected_visibility
else if vis == private_visibility.to_s then
return private_visibility
+ else if vis == package_visibility.to_s then
+ return package_visibility
else
return none_visibility
end
return enum_kind
else if kind == extern_kind.to_s then
return extern_kind
+ else
+ return raw_kind(kind)
end
- abort
end
# Extract the `MDoc` from `node` and link it to `mentity`.
for e in node["mdoc"].as(JsonArray) do
lines.add e.to_s#.replace("\n", "\\n")
end
- var mdoc = new MDoc
+ var location = to_location(node["mdoc_location"].to_s)
+ var mdoc = new MDoc(location)
mdoc.content.add_all(lines)
mdoc.original_mentity = mentity
mentity.mdoc = mdoc
end
end
end
+
+redef class MPackage
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ var root = root
+ if root != null then
+ node.out_edges.add(new NeoEdge(node, "ROOT", root.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MGroup
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ var parent = parent
+ node.out_edges.add(new NeoEdge(node, "PROJECT", mpackage.to_node(nodes, model_name)))
+ if parent != null then
+ node.out_edges.add(new NeoEdge(node, "PARENT", parent.to_node(nodes, model_name)))
+ end
+ for mmodule in mmodules do
+ node.out_edges.add(new NeoEdge(node, "DECLARES", mmodule.to_node(nodes, model_name)))
+ end
+ for subgroup in in_nesting.direct_smallers do
+ node.in_edges.add(new NeoEdge(node, "NESTS", subgroup.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MModule
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ for parent in in_importation.direct_greaters do
+ node.out_edges.add(new NeoEdge(node, "IMPORTS", parent.to_node(nodes, model_name)))
+ end
+ for mclass in intro_mclasses do
+ node.out_edges.add(new NeoEdge(node, "INTRODUCES", mclass.to_node(nodes, model_name)))
+ end
+ for mclassdef in mclassdefs do
+ node.out_edges.add(new NeoEdge(node, "DEFINES", mclassdef.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MClass
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node["kind"] = kind.to_s
+ node["visibility"] = visibility.to_s
+ if not mparameters.is_empty then
+ var parameter_names = new Array[String]
+ for p in mparameters do parameter_names.add(p.name)
+ node["parameter_names"] = new JsonArray.from(parameter_names)
+ end
+ node.out_edges.add(new NeoEdge(node, "CLASSTYPE", mclass_type.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MClassDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.out_edges.add(new NeoEdge(node, "BOUNDTYPE", bound_mtype.to_node(nodes, model_name)))
+ node.out_edges.add(new NeoEdge(node, "MCLASS", mclass.to_node(nodes, model_name)))
+ for mproperty in intro_mproperties do
+ node.out_edges.add(new NeoEdge(node, "INTRODUCES", mproperty.to_node(nodes, model_name)))
+ end
+ for mpropdef in mpropdefs do
+ node.out_edges.add(new NeoEdge(node, "DECLARES", mpropdef.to_node(nodes, model_name)))
+ end
+ for sup in supertypes do
+ node.out_edges.add(new NeoEdge(node, "INHERITS", sup.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MProperty
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = make_node(nodes, model_name)
+ node.labels.add "MProperty"
+ node["visibility"] = visibility.to_s
+ node.out_edges.add(new NeoEdge(node, "INTRO_CLASSDEF", intro_mclassdef.to_node(nodes, model_name)))
+ node.labels.add self.class_name
+ return node
+ end
+end
+
+redef class MMethod
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node["is_init"] = is_init
+ return node
+ end
+end
+
+redef class MInnerClass
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.out_edges.add(new NeoEdge(node, "NESTS", inner.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MPropDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = make_node(nodes, model_name)
+ node.labels.add "MPropDef"
+ node.out_edges.add(new NeoEdge(node, "DEFINES", mproperty.to_node(nodes, model_name)))
+ node.labels.add self.class_name
+ return node
+ end
+end
+
+redef class MMethodDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node["is_abstract"] = is_abstract
+ node["is_intern"] = is_intern
+ node["is_extern"] = is_extern
+ var msignature = msignature
+ if msignature != null then
+ node.out_edges.add(new NeoEdge(node, "SIGNATURE", msignature.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MAttributeDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ var static_mtype = static_mtype
+ if static_mtype != null then
+ node.out_edges.add(new NeoEdge(node, "TYPE", static_mtype.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MVirtualTypeDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ var bound = bound
+ if bound != null then
+ node.out_edges.add(new NeoEdge(node, "BOUND", bound.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MInnerClassDef
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.out_edges.add(new NeoEdge(node, "NESTS", inner.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MTypePart
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ if self.target != null then
+ var target_node = self.target.as(not null).to_node(nodes, model_name)
+ node.out_edges.add(new NeoEdge(node, "TARGET", target_node))
+ end
+ return node
+ end
+end
+
+redef class MParameter
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node["name"] = self.name
+ node["is_vararg"] = self.is_vararg
+ node.out_edges.add(new NeoEdge(node, "TYPE", self.mtype.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MClassType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MClassType"
+ node.out_edges.add(new NeoEdge(node, "CLASS", mclass.to_node(nodes, model_name)))
+ for arg in arguments do
+ node.out_edges.add(new NeoEdge(node, "ARGUMENT", arg.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+
+redef class MGenericType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MGenericType"
+ return node
+ end
+end
+
+redef class MVirtualType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MVirtualType"
+ node.out_edges.add(new NeoEdge(node, "PROPERTY", mproperty.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MParameterType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MParameterType"
+ node["rank"] = rank
+ node.out_edges.add(new NeoEdge(node, "CLASS", mclass.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MNullableType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MNullableType"
+ node.out_edges.add(new NeoEdge(node, "TYPE", mtype.to_node(nodes, model_name)))
+ return node
+ end
+end
+
+redef class MSignature
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MSignature"
+ var names = new JsonArray
+ var rank = 0
+ for mparameter in mparameters do
+ names.add mparameter.name
+ var pnode = mparameter.to_node(nodes, model_name)
+ pnode["rank"] = rank
+ node.out_edges.add(new NeoEdge(node, "PARAMETER", pnode))
+ rank += 1
+ end
+ if not names.is_empty then node["parameter_names"] = names
+ var return_mtype = return_mtype
+ if return_mtype != null then
+ node.out_edges.add(new NeoEdge(node, "RETURNTYPE", return_mtype.to_node(nodes, model_name)))
+ end
+ return node
+ end
+end
+
+redef class MRawType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = super
+ node.labels.add "MRawType"
+ var text = new JsonArray
+ var rank = 0
+ for part in self.parts do
+ text.add part.text
+ if part.target != null then
+ var pnode = part.to_node(nodes, model_name)
+ pnode["rank"] = rank
+ node.out_edges.add(new NeoEdge(node, "LINK", pnode))
+ end
+ rank += 1
+ end
+ if not text.is_empty then node["text"] = text
+ return node
+ end
+end
+
+redef class MType
+ redef fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = make_node(nodes, model_name)
+ node.labels.add "MType"
+ return node
+ end
+end
+
+redef class MEntity
+ # Build a `NeoNode` representing `self`.
+ private fun to_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ if nodes.has_key(self) then return nodes[self]
+ var node = make_node(nodes, model_name)
+ node.labels.add self.class_name
+ return node
+ end
+
+ # Make a new `NeoNode` based on `mentity`.
+ private fun make_node(nodes: HashMap[MEntity, NeoNode], model_name: nullable String): NeoNode do
+ var node = new NeoNode
+ nodes[self] = node
+ node.labels.add "MEntity"
+ if model_name != null then node.labels.add model_name
+ node["name"] = self.name
+ if not self isa MSignature then
+ #FIXME: MSignature is a MEntity, but has no model :/
+ node["location"] = self.location.to_s
+ end
+ var mdoc = self.mdoc
+ if mdoc != null then
+ node["mdoc"] = new JsonArray.from(mdoc.content)
+ node["mdoc_location"] = mdoc.location.to_s
+ end
+ return node
+ end
+end