ni_nitdoc: inform class name and namespace
[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 content
697 close("div")
698 end
699
700 fun properties_column do
701 open("nav").add_class("properties filterable")
702 add("h3").text("Properties")
703
704 if mclass.virtual_types.length > 0 then
705 add("h4").text("Virtual Types")
706 open("ul")
707 for prop in mclass.virtual_types do
708 add_html("<li class=\"redef\"><span title=\"Redefined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
709 end
710 close("ul")
711 end
712 if mclass.constructors.length > 0 then
713 add("h4").text("Constructors")
714 open("ul")
715 for prop in mclass.constructors do
716 add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
717 end
718 close("ul")
719 end
720 add("h4").text("Methods")
721 open("ul")
722 if mclass.intro_methods.length > 0 then
723 for prop in mclass.intro_methods do
724 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>")
725 end
726 end
727 if mclass.inherited_methods.length > 0 then
728 for prop in mclass.inherited_methods do
729 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>")
730 end
731 end
732 if mclass.redef_methods.length > 0 then
733 for prop in mclass.redef_methods do
734 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>")
735 end
736 end
737 close("ul")
738 close("nav")
739 end
740
741 fun inheritance_column do
742 open("nav")
743 add("h3").text("Inheritance")
744 if mclass.parents.length > 0 then
745 add("h4").text("Superclasses")
746 open("ul")
747 for sup in mclass.parents do add_html("<li><a href=\"{sup.name}.html\">{sup.name}</a></li>")
748 close("ul")
749 end
750
751 if mclass.descendants.length is 0 then
752 add("h4").text("No Known Subclasses")
753 else if mclass.descendants.length <= 100 then
754 add("h4").text("Subclasses")
755 open("ul")
756 for sub in mclass.descendants do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
757 close("ul")
758 else if mclass.children.length <= 100 then
759 add("h4").text("Direct Subclasses Only")
760 open("ul")
761 for sub in mclass.children do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
762 close("ul")
763 else
764 add("h4").text("Too much Subclasses to list")
765 end
766 close("nav")
767 end
768
769 fun content do
770 var subtitle = ""
771 var lmmodule = new List[MModule]
772 # Insert the subtitle part
773 add("h1").text(mclass.name)
774 open("div").add_class("subtitle")
775 if mclass.visibility is none_visibility then subtitle += "private "
776 subtitle += "{mclass.kind} <a href=\"{mclass.public_owner.name}.html\">{mclass.public_owner.name}</a>::{mclass.name}"
777 add_html(subtitle)
778 close("div")
779 add_html("<div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
780 # We add the class description
781 open("section").add_class("description")
782 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>")
783 close("section")
784 end
785
786 end
787
788 class NitdocPage
789 super HTMLPage
790
791 var opt_nodot: Bool
792 var destinationdir : String
793
794 redef fun head do
795 add("meta").attr("charset", "utf-8")
796 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
797 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
798 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
799 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
800 end
801
802 redef fun body do header
803 fun header do end
804
805 # Generate a clickable graphviz image using a dot content
806 fun generate_dot(dot: String, name: String, alt: String) do
807 if opt_nodot then return
808 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
809 file.write(dot)
810 file.close
811 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 ; \}")
812 open("article").add_class("graph")
813 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
814 close("article")
815 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
816 add_html(fmap.read_all)
817 fmap.close
818 end
819
820 end
821
822 redef class AModule
823 private fun comment: String do
824 var ret = ""
825 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
826 if n_moduledecl.n_doc is null then return ""
827 for t in n_moduledecl.n_doc.n_comment do
828 ret += "{t.text.replace("# ", "")}"
829 end
830 return ret
831 end
832
833 private fun short_comment: String do
834 var ret = ""
835 if n_moduledecl != null and n_moduledecl.n_doc != null then
836 var txt = n_moduledecl.n_doc.n_comment.first.text
837 txt = txt.replace("# ", "")
838 txt = txt.replace("\n", "")
839 ret += txt
840 end
841 return ret
842 end
843 end
844
845 redef class MModule
846
847 var amodule: nullable AModule
848
849 # Get the list of all methods in a module
850 fun imported_methods: Set[MMethod] do
851 var methods = new HashSet[MMethod]
852 for mclass in imported_mclasses do
853 for method in mclass.intro_methods do
854 methods.add(method)
855 end
856 end
857 return methods
858 end
859
860 # Get the list aof all refined methods in a module
861 fun redef_methods: Set[MMethod] do
862 var methods = new HashSet[MMethod]
863 for mclass in redef_mclasses do
864 for method in mclass.intro_methods do
865 methods.add(method)
866 end
867 end
868 return methods
869 end
870 end
871
872 redef class MProperty
873
874 var is_redef: Bool
875 var apropdef: nullable APropdef
876
877 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
878 do
879 super
880 is_redef = false
881 end
882
883 fun local_class: MClass do
884 var classdef = self.intro_mclassdef
885 return classdef.mclass
886 end
887
888 fun class_text: String do
889 return local_class.name
890 end
891
892 fun link_anchor: String do
893 return "{class_text}.html#{anchor}"
894 end
895
896 fun anchor: String do
897 return "PROP_{c_name}"
898 end
899
900 end
901
902 redef class MClass
903
904 # Associate all MMethods to each MModule concerns
905 fun all_methods: HashMap[MModule, Set[MMethod]] do
906 var hm = new HashMap[MModule, Set[MMethod]]
907 for mmodule, childs in concerns do
908 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
909 for prop in intro_methods do
910 if mmodule == prop.intro_mclassdef.mmodule then
911 prop.is_redef = false
912 hm[mmodule].add(prop)
913 end
914 end
915 for prop in redef_methods do
916 if mmodule == prop.intro_mclassdef.mmodule then
917 prop.is_redef = true
918 hm[mmodule].add(prop)
919 end
920 end
921
922 if childs != null then
923 for child in childs do
924 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
925 for prop in intro_methods do
926 if child == prop.intro_mclassdef.mmodule then
927 prop.is_redef = false
928 hm[child].add(prop)
929 end
930 end
931 for prop in redef_methods do
932 if child == prop.intro_mclassdef.mmodule then
933 prop.is_redef = true
934 hm[child].add(prop)
935 end
936 end
937 end
938 end
939 end
940 return hm
941 end
942
943 fun public_owner: MModule do
944 var owner = intro_mmodule
945 if owner.public_owner is null then
946 return owner
947 else
948 return owner.public_owner.as(not null)
949 end
950 end
951
952 end
953
954 redef class AStdClassdef
955 private fun comment: String do
956 var ret = ""
957 if n_doc != null then
958 for t in n_doc.n_comment do
959 var txt = t.text.replace("# ", "")
960 txt = txt.replace("#", "")
961 ret += "{txt}"
962 end
963 end
964 return ret
965 end
966
967 private fun short_comment: String do
968 var ret = ""
969 if n_doc != null then
970 var txt = n_doc.n_comment.first.text
971 txt = txt.replace("# ", "")
972 txt = txt.replace("\n", "")
973 ret += txt
974 end
975 return ret
976 end
977 end
978
979 redef class ASignature
980 redef fun to_s do
981 #TODO closures
982 var ret = ""
983 if not n_params.is_empty then
984 ret = "{ret}({n_params.join(", ")})"
985 end
986 if n_type != null and n_type.to_s != "" then ret += " {n_type.to_s}"
987 return ret
988 end
989 end
990
991 redef class AParam
992 redef fun to_s do
993 var ret = "{n_id.text}"
994 if n_type != null then
995 ret = "{ret}: {n_type.to_s}"
996 if n_dotdotdot != null then ret = "{ret}..."
997 end
998 return ret
999 end
1000 end
1001
1002 redef class AType
1003 redef fun to_s do
1004 var ret = "<a href=\"{n_id.text}.html\">{n_id.text}</a>"
1005 if n_kwnullable != null then ret = "nullable {ret}"
1006 if not n_types.is_empty then ret = "{ret}[{n_types.join(", ")}]"
1007 return ret
1008 end
1009 end
1010
1011 redef class APropdef
1012 private fun short_comment: String is abstract
1013 private fun signature: String is abstract
1014 private fun comment: String is abstract
1015 end
1016
1017 redef class AAttrPropdef
1018 redef fun short_comment do
1019 var ret = ""
1020 if n_doc != null then
1021 var txt = n_doc.n_comment.first.text
1022 txt = txt.replace("# ", "")
1023 txt = txt.replace("\n", "")
1024 ret += txt
1025 end
1026 return ret
1027 end
1028 end
1029
1030 redef class AMethPropdef
1031 redef fun short_comment do
1032 var ret = ""
1033 if n_doc != null then
1034 var txt = n_doc.n_comment.first.text
1035 txt = txt.replace("# ", "")
1036 txt = txt.replace("\n", "")
1037 ret += txt
1038 end
1039 return ret
1040 end
1041
1042 redef fun signature: String do
1043 var sign = ""
1044 if n_signature != null then sign = " {n_signature.to_s}"
1045 return sign
1046 end
1047
1048 redef private fun comment: String do
1049 var ret = ""
1050 if n_doc != null then
1051 for t in n_doc.n_comment do
1052 var txt = t.text.replace("# ", "")
1053 txt = txt.replace("#", "")
1054 ret += "{txt}"
1055 end
1056 end
1057 return ret
1058 end
1059 end
1060
1061 # Create a tool context to handle options and paths
1062 var toolcontext = new ToolContext
1063 toolcontext.process_options
1064
1065 # Here we launch the nit index
1066 var nitdoc = new Nitdoc(toolcontext)
1067 nitdoc.start