ni_nitdoc: Adding inheritance column in class page
[nit.git] / src / ni_nitdoc.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 module ni_nitdoc
18
19 import model_utils
20 import abstract_compiler
21 import html
22
23 class Nitdoc
24 private var toolcontext: ToolContext
25 private var model: Model
26 private var modelbuilder: ModelBuilder
27 private var mainmodule: MModule
28 private var arguments: Array[String]
29 private var destinationdir: nullable String
30 private var sharedir: nullable String
31
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 var classpage = new NitdocMClasses.with(mclass, aclassdef)
124 classpage.save("{destinationdir.to_s}/{mclass.name}.html")
125 end
126 end
127 end
128
129 end
130
131 class NitdocOverview
132 super NitdocPage
133
134 var amodules: Array[AModule]
135
136 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
137 # opt_nodot to inform about the graph gen
138 # destination: to know where will be saved dot files
139 init with(modules: Array[AModule], opt_nodot: Bool, destination: String) do
140 self.amodules = modules
141 self.opt_nodot = opt_nodot
142 self.destinationdir = destination
143 end
144
145 redef fun head do
146 super
147 add("title").text("Overview | Nit Standard Library")
148 end
149
150 redef fun header do
151 open("header")
152 open("nav").add_class("main")
153 open("ul")
154 add("li").add_class("current").text("Overview")
155 open("li")
156 add_html("<a href=\"full-index.html\">Full Index</a>")
157 close("li")
158 open("li").attr("id", "liGitHub")
159 open("a").add_class("btn").attr("id", "logGitHub")
160 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
161 close("a")
162 open("div").add_class("popover bottom")
163 add("div").add_class("arrow").text(" ")
164 open("div").add_class("githubTitle")
165 add("h3").text("Github Sign In")
166 close("div")
167 open("div")
168 add("label").attr("id", "lbloginGit").text("Username")
169 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
170 open("label").attr("id", "logginMessage").text("Hello ")
171 open("a").attr("id", "githubAccount")
172 add("strong").attr("id", "nickName").text(" ")
173 close("a")
174 close("label")
175 close("div")
176 open("div")
177 add("label").attr("id", "lbpasswordGit").text("Password")
178 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
179 open("div").attr("id", "listBranches")
180 add("label").attr("id", "lbBranches").text("Branch")
181 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
182 close("div")
183 close("div")
184 open("div")
185 add("label").attr("id", "lbrepositoryGit").text("Repository")
186 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
187 close("div")
188 open("div")
189 add("label").attr("id", "lbbranchGit").text("Branch")
190 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
191 close("div")
192 open("div")
193 add("a").attr("id", "signIn").text("Sign In")
194 close("div")
195 close("div")
196 close("li")
197 close("ul")
198 close("nav")
199 close("header")
200 end
201
202 redef fun body do
203 super
204 open("div").add_class("page")
205 open("div").add_class("content fullpage")
206 add("h1").text("Nit Standard Library")
207 open("article").add_class("overview")
208 add_html("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
209 close("article")
210 open("article").add_class("overview")
211 add("h2").text("Modules")
212 open("ul")
213 add_modules
214 close("ul")
215 process_generate_dot
216 close("article")
217 close("div")
218 close("div")
219 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
220 end
221
222 fun add_modules do
223 var ls = new List[nullable MModule]
224 for amodule in amodules do
225 var mmodule = amodule.mmodule.public_owner
226 if mmodule != null and not ls.has(mmodule) then
227 open("li")
228 add("a").attr("href", "{mmodule.name}.html").text("{mmodule.to_s} ")
229 add_html(amodule.comment)
230 close("li")
231 ls.add(mmodule)
232 end
233 end
234 end
235
236 fun process_generate_dot do
237 var op = new Buffer
238 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")
239 for amodule in amodules do
240 op.append("\"{amodule.mmodule.name}\"[URL=\"{amodule.mmodule.name}.html\"];\n")
241 for mmodule2 in amodule.mmodule.in_importation.direct_greaters do
242 op.append("\"{amodule.mmodule.name}\"->\"{mmodule2.name}\";\n")
243 end
244 end
245 op.append("\}\n")
246 generate_dot(op.to_s, "dep", "Modules hierarchy")
247 end
248
249 end
250
251 class NitdocFullindex
252 super NitdocPage
253
254 var mmodules: Array[MModule]
255
256 init with(mmodules: Array[MModule]) do
257 self.mmodules = mmodules
258 opt_nodot = false
259 destinationdir = ""
260 end
261
262 redef fun head do
263 super
264 add("title").text("Full Index | Nit Standard Library")
265 end
266
267 redef fun header do
268 open("header")
269 open("nav").add_class("main")
270 open("ul")
271 open("li")
272 add_html("<a href=\"index.html\">Overview</a>")
273 close("li")
274 add("li").add_class("current").text("Full Index")
275 open("li").attr("id", "liGitHub")
276 open("a").add_class("btn").attr("id", "logGitHub")
277 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
278 close("a")
279 open("div").add_class("popover bottom")
280 add("div").add_class("arrow").text(" ")
281 open("div").add_class("githubTitle")
282 add("h3").text("Github Sign In")
283 close("div")
284 open("div")
285 add("label").attr("id", "lbloginGit").text("Username")
286 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
287 open("label").attr("id", "logginMessage").text("Hello ")
288 open("a").attr("id", "githubAccount")
289 add("strong").attr("id", "nickName").text(" ")
290 close("a")
291 close("label")
292 close("div")
293 open("div")
294 add("label").attr("id", "lbpasswordGit").text("Password")
295 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
296 open("div").attr("id", "listBranches")
297 add("label").attr("id", "lbBranches").text("Branch")
298 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
299 close("div")
300 close("div")
301 open("div")
302 add("label").attr("id", "lbrepositoryGit").text("Repository")
303 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
304 close("div")
305 open("div")
306 add("label").attr("id", "lbbranchGit").text("Branch")
307 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
308 close("div")
309 open("div")
310 add("a").attr("id", "signIn").text("Sign In")
311 close("div")
312 close("div")
313 close("li")
314 close("ul")
315 close("nav")
316 close("header")
317 end
318
319 redef fun body do
320 super
321 open("div").add_class("page")
322 open("div").add_class("content fullpage")
323 add("h1").text("Full Index")
324 add_content
325 close("div")
326 close("div")
327 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
328 end
329
330 fun add_content do
331 module_column
332 classes_column
333 properties_column
334 end
335
336 # Add to content modules column
337 fun module_column do
338 var ls = new List[nullable MModule]
339 open("article").add_class("modules filterable")
340 add("h2").text("Modules")
341 open("ul")
342 for mmodule in mmodules do
343 if mmodule.public_owner != null and not ls.has(mmodule.public_owner) then
344 ls.add(mmodule.public_owner)
345 open("li")
346 add("a").attr("href", "{mmodule.public_owner.name}.html").text(mmodule.public_owner.name)
347 close("li")
348 end
349 end
350 close("ul")
351 close("article")
352 end
353
354 # Add to content classes modules
355 fun classes_column do
356 open("article").add_class("classes filterable")
357 add("h2").text("Classes")
358 open("ul")
359
360 for mclass in mmodules.first.imported_mclasses do
361 open("li")
362 add("a").attr("href", "{mclass.name}.html").text(mclass.name)
363 close("li")
364 end
365
366 close("ul")
367 close("article")
368 end
369
370 # Insert the properties column of fullindex page
371 fun properties_column do
372 open("article").add_class("properties filterable")
373 add("h2").text("Properties")
374 open("ul")
375
376 for method in mmodules.first.imported_methods do
377 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
378 open("li").add_class("intro")
379 add("span").attr("title", "introduction").text("I")
380 add_html("&nbsp;")
381 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
382 close("li")
383 end
384
385 for method in mmodules.first.redef_methods do
386 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
387 open("li").add_class("redef")
388 add("span").attr("title", "redefinition").text("R")
389 add_html("&nbsp;")
390 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
391 close("li")
392 end
393
394 close("ul")
395 close("article")
396 end
397
398 end
399
400 class NitdocModules
401 super NitdocPage
402
403 var amodule: AModule
404 var modulename: String
405 init with(amodule: AModule) do
406 self.amodule = amodule
407 self.modulename = self.amodule.mmodule.name
408 opt_nodot = false
409 destinationdir = ""
410 end
411
412 redef fun head do
413 super
414 add("title").text("{modulename} module | {amodule.short_comment}")
415 end
416
417 redef fun header do
418 open("header")
419 open("nav").add_class("main")
420 open("ul")
421 open("li")
422 add_html("<a href=\"index.html\">Overview</a>")
423 close("li")
424 add("li").add_class("current").text(modulename)
425 open("li")
426 add_html("<a href=\"full-index.html\" >Full Index</a>")
427 close("li")
428 open("li").attr("id", "liGitHub")
429 open("a").add_class("btn").attr("id", "logGitHub")
430 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
431 close("a")
432 open("div").add_class("popover bottom")
433 add("div").add_class("arrow").text(" ")
434 open("div").add_class("githubTitle")
435 add("h3").text("Github Sign In")
436 close("div")
437 open("div")
438 add("label").attr("id", "lbloginGit").text("Username")
439 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
440 open("label").attr("id", "logginMessage").text("Hello ")
441 open("a").attr("id", "githubAccount")
442 add("strong").attr("id", "nickName").text(" ")
443 close("a")
444 close("label")
445 close("div")
446 open("div")
447 add("label").attr("id", "lbpasswordGit").text("Password")
448 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
449 open("div").attr("id", "listBranches")
450 add("label").attr("id", "lbBranches").text("Branch")
451 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
452 close("div")
453 close("div")
454 open("div")
455 add("label").attr("id", "lbrepositoryGit").text("Repository")
456 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
457 close("div")
458 open("div")
459 add("label").attr("id", "lbbranchGit").text("Branch")
460 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
461 close("div")
462 open("div")
463 add("a").attr("id", "signIn").text("Sign In")
464 close("div")
465 close("div")
466 close("li")
467 close("ul")
468 close("nav")
469 close("header")
470 end
471
472 redef fun body do
473 super
474 open("div").add_class("page")
475 menu
476 add_content
477 close("div")
478 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
479 end
480
481 # Insert all tags in content part
482 fun add_content do
483 open("div").add_class("content")
484 add("h1").text(modulename)
485 add("div").add_class("subtitle").text("module {modulename}")
486 module_comment
487 classes
488 properties
489 close("div")
490 end
491
492 # Insert module comment in the content
493 fun module_comment do
494 var doc = amodule.comment
495 open("div").attr("id", "description")
496 add("pre").add_class("text_label").text(doc)
497 add("textarea").add_class("edit").attr("rows", "1").attr("cols", "76").attr("id", "fileContent").text(" ")
498 add("a").attr("id", "cancelBtn").text("Cancel")
499 add("a").attr("id", "commitBtn").text("Commit")
500 add("pre").add_class("text_label").attr("id", "preSave").attr("type", "2")
501 close("div")
502 end
503
504 fun menu do
505 var mmodule = amodule.mmodule
506 open("div").add_class("menu")
507 open("nav")
508 add("h3").text("Module Hierarchy").attr("style","cursor: pointer;")
509 if mmodule.in_importation.direct_greaters.length > 0 then
510 add_html("<h4>All dependencies</h4><ul>")
511 for m in mmodule.in_importation.direct_greaters do
512 if m == mmodule or mmodule == m.public_owner then continue
513 open("li")
514 add("a").attr("href", "{m.name}.html").text(m.name)
515 close("li")
516 end
517 add_html("</ul>")
518 end
519 if mmodule.in_importation.greaters.length > 0 then
520 add_html("<h4>All clients</h4><ul>")
521 for m in mmodule.in_importation.greaters do
522 if m == mmodule then continue
523 open("li")
524 add("a").attr("href", "{m.name}.html").text(m.name)
525 close("li")
526 end
527 add_html("</ul>")
528 end
529 close("nav")
530 if mmodule.in_nesting.direct_greaters.length > 0 then
531 open("nav")
532 add("h3").text("Nested Modules").attr("style","cursor: pointer;")
533 open("ul")
534 for m in mmodule.in_nesting.direct_greaters do
535 open("li")
536 add("a").attr("href", "{m.name}.html").text(m.name)
537 close("li")
538 end
539 close("ul")
540
541 close("nav")
542 end
543 close("div")
544 end
545
546 fun classes do
547 open("div").add_class("module")
548 open("article").add_class("classes filterable")
549 add("h2").text("Classes")
550 open("ul")
551 for c, state in amodule.mmodule.mclasses do
552 var name = c.name
553 if state == c_is_intro or state == c_is_imported then
554 open("li").add_class("intro")
555 add("span").attr("title", "introduced in this module").text("I ")
556 else
557 open("li").add_class("redef")
558 add("span").attr("title", "refined in this module").text("R ")
559 end
560 add("a").attr("href", "{name}.html").text(name)
561 close("li")
562 end
563 close("ul")
564 close("article")
565 close("div")
566 end
567
568 fun properties do
569 open("article").add_class("properties filterable")
570 add_html("<h2>Properties</h2>")
571 open("ul")
572 for method in amodule.mmodule.imported_methods do
573 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
574 open("li").add_class("intro")
575 add("span").attr("title", "introduction").text("I")
576 add_html("&nbsp;")
577 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
578 close("li")
579 end
580
581 for method in amodule.mmodule.redef_methods do
582 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
583 open("li").add_class("redef")
584 add("span").attr("title", "redefinition").text("R")
585 add_html("&nbsp;")
586 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
587 close("li")
588 end
589
590 close("ul")
591 close("article")
592 end
593
594 end
595
596 # Nit Standard Library
597 class NitdocMClasses
598 super NitdocPage
599
600 var mclass: MClass
601 var aclassdef: AClassdef
602 var stdclassdef: nullable AStdClassdef
603 var public_owner: nullable MModule
604
605 init with(mclass: MClass, aclassdef: AClassdef) do
606 self.mclass = mclass
607 self.aclassdef = aclassdef
608 if aclassdef isa AStdClassdef then self.stdclassdef = aclassdef
609 self.public_owner = mclass.intro_mmodule.public_owner
610 opt_nodot = false
611 destinationdir = ""
612 end
613
614 redef fun head do
615 super
616 add("title").text("{self.mclass.name} class | Nit Standard Library")
617 end
618
619 redef fun header do
620 open("header")
621 open("nav").add_class("main")
622 open("ul")
623 open("li")
624 add_html("<a href=\"index.html\">Overview</a>")
625 close("li")
626 open("li")
627 if public_owner is null then
628 add_html("<a href=\"{mclass.intro_mmodule.name}.html\">{mclass.intro_mmodule.name}</a>")
629 else
630 add_html("<a href=\"{public_owner.name}.html\">{public_owner.name}</a>")
631 end
632 close("li")
633 add("li").add_class("current").text(mclass.name)
634 open("li")
635 add_html("<a href=\"full-index.html\" >Full Index</a>")
636 close("li")
637 open("li").attr("id", "liGitHub")
638 open("a").add_class("btn").attr("id", "logGitHub")
639 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
640 close("a")
641 open("div").add_class("popover bottom")
642 add("div").add_class("arrow").text(" ")
643 open("div").add_class("githubTitle")
644 add("h3").text("Github Sign In")
645 close("div")
646 open("div")
647 add("label").attr("id", "lbloginGit").text("Username")
648 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
649 open("label").attr("id", "logginMessage").text("Hello ")
650 open("a").attr("id", "githubAccount")
651 add("strong").attr("id", "nickName").text(" ")
652 close("a")
653 close("label")
654 close("div")
655 open("div")
656 add("label").attr("id", "lbpasswordGit").text("Password")
657 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
658 open("div").attr("id", "listBranches")
659 add("label").attr("id", "lbBranches").text("Branch")
660 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
661 close("div")
662 close("div")
663 open("div")
664 add("label").attr("id", "lbrepositoryGit").text("Repository")
665 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
666 close("div")
667 open("div")
668 add("label").attr("id", "lbbranchGit").text("Branch")
669 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
670 close("div")
671 open("div")
672 add("a").attr("id", "signIn").text("Sign In")
673 close("div")
674 close("div")
675 close("li")
676 close("ul")
677 close("nav")
678 close("header")
679 end
680
681 redef fun body do
682 super
683 open("div").add_class("page")
684 add_content
685 close("div")
686 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
687 end
688
689 # Insert all tags in content part
690 fun add_content do
691 open("div").add_class("menu")
692 properties_column
693 inheritance_column
694 close("div")
695 open("div").add_class("content")
696 close("div")
697 end
698
699 fun properties_column do
700 open("nav").add_class("properties filterable")
701 add("h3").text("Properties")
702
703 if mclass.virtual_types.length > 0 then
704 add("h4").text("Virtual Types")
705 open("ul")
706 for prop in mclass.virtual_types do
707 add_html("<li class=\"redef\"><span title=\"Redefined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
708 end
709 close("ul")
710 end
711 if mclass.constructors.length > 0 then
712 add("h4").text("Constructors")
713 open("ul")
714 for prop in mclass.constructors do
715 add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
716 end
717 close("ul")
718 end
719 add("h4").text("Methods")
720 open("ul")
721 if mclass.intro_methods.length > 0 then
722 for prop in mclass.intro_methods do
723 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>")
724 end
725 end
726 if mclass.inherited_methods.length > 0 then
727 for prop in mclass.inherited_methods do
728 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>")
729 end
730 end
731 if mclass.redef_methods.length > 0 then
732 for prop in mclass.redef_methods do
733 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>")
734 end
735 end
736 close("ul")
737 close("nav")
738 end
739
740 fun inheritance_column do
741 open("nav")
742 add("h3").text("Inheritance")
743 if mclass.parents.length > 0 then
744 add("h4").text("Superclasses")
745 open("ul")
746 for sup in mclass.parents do add_html("<li><a href=\"{sup.name}.html\">{sup.name}</a></li>")
747 close("ul")
748 end
749
750 if mclass.descendants.length is 0 then
751 add("h4").text("No Known Subclasses")
752 else if mclass.descendants.length <= 100 then
753 add("h4").text("Subclasses")
754 open("ul")
755 for sub in mclass.descendants do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
756 close("ul")
757 else if mclass.children.length <= 100 then
758 add("h4").text("Direct Subclasses Only")
759 open("ul")
760 for sub in mclass.children do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
761 close("ul")
762 else
763 add("h4").text("Too much Subclasses to list")
764 end
765 close("nav")
766 end
767
768 end
769
770 class NitdocPage
771 super HTMLPage
772
773 var opt_nodot: Bool
774 var destinationdir : String
775
776 redef fun head do
777 add("meta").attr("charset", "utf-8")
778 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
779 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
780 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
781 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
782 end
783
784 redef fun body do header
785 fun header do end
786
787 # Generate a clickable graphviz image using a dot content
788 fun generate_dot(dot: String, name: String, alt: String) do
789 if opt_nodot then return
790 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
791 file.write(dot)
792 file.close
793 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 ; \}")
794 open("article").add_class("graph")
795 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
796 close("article")
797 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
798 add_html(fmap.read_all)
799 fmap.close
800 end
801
802 end
803
804 redef class AModule
805 private fun comment: String do
806 var ret = ""
807 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
808 if n_moduledecl.n_doc is null then return ""
809 for t in n_moduledecl.n_doc.n_comment do
810 ret += "{t.text.replace("# ", "")}"
811 end
812 return ret
813 end
814
815 private fun short_comment: String do
816 var ret = ""
817 if n_moduledecl != null and n_moduledecl.n_doc != null then
818 var txt = n_moduledecl.n_doc.n_comment.first.text
819 txt = txt.replace("# ", "")
820 txt = txt.replace("\n", "")
821 ret += txt
822 end
823 return ret
824 end
825 end
826
827 redef class MModule
828
829 var amodule: nullable AModule
830
831 # Get the list of all methods in a module
832 fun imported_methods: Set[MMethod] do
833 var methods = new HashSet[MMethod]
834 for mclass in imported_mclasses do
835 for method in mclass.intro_methods do
836 methods.add(method)
837 end
838 end
839 return methods
840 end
841
842 # Get the list aof all refined methods in a module
843 fun redef_methods: Set[MMethod] do
844 var methods = new HashSet[MMethod]
845 for mclass in redef_mclasses do
846 for method in mclass.intro_methods do
847 methods.add(method)
848 end
849 end
850 return methods
851 end
852 end
853
854 redef class MProperty
855
856 var is_redef: Bool
857 var apropdef: nullable APropdef
858
859 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
860 do
861 super
862 is_redef = false
863 end
864
865 fun local_class: MClass do
866 var classdef = self.intro_mclassdef
867 return classdef.mclass
868 end
869
870 fun class_text: String do
871 return local_class.name
872 end
873
874 fun link_anchor: String do
875 return "{class_text}.html#{anchor}"
876 end
877
878 fun anchor: String do
879 return "PROP_{c_name}"
880 end
881
882 end
883
884 redef class MClass
885
886 # Associate all MMethods to each MModule concerns
887 fun all_methods: HashMap[MModule, Set[MMethod]] do
888 var hm = new HashMap[MModule, Set[MMethod]]
889 for mmodule, childs in concerns do
890 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
891 for prop in intro_methods do
892 if mmodule == prop.intro_mclassdef.mmodule then
893 prop.is_redef = false
894 hm[mmodule].add(prop)
895 end
896 end
897 for prop in redef_methods do
898 if mmodule == prop.intro_mclassdef.mmodule then
899 prop.is_redef = true
900 hm[mmodule].add(prop)
901 end
902 end
903
904 if childs != null then
905 for child in childs do
906 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
907 for prop in intro_methods do
908 if child == prop.intro_mclassdef.mmodule then
909 prop.is_redef = false
910 hm[child].add(prop)
911 end
912 end
913 for prop in redef_methods do
914 if child == prop.intro_mclassdef.mmodule then
915 prop.is_redef = true
916 hm[child].add(prop)
917 end
918 end
919 end
920 end
921 end
922 return hm
923 end
924
925 end
926
927 # Create a tool context to handle options and paths
928 var toolcontext = new ToolContext
929 toolcontext.process_options
930
931 # Here we launch the nit index
932 var nitdoc = new Nitdoc(toolcontext)
933 nitdoc.start