Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / nitserial.nit
index 1c24d69..2b347f1 100644 (file)
 # generate and include its own serialization support module.
 module nitserial
 
-import frontend
-import rapid_type_analysis
 import template
+import gen_nit
 
-# A Nit module
-#
-# TODO add more features and move to lib
-class NitModule
-       super Template
-
-       var header: nullable Writable = null
-
-       # The module's name
-       var name: Writable
-
-       # Imports from this module
-       var imports = new Array[Writable]
-
-       # Main content of this module
-       var content = new Array[Writable]
-
-       redef fun rendering
-       do
-               var header = header
-               if header != null then add header
-
-               var name = name
-               add "module {name}\n\n"
-
-               for i in imports do add "import {i}\n"
-               add "\n"
-
-               for l in content do add "{l}\n"
-       end
-end
+import frontend
+import rapid_type_analysis
 
 redef class ToolContext
        # Where do we put a single result?
@@ -87,25 +57,24 @@ redef class MModule
 end
 
 redef class MType
-       # Is this type fully visible from `mmodule`?
-       fun is_visible_from(mmodule: MModule): Bool is abstract
+       # List classes composing this type
+       private fun related_mclasses(mmodule: MModule): Array[MClass] is abstract
 end
 
 redef class MClassType
-       redef fun is_visible_from(mmodule) do
-               return mmodule.is_visible(mclass.intro_mmodule, mclass.visibility)
-       end
+       redef fun related_mclasses(mmodule) do return [mclass]
 end
 
-redef class MNullableType
-       redef fun is_visible_from(mmodule) do return mtype.is_visible_from(mmodule)
+redef class MProxyType
+       redef fun related_mclasses(mmodule) do return undecorate.related_mclasses(mmodule)
 end
 
 redef class MGenericType
-       redef fun is_visible_from(mmodule)
+       redef fun related_mclasses(mmodule)
        do
-               for arg_mtype in arguments do if not arg_mtype.is_visible_from(mmodule) then return false
-               return super
+               var mods = super
+               for arg_mtype in arguments do mods.add_all(arg_mtype.related_mclasses(mmodule))
+               return mods
        end
 end
 
@@ -188,6 +157,8 @@ for mmodule in mmodules do
        if importations == null then importations = target_modules
 
        var nit_module = new NitModule(module_name)
+       nit_module.annotations.add """generated"""
+       nit_module.annotations.add """no_warning("property-conflict")"""
        nit_module.header = """
 # This file is generated by nitserial
 # Do not modify, but you can redef
@@ -217,10 +188,25 @@ redef class Deserializer
                        # and which are visible.
                        if mtype isa MGenericType and
                           mtype.is_subtype(m, null, serializable_type) and
-                          mtype.is_visible_from(mmodule) and
                           mtype.mclass.kind == concrete_kind and
                           not compiled_types.has(mtype) then
 
+                               # Intrude import the modules declaring private classes
+                               var related_mclasses = mtype.related_mclasses(mmodule)
+                               for mclass in related_mclasses do
+                                       if not mmodule.is_visible(mclass.intro_mmodule, mclass.visibility) then
+                                               var intro_mmodule = mclass.intro_mmodule
+                                               var intro_mgroup = intro_mmodule.mgroup
+
+                                               var to_import = intro_mmodule.full_name
+                                               if intro_mgroup == null or intro_mgroup.default_mmodule == intro_mmodule then
+                                                       to_import = intro_mmodule.name
+                                               end
+
+                                               nit_module.imports.add "intrude import {to_import}"
+                                       end
+                               end
+
                                compiled_types.add mtype
                                nit_module.content.add """
                if name == \"{{{mtype}}}\" then return new {{{mtype}}}.from_deserializer(self)"""