nitserial: intrude import modules when needed
authorAlexis Laferrière <alexis.laf@xymus.net>
Sat, 22 Jul 2017 01:23:07 +0000 (21:23 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Wed, 26 Jul 2017 15:03:44 +0000 (11:03 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

src/nitserial.nit
tests/sav/nitserial_args1.res

index 574bc5d..2b347f1 100644 (file)
@@ -57,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
 
@@ -189,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)"""
index 3e2cf64..8f3e651 100644 (file)
@@ -7,6 +7,7 @@ end
 
 import test_serialization
 import serialization
+intrude import serialization::engine_tools
 
 redef class Deserializer
        redef fun deserialize_class(name)
@@ -15,6 +16,7 @@ redef class Deserializer
                if name == "Array[Text]" then return new Array[Text].from_deserializer(self)
                if name == "Array[Map[String, nullable Object]]" then return new Array[Map[String, nullable Object]].from_deserializer(self)
                if name == "Array[String]" then return new Array[String].from_deserializer(self)
+               if name == "StrictHashMap[Int, Object]" then return new StrictHashMap[Int, Object].from_deserializer(self)
                if name == "Array[Error]" then return new Array[Error].from_deserializer(self)
                if name == "POSet[String]" then return new POSet[String].from_deserializer(self)
                if name == "Array[Int]" then return new Array[Int].from_deserializer(self)
@@ -27,6 +29,7 @@ redef class Deserializer
                if name == "Array[Float]" then return new Array[Float].from_deserializer(self)
                if name == "Array[Object]" then return new Array[Object].from_deserializer(self)
                if name == "Array[Serializable]" then return new Array[Serializable].from_deserializer(self)
+               if name == "StrictHashMap[Serializable, Int]" then return new StrictHashMap[Serializable, Int].from_deserializer(self)
                if name == "POSetElement[String]" then return new POSetElement[String].from_deserializer(self)
                if name == "HashMap[String, POSetElement[String]]" then return new HashMap[String, POSetElement[String]].from_deserializer(self)
                if name == "Array[Match]" then return new Array[Match].from_deserializer(self)