model: add nitunit for model_json
[nit.git] / src / model / model_json.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Make model entities Jsonable.
16 #
17 # To avoid cycles, every reference from a MEntity to another is replaced by a
18 # MEntityRef.
19 #
20 # How subobjects are retrieved using the MEntityRef is the responsability of the
21 # client. Json objects can be returned as this or inflated with concrete objet
22 # rather than the refs.
23 #
24 # TODO consider serialization module?
25 module model_json
26
27 import model::model_collect
28 import json::static
29 import json::serialization_write
30 import loader
31
32 # A reference to another mentity.
33 class MEntityRef
34 super MEntity
35
36 # MEntity to link to.
37 var mentity: MEntity
38
39 redef fun core_serialize_to(v) do
40 v.serialize_attribute("full_name", mentity.full_name)
41 end
42 end
43
44 redef class MEntity
45 super Jsonable
46 serialize
47
48 redef fun core_serialize_to(v) do
49 v.serialize_attribute("name", name)
50 v.serialize_attribute("class_name", class_name)
51 v.serialize_attribute("full_name", full_name)
52 v.serialize_attribute("mdoc", mdoc_or_fallback)
53 v.serialize_attribute("visibility", visibility.to_s)
54 v.serialize_attribute("modifiers", collect_modifiers)
55 v.serialize_attribute("location", location)
56 end
57
58 # Serialize the full version of `self` to JSON
59 #
60 # See: `FullJsonSerializer`
61 fun serialize_to_full_json(plain, pretty: nullable Bool): String do
62 var stream = new StringWriter
63 var serializer = new FullJsonSerializer(stream)
64 serializer.plain_json = plain or else false
65 serializer.pretty_json = pretty or else false
66 serializer.serialize self
67 stream.close
68 return stream.to_s
69 end
70
71 # Return the full json representation of `self` with references.
72 #
73 # By default, every reference to another MEntity is replaced by a pointer
74 # to the MEntity::json_id.
75 # Use this method to obtain a full object with mentities instead of pointers.
76 fun to_full_json: String do return serialize_to_full_json(plain=true)
77
78 # Same as `to_full_json` but with pretty json.
79 fun to_pretty_full_json: String do return serialize_to_full_json(plain=true, pretty=true)
80 end
81
82 redef class MDoc
83 super Jsonable
84 serialize
85
86 redef fun core_serialize_to(v) do
87 super
88 v.serialize_attribute("content", content.join("\n"))
89 v.serialize_attribute("location", location)
90 end
91 end
92
93 redef class Location
94 super Jsonable
95 serialize
96
97 redef fun core_serialize_to(v) do
98 v.serialize_attribute("column_end", column_end)
99 v.serialize_attribute("column_start", column_start)
100 v.serialize_attribute("line_end", line_end)
101 v.serialize_attribute("line_start", line_start)
102 var file = self.file
103 if file != null then
104 v.serialize_attribute("file", file.filename)
105 end
106 end
107 end
108
109 redef class MPackage
110 redef fun core_serialize_to(v) do
111 super
112 if v isa FullJsonSerializer then
113 v.serialize_attribute("root", to_mentity_ref(root))
114 v.serialize_attribute("mgroups", to_mentity_refs(mgroups))
115 var ini = self.ini
116 if ini != null then v.serialize_attribute("ini", ini.to_map)
117 end
118 end
119 end
120
121 redef class MGroup
122 redef fun core_serialize_to(v) do
123 super
124 if v isa FullJsonSerializer then
125 v.serialize_attribute("is_root", is_root)
126 v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
127 v.serialize_attribute("default_mmodule", to_mentity_ref(default_mmodule))
128 v.serialize_attribute("parent", to_mentity_ref(parent))
129 v.serialize_attribute("mmodules", to_mentity_refs(mmodules))
130 v.serialize_attribute("mgroups", to_mentity_refs(in_nesting.direct_smallers))
131 end
132 end
133 end
134
135 redef class MModule
136 redef fun core_serialize_to(v) do
137 super
138 if v isa FullJsonSerializer then
139 var view = private_view
140 v.serialize_attribute("mpackage", to_mentity_ref(mpackage))
141 v.serialize_attribute("mgroup", to_mentity_ref(mgroup))
142 v.serialize_attribute("intro_mclasses", to_mentity_refs(intro_mclasses))
143 v.serialize_attribute("mclassdefs", to_mentity_refs(mclassdefs))
144 v.serialize_attribute("intro_mclassdefs", to_mentity_refs(collect_intro_mclassdefs(view)))
145 v.serialize_attribute("redef_mclassdefs", to_mentity_refs(collect_redef_mclassdefs(view)))
146 v.serialize_attribute("imports", to_mentity_refs(in_importation.direct_greaters))
147 end
148 end
149 end
150
151 redef class MClass
152 redef fun core_serialize_to(v) do
153 super
154 v.serialize_attribute("mparameters", mparameters)
155 if v isa FullJsonSerializer then
156 var view = private_view
157 v.serialize_attribute("intro", to_mentity_ref(intro))
158 v.serialize_attribute("intro_mmodule", to_mentity_ref(intro_mmodule))
159 v.serialize_attribute("mpackage", to_mentity_ref(intro_mmodule.mpackage))
160 v.serialize_attribute("mclassdefs", to_mentity_refs(mclassdefs))
161 v.serialize_attribute("all_mproperties", to_mentity_refs(collect_accessible_mproperties(view)))
162 v.serialize_attribute("intro_mproperties", to_mentity_refs(collect_intro_mproperties(view)))
163 v.serialize_attribute("redef_mproperties", to_mentity_refs(collect_redef_mproperties(view)))
164 v.serialize_attribute("parents", to_mentity_refs(collect_parents(view)))
165 end
166 end
167 end
168
169 redef class MClassDef
170 redef fun core_serialize_to(v) do
171 super
172 v.serialize_attribute("is_intro", is_intro)
173 v.serialize_attribute("mparameters", mclass.mparameters)
174 if v isa FullJsonSerializer then
175 var view = private_view
176 v.serialize_attribute("mmodule", to_mentity_ref(mmodule))
177 v.serialize_attribute("mclass", to_mentity_ref(mclass))
178 v.serialize_attribute("mpropdefs", to_mentity_refs(mpropdefs))
179 v.serialize_attribute("intro_mproperties", to_mentity_refs(intro_mproperties))
180 v.serialize_attribute("intro", to_mentity_ref(mclass.intro))
181 v.serialize_attribute("mpackage", to_mentity_ref(mmodule.mpackage))
182 v.serialize_attribute("intro_mpropdefs", to_mentity_refs(collect_intro_mpropdefs(view)))
183 v.serialize_attribute("redef_mpropdefs", to_mentity_refs(collect_redef_mpropdefs(view)))
184 end
185 end
186 end
187
188 redef class MProperty
189 redef fun core_serialize_to(v) do
190 super
191 if v isa FullJsonSerializer then
192 v.serialize_attribute("intro", to_mentity_ref(intro))
193 v.serialize_attribute("intro_mclassdef", to_mentity_ref(intro_mclassdef))
194 v.serialize_attribute("mpropdefs", to_mentity_refs(mpropdefs))
195 v.serialize_attribute("intro_mclass", to_mentity_ref(intro_mclassdef.mclass))
196 v.serialize_attribute("mpackage", to_mentity_ref(intro_mclassdef.mmodule.mpackage))
197 end
198 end
199 end
200
201 redef class MMethod
202 redef fun core_serialize_to(v) do
203 super
204 v.serialize_attribute("is_init", is_init)
205 v.serialize_attribute("msignature", intro.msignature)
206 end
207 end
208
209 redef class MAttribute
210 redef fun core_serialize_to(v) do
211 super
212 v.serialize_attribute("static_mtype", to_mentity_ref(intro.static_mtype))
213 end
214 end
215
216 redef class MVirtualTypeProp
217 redef fun core_serialize_to(v) do
218 super
219 v.serialize_attribute("mvirtualtype", to_mentity_ref(mvirtualtype))
220 v.serialize_attribute("bound", to_mentity_ref(intro.bound))
221 end
222 end
223
224 redef class MPropDef
225 redef fun core_serialize_to(v) do
226 super
227 v.serialize_attribute("is_intro", is_intro)
228 if v isa FullJsonSerializer then
229 v.serialize_attribute("mclassdef", to_mentity_ref(mclassdef))
230 v.serialize_attribute("mproperty", to_mentity_ref(mproperty))
231 v.serialize_attribute("intro", to_mentity_ref(mproperty.intro))
232 v.serialize_attribute("intro_mclassdef", to_mentity_ref(mproperty.intro.mclassdef))
233 v.serialize_attribute("mmodule", to_mentity_ref(mclassdef.mmodule))
234 v.serialize_attribute("mgroup", to_mentity_ref(mclassdef.mmodule.mgroup))
235 v.serialize_attribute("mpackage", to_mentity_ref(mclassdef.mmodule.mpackage))
236 end
237 end
238 end
239
240 redef class MMethodDef
241 redef fun core_serialize_to(v) do
242 super
243 v.serialize_attribute("msignature", msignature)
244 end
245 end
246
247 redef class MAttributeDef
248 redef fun core_serialize_to(v) do
249 super
250 v.serialize_attribute("static_mtype", to_mentity_ref(static_mtype))
251 end
252 end
253
254 redef class MVirtualTypeDef
255 redef fun core_serialize_to(v) do
256 super
257 v.serialize_attribute("bound", to_mentity_ref(bound))
258 v.serialize_attribute("is_fixed", is_fixed)
259 end
260 end
261
262 redef class MSignature
263 redef fun core_serialize_to(v) do
264 v.serialize_attribute("arity", arity)
265 v.serialize_attribute("mparams", mparameters)
266 v.serialize_attribute("return_mtype", to_mentity_ref(return_mtype))
267 v.serialize_attribute("vararg_rank", vararg_rank)
268 end
269 end
270
271 redef class MParameterType
272 redef fun core_serialize_to(v) do
273 v.serialize_attribute("name", name)
274 v.serialize_attribute("rank", rank)
275 v.serialize_attribute("mtype", to_mentity_ref(mclass.intro.bound_mtype.arguments[rank]))
276 end
277 end
278
279 redef class MParameter
280 redef fun core_serialize_to(v) do
281 v.serialize_attribute("is_vararg", is_vararg)
282 v.serialize_attribute("name", name)
283 v.serialize_attribute("mtype", to_mentity_ref(mtype))
284 end
285 end
286
287 # Create a ref to a `mentity`.
288 fun to_mentity_ref(mentity: nullable MEntity): nullable MEntityRef do
289 if mentity == null then return null
290 return new MEntityRef(mentity)
291 end
292
293 # Return a collection of `mentities` as a JsonArray of MEntityRefs.
294 fun to_mentity_refs(mentities: Collection[MEntity]): Array[MEntityRef] do
295 var array = new Array[MEntityRef]
296 for mentity in mentities do
297 var ref = to_mentity_ref(mentity)
298 if ref == null then continue
299 array.add ref
300 end
301 return array
302 end
303
304 # Use the FullJsonSerializer to generate the full json representation of a MEntity.
305 #
306 # See MEntity::to_full_json.
307 class FullJsonSerializer
308 super JsonSerializer
309 end