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