Merge: serialization: redef inspect for an output useful to humans
authorJean Privat <jean@pryen.org>
Mon, 18 Sep 2017 19:00:47 +0000 (15:00 -0400)
committerJean Privat <jean@pryen.org>
Mon, 18 Sep 2017 19:00:47 +0000 (15:00 -0400)
commitc53f3221eaf849e7f09da8cb683e3f10b64d3a7d
tree5ab96bebf0634c360d5dd3cd9ca853f828f424ae
parent1f1aa04c817c9a8f2e31cb2f627f635a1ab4639c
parentff6028a9e65d92ac361df133c619be2e17863b28
Merge: serialization: redef inspect for an output useful to humans

Intro a new serialization engine to pretty print the attributes of the receiver on calls to `inspect`. The format is designed to be helpful, reproducible and compact.

Note that, asides from direct calls to `inspect`, this will also affect the default behavior of `Serializable::to_s`. And this will not affect all Nit programs, but it will affect all those importing the serialization services, so most larger projects using either `json`, `nitcorn`, `gamnit`, `more_collections`, etc.

Simple immutable data are inspected as they would be written in Nit code:
~~~
assert 123.inspect == "123"
assert 1.5.inspect == "1.5"
assert 0xa1u8.inspect == "0xa1u8"
assert 'c'.inspect == "'c'"
assert "asdf\n".inspect == "\"asdf\\n\""
~~~

Inspections of mutable object show their dynamic type and an id unique to each call to `inspect`. A change from using their `object_id`.

Items of collections are flattened:

~~~
assert [1, 2, 3].inspect == "<Array[Int]#0 [1, 2, 3]>"

var set = new HashSet[Object].from([1, 1.5, "two": Object])
assert set.inspect == """<HashSet[Object]#0 [1, 1.5, "two"]>"""

var map = new Map[Int, String]
map[1] = "one"
map[2] = "two"
assert map.inspect == """<HashMap[Int, String]#0 {1:"one", 2:"two"}>"""
~~~

Inspecting other `Serializable` classes shows the first level attributes only:

~~~
class MyClass
    serialize

    var i: Int
    var o: nullable Object
end

var class_with_null = new MyClass(123)
assert class_with_null.to_s == class_with_null.inspect
assert class_with_null.to_s == "<MyClass#0 i:123, o:null>"

var class_with_other = new MyClass(456, class_with_null)
assert class_with_other.to_s == "<MyClass#0 i:456, o:<MyClass#1>>"

var class_with_cycle = new MyClass(789)
class_with_cycle.o = class_with_cycle
assert class_with_cycle.to_s == "<MyClass#0 i:789, o:<MyClass#0>>"
~~~

Inspections producing over 80 characters are cut short:

~~~
var long_class = new MyClass(123456789, "Some " + "very "*8 + "long string")
assert long_class.to_s == "<MyClass#0 i:123456789, o:\"Some very very very very very very very very long s…>"
~~~

Pull-Request: #2548
Reviewed-by: Jean Privat <jean@pryen.org>