ni_nitdoc: Adds header/body in class pages
[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 close("div")
685 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
686 end
687
688 end
689
690 class NitdocPage
691 super HTMLPage
692
693 var opt_nodot: Bool
694 var destinationdir : String
695
696 redef fun head do
697 add("meta").attr("charset", "utf-8")
698 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
699 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
700 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
701 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
702 end
703
704 redef fun body do header
705 fun header do end
706
707 # Generate a clickable graphviz image using a dot content
708 fun generate_dot(dot: String, name: String, alt: String) do
709 if opt_nodot then return
710 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
711 file.write(dot)
712 file.close
713 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 ; \}")
714 open("article").add_class("graph")
715 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
716 close("article")
717 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
718 add_html(fmap.read_all)
719 fmap.close
720 end
721
722 end
723
724 redef class AModule
725 private fun comment: String do
726 var ret = ""
727 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
728 if n_moduledecl.n_doc is null then return ""
729 for t in n_moduledecl.n_doc.n_comment do
730 ret += "{t.text.replace("# ", "")}"
731 end
732 return ret
733 end
734
735 private fun short_comment: String do
736 var ret = ""
737 if n_moduledecl != null and n_moduledecl.n_doc != null then
738 var txt = n_moduledecl.n_doc.n_comment.first.text
739 txt = txt.replace("# ", "")
740 txt = txt.replace("\n", "")
741 ret += txt
742 end
743 return ret
744 end
745 end
746
747 redef class MModule
748
749 var amodule: nullable AModule
750
751 # Get the list of all methods in a module
752 fun imported_methods: Set[MMethod] do
753 var methods = new HashSet[MMethod]
754 for mclass in imported_mclasses do
755 for method in mclass.intro_methods do
756 methods.add(method)
757 end
758 end
759 return methods
760 end
761
762 # Get the list aof all refined methods in a module
763 fun redef_methods: Set[MMethod] do
764 var methods = new HashSet[MMethod]
765 for mclass in redef_mclasses do
766 for method in mclass.intro_methods do
767 methods.add(method)
768 end
769 end
770 return methods
771 end
772 end
773
774 redef class MProperty
775
776 var is_redef: Bool
777 var apropdef: nullable APropdef
778
779 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
780 do
781 super
782 is_redef = false
783 end
784
785 fun local_class: MClass do
786 var classdef = self.intro_mclassdef
787 return classdef.mclass
788 end
789
790 end
791
792 redef class MClass
793
794 # Associate all MMethods to each MModule concerns
795 fun all_methods: HashMap[MModule, Set[MMethod]] do
796 var hm = new HashMap[MModule, Set[MMethod]]
797 for mmodule, childs in concerns do
798 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
799 for prop in intro_methods do
800 if mmodule == prop.intro_mclassdef.mmodule then
801 prop.is_redef = false
802 hm[mmodule].add(prop)
803 end
804 end
805 for prop in redef_methods do
806 if mmodule == prop.intro_mclassdef.mmodule then
807 prop.is_redef = true
808 hm[mmodule].add(prop)
809 end
810 end
811
812 if childs != null then
813 for child in childs do
814 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
815 for prop in intro_methods do
816 if child == prop.intro_mclassdef.mmodule then
817 prop.is_redef = false
818 hm[child].add(prop)
819 end
820 end
821 for prop in redef_methods do
822 if child == prop.intro_mclassdef.mmodule then
823 prop.is_redef = true
824 hm[child].add(prop)
825 end
826 end
827 end
828 end
829 end
830 return hm
831 end
832
833 end
834
835 # Create a tool context to handle options and paths
836 var toolcontext = new ToolContext
837 toolcontext.process_options
838
839 # Here we launch the nit index
840 var nitdoc = new Nitdoc(toolcontext)
841 nitdoc.start