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