ni_nitdoc: Linked the amodule to its module
[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 end
786
787 end
788
789 class NitdocPage
790 super HTMLPage
791
792 var opt_nodot: Bool
793 var destinationdir : String
794
795 redef fun head do
796 add("meta").attr("charset", "utf-8")
797 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
798 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
799 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
800 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
801 end
802
803 redef fun body do header
804 fun header do end
805
806 # Generate a clickable graphviz image using a dot content
807 fun generate_dot(dot: String, name: String, alt: String) do
808 if opt_nodot then return
809 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
810 file.write(dot)
811 file.close
812 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 ; \}")
813 open("article").add_class("graph")
814 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
815 close("article")
816 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
817 add_html(fmap.read_all)
818 fmap.close
819 end
820
821 end
822
823 redef class AModule
824 private fun comment: String do
825 var ret = ""
826 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
827 if n_moduledecl.n_doc is null then return ""
828 for t in n_moduledecl.n_doc.n_comment do
829 ret += "{t.text.replace("# ", "")}"
830 end
831 return ret
832 end
833
834 private fun short_comment: String do
835 var ret = ""
836 if n_moduledecl != null and n_moduledecl.n_doc != null then
837 var txt = n_moduledecl.n_doc.n_comment.first.text
838 txt = txt.replace("# ", "")
839 txt = txt.replace("\n", "")
840 ret += txt
841 end
842 return ret
843 end
844 end
845
846 redef class MModule
847
848 var amodule: nullable AModule
849
850 # Get the list of all methods in a module
851 fun imported_methods: Set[MMethod] do
852 var methods = new HashSet[MMethod]
853 for mclass in imported_mclasses do
854 for method in mclass.intro_methods do
855 methods.add(method)
856 end
857 end
858 return methods
859 end
860
861 # Get the list aof all refined methods in a module
862 fun redef_methods: Set[MMethod] do
863 var methods = new HashSet[MMethod]
864 for mclass in redef_mclasses do
865 for method in mclass.intro_methods do
866 methods.add(method)
867 end
868 end
869 return methods
870 end
871 end
872
873 redef class MProperty
874
875 var is_redef: Bool
876 var apropdef: nullable APropdef
877
878 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
879 do
880 super
881 is_redef = false
882 end
883
884 fun local_class: MClass do
885 var classdef = self.intro_mclassdef
886 return classdef.mclass
887 end
888
889 fun class_text: String do
890 return local_class.name
891 end
892
893 fun link_anchor: String do
894 return "{class_text}.html#{anchor}"
895 end
896
897 fun anchor: String do
898 return "PROP_{c_name}"
899 end
900
901 end
902
903 redef class MClass
904
905 # Associate all MMethods to each MModule concerns
906 fun all_methods: HashMap[MModule, Set[MMethod]] do
907 var hm = new HashMap[MModule, Set[MMethod]]
908 for mmodule, childs in concerns do
909 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
910 for prop in intro_methods do
911 if mmodule == prop.intro_mclassdef.mmodule then
912 prop.is_redef = false
913 hm[mmodule].add(prop)
914 end
915 end
916 for prop in redef_methods do
917 if mmodule == prop.intro_mclassdef.mmodule then
918 prop.is_redef = true
919 hm[mmodule].add(prop)
920 end
921 end
922
923 if childs != null then
924 for child in childs do
925 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
926 for prop in intro_methods do
927 if child == prop.intro_mclassdef.mmodule then
928 prop.is_redef = false
929 hm[child].add(prop)
930 end
931 end
932 for prop in redef_methods do
933 if child == prop.intro_mclassdef.mmodule then
934 prop.is_redef = true
935 hm[child].add(prop)
936 end
937 end
938 end
939 end
940 end
941 return hm
942 end
943
944 fun public_owner: MModule do
945 var owner = intro_mmodule
946 if owner.public_owner is null then
947 return owner
948 else
949 return owner.public_owner.as(not null)
950 end
951 end
952
953 # Associate Amodule to all MModule concern by 'self'
954 fun amodule(amodules: HashMap[MModule, AModule]) do
955 for owner, childs in concerns do
956 if childs != null then for child in childs do child.amodule = amodules[child]
957 owner.amodule = amodules[owner]
958 end
959 end
960
961 end
962
963 redef class AStdClassdef
964 private fun comment: String do
965 var ret = ""
966 if n_doc != null then
967 for t in n_doc.n_comment do
968 var txt = t.text.replace("# ", "")
969 txt = txt.replace("#", "")
970 ret += "{txt}"
971 end
972 end
973 return ret
974 end
975
976 private fun short_comment: String do
977 var ret = ""
978 if n_doc != null then
979 var txt = n_doc.n_comment.first.text
980 txt = txt.replace("# ", "")
981 txt = txt.replace("\n", "")
982 ret += txt
983 end
984 return ret
985 end
986 end
987
988 redef class ASignature
989 redef fun to_s do
990 #TODO closures
991 var ret = ""
992 if not n_params.is_empty then
993 ret = "{ret}({n_params.join(", ")})"
994 end
995 if n_type != null and n_type.to_s != "" then ret += " {n_type.to_s}"
996 return ret
997 end
998 end
999
1000 redef class AParam
1001 redef fun to_s do
1002 var ret = "{n_id.text}"
1003 if n_type != null then
1004 ret = "{ret}: {n_type.to_s}"
1005 if n_dotdotdot != null then ret = "{ret}..."
1006 end
1007 return ret
1008 end
1009 end
1010
1011 redef class AType
1012 redef fun to_s do
1013 var ret = "<a href=\"{n_id.text}.html\">{n_id.text}</a>"
1014 if n_kwnullable != null then ret = "nullable {ret}"
1015 if not n_types.is_empty then ret = "{ret}[{n_types.join(", ")}]"
1016 return ret
1017 end
1018 end
1019
1020 redef class APropdef
1021 private fun short_comment: String is abstract
1022 private fun signature: String is abstract
1023 private fun comment: String is abstract
1024 end
1025
1026 redef class AAttrPropdef
1027 redef fun short_comment do
1028 var ret = ""
1029 if n_doc != null then
1030 var txt = n_doc.n_comment.first.text
1031 txt = txt.replace("# ", "")
1032 txt = txt.replace("\n", "")
1033 ret += txt
1034 end
1035 return ret
1036 end
1037 end
1038
1039 redef class AMethPropdef
1040 redef fun short_comment do
1041 var ret = ""
1042 if n_doc != null then
1043 var txt = n_doc.n_comment.first.text
1044 txt = txt.replace("# ", "")
1045 txt = txt.replace("\n", "")
1046 ret += txt
1047 end
1048 return ret
1049 end
1050
1051 redef fun signature: String do
1052 var sign = ""
1053 if n_signature != null then sign = " {n_signature.to_s}"
1054 return sign
1055 end
1056
1057 redef private fun comment: String do
1058 var ret = ""
1059 if n_doc != null then
1060 for t in n_doc.n_comment do
1061 var txt = t.text.replace("# ", "")
1062 txt = txt.replace("#", "")
1063 ret += "{txt}"
1064 end
1065 end
1066 return ret
1067 end
1068 end
1069
1070 # Create a tool context to handle options and paths
1071 var toolcontext = new ToolContext
1072 toolcontext.process_options
1073
1074 # Here we launch the nit index
1075 var nitdoc = new Nitdoc(toolcontext)
1076 nitdoc.start