model/json: simplify the basic rendering at a maximum level
authorAlexandre Terrasa <alexandre@moz-code.org>
Wed, 25 Oct 2017 19:01:27 +0000 (15:01 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Fri, 8 Dec 2017 19:59:56 +0000 (14:59 -0500)
No more nested objects and cross-references.

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/model/model_json.nit

index a48cef2..2b78692 100644 (file)
@@ -27,76 +27,53 @@ module model_json
 import model::model_collect
 import json::static
 import json::serialization_write
-import loader
-
-# A reference to another mentity.
-class MEntityRef
-       super MEntity
-
-       # MEntity to link to.
-       var mentity: MEntity
-
-       redef fun core_serialize_to(v) do
-               v.serialize_attribute("full_name", mentity.full_name)
-       end
-end
+import catalog
+import doc_down
 
 redef class MEntity
        serialize
 
-       redef fun core_serialize_to(v) do
+       private fun core_serialize_base(v: Serializer) do
                v.serialize_attribute("name", name)
+               var mdoc = mdoc_or_fallback
+               if mdoc != null then
+                       v.serialize_attribute("synopsis", mdoc.synopsis)
+               end
+       end
+
+       redef fun core_serialize_to(v) do
+               core_serialize_base(v)
+
+               v.serialize_attribute("namespace", json_namespace)
                v.serialize_attribute("class_name", class_name)
                v.serialize_attribute("full_name", full_name)
-               v.serialize_attribute("mdoc", mdoc_or_fallback)
                v.serialize_attribute("visibility", visibility.to_s)
-               v.serialize_attribute("modifiers", collect_modifiers)
-               v.serialize_attribute("location", location)
-       end
-
-       # Serialize the full version of `self` to JSON
-       #
-       # See: `FullJsonSerializer`
-       fun serialize_to_full_json(mainmodule: MModule, plain, pretty: nullable Bool): String do
-               var stream = new StringWriter
-               var serializer = new FullJsonSerializer(stream, mainmodule)
-               serializer.plain_json = plain or else false
-               serializer.pretty_json = pretty or else false
-               serializer.serialize self
-               stream.close
-               return stream.to_s
-       end
+               var mdoc = mdoc_or_fallback
+               if mdoc != null then
+                       v.serialize_attribute("html_synopsis", mdoc.html_synopsis.write_to_string)
+               end
 
-       # Return the full json representation of `self` with references.
-       #
-       # By default, every reference to another MEntity is replaced by a pointer
-       # to the MEntity::json_id.
-       # Use this method to obtain a full object with mentities instead of pointers.
-       fun to_full_json(mainmodule: MModule): String do
-               return serialize_to_full_json(mainmodule, plain=true)
+               var modifiers = collect_modifiers
+               if modifiers.not_empty then
+                       v.serialize_attribute("modifiers", modifiers)
+               end
        end
 
-       # Same as `to_full_json` but with pretty json.
-       fun to_pretty_full_json(mainmodule: MModule): String do
-               return serialize_to_full_json(mainmodule, plain=true, pretty=true)
-       end
+       # Return `self.full_name` as an object that can be serialized to json.
+       fun json_namespace: JsonNamespace is abstract
 
-       # Sort mentities by name
-       private fun sort_entities(mentities: Collection[MEntity]): Array[MEntity] do
-               var sorter = new MEntityNameSorter
-               var sorted = mentities.to_a
-               sorter.sort(sorted)
-               return sorted
-       end
+       # Return a new MEntityRef to `self`.
+       fun to_json_ref: MEntityRef do return new MEntityRef(self)
 end
 
 redef class MDoc
        serialize
 
        redef fun core_serialize_to(v) do
-               super
-               v.serialize_attribute("content", content.join("\n"))
-               v.serialize_attribute("location", location)
+               var doc = html_documentation.write_to_string.trim
+               if not doc.is_empty then
+                       v.serialize_attribute("html_documentation", doc)
+               end
        end
 end
 
@@ -118,101 +95,137 @@ end
 redef class MPackage
        redef fun core_serialize_to(v) do
                super
-               if v isa FullJsonSerializer then
-                       v.serialize_attribute("root", to_mentity_ref(root))
-                       v.serialize_attribute("mgroups", to_mentity_refs(sort_entities(mgroups)))
-                       var ini = self.ini
-                       if ini != null then v.serialize_attribute("ini", ini.to_map)
+
+               var metadata = self.metadata
+               if metadata.license != null then
+                       v.serialize_attribute("license", metadata.license)
+               end
+               if metadata.maintainers.not_empty then
+                       v.serialize_attribute("maintainer", metadata.maintainers.first)
+               end
+               if metadata.tags.not_empty then
+                       v.serialize_attribute("tags", metadata.tags)
                end
        end
+
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               ns.add to_json_ref
+               return ns
+       end
 end
 
 redef class MGroup
-       redef fun core_serialize_to(v) do
-               super
-               if v isa FullJsonSerializer then
-                       v.serialize_attribute("is_root", is_root)
-                       v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
-                       v.serialize_attribute("default_mmodule", to_mentity_ref(default_mmodule))
-                       v.serialize_attribute("parent", to_mentity_ref(parent))
-                       v.serialize_attribute("mmodules", to_mentity_refs(sort_entities(mmodules)))
-                       v.serialize_attribute("mgroups", to_mentity_refs(sort_entities(in_nesting.direct_smallers)))
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               if parent != null then
+                       ns.prepend parent.as(not null).json_namespace
                end
+               ns.add to_json_ref
+               ns.add ">"
+               return ns
        end
 end
 
 redef class MModule
-       redef fun core_serialize_to(v) do
-               super
-               if v isa FullJsonSerializer then
-                       var view = new ModelView(model, v.mainmodule)
-                       v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
-                       v.serialize_attribute("mgroup", to_mentity_ref(mgroup))
-                       v.serialize_attribute("intro_mclasses", to_mentity_refs(sort_entities(intro_mclasses)))
-                       v.serialize_attribute("mclassdefs", to_mentity_refs(sort_entities(mclassdefs)))
-                       v.serialize_attribute("intro_mclassdefs", to_mentity_refs(sort_entities(collect_intro_mclassdefs(view))))
-                       v.serialize_attribute("redef_mclassdefs", to_mentity_refs(sort_entities(collect_redef_mclassdefs(view))))
-                       v.serialize_attribute("imports", to_mentity_refs(in_importation.direct_greaters))
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               if mgroup != null then
+                       ns.add_all mgroup.as(not null).mpackage.json_namespace
+                       ns.add "::"
                end
+               ns.add to_json_ref
+               return ns
+       end
+
+       private fun ns_for(visibility: MVisibility): JsonNamespace do
+               if visibility <= private_visibility then return json_namespace
+               var mgroup = self.mgroup
+               if mgroup == null then return json_namespace
+               return mgroup.mpackage.json_namespace
        end
 end
 
 redef class MClass
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("mparameters", mparameters)
-               if v isa FullJsonSerializer then
-                       var filter = new ModelFilter(private_visibility)
-                       var view = new ModelView(model, v.mainmodule, filter)
-                       v.serialize_attribute("intro", to_mentity_ref(intro))
-                       v.serialize_attribute("intro_mmodule", to_mentity_ref(intro_mmodule))
-                       v.serialize_attribute("mpackage", to_mentity_ref(intro_mmodule.mpackage))
-                       v.serialize_attribute("mclassdefs", to_mentity_refs(mclassdefs))
-                       v.serialize_attribute("all_mproperties", to_mentity_refs(sort_entities(collect_accessible_mproperties(view))))
-                       v.serialize_attribute("intro_mproperties", to_mentity_refs(sort_entities(collect_intro_mproperties(view))))
-                       v.serialize_attribute("redef_mproperties", to_mentity_refs(sort_entities(collect_redef_mproperties(view))))
-                       v.serialize_attribute("parents", to_mentity_refs(sort_entities(collect_parents(view))))
+
+               if mparameters.not_empty then
+                       v.serialize_attribute("mparameters", mparameters)
                end
        end
+
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               ns.add_all intro_mmodule.ns_for(visibility)
+               ns.add "::"
+               ns.add to_json_ref
+               return ns
+       end
 end
 
 redef class MClassDef
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("is_intro", is_intro)
-               v.serialize_attribute("mparameters", mclass.mparameters)
-               if v isa FullJsonSerializer then
-                       var filter = new ModelFilter(private_visibility)
-                       var view = new ModelView(model, v.mainmodule, filter)
-                       v.serialize_attribute("mmodule", to_mentity_ref(mmodule))
-                       v.serialize_attribute("mclass", to_mentity_ref(mclass))
-                       v.serialize_attribute("mpropdefs", to_mentity_refs(sort_entities(mpropdefs)))
-                       v.serialize_attribute("intro_mproperties", to_mentity_refs(sort_entities(intro_mproperties)))
-                       v.serialize_attribute("intro", to_mentity_ref(mclass.intro))
-                       v.serialize_attribute("mpackage", to_mentity_ref(mmodule.mpackage))
-                       v.serialize_attribute("intro_mpropdefs", to_mentity_refs(sort_entities(collect_intro_mpropdefs(view))))
-                       v.serialize_attribute("redef_mpropdefs", to_mentity_refs(sort_entities(collect_redef_mpropdefs(view))))
+               if is_intro then
+                       v.serialize_attribute("is_intro", true)
+               end
+               if mclass.mparameters.not_empty then
+                       v.serialize_attribute("mparameters", mclass.mparameters)
                end
        end
+
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               if is_intro then
+                       ns.add_all mmodule.ns_for(mclass.visibility)
+                       ns.add "$"
+                       ns.add mclass.to_json_ref
+               else if mclass.intro_mmodule.mpackage != mmodule.mpackage then
+                       ns.add_all mmodule.json_namespace
+                       ns.add "$"
+                       ns.add_all mclass.json_namespace
+               else if mclass.visibility > private_visibility then
+                       ns.add_all mmodule.json_namespace
+                       ns.add "$"
+                       ns.add mclass.to_json_ref
+               else
+                       ns.add_all mmodule.json_namespace
+                       ns.add "$::"
+                       ns.add mclass.intro_mmodule.to_json_ref
+                       ns.add "::"
+                       ns.add mclass.to_json_ref
+               end
+               return ns
+       end
 end
 
 redef class MProperty
-       redef fun core_serialize_to(v) do
-               super
-               if v isa FullJsonSerializer then
-                       v.serialize_attribute("intro", to_mentity_ref(intro))
-                       v.serialize_attribute("intro_mclassdef", to_mentity_ref(intro_mclassdef))
-                       v.serialize_attribute("mpropdefs", to_mentity_refs(sort_entities(mpropdefs)))
-                       v.serialize_attribute("intro_mclass", to_mentity_ref(intro_mclassdef.mclass))
-                       v.serialize_attribute("mpackage", to_mentity_ref(intro_mclassdef.mmodule.mpackage))
+       redef fun json_namespace do
+               var ns = new JsonNamespace
+               if intro_mclassdef.is_intro then
+                       ns.add_all intro_mclassdef.mmodule.ns_for(visibility)
+                       ns.add "::"
+                       ns.add intro_mclassdef.mclass.to_json_ref
+                       ns.add "::"
+                       ns.add to_json_ref
+               else
+                       ns.add_all intro_mclassdef.mmodule.json_namespace
+                       ns.add "::"
+                       ns.add intro_mclassdef.mclass.to_json_ref
+                       ns.add "::"
+                       ns.add to_json_ref
                end
+               return ns
        end
 end
 
 redef class MMethod
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("is_init", is_init)
+               if is_init then
+                       v.serialize_attribute("is_init", true)
+               end
                v.serialize_attribute("msignature", intro.msignature)
        end
 end
@@ -220,32 +233,51 @@ end
 redef class MAttribute
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("static_mtype", to_mentity_ref(intro.static_mtype))
+               v.serialize_attribute("static_mtype", intro.static_mtype)
        end
 end
 
 redef class MVirtualTypeProp
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("mvirtualtype", to_mentity_ref(mvirtualtype))
-               v.serialize_attribute("bound", to_mentity_ref(intro.bound))
+               v.serialize_attribute("bound", intro.bound)
        end
 end
 
 redef class MPropDef
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("is_intro", is_intro)
-               if v isa FullJsonSerializer then
-                       v.serialize_attribute("mclassdef", to_mentity_ref(mclassdef))
-                       v.serialize_attribute("mproperty", to_mentity_ref(mproperty))
-                       v.serialize_attribute("intro", to_mentity_ref(mproperty.intro))
-                       v.serialize_attribute("intro_mclassdef", to_mentity_ref(mproperty.intro.mclassdef))
-                       v.serialize_attribute("mmodule", to_mentity_ref(mclassdef.mmodule))
-                       v.serialize_attribute("mgroup", to_mentity_ref(mclassdef.mmodule.mgroup))
-                       v.serialize_attribute("mpackage", to_mentity_ref(mclassdef.mmodule.mpackage))
+               if is_intro then
+                       v.serialize_attribute("is_intro", true)
                end
        end
+
+       redef fun json_namespace do
+               var res = new JsonNamespace
+               res.add_all mclassdef.json_namespace
+               res.add "$"
+
+               if mclassdef.mclass == mproperty.intro_mclassdef.mclass then
+                       res.add to_json_ref
+               else
+                       if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then
+                               res.add_all mproperty.intro_mclassdef.mmodule.ns_for(mproperty.visibility)
+                               res.add "::"
+                       else if mproperty.visibility <= private_visibility then
+                               if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then
+                                       res.add "::"
+                                       res.add mproperty.intro_mclassdef.mmodule.to_json_ref
+                                       res.add "::"
+                               end
+                       end
+                       if mclassdef.mclass != mproperty.intro_mclassdef.mclass then
+                               res.add mproperty.intro_mclassdef.to_json_ref
+                               res.add "::"
+                       end
+                       res.add to_json_ref
+               end
+               return res
+       end
 end
 
 redef class MMethodDef
@@ -258,32 +290,42 @@ end
 redef class MAttributeDef
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("static_mtype", to_mentity_ref(static_mtype))
+               v.serialize_attribute("static_mtype", static_mtype)
        end
 end
 
 redef class MVirtualTypeDef
        redef fun core_serialize_to(v) do
                super
-               v.serialize_attribute("bound", to_mentity_ref(bound))
-               v.serialize_attribute("is_fixed", is_fixed)
+               v.serialize_attribute("bound", bound)
+       end
+end
+
+redef class MType
+       redef fun core_serialize_to(v) do
+               v.serialize_attribute("name", name)
+
+               var mdoc = mdoc_or_fallback
+               if mdoc != null then
+                       v.serialize_attribute("synopsis", mdoc.synopsis)
+                       v.serialize_attribute("html_synopsis", mdoc.html_synopsis.write_to_string)
+               end
        end
 end
 
+
 redef class MSignature
        redef fun core_serialize_to(v) do
                v.serialize_attribute("arity", arity)
-               v.serialize_attribute("mparams", mparameters)
-               v.serialize_attribute("return_mtype", to_mentity_ref(return_mtype))
-               v.serialize_attribute("vararg_rank", vararg_rank)
+               v.serialize_attribute("mparameters", mparameters)
+               v.serialize_attribute("return_mtype", return_mtype)
        end
 end
 
 redef class MParameterType
        redef fun core_serialize_to(v) do
                v.serialize_attribute("name", name)
-               v.serialize_attribute("rank", rank)
-               v.serialize_attribute("mtype", to_mentity_ref(mclass.intro.bound_mtype.arguments[rank]))
+               v.serialize_attribute("mtype", mclass.intro.bound_mtype.arguments[rank])
        end
 end
 
@@ -291,33 +333,46 @@ redef class MParameter
        redef fun core_serialize_to(v) do
                v.serialize_attribute("is_vararg", is_vararg)
                v.serialize_attribute("name", name)
-               v.serialize_attribute("mtype", to_mentity_ref(mtype))
+               v.serialize_attribute("mtype", mtype)
        end
 end
 
-# Create a ref to a `mentity`.
-fun to_mentity_ref(mentity: nullable MEntity): nullable MEntityRef do
-       if mentity == null then return null
-       return new MEntityRef(mentity)
+# Fullname representation that can be used to build decorated links
+#
+# * MPackage: `mpackage_name`
+# * MGroup: `(mpackage_name::)mgroup_name`
+class JsonNamespace
+       super Array[nullable JsonRef]
+       serialize
+
+       redef fun to_s do return self.join("")
+       redef fun serialize_to(v) do to_a.serialize_to(v)
+end
+
+# Something that goes in a JsonNamespace
+#
+# Can be either:
+# * a `RefToken` for tokens like `::`, `>` and `$`
+# * a `MEntityRef` for references to mentities
+interface JsonRef
+       super Serializable
 end
 
-# Return a collection of `mentities` as a JsonArray of MEntityRefs.
-fun to_mentity_refs(mentities: Collection[MEntity]): Array[MEntityRef] do
-       var array = new Array[MEntityRef]
-       for mentity in mentities do
-               var ref = to_mentity_ref(mentity)
-               if ref == null then continue
-               array.add ref
+# A reference to another mentity.
+class MEntityRef
+       super JsonRef
+
+       # MEntity to link to.
+       var mentity: MEntity
+
+       redef fun core_serialize_to(v) do
+               mentity.core_serialize_base(v)
        end
-       return array
 end
 
-# Use the FullJsonSerializer to generate the full json representation of a MEntity.
+# A namespace token representation
 #
-# See MEntity::to_full_json.
-class FullJsonSerializer
-       super JsonSerializer
-
-       # FIXME tmp use of the mainmodule, a PR is comming to clean all the JSON mess
-       var mainmodule: MModule
+# Used for namespace tokens like `::`, `>` and `$`
+redef class String
+       super JsonRef
 end