From: Jean Privat Date: Sat, 30 May 2015 00:36:52 +0000 (-0400) Subject: Merge: Serialization: change annotation to `serialize` and intro `noserialize` X-Git-Tag: v0.7.5~8 X-Git-Url: http://nitlanguage.org?hp=91136cda6e5cf63bcc2a92800bc76a1e5c7f6fac Merge: Serialization: change annotation to `serialize` and intro `noserialize` The annotation `serialize` replaces `auto_serialize` and it is also more versatile. It can annotate a module so all its class definitions are serializable. It can also annotate an attribute so only this attribute is serialized. The `noserialize` annotation is for exceptions to `serialize`. The most common case is to mark as non-serializable an attribute such as a password or a data blob. Pull-Request: #1389 Reviewed-by: Alexandre Terrasa Reviewed-by: Jean Privat Reviewed-by: Lucas Bajolet --- diff --git a/lib/a_star.nit b/lib/a_star.nit index a0b1b48..9780e12 100644 --- a/lib/a_star.nit +++ b/lib/a_star.nit @@ -211,7 +211,7 @@ end # Link between two nodes and associated to a graph class Link - auto_serializable + serialize # Type of the nodes in `graph` type N: Node @@ -287,7 +287,7 @@ end # Result from path finding and a walkable path class AStarPath[N] - auto_serializable + serialize # Total cost of this path var total_cost: Int @@ -317,7 +317,7 @@ end # Context related to an evocation of pathfinding class PathContext - auto_serializable + serialize # Type of the nodes in `graph` type N: Node @@ -352,7 +352,7 @@ end # Warning: A* is not optimize for such a case class ConstantPathContext super PathContext - auto_serializable + serialize redef fun worst_cost do return 1 redef fun cost(l) do return 1 @@ -364,7 +364,7 @@ end # A `PathContext` for graphs with `WeightedLink` class WeightedPathContext super PathContext - auto_serializable + serialize redef type L: WeightedLink @@ -393,7 +393,7 @@ end # A `Link` with a `weight` class WeightedLink super Link - auto_serializable + serialize # The `weight`, or cost, of this link var weight: Int @@ -401,7 +401,7 @@ end # Advanced path conditions with customizable accept states class TargetCondition[N: Node] - auto_serializable + serialize # Should the pathfinding accept `node` as a goal? fun accept(node: N): Bool is abstract diff --git a/lib/android/bundle/bundle.nit b/lib/android/bundle/bundle.nit index fde88af..edb0c88 100644 --- a/lib/android/bundle/bundle.nit +++ b/lib/android/bundle/bundle.nit @@ -503,7 +503,7 @@ class Bundle # Retrieve an `Object` serialized via `[]=` function # Returns `null` if there's no serialized object corresponding to the given key # or if it's the wrong value type - # Make sure that the serialized object is `auto_serializable` or that it + # Make sure that the serialized object is `serialize` or that it # redefines the appropriate methods. Refer to `Serializable` documentation # for further details fun deserialize(key: String): nullable Object @@ -520,7 +520,7 @@ class Bundle # Retrieve an `Array` of `Object` serialized via `[]=` function # Returns `null` if there's no serialized `Array` corresponding to the given key # or if it's the wrong value type - # Make sure that the serialized objects are `auto_serializable` or that they + # Make sure that the serialized objects are `serialize` or that they # redefine the appropriate methods. Refer to `Serializable` documentation # for further details fun deserialize_array(key: String): nullable Array[nullable Object] diff --git a/lib/android/shared_preferences/shared_preferences_api10.nit b/lib/android/shared_preferences/shared_preferences_api10.nit index d4e71a8..ca3a2b9 100644 --- a/lib/android/shared_preferences/shared_preferences_api10.nit +++ b/lib/android/shared_preferences/shared_preferences_api10.nit @@ -390,7 +390,7 @@ class SharedPreferences # Retrieve an `Object` stored via `[]=` function # # Returns `null` if there's no serialized object corresponding to the given key - # Make sure that the serialized object is `auto_serializable` or that it redefines + # Make sure that the serialized object is `serialize` or that it redefines # the appropriate methods. Refer to `Serializable` documentation for further details fun [](key: String): nullable Object do diff --git a/lib/bucketed_game.nit b/lib/bucketed_game.nit index a621c54..ad79e6c 100644 --- a/lib/bucketed_game.nit +++ b/lib/bucketed_game.nit @@ -20,13 +20,12 @@ # # Allows for fast support of a large number of entities with rare actions, # such as a forest with many individual trees. -module bucketed_game +module bucketed_game is serialize import serialization # Something acting on the game class Turnable[G: Game] - auto_serializable # Execute `turn` for this instance. fun do_turn(turn: GameTurn[G]) is abstract @@ -35,7 +34,6 @@ end # Something acting on the game from time to time class Bucketable[G: Game] super Turnable[G] - auto_serializable private var act_at: nullable Int = null @@ -49,7 +47,6 @@ end # Optimized organization of `Bucketable` instances class Buckets[G: Game] super Turnable[G] - auto_serializable # Bucket type used in this implementation. type BUCKET: HashSet[Bucketable[G]] @@ -118,12 +115,10 @@ end # Event raised at the first turn class FirstTurnEvent super GameEvent - auto_serializable end # Game logic on the client class ThinGame - auto_serializable # Game tick when `self` should act. # @@ -133,7 +128,6 @@ end # Game turn on the client class ThinGameTurn[G: ThinGame] - auto_serializable # Game tick when `self` should act. var tick: Int is protected writable @@ -145,7 +139,6 @@ end # Game turn on the full logic class GameTurn[G: Game] super ThinGameTurn[G] - auto_serializable # Game that `self` belongs to. var game: G @@ -173,7 +166,6 @@ end # Full game logic class Game super ThinGame - auto_serializable # Game type used in this implementation. type G: Game diff --git a/lib/json/serialization.nit b/lib/json/serialization.nit index 4b7cb15..359acf5 100644 --- a/lib/json/serialization.nit +++ b/lib/json/serialization.nit @@ -39,7 +39,7 @@ # import json::serialization # # class Person -# auto_serializable +# serialize # # var name: String # var year_of_birth: Int diff --git a/lib/more_collections.nit b/lib/more_collections.nit index 4f75430..019dc67 100644 --- a/lib/more_collections.nit +++ b/lib/more_collections.nit @@ -13,7 +13,7 @@ # limitations under the License. # Highly specific, but useful, collections-related classes. -module more_collections +module more_collections is serialize import serialization @@ -32,7 +32,6 @@ import serialization # assert m["four"] == ['i', 'i', 'i', 'i'] # assert m["zzz"] == new Array[Char] class MultiHashMap[K, V] - auto_serializable super HashMap[K, Array[V]] # Add `v` to the array associated with `k`. @@ -64,7 +63,6 @@ end # assert hm2[2, "not-two"] == null # ~~~~ class HashMap2[K1, K2, V] - auto_serializable private var level1 = new HashMap[K1, HashMap[K2, V]] @@ -113,7 +111,6 @@ end # assert hm3[2, "not-two", 22] == null # ~~~~ class HashMap3[K1, K2, K3, V] - auto_serializable private var level1 = new HashMap[K1, HashMap2[K2, K3, V]] @@ -193,7 +190,6 @@ end # assert dma.default == [65] # ~~~~ class DefaultMap[K, V] - auto_serializable super HashMap[K, V] # The default value. diff --git a/lib/serialization/README.md b/lib/serialization/README.md index 4cbcf64..ef8c445 100644 --- a/lib/serialization/README.md +++ b/lib/serialization/README.md @@ -1,11 +1,11 @@ # Abstract serialization services -The serialization services are centered around the `auto_serializable` annotation, +The serialization services are based on the `serialize` and the `noserialize` annotations, the `Serializable` interface and the implementations of `Serializer` and `Deserializer`. -## The `auto_serializable` annotation +## The `serialize` annotation -A class annotated with `auto_serializable` identifies it as a subclass of Serializable and +A class annotated with `serialize` identifies it as a subclass of Serializable and triggers the generation of customized serialization and deserialization services. ~~~ @@ -13,7 +13,7 @@ import serialization # Simple serializable class identifying a human class Person - auto_serializable + serialize # First and last name var name: String @@ -31,19 +31,19 @@ By definition of a serializable class, an instance can be serialized to a stream The deserialized instance will not be the same instance, but they should be equal. So, in this case, we can compare both instances with `==` to test their equality. -Some conditions applies to the classes that can be annotated as `auto_serializable`. +Some conditions applies to the classes that can be annotated as `serialize`. All attributes of the class must be serializable, runtime errors will be raised when trying to serialize non-serializable attributes. In the class `Person`, all attributes are typed with classes the standards library. These common types are defined defined as serializable by this project. -The attributes could also be typed with user-defined `auto_serializable` +The attributes could also be typed with user-defined `serialize` classes or any other subclass of `Serializable`. ~~~ -# This `auto_serializable` class is composed of two `auto_serializable` attributes +# This `serialize` class is composed of two `serialize` attributes class Partnership - auto_serializable + serialize var partner_a: Person var partner_b: Person @@ -53,14 +53,59 @@ class Partnership end ~~~ -The `auto_serializable` applies only to the class definition, -only attributes declared locally will be serialized. -However, each definition of a class (a refinement or specialization) -can declare `auto_serializable`. +### Scope of the `serialize` annotation + +`serialize` can annotate class definitions, modules and attributes: + +* The annotation on a class applies only to the class definition, + only attributes declared locally will be serialized. + However, each definition of a class (a refinement or specialization) can be annotated with `serialize`. + +* A module declaration annotated with `serialize` states that all its class definitions + and locally declared attributes are serializable. + + ~~~ + module shared_between_clients is serialize + ~~~ + +* Attribute annotated with `serialize` states that it is to be serialized, when the rest of the class does not. + The class will become subclass to `Serializable` but its attributes are not to be serialized by default. + Only the attributes with the `serialize` annotation will be serialized. + + ~~~ + # Only serialize the `name` + class UserCredentials + var name: String is serialize + var avatar_path: String = "/somepath/"+name is lazy + end + ~~~ + +## The `noserialize` annotation + +The `noserialize` annotation mark an exception in a `serialize` module or class definition. + +* By default a module is `noserialize`. There is no need to declare it as such. + +* A class definition annotated with `noserialize` within a `serialize` module will not be made serializable. + +* A `noserialize` attribute within a class or module annotated with `serialize` will not serialize this attribute. + The class will still be made subclass of `Serializable` and it won't affect the other attributes. + The `noserialize` attribute will not be set at deserialization. + Usually, it will also be annotated with `lazy` to get its value by another mean after the object has been deserialized. + + ~~~ + # Once again, only serialize the `name` + class UserCredentials + serialize + + var name: String + var avatar_path: String = "/somepath/"+name is noserialize, lazy + end + ~~~ ## Custom serializable classes -The annotation `auto_serializable` should be enough for most cases, +The annotation `serialize` should be enough for most cases, but in some cases you need more control over the serialization process. For more control, create a subclass to `Serializable` and redefine `core_serialize_to`. @@ -72,7 +117,7 @@ The method should only act on known class names, and call super otherwise. ### Example: the User class -The following example cannot use the `auto_serializable` annotations +The following example cannot use the `serialize` annotations because some of the arguments to the `User` class need special treatment: * The `name` attribute is perfectly normal, it can be serialized and deserialized @@ -160,7 +205,7 @@ information on the services to redefine. ## Serialization services -The `auto_serializable` annotation and the `Serializable` class are used on +The `serialize` annotation and the `Serializable` class are used on classes specific to the business domain. To write (and read) instances of these classes to a persistent format you must use implementations of `Serializer` and `Deserializer`. @@ -198,7 +243,7 @@ The serialization has some limitations: * Not enough classes from the standard library are supported. This only requires someone to actually code the support. It should not be especially hard for most classes, some can - simply declare the `auto_serializable` annotation. + simply declare the `serialize` annotation. * A limitation of the Json parser prevents deserializing from files with more than one object. @@ -206,9 +251,9 @@ The serialization has some limitations: serialize a single object to each filesand use different instances of serializer and deserializer each time. -* The `auto_serializable` annotation does not handle very well +* The `serialize` annotation does not handle very well complex constructors. This could be improved in the compiler. - For now, you may prefer to use `auto_serializable` on simple classes, + For now, you may prefer to use `serialize` on simple classes, of by using custom `Serializable`. * The serialization uses only the short name of a class, not its qualified name. diff --git a/lib/serialization/serialization.nit b/lib/serialization/serialization.nit index 8977baa..ca60d7a 100644 --- a/lib/serialization/serialization.nit +++ b/lib/serialization/serialization.nit @@ -16,7 +16,7 @@ # Abstract services to serialize Nit objects to different formats # -# This module declares the `auto_serializable` annotation to mark Nit classes as serializable. +# This module declares the `serialize` annotation to mark Nit classes as serializable. # For an introduction to this service, refer to the documentation of the `serialization` group. # This documentation provides more technical information on interesting entitie of this module. # @@ -44,6 +44,8 @@ # `notify_of_creation` must be redefined. module serialization is new_annotation auto_serializable + new_annotation serialize + new_annotation noserialize end # Abstract serialization service to be sub-classed by specialized services. diff --git a/src/frontend/serialization_phase.nit b/src/frontend/serialization_phase.nit index 90924f2..8d576ba 100644 --- a/src/frontend/serialization_phase.nit +++ b/src/frontend/serialization_phase.nit @@ -34,27 +34,118 @@ redef class ToolContext private fun place_holder_type_name: String do return "PlaceHolderTypeWhichShouldNotExist" end +redef class ANode + # Is this node annotated to be made serializable? + private fun is_serialize: Bool do return false + + # Is this node annotated to not be made serializable? + private fun is_noserialize: Bool do return false + + private fun accept_precise_type_visitor(v: PreciseTypeVisitor) do visit_all(v) +end + +redef class ADefinition + + redef fun is_serialize do + return get_annotations("serialize").not_empty or + get_annotations("auto_serializable").not_empty + end + + redef fun is_noserialize do + return get_annotations("noserialize").not_empty + end +end + # TODO add annotations on attributes (volatile, sensitive or do_not_serialize?) private class SerializationPhasePreModel super Phase - redef fun process_annotated_node(nclassdef, nat) + redef fun process_annotated_node(node, nat) do # Skip if we are not interested - if nat.n_atid.n_id.text != "auto_serializable" then return - if not nclassdef isa AStdClassdef then - toolcontext.error(nclassdef.location, "Syntax Error: only a concrete class can be automatically serialized.") + var text = nat.n_atid.n_id.text + var serialize = text == "auto_serializable" or text == "serialize" + var noserialize = text == "noserialize" + if not (serialize or noserialize) then return + + # Check legality of annotation + if node isa AModuledecl then + if noserialize then toolcontext.error(node.location, "Syntax Error: superfluous use of `{text}`, by default a module is `{text}`") + return + else if not (node isa AStdClassdef or node isa AAttrPropdef) then + toolcontext.error(node.location, + "Syntax Error: only a class, a module or an attribute can be annotated with `{text}`.") return + else if serialize and node.is_noserialize then + toolcontext.error(node.location, + "Syntax Error: an entity cannot be both `{text}` and `noserialize`.") + return + else if node.as(Prod).get_annotations(text).length > 1 then + toolcontext.warning(node.location, "useless-{text}", + "Warning: duplicated annotation `{text}`.") end - # Add `super Serializable` - var sc = toolcontext.parse_superclass("Serializable") - sc.location = nat.location - nclassdef.n_propdefs.add sc + # Check the `serialize` state of the parent + if not node isa AModuledecl then + var up_serialize = false + var up: nullable ANode = node + loop + up = up.parent + if up == null then + break + else if up.is_serialize then + up_serialize = true + break + else if up.is_noserialize then + break + end + end - generate_serialization_method(nclassdef) + # Check for useless double declarations + if serialize and up_serialize then + toolcontext.warning(node.location, "useless-serialize", + "Warning: superfluous use of `{text}`.") + else if noserialize and not up_serialize then + toolcontext.warning(node.location, "useless-noserialize", + "Warning: superfluous use of `{text}`.") + end + end + end - generate_deserialization_init(nclassdef) + redef fun process_nclassdef(nclassdef) + do + if not nclassdef isa AStdClassdef then return + + # Is there a declaration on the classdef or the module? + var serialize = nclassdef.is_serialize + + if not serialize and not nclassdef.is_noserialize then + # Is the module marked serialize? + serialize = nclassdef.parent.as(AModule).is_serialize + end + + var per_attribute = false + if not serialize then + # Is there an attribute marked serialize? + for npropdef in nclassdef.n_propdefs do + if npropdef.is_serialize then + serialize = true + per_attribute = true + break + end + end + end + + if serialize then + # Add `super Serializable` + var sc = toolcontext.parse_superclass("Serializable") + sc.location = nclassdef.location + nclassdef.n_propdefs.add sc + + # Add services + generate_serialization_method(nclassdef, per_attribute) + generate_deserialization_init(nclassdef, per_attribute) + end end redef fun process_nmodule(nmodule) @@ -65,8 +156,7 @@ private class SerializationPhasePreModel # collect all classes var auto_serializable_nclassdefs = new Array[AStdClassdef] for nclassdef in nmodule.n_classdefs do - if nclassdef isa AStdClassdef and - not nclassdef.get_annotations("auto_serializable").is_empty then + if nclassdef isa AStdClassdef and nclassdef.is_serialize then auto_serializable_nclassdefs.add nclassdef end end @@ -76,7 +166,7 @@ private class SerializationPhasePreModel end end - fun generate_serialization_method(nclassdef: AClassdef) + fun generate_serialization_method(nclassdef: AClassdef, per_attribute: Bool) do var npropdefs = nclassdef.n_propdefs @@ -86,6 +176,11 @@ private class SerializationPhasePreModel code.add " super" for attribute in npropdefs do if attribute isa AAttrPropdef then + + # Is `attribute` to be skipped? + if (per_attribute and not attribute.is_serialize) or + attribute.is_noserialize then continue + var name = attribute.name code.add " v.serialize_attribute(\"{name}\", {name})" end @@ -97,7 +192,7 @@ private class SerializationPhasePreModel end # Add a constructor to the automated nclassdef - fun generate_deserialization_init(nclassdef: AStdClassdef) + fun generate_deserialization_init(nclassdef: AClassdef, per_attribute: Bool) do var npropdefs = nclassdef.n_propdefs @@ -108,6 +203,11 @@ private class SerializationPhasePreModel code.add " v.notify_of_creation self" for attribute in npropdefs do if attribute isa AAttrPropdef then + + # Is `attribute` to be skipped? + if (per_attribute and not attribute.is_serialize) or + attribute.is_noserialize then continue + var n_type = attribute.n_type var type_name if n_type == null then @@ -201,10 +301,6 @@ private class PreciseTypeVisitor redef fun visit(n) do n.accept_precise_type_visitor(self) end -redef class ANode - private fun accept_precise_type_visitor(v: PreciseTypeVisitor) do visit_all(v) -end - redef class AIsaExpr redef fun accept_precise_type_visitor(v) do @@ -257,6 +353,8 @@ redef class AModule end private var inits_to_retype = new Array[AMethPropdef] + + redef fun is_serialize do return n_moduledecl != null and n_moduledecl.is_serialize end redef class AStdClassdef diff --git a/src/nitserial.nit b/src/nitserial.nit index 0b60a1b..8ead776 100644 --- a/src/nitserial.nit +++ b/src/nitserial.nit @@ -94,7 +94,7 @@ end redef class MClassType redef fun is_visible_from(mmodule) do - return mmodule.is_visible(mclass.intro_mmodule, public_visibility) + return mmodule.is_visible(mclass.intro_mmodule, mclass.visibility) end end diff --git a/tests/sav/nitg-e/test_json_deserialization_alt1.res b/tests/sav/nitg-e/test_json_deserialization_alt1.res index 90e0d60..f4b4a49 100644 --- a/tests/sav/nitg-e/test_json_deserialization_alt1.res +++ b/tests/sav/nitg-e/test_json_deserialization_alt1.res @@ -1,40 +1,40 @@ -Runtime error: Aborted (../lib/serialization/serialization.nit:109) +Runtime error: Aborted (../lib/serialization/serialization.nit:111) # Nit: - + # Json: {"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null} # Back in Nit: - + # Nit: - 1111 qwer> + 1111 qwer> # Json: {"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"} # Back in Nit: - 1111 qwer> + 1111 qwer> # Nit: - 1111 qwer>> + 1111 qwer>> # Json: {"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"__kind": "obj", "__id": 2, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} # Back in Nit: - 1111 qwer>> + 1111 qwer>> # Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> # Json: {"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} # Back in Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> Error: doesn't know how to deserialize class "Array" diff --git a/tests/sav/nitg-e/test_serialization_alt2.res b/tests/sav/nitg-e/test_serialization_alt2.res new file mode 100644 index 0000000..34da2d6 --- /dev/null +++ b/tests/sav/nitg-e/test_serialization_alt2.res @@ -0,0 +1,28 @@ +alt/test_serialization_alt2.nit:22,1--47,3: Warning: superfluous use of `serialize`. +alt/test_serialization_alt2.nit:70,1--86,3: Warning: superfluous use of `auto_serializable`. +alt/test_serialization_alt2.nit:88,1--96,3: Warning: superfluous use of `auto_serializable`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/nitg-e/test_serialization_alt3.res b/tests/sav/nitg-e/test_serialization_alt3.res new file mode 100644 index 0000000..afd0ee8 --- /dev/null +++ b/tests/sav/nitg-e/test_serialization_alt3.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt3.nit:49,1--68,3: Warning: superfluous use of `noserialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/nitg-e/test_serialization_alt4.res b/tests/sav/nitg-e/test_serialization_alt4.res new file mode 100644 index 0000000..e843c62 --- /dev/null +++ b/tests/sav/nitg-e/test_serialization_alt4.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt4.nit:29,2--31,26: Warning: superfluous use of `serialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/nitg-e/test_serialization_alt5.res b/tests/sav/nitg-e/test_serialization_alt5.res new file mode 100644 index 0000000..d4ba4e1 --- /dev/null +++ b/tests/sav/nitg-e/test_serialization_alt5.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt5.nit:22,1--47,3: Warning: duplicated annotation `serialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/test_json_deserialization.res b/tests/sav/test_json_deserialization.res index 047314c..f4172ad 100644 --- a/tests/sav/test_json_deserialization.res +++ b/tests/sav/test_json_deserialization.res @@ -1,38 +1,38 @@ # Nit: - + # Json: {"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null} # Back in Nit: - + # Nit: - 1111 qwer> + 1111 qwer> # Json: {"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"} # Back in Nit: - 1111 qwer> + 1111 qwer> # Nit: - 1111 qwer>> + 1111 qwer>> # Json: {"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"__kind": "obj", "__id": 2, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} # Back in Nit: - 1111 qwer>> + 1111 qwer>> # Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> # Json: {"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} # Back in Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> diff --git a/tests/sav/test_json_deserialization_alt1.res b/tests/sav/test_json_deserialization_alt1.res index 58293c5..8c7e49a 100644 --- a/tests/sav/test_json_deserialization_alt1.res +++ b/tests/sav/test_json_deserialization_alt1.res @@ -1,40 +1,40 @@ # Nit: - + # Json: {"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null} # Back in Nit: - + # Nit: - 1111 qwer> + 1111 qwer> # Json: {"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"} # Back in Nit: - 1111 qwer> + 1111 qwer> # Nit: - 1111 qwer>> + 1111 qwer>> # Json: {"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"__kind": "obj", "__id": 2, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} # Back in Nit: - 1111 qwer>> + 1111 qwer>> # Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> # Json: {"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} # Back in Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> # Nit: diff --git a/tests/sav/test_json_deserialization_alt2.res b/tests/sav/test_json_deserialization_alt2.res index 99e49d6..2dde071 100644 --- a/tests/sav/test_json_deserialization_alt2.res +++ b/tests/sav/test_json_deserialization_alt2.res @@ -1,24 +1,24 @@ # Nit: - + # Json: {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null} # Nit: - 1111 qwer> + 1111 qwer> # Json: {"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"} # Nit: - 1111 qwer>> + 1111 qwer>> # Json: {"a": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null}} # Nit: -<- false> 1111 f" \/> true> +<- false p4ssw0rd> 1111 f" \/> true> # Json: {"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": null} diff --git a/tests/sav/test_serialization_alt2.res b/tests/sav/test_serialization_alt2.res new file mode 100644 index 0000000..e5910cf --- /dev/null +++ b/tests/sav/test_serialization_alt2.res @@ -0,0 +1,28 @@ +alt/test_serialization_alt2.nit:22,1--47,3: Warning: superfluous use of `serialize`. +alt/test_serialization_alt2.nit:70,1--86,3: Warning: superfluous use of `auto_serializable`. +alt/test_serialization_alt2.nit:88,1--96,3: Warning: superfluous use of `auto_serializable`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/test_serialization_alt3.res b/tests/sav/test_serialization_alt3.res new file mode 100644 index 0000000..c8f072c --- /dev/null +++ b/tests/sav/test_serialization_alt3.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt3.nit:49,1--68,3: Warning: superfluous use of `noserialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/test_serialization_alt4.res b/tests/sav/test_serialization_alt4.res new file mode 100644 index 0000000..966388f --- /dev/null +++ b/tests/sav/test_serialization_alt4.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt4.nit:29,2--31,26: Warning: superfluous use of `serialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/sav/test_serialization_alt5.res b/tests/sav/test_serialization_alt5.res new file mode 100644 index 0000000..d1b73a6 --- /dev/null +++ b/tests/sav/test_serialization_alt5.res @@ -0,0 +1,26 @@ +alt/test_serialization_alt5.nit:22,1--47,3: Warning: duplicated annotation `serialize`. +# Nit: + + +# Json: +{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}} + +# Nit: + 1111 qwer> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"} + +# Nit: + 1111 qwer>> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": {"__kind": "obj", "__id": 2, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}}, "b": {"__kind": "obj", "__id": 3, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": {"__kind": "obj", "__id": 4, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}} + +# Nit: + +<- false> 1111 f" \/> true> + +# Json: +{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": {"__kind": "obj", "__id": 1, "__class": "Array[nullable Object]", "__length": 3, "__items": [88, "hello", null]}, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}} + diff --git a/tests/test_deserialization.nit b/tests/test_deserialization.nit index 1360bf2..deb8997 100644 --- a/tests/test_deserialization.nit +++ b/tests/test_deserialization.nit @@ -26,6 +26,7 @@ class A var i = 123 var s = "asdf" var n: nullable Int + var password = "p4ssw0rd" is lazy, noserialize init(b: Bool, c: Char, f: Float, i: Int, s: String, n: nullable Int) do @@ -36,7 +37,7 @@ class A self.s = s end - redef fun to_s do return "" + redef fun to_s do return "" end # Sub-class of A diff --git a/tests/test_serialization.nit b/tests/test_serialization.nit index 5517cff..75c7a9d 100644 --- a/tests/test_serialization.nit +++ b/tests/test_serialization.nit @@ -14,16 +14,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +#alt2#module test_serialization_alt2 is serialize + import serialization import json::serialization # Simple class class A - auto_serializable + serialize +#alt5# serialize var b = false - var c: Char - var f: Float + var c: Char#alt2# + #alt2#var c: Char is noserialize + var f: Float#alt4# + #alt4#var f: Float is serialize var i = 123 var s = "asdf" var n: nullable Int @@ -43,7 +48,9 @@ end # Sub-class of A class B - auto_serializable + auto_serializable#alt2##alt3# +#alt2# noserialize +#alt3# noserialize super A var ii: Int