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