1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Base classes used by `nitweb`.
18 import model
::model_views
19 import model
::model_json
22 import popcorn
::pop_config
23 import popcorn
::pop_repos
29 redef var default_db_name
= "nitweb"
34 # MModule used to flatten model.
35 var mainmodule
: MModule
37 # Modelbuilder used to access sources.
38 var modelbuilder
: ModelBuilder
40 # The JSON API does not filter anything by default.
42 # So we can cache the model view.
43 var view
: ModelView is lazy
do
44 var view
= new ModelView(model
)
45 view
.min_visibility
= private_visibility
46 view
.include_fictive
= true
47 view
.include_empty_doc
= true
48 view
.include_attribute
= true
49 view
.include_test_suite
= true
54 # Specific handler for the nitweb API.
55 abstract class APIHandler
59 var config
: NitwebConfig
61 # Find the MEntity ` with `full_name`.
62 fun find_mentity
(model
: ModelView, full_name
: nullable String): nullable MEntity do
63 if full_name
== null then return null
64 return model
.mentity_by_full_name
(full_name
.from_percent_encoding
)
67 # Try to load the mentity from uri with `/:id`.
69 # Send 400 if `:id` is null.
70 # Send 404 if no entity is found.
71 # Return null in both cases.
72 fun mentity_from_uri
(req
: HttpRequest, res
: HttpResponse): nullable MEntity do
73 var id
= req
.param
("id")
75 res
.api_error
(400, "Expected mentity full name")
78 var mentity
= find_mentity
(config
.view
, id
)
79 if mentity
== null then
80 res
.api_error
(404, "MEntity `{id}` not found")
86 # A Rooter dedicated to APIHandlers.
91 var config
: NitwebConfig
94 redef class HttpResponse
96 # Return an HTTP error response with `status`
98 # Like the rest of the API, errors are formated as JSON:
100 # { "status": 404, "message": "Not found" }
102 fun api_error
(status
: Int, message
: String) do
103 json
(new APIError(status
, message
), status
)
107 # An error returned by the API.
109 # Can be serialized to json.
116 # Response error message
119 # Json Object for this error
120 var json
: JsonObject is lazy
do
121 var obj
= new JsonObject
122 obj
["status"] = status
123 obj
["message"] = message
127 redef fun serialize_to
(v
) do json
.serialize_to
(v
)
130 # Fullname representation that can be used to build decorated links
132 # * MPackage: `mpackage_name`
133 # * MGroup: `(mpackage_name::)mgroup_name`
135 super Array[nullable NSEntity]
139 redef fun to_s
do return self.join
("")
140 redef fun serialize_to
(v
) do to_a
.serialize_to
(v
)
143 # Something that goes in a Namespace
146 # * a `NSToken` for tokens like `::`, `>` and `$`
147 # * a `MSRef` for references to mentities
152 # A reference to a MEntity that can be rendered as a link.
154 # We do not reuse `MEntityRef` ref since NSRef can be found in a ref and create
160 # The mentity to link to/
163 redef fun serialize_to
(v
) do
164 var obj
= new JsonObject
165 obj
["web_url"] = mentity
.web_url
166 obj
["api_url"] = mentity
.api_url
167 obj
["name"] = mentity
.name
172 # A namespace token representation
174 # Used for namespace tokens like `::`, `>` and `$`
181 # URL to `self` within the web interface.
182 fun web_url
: String do return "/doc/" / full_name
184 # URL to `self` within the JSON api.
185 fun api_url
: String do return "/api/entity/" / full_name
189 obj
["namespace"] = namespace
190 obj
["web_url"] = web_url
191 obj
["api_url"] = api_url
195 # Get the full json repesentation of `self` with MEntityRefs resolved.
196 fun api_json
(handler
: APIHandler): JsonObject do return full_json
198 # Return `self.full_name` as an object that can be serialized to json.
199 fun namespace
: nullable Namespace do return null
201 # Return a new NSRef to `self`.
202 fun to_ns_ref
: NSRef do return new NSRef(self)
205 redef class MEntityRef
208 obj
["namespace"] = mentity
.namespace
209 obj
["web_url"] = mentity
.web_url
210 obj
["api_url"] = mentity
.api_url
211 obj
["name"] = mentity
.name
212 obj
["mdoc"] = mentity
.mdoc_or_fallback
213 obj
["visibility"] = mentity
.visibility
214 var modifiers
= new JsonArray
215 for modifier
in mentity
.collect_modifiers
do
216 modifiers
.add modifier
218 obj
["modifiers"] = modifiers
219 var mentity
= self.mentity
220 if mentity
isa MMethod then
221 obj
["msignature"] = mentity
.intro
.msignature
222 else if mentity
isa MMethodDef then
223 obj
["msignature"] = mentity
.msignature
224 else if mentity
isa MVirtualTypeProp then
225 obj
["bound"] = to_mentity_ref
(mentity
.intro
.bound
)
226 else if mentity
isa MVirtualTypeDef then
227 obj
["bound"] = to_mentity_ref
(mentity
.bound
)
232 redef fun full_json
do
234 obj
["location"] = mentity
.location
241 # Add doc down processing
243 var obj
= new JsonObject
244 obj
["html_synopsis"] = html_synopsis
.write_to_string
245 obj
["html_documentation"] = html_documentation
.write_to_string
251 redef fun namespace
do return new Namespace.from
([to_ns_ref
])
255 redef fun namespace
do
258 return new Namespace.from
([to_ns_ref
, ">": nullable NSEntity])
260 return new Namespace.from
([p
.namespace
, to_ns_ref
, ">": nullable NSEntity])
265 redef fun namespace
do
266 var mgroup
= self.mgroup
267 if mgroup
== null then
268 return new Namespace.from
([to_ns_ref
])
270 return new Namespace.from
([mgroup
.mpackage
.to_ns_ref
, "::", to_ns_ref
: nullable NSEntity])
273 private fun ns_for
(visibility
: MVisibility): nullable Namespace do
274 if visibility
<= private_visibility
then return namespace
275 var mgroup
= self.mgroup
276 if mgroup
== null then return namespace
277 return mgroup
.mpackage
.namespace
282 redef fun namespace
do
283 return new Namespace.from
([intro_mmodule
.ns_for
(visibility
), "::", to_ns_ref
: nullable NSEntity])
287 redef class MClassDef
288 redef fun namespace
do
290 return new Namespace.from
([mmodule
.ns_for
(mclass
.visibility
), "$", to_ns_ref
: nullable NSEntity])
291 else if mclass
.intro_mmodule
.mpackage
!= mmodule
.mpackage
then
292 return new Namespace.from
([mmodule
.namespace
, "$", mclass
.namespace
: nullable NSEntity])
293 else if mclass
.visibility
> private_visibility
then
294 return new Namespace.from
([mmodule
.namespace
, "$", mclass
.to_ns_ref
: nullable NSEntity])
296 return new Namespace.from
([mmodule
.full_name
, "$::", mclass
.intro_mmodule
.to_ns_ref
: nullable NSEntity])
300 redef class MProperty
301 redef fun namespace
do
302 if intro_mclassdef
.is_intro
then
303 return new Namespace.from
([intro_mclassdef
.mmodule
.ns_for
(visibility
), "::", intro_mclassdef
.mclass
.to_ns_ref
, "::", to_ns_ref
: nullable NSEntity])
305 return new Namespace.from
([intro_mclassdef
.mmodule
.namespace
, "::", intro_mclassdef
.mclass
.to_ns_ref
, "::", to_ns_ref
: nullable NSEntity])
311 redef fun namespace
do
312 var res
= new Namespace
313 res
.add mclassdef
.namespace
316 if mclassdef
.mclass
== mproperty
.intro_mclassdef
.mclass
then
319 if mclassdef
.mmodule
.mpackage
!= mproperty
.intro_mclassdef
.mmodule
.mpackage
then
320 res
.add mproperty
.intro_mclassdef
.mmodule
.ns_for
(mproperty
.visibility
)
322 else if mproperty
.visibility
<= private_visibility
then
323 if mclassdef
.mmodule
.namespace_for
(mclassdef
.mclass
.visibility
) != mproperty
.intro_mclassdef
.mmodule
.mpackage
then
325 res
.add mproperty
.intro_mclassdef
.mmodule
.to_ns_ref
329 if mclassdef
.mclass
!= mproperty
.intro_mclassdef
.mclass
then
330 res
.add mproperty
.intro_mclassdef
.to_ns_ref
339 redef class MClassType
340 redef var web_url
= mclass
.web_url
is lazy
343 redef class MNullableType
344 redef var web_url
= mtype
.web_url
is lazy
347 redef class MParameterType
348 redef var web_url
= mclass
.web_url
is lazy
351 redef class MVirtualType
352 redef var web_url
= mproperty
.web_url
is lazy
355 redef class POSetElement[E
]
358 # Return JSON representation of `self`.
359 fun json
: JsonObject do
360 assert self isa POSetElement[MEntity]
361 var obj
= new JsonObject
362 obj
["greaters"] = to_mentity_refs
(greaters
)
363 obj
["direct_greaters"] = to_mentity_refs
(direct_greaters
)
364 obj
["direct_smallers"] = to_mentity_refs
(direct_smallers
)
365 obj
["smallers"] = to_mentity_refs
(smallers
)
369 redef fun serialize_to
(v
) do json
.serialize_to
(v
)