ni_nitdoc: better sorting for mproperties column
[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.parents.length > 0 then
852 sorted = mclass.parents.to_a
853 sorterp.sort(sorted)
854 add("h4").text("Superclasses")
855 open("ul")
856 for sup in sorted do add_html("<li><a href=\"{sup.name}.html\">{sup.name}</a></li>")
857 close("ul")
858 end
859
860 if mclass.descendants.length is 0 then
861 add("h4").text("No Known Subclasses")
862 else if mclass.descendants.length <= 100 then
863 sorted = mclass.descendants.to_a
864 sorterp.sort(sorted)
865 add("h4").text("Subclasses")
866 open("ul")
867 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
868 close("ul")
869 else if mclass.children.length <= 100 then
870 sorted = mclass.children.to_a
871 sorterp.sort(sorted)
872 add("h4").text("Direct Subclasses Only")
873 open("ul")
874 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
875 close("ul")
876 else
877 add("h4").text("Too much Subclasses to list")
878 end
879 close("nav")
880 end
881
882 fun content do
883 var nclass = mbuilder.mclassdef2nclassdef[mclass.intro]
884 var sorted = new Array[MModule]
885 sorted.add_all(mclass.concerns.keys)
886 var sorterp = new ComparableSorter[MModule]
887 var sorterprop = new ComparableSorter[MProperty]
888 var sorterc = new ComparableSorter[MClass]
889 sorterp.sort(sorted)
890 var subtitle = ""
891 var lmmodule = new List[MModule]
892 # Insert the subtitle part
893 add("h1").text(mclass.name)
894 open("div").add_class("subtitle")
895 if mclass.visibility is none_visibility then subtitle += "private "
896 subtitle += "{mclass.kind} <a href=\"{mclass.public_owner.name}.html\">{mclass.public_owner.name}</a>::{mclass.name}"
897 add_html(subtitle)
898 close("div")
899 add_html("<div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
900 # We add the class description
901 open("section").add_class("description")
902 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>")
903 close("section")
904 open("section").add_class("concerns")
905 add("h2").add_class("section-header").text("Concerns")
906 open("ul")
907 for owner in sorted do
908 var nmodule = mbuilder.mmodule2nmodule[owner]
909 var childs = mclass.concerns[owner]
910 open("li")
911 add_html("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
912 if not childs is null then
913 open("ul")
914 var sortedc = childs.to_a
915 var sorterpc = new ComparableSorter[MModule]
916 sorterpc.sort(sortedc)
917 for child in sortedc do
918 var nchild = mbuilder.mmodule2nmodule[child]
919 add_html("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
920 end
921 close("ul")
922 end
923 close("li")
924 end
925 close("ul")
926 close("section")
927 # Insert virtual types if there is almost one
928 if mclass.virtual_types.length > 0 or mclass.arity > 0 then
929 open("section").add_class("types")
930 add("h2").text("Formal and Virtual Types")
931 if mclass.virtual_types.length > 0 then for prop in mclass.virtual_types do description(prop)
932 if mclass.arity > 0 and nclass isa AStdClassdef then
933 for prop in nclass.n_formaldefs do
934 open("article").attr("id", "FT_Object_{prop.collect_text}")
935 open("h3").add_class("signature").text("{prop.collect_text}: nullable ")
936 add_html("<a title=\"The root of the class hierarchy.\" href=\"Object.html\">Object</a>")
937 close("h3")
938 add_html("<div class=\"info\">formal generic type</div>")
939 close("article")
940 end
941 end
942 close("section")
943 end
944 # Insert constructors if there is almost one
945 if mclass.constructors.length > 0 then
946 var sortedc = mclass.constructors.to_a
947 sorterprop.sort(sortedc)
948 open("section").add_class("constructors")
949 add("h2").add_class("section-header").text("Constructors")
950 for prop in sortedc do description(prop)
951 close("section")
952 end
953 open("section").add_class("methods")
954 add("h2").add_class("section-header").text("Methods")
955 for mmodule, mmethods in mclass.all_methods do
956 var nmodule = mbuilder.mmodule2nmodule[mmodule]
957 add_html("<a id=\"MOD_{mmodule.name}\"></a>")
958 if mmodule != mclass.intro_mmodule and mmodule != mclass.public_owner then
959 if mclass.has_mmodule(mmodule) then
960 add_html("<p class=\"concern-doc\">{mmodule.name}: {nmodule.short_comment}</p>")
961 else
962 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>")
963 end
964 end
965 var sortedc = mmethods.to_a
966 sorterprop.sort(sortedc)
967 for prop in sortedc do description(prop)
968 end
969 # Insert inherited methods
970 if mclass.inherited_methods.length > 0 then
971 var sortedc = new Array[MClass]
972 sortedc.add_all(mclass.inherited.keys)
973 sorterc.sort(sortedc)
974 add("h3").text("Inherited Methods")
975 for i_mclass in sortedc do
976 var sortedp = mclass.inherited[i_mclass].to_a
977 sorterprop.sort(sortedp)
978 open("p")
979 add_html("Defined in <a href=\"{i_mclass.name}.html\">{i_mclass.name}</a>: ")
980 for method in sortedp do
981 add_html("<a href=\"{method.link_anchor}\">{method.name}</a>")
982 if method != sortedp.last then add_html(", ")
983 end
984 close("p")
985 end
986 end
987 close("section")
988 end
989
990 # Insert description tags for 'prop'
991 fun description(prop: MProperty) do
992 open("article").add_class("fun public {if prop.is_redef then "redef" else ""}").attr("id", "{prop.anchor}")
993 var sign = prop.name
994 if prop.apropdef != null then sign += prop.apropdef.signature
995 add_html("<h3 class=\"signature\">{sign}</h3>")
996 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>")
997
998 open("div").add_class("description")
999 if prop.apropdef is null or prop.apropdef.comment == "" then
1000 add_html("<a class=\"newComment\" title=\"32\" tag=\"\">New Comment</a>")
1001 else
1002 add_html("<pre class=\"text_label\" title=\"\" name=\"\" tag=\"\" type=\"1\">{prop.apropdef.comment}</pre>")
1003 end
1004 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>")
1005 open("p")
1006 if prop.local_class != mclass then add_html("inherited from {prop.local_class.intro_mmodule.name} ")
1007 #TODO display show code if doc github
1008 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)}.")
1009
1010 for parent in mclass.parents do
1011 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>.")
1012 end
1013 close("p")
1014 close("div")
1015
1016 close("article")
1017 end
1018
1019 end
1020
1021 class NitdocPage
1022 super HTMLPage
1023
1024 var opt_nodot: Bool
1025 var destinationdir : String
1026 var source: nullable String
1027
1028 redef fun head do
1029 add("meta").attr("charset", "utf-8")
1030 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
1031 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
1032 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
1033 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
1034 end
1035
1036 redef fun body do header
1037 fun header do end
1038
1039 # Generate a clickable graphviz image using a dot content
1040 fun generate_dot(dot: String, name: String, alt: String) do
1041 if opt_nodot then return
1042 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
1043 file.write(dot)
1044 file.close
1045 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 ; \}")
1046 open("article").add_class("graph")
1047 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
1048 close("article")
1049 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
1050 add_html(fmap.read_all)
1051 fmap.close
1052 end
1053
1054 # Add a (source) link fo a given location
1055 fun show_source(l: Location): String
1056 do
1057 if source == null then
1058 return "({l.file.filename.simplify_path})"
1059 else
1060 # THIS IS JUST UGLY ! (but there is no replace yet)
1061 var x = source.split_with("%f")
1062 source = x.join(l.file.filename.simplify_path)
1063 x = source.split_with("%l")
1064 source = x.join(l.line_start.to_s)
1065 x = source.split_with("%L")
1066 source = x.join(l.line_end.to_s)
1067 return " (<a href=\"{source.to_s}\">show code</a>)"
1068 end
1069 end
1070
1071 end
1072
1073 redef class AModule
1074 private fun comment: String do
1075 var ret = ""
1076 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
1077 if n_moduledecl.n_doc is null then return ""
1078 for t in n_moduledecl.n_doc.n_comment do
1079 var txt = t.text
1080 txt = txt.replace("# ", "")
1081 txt = txt.replace("#", "")
1082 ret += txt
1083 end
1084 return ret
1085 end
1086
1087 private fun short_comment: String do
1088 var ret = ""
1089 if n_moduledecl != null and n_moduledecl.n_doc != null then
1090 var txt = n_moduledecl.n_doc.n_comment.first.text
1091 txt = txt.replace("# ", "")
1092 txt = txt.replace("\n", "")
1093 ret += txt
1094 end
1095 return ret
1096 end
1097 end
1098
1099 redef class MModule
1100
1101 super Comparable
1102 redef type OTHER: MModule
1103 redef fun <(other: OTHER): Bool do return self.name < other.name
1104
1105 var amodule: nullable AModule
1106
1107 # Get the list of all methods in a module
1108 fun imported_methods: Set[MMethod] do
1109 var methods = new HashSet[MMethod]
1110 for mclass in imported_mclasses do
1111 for method in mclass.intro_methods do
1112 methods.add(method)
1113 end
1114 end
1115 return methods
1116 end
1117
1118 # Get the list aof all refined methods in a module
1119 fun redef_methods: Set[MMethod] do
1120 var methods = new HashSet[MMethod]
1121 for mclass in redef_mclasses do
1122 for method in mclass.intro_methods do
1123 methods.add(method)
1124 end
1125 end
1126 return methods
1127 end
1128 end
1129 redef class MPropDef
1130 super Comparable
1131 redef type OTHER: MPropDef
1132 redef fun <(other: OTHER): Bool do return self.mproperty.name < other.mproperty.name
1133 end
1134
1135 redef class MProperty
1136
1137 super Comparable
1138 redef type OTHER: MProperty
1139 redef fun <(other: OTHER): Bool do return self.name < other.name
1140
1141 var is_redef: Bool
1142 var apropdef: nullable APropdef
1143
1144 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1145 do
1146 super
1147 is_redef = false
1148 end
1149
1150 fun local_class: MClass do
1151 var classdef = self.intro_mclassdef
1152 return classdef.mclass
1153 end
1154
1155 fun class_text: String do
1156 return local_class.name
1157 end
1158
1159 fun link_anchor: String do
1160 return "{class_text}.html#{anchor}"
1161 end
1162
1163 fun anchor: String do
1164 return "PROP_{c_name}"
1165 end
1166
1167 end
1168
1169 redef class MClass
1170
1171 super Comparable
1172 redef type OTHER: MClass
1173 redef fun <(other: OTHER): Bool do return self.name < other.name
1174
1175 # Associate all MMethods to each MModule concerns
1176 fun all_methods: HashMap[MModule, Set[MMethod]] do
1177 var hm = new HashMap[MModule, Set[MMethod]]
1178 for mmodule, childs in concerns do
1179 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
1180 for prop in intro_methods do
1181 if mmodule == prop.intro_mclassdef.mmodule then
1182 prop.is_redef = false
1183 hm[mmodule].add(prop)
1184 end
1185 end
1186 for prop in redef_methods do
1187 if mmodule == prop.intro_mclassdef.mmodule then
1188 prop.is_redef = true
1189 hm[mmodule].add(prop)
1190 end
1191 end
1192
1193 if childs != null then
1194 for child in childs do
1195 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
1196 for prop in intro_methods do
1197 if child == prop.intro_mclassdef.mmodule then
1198 prop.is_redef = false
1199 hm[child].add(prop)
1200 end
1201 end
1202 for prop in redef_methods do
1203 if child == prop.intro_mclassdef.mmodule then
1204 prop.is_redef = true
1205 hm[child].add(prop)
1206 end
1207 end
1208 end
1209 end
1210 end
1211 return hm
1212 end
1213
1214 fun public_owner: MModule do
1215 var owner = intro_mmodule
1216 if owner.public_owner is null then
1217 return owner
1218 else
1219 return owner.public_owner.as(not null)
1220 end
1221 end
1222
1223 # Associate Amodule to all MModule concern by 'self'
1224 fun amodule(amodules: HashMap[MModule, AModule]) do
1225 for owner, childs in concerns do
1226 if childs != null then for child in childs do child.amodule = amodules[child]
1227 owner.amodule = amodules[owner]
1228 end
1229 end
1230
1231 # Associate MClass to all MMethod include in 'inherited_methods'
1232 fun inherited: HashMap[MClass, Set[MMethod]] do
1233 var hm = new HashMap[MClass, Set[MMethod]]
1234 for method in inherited_methods do
1235 var mclass = method.intro_mclassdef.mclass
1236 if not hm.has_key(mclass) then hm[mclass] = new HashSet[MMethod]
1237 hm[mclass].add(method)
1238 end
1239 return hm
1240 end
1241
1242 # Return true if MModule concern contain subMModule
1243 fun has_mmodule(sub: MModule): Bool do
1244 for mmodule, childs in concerns do
1245 if childs is null then continue
1246 if childs.has(sub) then return true
1247 end
1248 return false
1249 end
1250
1251 fun mmethod(mprop2npropdef: Map[MProperty, APropdef]) do
1252 for const in constructors do
1253 if mprop2npropdef.has_key(const)then
1254 const.apropdef = mprop2npropdef[const].as(AMethPropdef)
1255 end
1256 end
1257
1258 for intro in intro_methods do
1259 if mprop2npropdef.has_key(intro)then
1260 if mprop2npropdef[intro] isa AMethPropdef then intro.apropdef = mprop2npropdef[intro].as(AMethPropdef)
1261 end
1262 end
1263
1264 for rd in redef_methods do
1265 if mprop2npropdef.has_key(rd)then
1266 if mprop2npropdef[rd] isa AMethPropdef then rd.apropdef = mprop2npropdef[rd].as(AMethPropdef)
1267 end
1268 end
1269 end
1270
1271 fun link_anchor: String do
1272 return "{name}.html"
1273 end
1274
1275 end
1276
1277 redef class AStdClassdef
1278 private fun comment: String do
1279 var ret = ""
1280 if n_doc != null then
1281 for t in n_doc.n_comment do
1282 var txt = t.text.replace("# ", "")
1283 txt = txt.replace("#", "")
1284 ret += "{txt}"
1285 end
1286 end
1287 return ret
1288 end
1289
1290 private fun short_comment: String do
1291 var ret = ""
1292 if n_doc != null then
1293 var txt = n_doc.n_comment.first.text
1294 txt = txt.replace("# ", "")
1295 txt = txt.replace("\n", "")
1296 ret += txt
1297 end
1298 return ret
1299 end
1300 end
1301
1302 redef class ASignature
1303 redef fun to_s do
1304 #TODO closures
1305 var ret = ""
1306 if not n_params.is_empty then
1307 ret = "{ret}({n_params.join(", ")})"
1308 end
1309 if n_type != null and n_type.to_s != "" then ret += " {n_type.to_s}"
1310 return ret
1311 end
1312 end
1313
1314 redef class AParam
1315 redef fun to_s do
1316 var ret = "{n_id.text}"
1317 if n_type != null then
1318 ret = "{ret}: {n_type.to_s}"
1319 if n_dotdotdot != null then ret = "{ret}..."
1320 end
1321 return ret
1322 end
1323 end
1324
1325 redef class AType
1326 redef fun to_s do
1327 var ret = "<a href=\"{n_id.text}.html\">{n_id.text}</a>"
1328 if n_kwnullable != null then ret = "nullable {ret}"
1329 if not n_types.is_empty then ret = "{ret}[{n_types.join(", ")}]"
1330 return ret
1331 end
1332 end
1333
1334 redef class APropdef
1335 private fun short_comment: String is abstract
1336 private fun signature: String is abstract
1337 private fun comment: String is abstract
1338 end
1339
1340 redef class AAttrPropdef
1341 redef fun short_comment do
1342 var ret = ""
1343 if n_doc != null then
1344 var txt = n_doc.n_comment.first.text
1345 txt = txt.replace("# ", "")
1346 txt = txt.replace("\n", "")
1347 ret += txt
1348 end
1349 return ret
1350 end
1351 end
1352
1353 redef class AMethPropdef
1354 redef fun short_comment do
1355 var ret = ""
1356 if n_doc != null then
1357 var txt = n_doc.n_comment.first.text
1358 txt = txt.replace("# ", "")
1359 txt = txt.replace("\n", "")
1360 ret += txt
1361 end
1362 return ret
1363 end
1364
1365 redef fun signature: String do
1366 var sign = ""
1367 if n_signature != null then sign = " {n_signature.to_s}"
1368 return sign
1369 end
1370
1371 redef private fun comment: String do
1372 var ret = ""
1373 if n_doc != null then
1374 for t in n_doc.n_comment do
1375 var txt = t.text.replace("# ", "")
1376 txt = txt.replace("#", "")
1377 ret += "{txt}"
1378 end
1379 end
1380 return ret
1381 end
1382 end
1383
1384 redef class MClassDef
1385 private fun namespace(mclass: MClass): String do
1386
1387 if mmodule.public_owner is null then
1388 return "{mmodule.full_name}::{mclass.name}"
1389 else if mclass is self.mclass then
1390 return "{mmodule.public_owner.name}::{mclass.name}"
1391 else
1392 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\">{mclass.name}</a>"
1393 end
1394 end
1395 end
1396
1397 redef class Set[E]
1398 fun last: E do
1399 return to_a[length-1]
1400 end
1401 end
1402
1403 # Create a tool context to handle options and paths
1404 var toolcontext = new ToolContext
1405
1406 # Here we launch the nit index
1407 var nitdoc = new Nitdoc(toolcontext)
1408 nitdoc.start