1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
22 var content
: String = ""
23 fun add
(text
: String) do addn
("{text}\n")
24 fun addn
(text
: String) do content
+= text
.escape
25 fun add_rule
do add
("\n---\n")
26 fun render
do sys
.system
("echo \"{content}\
" | pager -r")
30 private var toolcontext
: ToolContext
31 private var model
: Model
32 private var mbuilder
: ModelBuilder
33 private var mainmodule
: MModule
34 private var arguments
: Array[String]
36 init(toolcontext
: ToolContext) do
37 # We need a model to collect stufs
38 self.toolcontext
= toolcontext
39 self.arguments
= toolcontext
.option_context
.rest
41 if arguments
.length
> 2 then
42 print
"usage: ni path/to/module.nit [expression]"
43 toolcontext
.option_context
.usage
48 mbuilder
= new ModelBuilder(model
, toolcontext
)
50 # Here we load an process std modules
51 #var dir = "NIT_DIR".environ
52 #var mmodules = modelbuilder.parse_and_build(["{dir}/lib/standard/standard.nit"])
53 var mmodules
= mbuilder
.parse_and_build
([arguments
.first
])
54 if mmodules
.is_empty
then return
55 mbuilder
.full_propdef_semantic_analysis
56 assert mmodules
.length
== 1
57 self.mainmodule
= mmodules
.first
61 if arguments
.length
== 1 then
70 print
"Welcome in Nit Index.\n"
71 print
"Loaded modules"
72 for m
in mbuilder
.nmodules
do
73 print
" - {m.mmodule.name}"
75 print
"\nEnter the module, class or property name you want to look up."
76 print
"Enter a blank line to exit.\n"
84 fun seek
(entry
: String) do
86 if entry
.is_empty
then exit
(0)
89 for m
in model
.mmodules
do
90 if m
.name
== entry
then
95 for c
in model
.mclasses
do
96 if c
.name
== entry
then
97 if not mbuilder
.mclassdef2nclassdef
[c
.intro
] isa AStdClassdef then continue
102 var matches
= new List[MProperty]
103 for p
in model
.mproperties
do
104 if p
.name
== entry
then
109 if not matches
.is_empty
then props_fulldoc
(matches
)
111 if not flag
then print
"Nothing known about '{entry}'"
112 if arguments
.length
== 1 then prompt
115 private fun module_fulldoc
(mmodule
: MModule) do
116 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
117 var pager
= new Pager
118 pager
.add
("# module {mmodule.name}\n".bold
)
119 pager
.add
("import {mmodule.in_importation.direct_greaters.join(", ")}")
120 #TODO add kmown clients
122 pager
.addn
(nmodule
.comment
.green
)
125 var cats
= new HashMap[String, Collection[MClass]]
126 cats
["introduced classes"] = mmodule
.intro_mclasses
127 cats
["refined classes"] = mmodule
.redef_mclasses
128 cats
["inherited classes"] = mmodule
.imported_mclasses
130 for cat
, list
in cats
do
131 if not list
.is_empty
then
132 pager
.add
("# {cat}\n".bold
)
133 for mclass
in list
do
134 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
].as(AStdClassdef)
135 if not nclass
.short_comment
.is_empty
then
136 pager
.add
("\t# {nclass.short_comment}")
138 if cat
== "refined classes" then
139 pager
.add
("\tredef {mclass.short_doc}")
141 pager
.add
("\t{mclass.short_doc}")
143 if not mclass
.intro_mmodule
== mmodule
then
144 pager
.add
("\t\t" + "introduced in {mmodule.full_name}::{mclass}".gray
)
146 for mclassdef
in mclass
.mclassdefs
do
147 if mclassdef
!= mclass
.intro
then
148 pager
.add
("\t\t" + "refined in {mclassdef.namespace}".gray
)
159 private fun class_fulldoc
(mclass
: MClass) do
160 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
].as(AStdClassdef)
161 var pager
= new Pager
162 pager
.add
("# {mclass.intro_mmodule.public_owner.name}::{mclass.name}\n".bold
)
163 pager
.add
("{mclass.short_doc} ")
164 #TODO add kmown subclasses
166 pager
.addn
(nclass
.comment
.green
)
168 if not mclass
.parameter_types
.is_empty
then
169 pager
.add
("# formal types\n".bold
)
170 for ft
, bound
in mclass
.parameter_types
do
171 pager
.add
("\t{ft.to_s.green}: {bound}")
175 if not mclass
.virtual_types
.is_empty
then
176 pager
.add
("# virtual types\n".bold
)
177 for vt
in mclass
.virtual_types
do
178 if vt
.visibility
.to_s
== "public" then pager
.add
("\t{vt.to_s.green}: {vt.intro.bound.to_s}")
179 if vt
.visibility
.to_s
== "private" then pager
.add
("\t{vt.to_s.red}: {vt.intro.bound.to_s}")
180 if vt
.visibility
.to_s
== "protected" then pager
.add
("\t{vt.to_s.yellow}: {vt.intro.bound.to_s}")
181 if vt
.intro_mclassdef
!= mclass
.intro
then
182 pager
.add
("\t\t" + "introduced in {vt.intro_mclassdef.namespace}::{vt}".gray
)
184 for mpropdef
in vt
.mpropdefs
do
185 if mpropdef
!= vt
.intro
then
186 pager
.add
("\t\t" + "refined in {mpropdef.mclassdef.namespace}".gray
)
194 var cats
= new HashMap[String, Collection[MMethod]]
195 cats
["constructors"] = mclass
.constructors
196 cats
["introduced methods"] = mclass
.intro_methods
197 cats
["refined methods"] = mclass
.redef_methods
198 cats
["inherited methods"] = mclass
.inherited_methods
200 for cat
, list
in cats
do
201 if not list
.is_empty
then
202 pager
.add
("# {cat}\n".bold
)
205 var nmethod
= mbuilder
.mpropdef2npropdef
[mprop
.intro
].as(AMethPropdef)
206 if not nmethod
.short_comment
.is_empty
then
207 pager
.add
("\t# {nmethod.short_comment}")
209 if cat
== "refined methods" then
210 pager
.add
("\tredef {nmethod}")
212 pager
.add
("\t{nmethod}")
214 if not mprop
.intro_mclassdef
== mclass
.intro
then
215 pager
.add
("\t\t" + "introduced in {mprop.intro_mclassdef.namespace}".gray
)
217 for mpropdef
in mprop
.mpropdefs
do
218 if mpropdef
!= mprop
.intro
then
219 pager
.add
("\t\t" + "refined in {mpropdef.mclassdef.namespace}".gray
)
229 private fun props_fulldoc
(mprops
: List[MProperty]) do
230 var pager
= new Pager
231 for mprop
in mprops
do
232 var nprop
= mbuilder
.mpropdef2npropdef
[mprop
.intro
]
233 if nprop
isa AMethPropdef then
234 pager
.add
("# {mprop.intro_mclassdef.namespace.bold}\n")
235 if not nprop
.short_comment
.is_empty
then
236 pager
.add
("\t# {nprop.short_comment}")
238 pager
.add
("\t{nprop}")
239 pager
.add
("\t\t" + "introduced in {mprop.intro_mclassdef.namespace}".gray
)
240 for mpropdef
in mprop
.mpropdefs
do
241 if mpropdef
!= mprop
.intro
then
242 pager
.add
("\t\t" + "refined in {mpropdef.mclassdef.namespace}".gray
)
252 # Printing facilities
256 redef fun to_s
: String do
258 return "{name}[{intro.parameter_names.join(", ")}]"
264 private fun short_doc
: String do
266 if is_interface
then ret
= "interface {ret}"
267 if is_enum
then ret
= "enum {ret}"
268 if is_class
then ret
= "class {ret}"
269 if is_abstract
then ret
= "abstract {ret}"
270 if visibility
.to_s
== "public" then ret
= "{ret}{to_s.green}"
271 if visibility
.to_s
== "private" then ret
= "{ret}{to_s.red}"
272 if visibility
.to_s
== "protected" then ret
= "{ret}{to_s.yellow}"
273 ret
= "{ret} super {parents.join(", ")}"
278 redef class MClassDef
279 private fun namespace
: String do
280 return "{mmodule.full_name}::{mclass.name}"
285 private fun comment
: String do
287 for t
in n_moduledecl
.n_doc
.n_comment
do
288 ret
+= "{t.text.replace("# ", "")}"
294 redef class AStdClassdef
295 private fun comment
: String do
297 if n_doc
!= null then
298 for t
in n_doc
.n_comment
do
299 var txt
= t
.text
.replace
("# ", "")
300 txt
= txt
.replace
("#", "")
307 private fun short_comment
: String do
309 if n_doc
!= null then
310 var txt
= n_doc
.n_comment
.first
.text
311 txt
= txt
.replace
("# ", "")
312 txt
= txt
.replace
("\n", "")
319 redef class AMethPropdef
320 private fun short_comment
: String do
322 if n_doc
!= null then
323 var txt
= n_doc
.n_comment
.first
.text
324 txt
= txt
.replace
("# ", "")
325 txt
= txt
.replace
("\n", "")
333 if not mpropdef
.mproperty
.is_init
then
336 if mpropdef
.mproperty
.visibility
.to_s
== "public" then ret
= "{ret}{mpropdef.mproperty.name.green}"
337 if mpropdef
.mproperty
.visibility
.to_s
== "private" then ret
= "{ret}{mpropdef.mproperty.name.red}"
338 if mpropdef
.mproperty
.visibility
.to_s
== "protected" then ret
= "{ret}{mpropdef.mproperty.name.yellow}"
339 if n_signature
!= null then ret
= "{ret}{n_signature.to_s}"
340 if n_kwredef
!= null then ret
= "redef {ret}"
341 if self isa ADeferredMethPropdef then ret
= "{ret} is abstract"
342 if self isa AInternMethPropdef then ret
= "{ret} is intern"
343 if self isa AExternMethPropdef then ret
= "{ret} is extern"
348 redef class ASignature
352 if not n_params
.is_empty
then
353 ret
= "{ret}({n_params.join(", ")})"
355 if n_type
!= null then ret
+= ": {n_type.to_s}"
362 var ret
= "{n_id.text}"
363 if n_type
!= null then
364 ret
= "{ret}: {n_type.to_s}"
365 if n_dotdotdot
!= null then ret
= "{ret}..."
374 if n_kwnullable
!= null then ret
= "nullable {ret}"
375 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
380 # Redef String class to add a function to color the string
383 private fun add_escape_char
(escapechar
: String): String do
384 return "{escapechar}{self}\\033[0m"
387 private fun esc
: Char do return 27.ascii
388 private fun red
: String do return add_escape_char
("{esc}[1;31m")
389 private fun yellow
: String do return add_escape_char
("{esc}[1;33m")
390 private fun green
: String do return add_escape_char
("{esc}[1;32m")
391 private fun blue
: String do return add_escape_char
("{esc}[1;34m")
392 private fun cyan
: String do return add_escape_char
("{esc}[1;36m")
393 private fun gray
: String do return add_escape_char
("{esc}[30;1m")
394 private fun bold
: String do return add_escape_char
("{esc}[1m")
395 private fun underline
: String do return add_escape_char
("{esc}[4m")
397 private fun escape
: String
403 else if c
== '\0' then
405 else if c
== '"' then
407 else if c == '\\' then
409 else if c == '`' then
411 else if c.ascii < 32 then
412 b.append("\\{c.ascii.to_base(8, false)}")
421 # Create a tool context to handle options and paths
422 var toolcontext = new ToolContext
423 toolcontext.process_options
425 # Here we launch the nit index
426 var ni = new NitIndex(toolcontext)
430 # TODO lister les methods qui retournent un certain type
431 # TODO lister les methods qui utilisent un certain type
432 # TODO lister les sous-types connus d'une
type
433 # TODO sorter par ordre alphabétique