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 # Doc commands about a Model or a MEntity
17 # This module defines several commands to retrieve data about a Model and MEntities.
23 # Retrieve the MDoc related to a MEntity
29 # If `true`, the command uses `mdoc_or_fallback`.
31 var fallback
= true is optional
, writable
33 # Retrieve the full documentation
35 # If `true`, retrieves the full documentation.
36 # If `false`, retrieves only the synopsis.
39 # Since the rendering the final string (md, html...) depends on the kind of
40 # client, the handling of this option is delegated to submodules.
41 var full_doc
= true is optional
, writable
43 # Format to render the comment
45 # Can be one of `raw`, `html` or `md`.
47 var format
= "raw" is optional
, writable
50 var mdoc
: nullable MDoc = null is optional
, writable
52 # Same states than `CmdEntity::init_mentity`
54 # Plus returns `WarningNoMDoc` if no MDoc was found for the MEntity.
55 redef fun init_command
do
57 if not res
isa CmdSuccess then return res
58 var mentity
= self.mentity
.as(not null)
61 mdoc
= if fallback
then mentity
.mdoc_or_fallback
else mentity
.mdoc
63 if mdoc
== null then return new WarningNoMDoc(mentity
)
67 # Render `mdoc` depending on `full_doc` and `format`
68 fun render_comment
: nullable Writable do
70 if mdoc
== null then return null
72 if full_doc
then return mdoc
.documentation
77 # No MDoc for `mentity`
84 redef fun to_s
do return "No documentation for `{mentity.full_name}`."
87 # Get the link to a MEntity API documentation
91 # The link text to display
92 var text
: nullable String = null is optional
, writable
94 # The link title to display when the link is hovered
95 var title
: nullable String = null is optional
, writable
97 redef fun init_command
do
99 if not res
isa CmdSuccess then return res
100 var mentity
= self.mentity
.as(not null)
105 if title
== null then
106 var mdoc
= mentity
.mdoc_or_fallback
108 title
= mdoc
.synopsis
115 # An abstract inheritance command
117 # For things like ancestors, parents, children and descendants.
118 abstract class CmdInheritance
121 autoinit
(model
, mainmodule
, filter
, mentity
, mentity_name
, limit
, page
, count
, max
)
123 # Mainmodule for class linearization
124 var mainmodule
: MModule
127 # MEntity ancestors command
129 # Retrieve all the ancestors (direct and indirect) of a MEntity.
133 # Include direct parents in the ancestors list
136 var parents
= true is optional
, writable
138 redef fun init_results
do
139 if results
!= null then return new CmdSuccess
142 if not res
isa CmdSuccess then return res
143 var mentity
= self.mentity
.as(not null)
145 var ancestors
= mentity
.collect_ancestors
(mainmodule
, filter
).to_a
151 var parents
= mentity
.collect_parents
(mainmodule
, filter
)
152 var mentities
= new HashSet[MEntity]
153 for ancestor
in ancestors
do
154 if not parents
.has
(ancestor
) then mentities
.add ancestor
156 results
= mentities
.to_a
161 # MEntity parents command
165 redef fun init_results
do
166 if results
!= null then return new CmdSuccess
169 if not res
isa CmdSuccess then return res
170 var mentity
= self.mentity
.as(not null)
172 results
= mentity
.collect_parents
(mainmodule
, filter
).to_a
177 # MEntity children command
181 redef fun init_results
do
182 if results
!= null then return new CmdSuccess
185 if not res
isa CmdSuccess then return res
186 var mentity
= self.mentity
.as(not null)
188 results
= mentity
.collect_children
(mainmodule
, filter
).to_a
193 # MEntity descendants command
197 # Include direct children in the descendants list
200 var children
= true is optional
, writable
202 redef fun init_results
do
203 if results
!= null then return new CmdSuccess
206 if not res
isa CmdSuccess then return res
207 var mentity
= self.mentity
.as(not null)
209 var descendants
= mentity
.collect_descendants
(mainmodule
, filter
).to_a
211 results
= descendants
215 var children
= mentity
.collect_children
(mainmodule
, filter
)
216 var mentities
= new HashSet[MEntity]
217 for descendant
in descendants
do
218 if not children
.has
(descendant
) then mentities
.add descendant
220 results
= mentities
.to_a
225 # Linearization command
227 # Collects and linearizes definitions about an MEntity.
228 class CmdLinearization
231 # Same states than `CmdEntity::init_mentity`
233 # Plus returns `WarningNoLinearization` if no linearization can be computed
235 redef fun init_results
do
236 if results
!= null then return new CmdSuccess
239 if not res
isa CmdSuccess then return res
240 var mentity
= self.mentity
.as(not null)
243 results
= mentity
.collect_linearization
(mainmodule
)
244 if results
== null then return new WarningNoLinearization(mentity
)
249 # No linearization computed for `mentity`.
250 class WarningNoLinearization
256 redef fun to_s
do return "No linearization for `{mentity.full_name}`"
259 # A free text search command
263 # Free text command string
264 var query
: nullable String = null is optional
, writable
267 # * `CmdSuccess`: everything was ok;
268 # * `ErrorNoQuery`: no `query` provided.
269 redef fun init_results
do
270 if results
!= null then return new CmdSuccess
273 if not res
isa CmdSuccess then return res
275 var query
= self.query
276 if query
== null then return new ErrorNoQuery
278 results
= model
.find
(query
)
283 # No query string given
287 redef fun to_s
do return "Missing search string"
290 # MEntity feature list
292 # Mostly a list of mentities defined in `mentity`.
296 # Same as `CmdEntity::init_mentity`
298 # Plus `WarningNoFeatures` if no features are found for `mentity`.
299 redef fun init_results
do
300 if results
!= null then return new CmdSuccess
303 if not res
isa CmdSuccess then return res
304 var mentity
= self.mentity
.as(not null)
306 var mentities
= new Array[MEntity]
307 if mentity
isa MPackage then
308 mentities
.add_all mentity
.collect_mgroups
(filter
)
309 mentities
.add_all mentity
.collect_mmodules
(filter
)
310 else if mentity
isa MGroup then
311 mentities
.add_all mentity
.collect_mgroups
(filter
)
312 mentities
.add_all mentity
.collect_mmodules
(filter
)
313 else if mentity
isa MModule then
314 mentities
.add_all mentity
.collect_local_mclassdefs
(filter
)
315 else if mentity
isa MClass then
316 mentities
.add_all mentity
.collect_intro_mproperties
(filter
)
317 mentities
.add_all mentity
.collect_redef_mpropdefs
(filter
)
318 else if mentity
isa MClassDef then
319 mentities
.add_all mentity
.collect_intro_mpropdefs
(filter
)
320 mentities
.add_all mentity
.collect_redef_mpropdefs
(filter
)
321 else if mentity
isa MProperty then
322 mentities
.add_all mentity
.collect_mpropdefs
(filter
)
324 return new WarningNoFeatures(mentity
)
326 self.results
= mentities
331 # TODO remove once the filters/sorters are merged
335 redef fun init_results
do
336 if results
!= null then return new CmdSuccess
339 if not res
isa CmdSuccess then return res
340 var mentity
= self.mentity
.as(not null)
342 if mentity
isa MModule then
343 var mentities
= mentity
.collect_intro_mclasses
(filter
).to_a
344 self.results
= mentities
345 else if mentity
isa MClass then
346 var mentities
= mentity
.collect_intro_mproperties
(filter
).to_a
347 self.results
= mentities
348 else if mentity
isa MClassDef then
349 var mentities
= mentity
.collect_intro_mpropdefs
(filter
).to_a
350 mainmodule
.linearize_mpropdefs
(mentities
)
351 self.results
= mentities
353 return new WarningNoFeatures(mentity
)
359 # TODO remove once the filters/sorters are merged
363 redef fun init_results
do
364 if results
!= null then return new CmdSuccess
367 if not res
isa CmdSuccess then return res
368 var mentity
= self.mentity
.as(not null)
370 if mentity
isa MModule then
371 var mentities
= mentity
.collect_redef_mclassdefs
(filter
).to_a
372 self.results
= mentities
373 else if mentity
isa MClass then
374 var mentities
= mentity
.collect_redef_mpropdefs
(filter
).to_a
375 self.results
= mentities
376 else if mentity
isa MClassDef then
377 var mentities
= mentity
.collect_redef_mpropdefs
(filter
).to_a
378 mainmodule
.linearize_mpropdefs
(mentities
)
379 self.results
= mentities
381 return new WarningNoFeatures(mentity
)
387 # TODO remove once the filters/sorters are merged
391 redef fun init_results
do
392 if results
!= null then return new CmdSuccess
395 if not res
isa CmdSuccess then return res
396 var mentity
= self.mentity
.as(not null)
398 if mentity
isa MClass then
399 results
= mentity
.collect_accessible_mproperties
(mainmodule
, filter
).to_a
401 return new WarningNoFeatures(mentity
)
407 # No feature list for `mentity`
408 class WarningNoFeatures
414 redef fun to_s
do return "No features for `{mentity.full_name}`"
417 # Abstract command that returns source-code pieces
418 abstract class CmdCode
421 autoinit
(model
, filter
, node
, format
)
423 # AST node to display code from
424 var node
: nullable ANode = null is optional
, writable
428 # Set the output format for this piece of code.
429 # Can be "raw", "html" or "ansi".
432 # This format can be different than the format used in the command response.
433 # For example you can choose to render code as HTML inside a JSON object response.
434 # Another example is to render raw format to put into a HTML code tag.
435 var format
= "raw" is optional
, writable
437 # Render `node` depending on the selected `format`
438 fun render_code
(node
: ANode): Writable do
439 return node
.location
.text
443 # Cmd that finds the source code related to an `mentity`
448 autoinit
(model
, modelbuilder
, filter
, mentity
, mentity_name
, format
)
450 # ModelBuilder used to get AST nodes from entities
451 var modelbuilder
: ModelBuilder
453 # Same as `CmdEntity::init_mentity`
455 # Plus `WarningNoCode` if no code/AST node is found for `mentity`.
456 redef fun init_command
do
457 if node
!= null then return new CmdSuccess
460 if not res
isa CmdSuccess then return res
461 var mentity
= self.mentity
.as(not null)
463 if mentity
isa MClass then mentity
= mentity
.intro
464 if mentity
isa MProperty then mentity
= mentity
.intro
465 node
= modelbuilder
.mentity2node
(mentity
)
466 if node
== null then return new WarningNoCode(mentity
)
471 # No code for `mentity`
478 redef fun to_s
do return "No code for `{mentity.full_name}`"
483 # A command that returns a list of all mentities in a model
484 class CmdModelEntities
487 # Kind of mentities to be returned.
489 # Value must be one of "packages", "groups", "modules", "classes", "classdefs",
490 # "properties", "propdefs" or "all".
493 var kind
= "all" is optional
, writable
495 # Default limit is `10`
498 redef fun init_results
do
499 if results
!= null then return new CmdSuccess
502 if not res
isa CmdSuccess then return res
504 var mentities
= new Array[MEntity]
505 if kind
== "packages" then
506 mentities
= model
.collect_mpackages
(filter
).to_a
507 else if kind
== "groups" then
508 mentities
= model
.collect_mgroups
(filter
).to_a
509 else if kind
== "modules" then
510 mentities
= model
.collect_mmodules
(filter
).to_a
511 else if kind
== "classes" then
512 mentities
= model
.collect_mclasses
(filter
).to_a
513 else if kind
== "classdefs" then
514 mentities
= model
.collect_mclassdefs
(filter
).to_a
515 else if kind
== "properties" then
516 mentities
= model
.collect_mproperties
(filter
).to_a
517 else if kind
== "propdefs" then
518 mentities
= model
.collect_mpropdefs
(filter
).to_a
520 mentities
= model
.collect_mentities
(filter
).to_a
527 # A command that returns a random list of mentities from a model
528 class CmdRandomEntities
529 super CmdModelEntities
531 # Always return `CmdSuccess`
532 redef fun init_results
do
533 if results
!= null then return new CmdSuccess
535 if not res
isa CmdSuccess then return res
540 # Randomize mentities order
542 var results
= self.results
543 if results
== null then return