ni_nitdoc: fixed lists items in module page
[nit.git] / src / ni_nitdoc.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 module ni_nitdoc
18
19 import model_utils
20 import abstract_compiler
21 import html
22
23 class Nitdoc
24 private var toolcontext: ToolContext
25 private var model: Model
26 private var modelbuilder: ModelBuilder
27 private var mainmodule: MModule
28 private var arguments: Array[String]
29 private var destinationdir: nullable String
30 private var sharedir: nullable String
31 private var source: nullable String
32
33 private var opt_dir = new OptionString("Directory where doc is generated", "-d", "--dir")
34 private var opt_source = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
35 private var opt_sharedir = new OptionString("Directory containing the nitdoc files", "--sharedir")
36 private var opt_nodot = new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
37
38 init(toolcontext: ToolContext) do
39 # We need a model to collect stufs
40 self.toolcontext = toolcontext
41 self.arguments = toolcontext.option_context.rest
42 toolcontext.option_context.options.clear
43 toolcontext.option_context.add_option(opt_dir)
44 toolcontext.option_context.add_option(opt_source)
45 toolcontext.option_context.add_option(opt_sharedir)
46 toolcontext.option_context.add_option(opt_nodot)
47 toolcontext.process_options
48 process_options
49
50 if arguments.length < 1 then
51 toolcontext.option_context.usage
52 exit(1)
53 end
54
55 model = new Model
56 modelbuilder = new ModelBuilder(model, toolcontext)
57
58 # Here we load an process std modules
59 var mmodules = modelbuilder.parse_and_build([arguments.first])
60 if mmodules.is_empty then return
61 modelbuilder.full_propdef_semantic_analysis
62 assert mmodules.length == 1
63 self.mainmodule = mmodules.first
64 end
65
66 private fun process_options do
67 if not opt_dir.value is null then
68 destinationdir = opt_dir.value
69 else
70 destinationdir = "nitdoc_directory"
71 end
72 if not opt_sharedir.value is null then
73 sharedir = opt_sharedir.value
74 else
75 var dir = "NIT_DIR".environ
76 if dir.is_empty then
77 dir = "{sys.program_name.dirname}/../share/nitdoc"
78 else
79 dir = "{dir}/share/nitdoc"
80 end
81 sharedir = dir
82 if sharedir is null then
83 print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
84 abort
85 end
86 dir = "{sharedir.to_s}/scripts/js-facilities.js"
87 if sharedir is null then
88 print "Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
89 abort
90 end
91 end
92 if not opt_source.value is null then
93 source = ""
94 else
95 source = opt_source.value
96 end
97 end
98
99 fun start do
100 if arguments.length == 1 then
101 # Create destination dir if it's necessary
102 if not destinationdir.file_exists then destinationdir.mkdir
103 sys.system("cp -r {sharedir.to_s}/* {destinationdir.to_s}/")
104 overview
105 fullindex
106 modules
107 classes
108 quicksearch_list
109 end
110 end
111
112 fun overview do
113 var overviewpage = new NitdocOverview.with(modelbuilder, self.opt_nodot.value, destinationdir.to_s)
114 overviewpage.save("{destinationdir.to_s}/index.html")
115 end
116
117 fun fullindex do
118 var fullindex = new NitdocFullindex.with(model.mmodules)
119 fullindex.save("{destinationdir.to_s}/full-index.html")
120 end
121
122 fun modules do
123 for mmodule in model.mmodules do
124 var modulepage = new NitdocModules.with(mmodule, modelbuilder)
125 modulepage.save("{destinationdir.to_s}/{mmodule.name}.html")
126 end
127 end
128
129 fun classes do
130 for amodule in modelbuilder.nmodules do
131 for mclass, aclassdef in amodule.mclass2nclassdef do
132 mclass.amodule(modelbuilder.mmodule2nmodule)
133 mclass.mmethod(aclassdef.mprop2npropdef)
134 var classpage = new NitdocMClasses.with(mclass, aclassdef, source)
135 classpage.save("{destinationdir.to_s}/{mclass.name}.html")
136 end
137 end
138 end
139
140 # Generate QuickSearch file
141 fun quicksearch_list do
142 var file = new OFStream.open("{destinationdir.to_s}/quicksearch-list.js")
143 var content = new Buffer
144 content.append("var entries = \{ ")
145 for prop in model.mproperties do
146 if not prop isa MMethod then continue
147 content.append("\"{prop.name}\": [")
148 for propdef in prop.mpropdefs do
149 content.append("\{txt: \"{propdef.mproperty.full_name}\", url:\"{propdef.mproperty.link_anchor}\" \}")
150 if not propdef is prop.mpropdefs.last then content.append(", ")
151 end
152 content.append("]")
153 content.append(", ")
154 end
155
156 for mclass in model.mclasses do
157 content.append("\"{mclass.name}\": [")
158 for mclassdef in mclass.mclassdefs do
159 content.append("\{txt: \"{mclassdef.mclass.full_name}\", url:\"{mclass.link_anchor}\" \}")
160 if not mclassdef is mclass.mclassdefs.last then content.append(", ")
161 end
162 content.append("]")
163 if not mclass is model.mclasses.last then content.append(", ")
164 end
165
166 content.append(" \};")
167 file.write(content.to_s)
168 file.close
169 end
170
171 end
172
173 class NitdocOverview
174 super NitdocPage
175
176 var mbuilder: ModelBuilder
177
178 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
179 # opt_nodot to inform about the graph gen
180 # destination: to know where will be saved dot files
181 init with(mbuilder: ModelBuilder, opt_nodot: Bool, destination: String) do
182 self.mbuilder = mbuilder
183 self.opt_nodot = opt_nodot
184 self.destinationdir = destination
185 end
186
187 redef fun head do
188 super
189 add("title").text("Overview | Nit Standard Library")
190 end
191
192 redef fun header do
193 open("header")
194 open("nav").add_class("main")
195 open("ul")
196 add("li").add_class("current").text("Overview")
197 open("li")
198 add_html("<a href=\"full-index.html\">Full Index</a>")
199 close("li")
200 open("li").attr("id", "liGitHub")
201 open("a").add_class("btn").attr("id", "logGitHub")
202 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
203 close("a")
204 open("div").add_class("popover bottom")
205 add("div").add_class("arrow").text(" ")
206 open("div").add_class("githubTitle")
207 add("h3").text("Github Sign In")
208 close("div")
209 open("div")
210 add("label").attr("id", "lbloginGit").text("Username")
211 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
212 open("label").attr("id", "logginMessage").text("Hello ")
213 open("a").attr("id", "githubAccount")
214 add("strong").attr("id", "nickName").text(" ")
215 close("a")
216 close("label")
217 close("div")
218 open("div")
219 add("label").attr("id", "lbpasswordGit").text("Password")
220 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
221 open("div").attr("id", "listBranches")
222 add("label").attr("id", "lbBranches").text("Branch")
223 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
224 close("div")
225 close("div")
226 open("div")
227 add("label").attr("id", "lbrepositoryGit").text("Repository")
228 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
229 close("div")
230 open("div")
231 add("label").attr("id", "lbbranchGit").text("Branch")
232 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
233 close("div")
234 open("div")
235 add("a").attr("id", "signIn").text("Sign In")
236 close("div")
237 close("div")
238 close("li")
239 close("ul")
240 close("nav")
241 close("header")
242 end
243
244 redef fun body do
245 super
246 open("div").add_class("page")
247 open("div").add_class("content fullpage")
248 add("h1").text("Nit Standard Library")
249 open("article").add_class("overview")
250 add_html("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
251 close("article")
252 open("article").add_class("overview")
253 add("h2").text("Modules")
254 open("ul")
255 add_modules
256 close("ul")
257 process_generate_dot
258 close("article")
259 close("div")
260 close("div")
261 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
262 end
263
264 fun add_modules do
265 var mmodules = list_mmodules
266 var sorted = new Array[MModule].from(mmodules)
267 var sorter = new ComparableSorter[MModule]
268 sorter.sort(sorted)
269 for mmodule in sorted do
270 var amodule = mbuilder.mmodule2nmodule[mmodule]
271 open("li")
272 add("a").attr("href", "{mmodule.name}.html").text("{mmodule.to_s} ")
273 add_html(amodule.short_comment)
274 close("li")
275 end
276 end
277
278 fun process_generate_dot do
279 var op = new Buffer
280 op.append("digraph dep \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
281 for mmodule in list_mmodules do
282 op.append("\"{mmodule.name}\"[URL=\"{mmodule.name}.html\"];\n")
283 for imported in mmodule.in_importation.direct_greaters do
284 if imported.direct_owner == null then
285 op.append("\"{mmodule.name}\"->\"{imported.name}\";\n")
286 end
287 end
288 end
289 op.append("\}\n")
290 generate_dot(op.to_s, "dep", "Modules hierarchy")
291 end
292
293 private fun list_mmodules: Set[MModule] do
294 var mmodules = new HashSet[MModule]
295 for mmodule in mbuilder.model.mmodules do
296 var owner = mmodule.public_owner
297 if owner != null then
298 mmodules.add(owner)
299 else
300 mmodules.add(mmodule)
301 end
302 end
303 return mmodules
304 end
305
306 end
307
308 class NitdocFullindex
309 super NitdocPage
310
311 var mmodules: Array[MModule]
312
313 init with(mmodules: Array[MModule]) do
314 self.mmodules = mmodules
315 opt_nodot = false
316 destinationdir = ""
317 end
318
319 redef fun head do
320 super
321 add("title").text("Full Index | Nit Standard Library")
322 end
323
324 redef fun header do
325 open("header")
326 open("nav").add_class("main")
327 open("ul")
328 open("li")
329 add_html("<a href=\"index.html\">Overview</a>")
330 close("li")
331 add("li").add_class("current").text("Full Index")
332 open("li").attr("id", "liGitHub")
333 open("a").add_class("btn").attr("id", "logGitHub")
334 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
335 close("a")
336 open("div").add_class("popover bottom")
337 add("div").add_class("arrow").text(" ")
338 open("div").add_class("githubTitle")
339 add("h3").text("Github Sign In")
340 close("div")
341 open("div")
342 add("label").attr("id", "lbloginGit").text("Username")
343 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
344 open("label").attr("id", "logginMessage").text("Hello ")
345 open("a").attr("id", "githubAccount")
346 add("strong").attr("id", "nickName").text(" ")
347 close("a")
348 close("label")
349 close("div")
350 open("div")
351 add("label").attr("id", "lbpasswordGit").text("Password")
352 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
353 open("div").attr("id", "listBranches")
354 add("label").attr("id", "lbBranches").text("Branch")
355 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
356 close("div")
357 close("div")
358 open("div")
359 add("label").attr("id", "lbrepositoryGit").text("Repository")
360 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
361 close("div")
362 open("div")
363 add("label").attr("id", "lbbranchGit").text("Branch")
364 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
365 close("div")
366 open("div")
367 add("a").attr("id", "signIn").text("Sign In")
368 close("div")
369 close("div")
370 close("li")
371 close("ul")
372 close("nav")
373 close("header")
374 end
375
376 redef fun body do
377 super
378 open("div").add_class("page")
379 open("div").add_class("content fullpage")
380 add("h1").text("Full Index")
381 add_content
382 close("div")
383 close("div")
384 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
385 end
386
387 fun add_content do
388 module_column
389 classes_column
390 properties_column
391 end
392
393 # Add to content modules column
394 fun module_column do
395 var ls = new List[nullable MModule]
396 var sorted = mmodules
397 var sorterp = new ComparableSorter[MModule]
398 sorterp.sort(sorted)
399 open("article").add_class("modules filterable")
400 add("h2").text("Modules")
401 open("ul")
402 for mmodule in sorted do
403 if mmodule.public_owner != null and not ls.has(mmodule.public_owner) then
404 ls.add(mmodule.public_owner)
405 open("li")
406 add("a").attr("href", "{mmodule.public_owner.name}.html").text(mmodule.public_owner.name)
407 close("li")
408 end
409 end
410 close("ul")
411 close("article")
412 end
413
414 # Add to content classes modules
415 fun classes_column do
416 var sorted = mmodules.first.imported_mclasses.to_a
417 var sorterp = new ComparableSorter[MClass]
418 sorterp.sort(sorted)
419 open("article").add_class("classes filterable")
420 add("h2").text("Classes")
421 open("ul")
422
423 for mclass in sorted do
424 open("li")
425 add("a").attr("href", "{mclass.name}.html").text(mclass.name)
426 close("li")
427 end
428
429 close("ul")
430 close("article")
431 end
432
433 # Insert the properties column of fullindex page
434 fun properties_column do
435 open("article").add_class("properties filterable")
436 add("h2").text("Properties")
437 open("ul")
438 var sorted_imported = mmodules.first.imported_methods.to_a
439 var sorted_redef = mmodules.first.redef_methods.to_a
440 var sorterp = new ComparableSorter[MProperty]
441 sorterp.sort(sorted_imported)
442 sorterp.sort(sorted_redef)
443
444 for method in sorted_imported do
445 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
446 open("li").add_class("intro")
447 add("span").attr("title", "introduction").text("I")
448 add_html("&nbsp;")
449 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
450 close("li")
451 end
452
453 for method in sorted_redef do
454 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
455 open("li").add_class("redef")
456 add("span").attr("title", "redefinition").text("R")
457 add_html("&nbsp;")
458 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
459 close("li")
460 end
461
462 close("ul")
463 close("article")
464 end
465
466 end
467
468 class NitdocModules
469 super NitdocPage
470
471 var mmodule: MModule
472 var mbuilder: ModelBuilder
473
474 init with(mmodule: MModule, mbuilder: ModelBuilder) do
475 self.mmodule = mmodule
476 self.mbuilder = mbuilder
477 opt_nodot = false
478 destinationdir = ""
479 end
480
481 redef fun head do
482 super
483 var amodule = mbuilder.mmodule2nmodule[mmodule]
484 add("title").text("{mmodule.name} module | {amodule.short_comment}")
485 end
486
487 redef fun header do
488 open("header")
489 open("nav").add_class("main")
490 open("ul")
491 open("li")
492 add_html("<a href=\"index.html\">Overview</a>")
493 close("li")
494 add("li").add_class("current").text(mmodule.name)
495 open("li")
496 add_html("<a href=\"full-index.html\" >Full Index</a>")
497 close("li")
498 open("li").attr("id", "liGitHub")
499 open("a").add_class("btn").attr("id", "logGitHub")
500 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
501 close("a")
502 open("div").add_class("popover bottom")
503 add("div").add_class("arrow").text(" ")
504 open("div").add_class("githubTitle")
505 add("h3").text("Github Sign In")
506 close("div")
507 open("div")
508 add("label").attr("id", "lbloginGit").text("Username")
509 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
510 open("label").attr("id", "logginMessage").text("Hello ")
511 open("a").attr("id", "githubAccount")
512 add("strong").attr("id", "nickName").text(" ")
513 close("a")
514 close("label")
515 close("div")
516 open("div")
517 add("label").attr("id", "lbpasswordGit").text("Password")
518 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
519 open("div").attr("id", "listBranches")
520 add("label").attr("id", "lbBranches").text("Branch")
521 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
522 close("div")
523 close("div")
524 open("div")
525 add("label").attr("id", "lbrepositoryGit").text("Repository")
526 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
527 close("div")
528 open("div")
529 add("label").attr("id", "lbbranchGit").text("Branch")
530 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
531 close("div")
532 open("div")
533 add("a").attr("id", "signIn").text("Sign In")
534 close("div")
535 close("div")
536 close("li")
537 close("ul")
538 close("nav")
539 close("header")
540 end
541
542 redef fun body do
543 super
544 open("div").add_class("page")
545 menu
546 add_content
547 close("div")
548 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
549 end
550
551 # Insert all tags in content part
552 fun add_content do
553 open("div").add_class("content")
554 add("h1").text(mmodule.name)
555 add("div").add_class("subtitle").text("module {mmodule.name}")
556 module_comment
557 classes
558 properties
559 close("div")
560 end
561
562 # Insert module comment in the content
563 fun module_comment do
564 var amodule = mbuilder.mmodule2nmodule[mmodule]
565 var doc = amodule.comment
566 open("div").attr("id", "description")
567 add("pre").add_class("text_label").text(doc)
568 add("textarea").add_class("edit").attr("rows", "1").attr("cols", "76").attr("id", "fileContent").text(" ")
569 add("a").attr("id", "cancelBtn").text("Cancel")
570 add("a").attr("id", "commitBtn").text("Commit")
571 add("pre").add_class("text_label").attr("id", "preSave").attr("type", "2")
572 close("div")
573 end
574
575 fun menu do
576 var amodule = mbuilder.mmodule2nmodule[mmodule]
577 open("div").add_class("menu")
578 open("nav")
579 add("h3").text("Module Hierarchy").attr("style","cursor: pointer;")
580 if mmodule.in_importation.greaters.length > 0 then
581 add_html("<h4>All dependencies</h4><ul>")
582 var sorted = mmodule.in_importation.greaters.to_a
583 var sorter = new ComparableSorter[MModule]
584 sorter.sort(sorted)
585 for m in sorted do
586 if m == mmodule or m.public_owner != null then continue
587 open("li")
588 add("a").attr("href", "{m.name}.html").text(m.name)
589 close("li")
590 end
591 add_html("</ul>")
592 end
593 if mmodule.in_importation.smallers.length > 0 then
594 add_html("<h4>All clients</h4><ul>")
595 var sorted = mmodule.in_importation.smallers.to_a
596 var sorter = new ComparableSorter[MModule]
597 sorter.sort(sorted)
598 for m in sorted do
599 if m == mmodule or m.public_owner != null then continue
600 open("li")
601 add("a").attr("href", "{m.name}.html").text(m.name)
602 close("li")
603 end
604 add_html("</ul>")
605 end
606 close("nav")
607 if mmodule.in_nesting.direct_greaters.length > 0 then
608 var sorted = mmodule.in_nesting.direct_greaters.to_a
609 var sorter = new ComparableSorter[MModule]
610 sorter.sort(sorted)
611 open("nav")
612 add("h3").text("Nested Modules").attr("style","cursor: pointer;")
613 open("ul")
614 for m in sorted do
615 open("li")
616 add("a").attr("href", "{m.name}.html").text(m.name)
617 close("li")
618 end
619 close("ul")
620
621 close("nav")
622 end
623 close("div")
624 end
625
626 fun classes do
627 var amodule = mbuilder.mmodule2nmodule[mmodule]
628 var intro_mclasses = mmodule.intro_mclasses
629 var redef_mclasses = mmodule.redef_mclasses
630 var all_mclasses = new HashSet[MClass]
631 for m in mmodule.in_nesting.greaters do
632 all_mclasses.add_all(m.intro_mclasses)
633 all_mclasses.add_all(m.redef_mclasses)
634 end
635 all_mclasses.add_all(intro_mclasses)
636 all_mclasses.add_all(redef_mclasses)
637
638 var sorted = new Array[MClass]
639 sorted.add_all(all_mclasses)
640 var sorter = new ComparableSorter[MClass]
641 sorter.sort(sorted)
642 open("div").add_class("module")
643 open("article").add_class("classes filterable")
644 add("h2").text("Classes")
645 open("ul")
646 for c in sorted do
647 var name = c.name
648 if redef_mclasses.has(c) and c.intro_mmodule.public_owner != mmodule then
649 open("li").add_class("redef")
650 add("span").attr("title", "refined in this module").text("R ")
651 else
652 open("li").add_class("intro")
653 add("span").attr("title", "introduced in this module").text("I ")
654 end
655 add("a").attr("href", "{name}.html").text(name)
656 close("li")
657 end
658 close("ul")
659 close("article")
660 close("div")
661 end
662
663 fun properties do
664 var amodule = mbuilder.mmodule2nmodule[mmodule]
665 var mpropdefs = new HashSet[MPropDef]
666 for m in mmodule.in_nesting.greaters do
667 for c in m.mclassdefs do mpropdefs.add_all(c.mpropdefs)
668 end
669 for c in mmodule.mclassdefs do mpropdefs.add_all(c.mpropdefs)
670 var sorted = mpropdefs.to_a
671 var sorter = new ComparableSorter[MPropDef]
672 sorter.sort(sorted)
673 open("article").add_class("properties filterable")
674 add_html("<h2>Properties</h2>")
675 open("ul")
676 for p in sorted do
677 if p.mproperty.visibility <= none_visibility then continue
678 if p.is_intro then
679 open("li").add_class("intro")
680 add("span").attr("title", "introduction").text("I")
681 else
682 open("li").add_class("redef")
683 add("span").attr("title", "redefinition").text("R")
684 end
685 add_html("&nbsp;")
686 add("a").attr("href", "{p.mclassdef.mclass.name}.html").attr("title", "").text("{p.mproperty.name} ({p.mclassdef.mclass.name})")
687 close("li")
688 end
689 close("ul")
690 close("article")
691 end
692 end
693
694 # Nit Standard Library
695 class NitdocMClasses
696 super NitdocPage
697
698 var mclass: MClass
699 var aclassdef: AClassdef
700 var stdclassdef: nullable AStdClassdef
701 var public_owner: nullable MModule
702
703 init with(mclass: MClass, aclassdef: AClassdef, source: nullable String) do
704 self.mclass = mclass
705 self.aclassdef = aclassdef
706 if aclassdef isa AStdClassdef then self.stdclassdef = aclassdef
707 self.public_owner = mclass.intro_mmodule.public_owner
708 opt_nodot = false
709 destinationdir = ""
710 self.source = source
711 end
712
713 redef fun head do
714 super
715 add("title").text("{self.mclass.name} class | Nit Standard Library")
716 end
717
718 redef fun header do
719 open("header")
720 open("nav").add_class("main")
721 open("ul")
722 open("li")
723 add_html("<a href=\"index.html\">Overview</a>")
724 close("li")
725 open("li")
726 if public_owner is null then
727 add_html("<a href=\"{mclass.intro_mmodule.name}.html\">{mclass.intro_mmodule.name}</a>")
728 else
729 add_html("<a href=\"{public_owner.name}.html\">{public_owner.name}</a>")
730 end
731 close("li")
732 add("li").add_class("current").text(mclass.name)
733 open("li")
734 add_html("<a href=\"full-index.html\" >Full Index</a>")
735 close("li")
736 open("li").attr("id", "liGitHub")
737 open("a").add_class("btn").attr("id", "logGitHub")
738 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
739 close("a")
740 open("div").add_class("popover bottom")
741 add("div").add_class("arrow").text(" ")
742 open("div").add_class("githubTitle")
743 add("h3").text("Github Sign In")
744 close("div")
745 open("div")
746 add("label").attr("id", "lbloginGit").text("Username")
747 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
748 open("label").attr("id", "logginMessage").text("Hello ")
749 open("a").attr("id", "githubAccount")
750 add("strong").attr("id", "nickName").text(" ")
751 close("a")
752 close("label")
753 close("div")
754 open("div")
755 add("label").attr("id", "lbpasswordGit").text("Password")
756 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
757 open("div").attr("id", "listBranches")
758 add("label").attr("id", "lbBranches").text("Branch")
759 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
760 close("div")
761 close("div")
762 open("div")
763 add("label").attr("id", "lbrepositoryGit").text("Repository")
764 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
765 close("div")
766 open("div")
767 add("label").attr("id", "lbbranchGit").text("Branch")
768 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
769 close("div")
770 open("div")
771 add("a").attr("id", "signIn").text("Sign In")
772 close("div")
773 close("div")
774 close("li")
775 close("ul")
776 close("nav")
777 close("header")
778 end
779
780 redef fun body do
781 super
782 open("div").add_class("page")
783 add_content
784 close("div")
785 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
786 end
787
788 # Insert all tags in content part
789 fun add_content do
790 open("div").add_class("menu")
791 properties_column
792 inheritance_column
793 close("div")
794 open("div").add_class("content")
795 content
796 close("div")
797 end
798
799 fun properties_column do
800 var sorted = new Array[MProperty]
801 var sorterp = new ComparableSorter[MProperty]
802 open("nav").add_class("properties filterable")
803 add("h3").text("Properties")
804
805 if mclass.virtual_types.length > 0 then
806 add("h4").text("Virtual Types")
807 open("ul")
808 sorted = mclass.virtual_types.to_a
809 sorterp.sort(sorted)
810 for prop in sorted do
811 add_html("<li class=\"redef\"><span title=\"Redefined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
812 end
813 close("ul")
814 end
815 if mclass.constructors.length > 0 then
816 sorted = mclass.constructors.to_a
817 sorterp.sort(sorted)
818 add("h4").text("Constructors")
819 open("ul")
820 for prop in sorted do
821 add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
822 end
823 close("ul")
824 end
825 add("h4").text("Methods")
826 open("ul")
827 if mclass.intro_methods.length > 0 then
828 sorted = mclass.intro_methods.to_a
829 sorterp.sort(sorted)
830 for prop in sorted do
831 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
832 end
833 end
834 if mclass.inherited_methods.length > 0 then
835 sorted = mclass.inherited_methods.to_a
836 sorterp.sort(sorted)
837 for prop in sorted do
838 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"inherit\"><span title=\"Inherited\">H</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
839 end
840 end
841 if mclass.redef_methods.length > 0 then
842 sorted = mclass.redef_methods.to_a
843 sorterp.sort(sorted)
844 for prop in sorted do
845 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"redef\"><span title=\"Refined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
846 end
847 end
848 close("ul")
849 close("nav")
850 end
851
852 fun inheritance_column do
853 var sorted = new Array[MClass]
854 var sorterp = new ComparableSorter[MClass]
855 open("nav")
856 add("h3").text("Inheritance")
857 if mclass.parents.length > 0 then
858 sorted = mclass.parents.to_a
859 sorterp.sort(sorted)
860 add("h4").text("Superclasses")
861 open("ul")
862 for sup in sorted do add_html("<li><a href=\"{sup.name}.html\">{sup.name}</a></li>")
863 close("ul")
864 end
865
866 if mclass.descendants.length is 0 then
867 add("h4").text("No Known Subclasses")
868 else if mclass.descendants.length <= 100 then
869 sorted = mclass.descendants.to_a
870 sorterp.sort(sorted)
871 add("h4").text("Subclasses")
872 open("ul")
873 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
874 close("ul")
875 else if mclass.children.length <= 100 then
876 sorted = mclass.children.to_a
877 sorterp.sort(sorted)
878 add("h4").text("Direct Subclasses Only")
879 open("ul")
880 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
881 close("ul")
882 else
883 add("h4").text("Too much Subclasses to list")
884 end
885 close("nav")
886 end
887
888 fun content do
889 var sorted = new Array[MModule]
890 sorted.add_all(mclass.concerns.keys)
891 var sorterp = new ComparableSorter[MModule]
892 var sorterprop = new ComparableSorter[MProperty]
893 var sorterc = new ComparableSorter[MClass]
894 sorterp.sort(sorted)
895 var subtitle = ""
896 var lmmodule = new List[MModule]
897 # Insert the subtitle part
898 add("h1").text(mclass.name)
899 open("div").add_class("subtitle")
900 if mclass.visibility is none_visibility then subtitle += "private "
901 subtitle += "{mclass.kind} <a href=\"{mclass.public_owner.name}.html\">{mclass.public_owner.name}</a>::{mclass.name}"
902 add_html(subtitle)
903 close("div")
904 add_html("<div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
905 # We add the class description
906 open("section").add_class("description")
907 if not stdclassdef is null and not stdclassdef.comment.is_empty then add_html("<pre class=\"text_label\" title=\"122\" name=\"\" tag=\"{mclass.mclassdefs.first.location.to_s}\" type=\"2\">{stdclassdef.comment} </pre><textarea id=\"fileContent\" class=\"edit\" cols=\"76\" rows=\"1\" style=\"display: none;\"></textarea><a id=\"cancelBtn\" style=\"display: none;\">Cancel</a><a id=\"commitBtn\" style=\"display: none;\">Commit</a><pre id=\"preSave\" class=\"text_label\" type=\"2\"></pre>")
908 close("section")
909 open("section").add_class("concerns")
910 add("h2").add_class("section-header").text("Concerns")
911 open("ul")
912 for owner in sorted do
913 var childs = mclass.concerns[owner]
914 open("li")
915 add_html("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {owner.amodule.short_comment}")
916 if not childs is null then
917 open("ul")
918 var sortedc = childs.to_a
919 var sorterpc = new ComparableSorter[MModule]
920 sorterpc.sort(sortedc)
921 for child in sortedc do
922 add_html("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {child.amodule.short_comment} </li>")
923 end
924 close("ul")
925 end
926 close("li")
927 end
928 close("ul")
929 close("section")
930 # Insert virtual types if there is almost one
931 if mclass.virtual_types.length > 0 or (stdclassdef != null and stdclassdef.n_formaldefs.length > 0) then
932 open("section").add_class("types")
933 add("h2").text("Formal and Virtual Types")
934 if mclass.virtual_types.length > 0 then for prop in mclass.virtual_types do description(prop)
935 if stdclassdef.n_formaldefs.length > 0 then
936 for prop in stdclassdef.n_formaldefs do
937 open("article").attr("id", "FT_Object_{prop.collect_text}")
938 open("h3").add_class("signature").text("{prop.collect_text}: nullable ")
939 add_html("<a title=\"The root of the class hierarchy.\" href=\"Object.html\">Object</a>")
940 close("h3")
941 add_html("<div class=\"info\">formal generic type</div>")
942 close("article")
943 end
944 end
945 close("section")
946 end
947 # Insert constructors if there is almost one
948 if mclass.constructors.length > 0 then
949 var sortedc = mclass.constructors.to_a
950 sorterprop.sort(sortedc)
951 open("section").add_class("constructors")
952 add("h2").add_class("section-header").text("Constructors")
953 for prop in sortedc do description(prop)
954 close("section")
955 end
956 open("section").add_class("methods")
957 add("h2").add_class("section-header").text("Methods")
958 for mmodule, mmethods in mclass.all_methods do
959 add_html("<a id=\"MOD_{mmodule.name}\"></a>")
960 if mmodule != mclass.intro_mmodule and mmodule != mclass.public_owner then
961 if mclass.has_mmodule(mmodule) then
962 add_html("<p class=\"concern-doc\">{mmodule.name}: {mmodule.amodule.short_comment}</p>")
963 else
964 add_html("<h3 class=\"concern-toplevel\">Methods refined in <a href=\"{mmodule.name}.html\">{mmodule.name}</a></h3><p class=\"concern-doc\">{mmodule.name}: {mmodule.amodule.short_comment}</p>")
965 end
966 end
967 var sortedc = mmethods.to_a
968 sorterprop.sort(sortedc)
969 for prop in sortedc do description(prop)
970 end
971 # Insert inherited methods
972 if mclass.inherited_methods.length > 0 then
973 var sortedc = new Array[MClass]
974 sortedc.add_all(mclass.inherited.keys)
975 sorterc.sort(sortedc)
976 add("h3").text("Inherited Methods")
977 for i_mclass in sortedc do
978 var sortedp = mclass.inherited[i_mclass].to_a
979 sorterprop.sort(sortedp)
980 open("p")
981 add_html("Defined in <a href=\"{i_mclass.name}.html\">{i_mclass.name}</a>: ")
982 for method in sortedp do
983 add_html("<a href=\"{method.link_anchor}\">{method.name}</a>")
984 if method != sortedp.last then add_html(", ")
985 end
986 close("p")
987 end
988 end
989 close("section")
990 end
991
992 # Insert description tags for 'prop'
993 fun description(prop: MProperty) do
994 open("article").add_class("fun public {if prop.is_redef then "redef" else ""}").attr("id", "{prop.anchor}")
995 var sign = prop.name
996 if prop.apropdef != null then sign += prop.apropdef.signature
997 add_html("<h3 class=\"signature\">{sign}</h3>")
998 add_html("<div class=\"info\">{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}</div><div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
999
1000 open("div").add_class("description")
1001 if prop.apropdef is null or prop.apropdef.comment == "" then
1002 add_html("<a class=\"newComment\" title=\"32\" tag=\"\">New Comment</a>")
1003 else
1004 add_html("<pre class=\"text_label\" title=\"\" name=\"\" tag=\"\" type=\"1\">{prop.apropdef.comment}</pre>")
1005 end
1006 add_html("<textarea id=\"fileContent\" class=\"edit\" cols=\"76\" rows=\"1\" style=\"display: none;\"></textarea><a id=\"cancelBtn\" style=\"display: none;\">Cancel</a><a id=\"commitBtn\" style=\"display: none;\">Commit</a><pre id=\"preSave\" class=\"text_label\" type=\"2\"></pre>")
1007 open("p")
1008 if prop.local_class != mclass then add_html("inherited from {prop.local_class.intro_mmodule.name} ")
1009 #TODO display show code if doc github
1010 add_html("defined by the module <a href=\"{prop.intro_mclassdef.mmodule.name}.html\">{prop.intro_mclassdef.mmodule.name}</a> {if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
1011
1012 for parent in mclass.parents do
1013 if prop isa MMethod then if parent.constructors.has(prop) then add_html(" Previously defined by: <a href=\"{parent.intro_mmodule.name}.html\">{parent.intro_mmodule.name}</a> for <a href=\"{parent.name}.html\">{parent.name}</a>.")
1014 end
1015 close("p")
1016 close("div")
1017
1018 close("article")
1019 end
1020
1021 end
1022
1023 class NitdocPage
1024 super HTMLPage
1025
1026 var opt_nodot: Bool
1027 var destinationdir : String
1028 var source: nullable String
1029
1030 redef fun head do
1031 add("meta").attr("charset", "utf-8")
1032 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
1033 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
1034 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
1035 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
1036 end
1037
1038 redef fun body do header
1039 fun header do end
1040
1041 # Generate a clickable graphviz image using a dot content
1042 fun generate_dot(dot: String, name: String, alt: String) do
1043 if opt_nodot then return
1044 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
1045 file.write(dot)
1046 file.close
1047 sys.system("\{ test -f {self.destinationdir}/{name}.png && test -f {self.destinationdir}/{name}.s.dot && diff {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot && dot -Tpng -o{self.destinationdir}/{name}.png -Tcmapx -o{self.destinationdir}/{name}.map {self.destinationdir}/{name}.s.dot ; \}")
1048 open("article").add_class("graph")
1049 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
1050 close("article")
1051 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
1052 add_html(fmap.read_all)
1053 fmap.close
1054 end
1055
1056 # Add a (source) link fo a given location
1057 fun show_source(l: Location): String
1058 do
1059 if source == null then
1060 return "({l.file.filename.simplify_path})"
1061 else
1062 # THIS IS JUST UGLY ! (but there is no replace yet)
1063 var x = source.split_with("%f")
1064 source = x.join(l.file.filename.simplify_path)
1065 x = source.split_with("%l")
1066 source = x.join(l.line_start.to_s)
1067 x = source.split_with("%L")
1068 source = x.join(l.line_end.to_s)
1069 return " (<a href=\"{source.to_s}\">show code</a>)"
1070 end
1071 end
1072
1073 end
1074
1075 redef class AModule
1076 private fun comment: String do
1077 var ret = ""
1078 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
1079 if n_moduledecl.n_doc is null then return ""
1080 for t in n_moduledecl.n_doc.n_comment do
1081 var txt = t.text
1082 txt = txt.replace("# ", "")
1083 txt = txt.replace("#", "")
1084 ret += txt
1085 end
1086 return ret
1087 end
1088
1089 private fun short_comment: String do
1090 var ret = ""
1091 if n_moduledecl != null and n_moduledecl.n_doc != null then
1092 var txt = n_moduledecl.n_doc.n_comment.first.text
1093 txt = txt.replace("# ", "")
1094 txt = txt.replace("\n", "")
1095 ret += txt
1096 end
1097 return ret
1098 end
1099 end
1100
1101 redef class MModule
1102
1103 super Comparable
1104 redef type OTHER: MModule
1105 redef fun <(other: OTHER): Bool do return self.name < other.name
1106
1107 var amodule: nullable AModule
1108
1109 # Get the list of all methods in a module
1110 fun imported_methods: Set[MMethod] do
1111 var methods = new HashSet[MMethod]
1112 for mclass in imported_mclasses do
1113 for method in mclass.intro_methods do
1114 methods.add(method)
1115 end
1116 end
1117 return methods
1118 end
1119
1120 # Get the list aof all refined methods in a module
1121 fun redef_methods: Set[MMethod] do
1122 var methods = new HashSet[MMethod]
1123 for mclass in redef_mclasses do
1124 for method in mclass.intro_methods do
1125 methods.add(method)
1126 end
1127 end
1128 return methods
1129 end
1130 end
1131 redef class MPropDef
1132 super Comparable
1133 redef type OTHER: MPropDef
1134 redef fun <(other: OTHER): Bool do return self.mproperty.name < other.mproperty.name
1135 end
1136
1137 redef class MProperty
1138
1139 super Comparable
1140 redef type OTHER: MProperty
1141 redef fun <(other: OTHER): Bool do return self.name < other.name
1142
1143 var is_redef: Bool
1144 var apropdef: nullable APropdef
1145
1146 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1147 do
1148 super
1149 is_redef = false
1150 end
1151
1152 fun local_class: MClass do
1153 var classdef = self.intro_mclassdef
1154 return classdef.mclass
1155 end
1156
1157 fun class_text: String do
1158 return local_class.name
1159 end
1160
1161 fun link_anchor: String do
1162 return "{class_text}.html#{anchor}"
1163 end
1164
1165 fun anchor: String do
1166 return "PROP_{c_name}"
1167 end
1168
1169 end
1170
1171 redef class MClass
1172
1173 super Comparable
1174 redef type OTHER: MClass
1175 redef fun <(other: OTHER): Bool do return self.name < other.name
1176
1177 # Associate all MMethods to each MModule concerns
1178 fun all_methods: HashMap[MModule, Set[MMethod]] do
1179 var hm = new HashMap[MModule, Set[MMethod]]
1180 for mmodule, childs in concerns do
1181 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
1182 for prop in intro_methods do
1183 if mmodule == prop.intro_mclassdef.mmodule then
1184 prop.is_redef = false
1185 hm[mmodule].add(prop)
1186 end
1187 end
1188 for prop in redef_methods do
1189 if mmodule == prop.intro_mclassdef.mmodule then
1190 prop.is_redef = true
1191 hm[mmodule].add(prop)
1192 end
1193 end
1194
1195 if childs != null then
1196 for child in childs do
1197 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
1198 for prop in intro_methods do
1199 if child == prop.intro_mclassdef.mmodule then
1200 prop.is_redef = false
1201 hm[child].add(prop)
1202 end
1203 end
1204 for prop in redef_methods do
1205 if child == prop.intro_mclassdef.mmodule then
1206 prop.is_redef = true
1207 hm[child].add(prop)
1208 end
1209 end
1210 end
1211 end
1212 end
1213 return hm
1214 end
1215
1216 fun public_owner: MModule do
1217 var owner = intro_mmodule
1218 if owner.public_owner is null then
1219 return owner
1220 else
1221 return owner.public_owner.as(not null)
1222 end
1223 end
1224
1225 # Associate Amodule to all MModule concern by 'self'
1226 fun amodule(amodules: HashMap[MModule, AModule]) do
1227 for owner, childs in concerns do
1228 if childs != null then for child in childs do child.amodule = amodules[child]
1229 owner.amodule = amodules[owner]
1230 end
1231 end
1232
1233 # Associate MClass to all MMethod include in 'inherited_methods'
1234 fun inherited: HashMap[MClass, Set[MMethod]] do
1235 var hm = new HashMap[MClass, Set[MMethod]]
1236 for method in inherited_methods do
1237 var mclass = method.intro_mclassdef.mclass
1238 if not hm.has_key(mclass) then hm[mclass] = new HashSet[MMethod]
1239 hm[mclass].add(method)
1240 end
1241 return hm
1242 end
1243
1244 # Return true if MModule concern contain subMModule
1245 fun has_mmodule(sub: MModule): Bool do
1246 for mmodule, childs in concerns do
1247 if childs is null then continue
1248 if childs.has(sub) then return true
1249 end
1250 return false
1251 end
1252
1253 fun mmethod(mprop2npropdef: Map[MProperty, APropdef]) do
1254 for const in constructors do
1255 if mprop2npropdef.has_key(const)then
1256 const.apropdef = mprop2npropdef[const].as(AMethPropdef)
1257 end
1258 end
1259
1260 for intro in intro_methods do
1261 if mprop2npropdef.has_key(intro)then
1262 if mprop2npropdef[intro] isa AMethPropdef then intro.apropdef = mprop2npropdef[intro].as(AMethPropdef)
1263 end
1264 end
1265
1266 for rd in redef_methods do
1267 if mprop2npropdef.has_key(rd)then
1268 if mprop2npropdef[rd] isa AMethPropdef then rd.apropdef = mprop2npropdef[rd].as(AMethPropdef)
1269 end
1270 end
1271 end
1272
1273 fun link_anchor: String do
1274 return "{name}.html"
1275 end
1276
1277 end
1278
1279 redef class AStdClassdef
1280 private fun comment: String do
1281 var ret = ""
1282 if n_doc != null then
1283 for t in n_doc.n_comment do
1284 var txt = t.text.replace("# ", "")
1285 txt = txt.replace("#", "")
1286 ret += "{txt}"
1287 end
1288 end
1289 return ret
1290 end
1291
1292 private fun short_comment: String do
1293 var ret = ""
1294 if n_doc != null then
1295 var txt = n_doc.n_comment.first.text
1296 txt = txt.replace("# ", "")
1297 txt = txt.replace("\n", "")
1298 ret += txt
1299 end
1300 return ret
1301 end
1302 end
1303
1304 redef class ASignature
1305 redef fun to_s do
1306 #TODO closures
1307 var ret = ""
1308 if not n_params.is_empty then
1309 ret = "{ret}({n_params.join(", ")})"
1310 end
1311 if n_type != null and n_type.to_s != "" then ret += " {n_type.to_s}"
1312 return ret
1313 end
1314 end
1315
1316 redef class AParam
1317 redef fun to_s do
1318 var ret = "{n_id.text}"
1319 if n_type != null then
1320 ret = "{ret}: {n_type.to_s}"
1321 if n_dotdotdot != null then ret = "{ret}..."
1322 end
1323 return ret
1324 end
1325 end
1326
1327 redef class AType
1328 redef fun to_s do
1329 var ret = "<a href=\"{n_id.text}.html\">{n_id.text}</a>"
1330 if n_kwnullable != null then ret = "nullable {ret}"
1331 if not n_types.is_empty then ret = "{ret}[{n_types.join(", ")}]"
1332 return ret
1333 end
1334 end
1335
1336 redef class APropdef
1337 private fun short_comment: String is abstract
1338 private fun signature: String is abstract
1339 private fun comment: String is abstract
1340 end
1341
1342 redef class AAttrPropdef
1343 redef fun short_comment do
1344 var ret = ""
1345 if n_doc != null then
1346 var txt = n_doc.n_comment.first.text
1347 txt = txt.replace("# ", "")
1348 txt = txt.replace("\n", "")
1349 ret += txt
1350 end
1351 return ret
1352 end
1353 end
1354
1355 redef class AMethPropdef
1356 redef fun short_comment do
1357 var ret = ""
1358 if n_doc != null then
1359 var txt = n_doc.n_comment.first.text
1360 txt = txt.replace("# ", "")
1361 txt = txt.replace("\n", "")
1362 ret += txt
1363 end
1364 return ret
1365 end
1366
1367 redef fun signature: String do
1368 var sign = ""
1369 if n_signature != null then sign = " {n_signature.to_s}"
1370 return sign
1371 end
1372
1373 redef private fun comment: String do
1374 var ret = ""
1375 if n_doc != null then
1376 for t in n_doc.n_comment do
1377 var txt = t.text.replace("# ", "")
1378 txt = txt.replace("#", "")
1379 ret += "{txt}"
1380 end
1381 end
1382 return ret
1383 end
1384 end
1385
1386 redef class MClassDef
1387 private fun namespace(mclass: MClass): String do
1388
1389 if mmodule.public_owner is null then
1390 return "{mmodule.full_name}::{mclass.name}"
1391 else if mclass is self.mclass then
1392 return "{mmodule.public_owner.name}::{mclass.name}"
1393 else
1394 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\">{mclass.name}</a>"
1395 end
1396 end
1397 end
1398
1399 redef class Set[E]
1400 fun last: E do
1401 return to_a[length-1]
1402 end
1403 end
1404
1405 # Create a tool context to handle options and paths
1406 var toolcontext = new ToolContext
1407
1408 # Here we launch the nit index
1409 var nitdoc = new Nitdoc(toolcontext)
1410 nitdoc.start