1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
20 import abstract_compiler
24 private var toolcontext
: ToolContext
25 private var model
: Model
26 private var modelbuilder
: ModelBuilder
27 private var mainmodule
: MModule
28 private var class_hierarchy
: POSet[MClass]
29 private var arguments
: Array[String]
30 private var output_dir
: nullable String
31 private var dot_dir
: nullable String
32 private var share_dir
: nullable String
33 private var source
: nullable String
35 private var opt_dir
= new OptionString("Directory where doc is generated", "-d", "--dir")
36 private var opt_source
= new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
37 private var opt_sharedir
= new OptionString("Directory containing the nitdoc files", "--sharedir")
38 private var opt_nodot
= new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
40 init(toolcontext
: ToolContext) do
41 # We need a model to collect stufs
42 self.toolcontext
= toolcontext
43 self.arguments
= toolcontext
.option_context
.rest
44 toolcontext
.option_context
.options
.clear
45 toolcontext
.option_context
.add_option
(opt_dir
)
46 toolcontext
.option_context
.add_option
(opt_source
)
47 toolcontext
.option_context
.add_option
(opt_sharedir
)
48 toolcontext
.option_context
.add_option
(opt_nodot
)
49 toolcontext
.process_options
52 if arguments
.length
< 1 then
53 toolcontext
.option_context
.usage
58 modelbuilder
= new ModelBuilder(model
, toolcontext
)
60 # Here we load an process std modules
61 var mmodules
= modelbuilder
.parse_and_build
([arguments
.first
])
62 if mmodules
.is_empty
then return
63 modelbuilder
.full_propdef_semantic_analysis
64 assert mmodules
.length
== 1
65 self.mainmodule
= mmodules
.first
66 self.class_hierarchy
= mainmodule
.flatten_mclass_hierarchy
69 private fun process_options
do
70 if not opt_dir
.value
is null then
71 output_dir
= opt_dir
.value
75 if not opt_sharedir
.value
is null then
76 share_dir
= opt_sharedir
.value
78 var dir
= "NIT_DIR".environ
80 dir
= "{sys.program_name.dirname}/../share/nitdoc"
82 dir
= "{dir}/share/nitdoc"
85 if share_dir
is null then
86 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
89 dir
= "{share_dir.to_s}/scripts/js-facilities.js"
90 if share_dir
is null then
91 print
"Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
95 if not opt_source
.value
is null then
98 source
= opt_source
.value
103 if arguments
.length
== 1 then
104 # Create destination dir if it's necessary
105 if not output_dir
.file_exists
then output_dir
.mkdir
106 sys
.system
("cp -r {share_dir.to_s}/* {output_dir.to_s}/")
108 if not opt_nodot
.value
then self.dot_dir
= output_dir
.to_s
118 var overviewpage
= new NitdocOverview(modelbuilder
, dot_dir
)
119 overviewpage
.save
("{output_dir.to_s}/index.html")
123 var fullindex
= new NitdocFullindex(model
.mmodules
)
124 fullindex
.save
("{output_dir.to_s}/full-index.html")
128 for mmodule
in model
.mmodules
do
129 var modulepage
= new NitdocModule(mmodule
, modelbuilder
, dot_dir
)
130 modulepage
.save
("{output_dir.to_s}/{mmodule.name}.html")
135 for mclass
in modelbuilder
.model
.mclasses
do
136 var classpage
= new NitdocClass(mclass
, self, dot_dir
, source
)
137 classpage
.save
("{output_dir.to_s}/{mclass.name}.html")
141 # Generate QuickSearch file
142 fun quicksearch_list
do
143 var file
= new OFStream.open
("{output_dir.to_s}/quicksearch-list.js")
144 var content
= new Buffer
145 content
.append
("var entries = \{ ")
146 for prop
in model
.mproperties
do
147 if not prop
isa MMethod then continue
148 content
.append
("\"{prop.name}\
": [")
149 for propdef
in prop
.mpropdefs
do
150 content
.append
("\{txt: \"{propdef.mproperty.full_name}\", url
:\
"{propdef.mproperty.anchor}\" \
}")
151 if not propdef is prop.mpropdefs.last then content.append(", ")
157 for mclass in model.mclasses do
158 content.append("\
"{mclass.name}\": [")
159 for mclassdef in mclass.mclassdefs do
160 content.append("\
{txt: \"{mclassdef.mclass.full_name}\
", url:\"{mclass.link_anchor}\
" \}")
161 if not mclassdef
is mclass
.mclassdefs
.last
then content
.append
(", ")
164 if not mclass
is model
.mclasses
.last
then content
.append
(", ")
167 content
.append
(" \};")
168 file
.write
(content
.to_s
)
175 abstract class NitdocPage
178 var dot_dir
: nullable String
179 var source
: nullable String
182 add
("meta").attr
("charset", "utf-8")
183 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/jquery-1.7.1.min.js")
184 add
("script").attr
("type", "text/javascript").attr
("src", "quicksearch-list.js")
185 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/js-facilities.js")
186 add
("link").attr
("rel", "stylesheet").attr
("href", "styles/main.css").attr
("type", "text/css").attr
("media", "screen")
191 open
("div").add_class
("page")
201 open
("nav").add_class
("main")
204 open
("li").attr
("id", "liGitHub")
205 open
("a").add_class
("btn").attr
("id", "logGitHub")
206 add
("img").attr
("id", "imgGitHub").attr
("src", "resources/icons/github-icon.png")
208 open
("div").add_class
("popover bottom")
209 add
("div").add_class
("arrow").text
(" ")
210 open
("div").add_class
("githubTitle")
211 add
("h3").text
("Github Sign In")
214 add
("label").attr
("id", "lbloginGit").text
("Username")
215 add
("input").attr
("id", "loginGit").attr
("name", "login").attr
("type", "text")
216 open
("label").attr
("id", "logginMessage").text
("Hello ")
217 open
("a").attr
("id", "githubAccount")
218 add
("strong").attr
("id", "nickName").text
(" ")
223 add
("label").attr
("id", "lbpasswordGit").text
("Password")
224 add
("input").attr
("id", "passwordGit").attr
("name", "password").attr
("type", "password")
225 open
("div").attr
("id", "listBranches")
226 add
("label").attr
("id", "lbBranches").text
("Branch")
227 add
("select").add_class
("dropdown").attr
("id", "dropBranches").attr
("name", "dropBranches").attr
("tabindex", "1").text
(" ")
231 add
("label").attr
("id", "lbrepositoryGit").text
("Repository")
232 add
("input").attr
("id", "repositoryGit").attr
("name", "repository").attr
("type", "text")
235 add
("label").attr
("id", "lbbranchGit").text
("Branch")
236 add
("input").attr
("id", "branchGit").attr
("name", "branch").attr
("type", "text")
239 add
("a").attr
("id", "signIn").text
("Sign In")
248 fun content
is abstract
251 add
("footer").text
("Nit standard library. Version jenkins-component=stdlib-19.")
254 # Generate a clickable graphviz image using a dot content
255 fun generate_dot
(dot
: String, name
: String, alt
: String) do
256 var output_dir
= dot_dir
257 if output_dir
== null then return
258 var file
= new OFStream.open
("{output_dir}/{name}.dot")
261 sys
.system
("\{ test -f {output_dir}/{name}.png && test -f {output_dir}/{name}.s.dot && diff {output_dir}/{name}.dot {output_dir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {output_dir}/{name}.dot {output_dir}/{name}.s.dot && dot -Tpng -o{output_dir}/{name}.png -Tcmapx -o{output_dir}/{name}.map {output_dir}/{name}.s.dot ; \}")
262 open
("article").add_class
("graph")
263 add
("img").attr
("src", "{name}.png").attr
("usemap", "#{name}").attr
("style", "margin:auto").attr
("alt", "{alt}")
265 var fmap
= new IFStream.open
("{output_dir}/{name}.map")
266 add_html
(fmap
.read_all
)
270 # Add a (source) link for a given location
271 fun show_source
(l
: Location): String
273 if source
== null then
274 return "({l.file.filename.simplify_path})"
276 # THIS IS JUST UGLY ! (but there is no replace yet)
277 var x
= source
.split_with
("%f")
278 source
= x
.join
(l
.file
.filename
.simplify_path
)
279 x
= source
.split_with
("%l")
280 source
= x
.join
(l
.line_start
.to_s
)
281 x
= source
.split_with
("%L")
282 source
= x
.join
(l
.line_end
.to_s
)
283 return " (<a href=\"{source.to_s}\
">show code</a>)"
291 private var mbuilder
: ModelBuilder
292 private var mmodules
= new Array[MModule]
294 init(mbuilder
: ModelBuilder, dot_dir
: nullable String) do
295 self.mbuilder
= mbuilder
296 self.dot_dir
= dot_dir
298 var mmodules
= new HashSet[MModule]
299 for mmodule
in mbuilder
.model
.mmodules
do
300 var owner
= mmodule
.public_owner
301 if owner
!= null then
304 mmodules
.add
(mmodule
)
308 var sorter
= new ComparableSorter[MModule]
309 self.mmodules
.add_all
(mmodules
)
310 sorter
.sort
(self.mmodules
)
315 add
("title").text
("Overview | Nit Standard Library")
319 add
("li").add_class
("current").text
("Overview")
321 add
("a").attr
("href", "full-index.html").text
("Full Index")
326 open
("div").add_class
("content fullpage")
327 add
("h1").text
("Nit Standard Library")
328 open
("article").add_class
("overview")
329 add_html
("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
331 open
("article").add_class
("overview")
333 add
("h2").text
("Modules")
335 for mmodule
in mmodules
do
336 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
338 add_html
("{mmodule.link(amodule)} {amodule.short_comment}")
348 fun process_generate_dot
do
350 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")
351 for mmodule
in mmodules
do
352 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
353 for imported
in mmodule
.in_importation
.direct_greaters
do
354 if imported
.direct_owner
== null then
355 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
360 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
364 # The full index page
365 class NitdocFullindex
368 private var mmodules
: Array[MModule]
370 init(mmodules
: Array[MModule]) do
371 self.mmodules
= mmodules
377 add
("title").text
("Full Index | Nit Standard Library")
382 add
("a").attr
("href", "index.html").text
("Overview")
384 add
("li").add_class
("current").text
("Full Index")
388 open
("div").add_class
("content fullpage")
389 add
("h1").text
("Full Index")
396 # Add to content modules column
398 var ls
= new List[nullable MModule]
399 var sorted
= mmodules
400 var sorterp
= new ComparableSorter[MModule]
402 open
("article").add_class
("modules filterable")
403 add
("h2").text
("Modules")
405 for mmodule
in sorted
do
406 if mmodule
.public_owner
!= null and not ls
.has
(mmodule
.public_owner
) then
407 ls
.add
(mmodule
.public_owner
)
409 add
("a").attr
("href", "{mmodule.public_owner.name}.html").text
(mmodule
.public_owner
.name
)
417 # Add to content classes modules
418 fun classes_column
do
419 var sorted
= mmodules
.first
.imported_mclasses
.to_a
420 var sorterp
= new ComparableSorter[MClass]
422 open
("article").add_class
("classes filterable")
423 add
("h2").text
("Classes")
426 for mclass
in sorted
do
428 add
("a").attr
("href", "{mclass}.html").text
(mclass
.name
)
436 # Insert the properties column of fullindex page
437 fun properties_column
do
438 open
("article").add_class
("properties filterable")
439 add
("h2").text
("Properties")
441 var sorted_imported
= mmodules
.first
.imported_methods
.to_a
442 var sorted_redef
= mmodules
.first
.redef_methods
.to_a
443 var sorterp
= new ComparableSorter[MProperty]
444 sorterp
.sort
(sorted_imported
)
445 sorterp
.sort
(sorted_redef
)
447 for method
in sorted_imported
do
448 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
449 open
("li").add_class
("intro")
450 add
("span").attr
("title", "introduction").text
("I")
452 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
456 for method
in sorted_redef
do
457 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
458 open
("li").add_class
("redef")
459 add
("span").attr
("title", "redefinition").text
("R")
461 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
475 private var mmodule
: MModule
476 private var mbuilder
: ModelBuilder
478 init(mmodule
: MModule, mbuilder
: ModelBuilder, dot_dir
: nullable String) do
479 self.mmodule
= mmodule
480 self.mbuilder
= mbuilder
481 self.dot_dir
= dot_dir
486 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
487 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
492 add
("a").attr
("href", "index.html").text
("Overview")
494 add
("li").add_class
("current").text
(mmodule
.name
)
496 add
("a").attr
("href", "full-index.html").text
("Full Index")
502 open
("div").add_class
("content")
503 add
("h1").text
(mmodule
.name
)
504 add
("div").add_class
("subtitle")
505 add_html
("module {mmodule.namespace(mbuilder)}")
513 # Insert module comment in the content
514 fun module_comment
do
515 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
516 var doc
= amodule
.comment
517 open
("div").attr
("id", "description")
518 add
("pre").add_class
("text_label").text
(doc
)
519 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
520 add
("a").attr
("id", "cancelBtn").text
("Cancel")
521 add
("a").attr
("id", "commitBtn").text
("Commit")
522 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
526 fun process_generate_dot
do
527 var name
= "dep_{mmodule.name}"
529 op
.append
("digraph {name} \{ 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")
530 for m
in mmodule
.in_importation
.poset
do
531 var public_owner
= m
.public_owner
532 if public_owner
== null then
535 op
.append
("\"{m.name}\
"[shape=box,margin=0.03];\n")
537 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
540 for imported
in m
.in_importation
.direct_greaters
do
541 if imported
.public_owner
== null then
542 op
.append
("\"{public_owner.name}\
"->\"{imported.name}\
";\n")
547 generate_dot
(op
.to_s
, name
, "Dependency graph for module {mmodule.name}")
551 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
552 open
("div").add_class
("menu")
554 add
("h3").text
("Module Hierarchy")
555 var dependencies
= new Array[MModule]
556 for dep
in mmodule
.in_importation
.greaters
do
557 if dep
== mmodule
or dep
.public_owner
!= null then continue
558 dependencies
.add
(dep
)
560 if dependencies
.length
> 0 then
561 add
("h4").text
("All dependencies")
562 display_module_list
(dependencies
)
564 var clients
= new Array[MModule]
565 for dep
in mmodule
.in_importation
.smallers
do
566 if dep
== mmodule
or dep
.public_owner
!= null then continue
569 if clients
.length
> 0 then
570 add
("h4").text
("All clients")
571 display_module_list
(clients
)
574 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
576 add
("h3").text
("Nested Modules")
577 display_module_list
(mmodule
.in_nesting
.direct_greaters
.to_a
)
583 private fun display_module_list
(list
: Array[MModule]) do
585 var sorter
= new ComparableSorter[MModule]
588 var am
= mbuilder
.mmodule2nmodule
[m
]
597 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
598 var intro_mclasses
= mmodule
.intro_mclasses
599 var redef_mclasses
= mmodule
.redef_mclasses
600 var all_mclasses
= new HashSet[MClass]
601 for m
in mmodule
.in_nesting
.greaters
do
602 all_mclasses
.add_all
(m
.intro_mclasses
)
603 all_mclasses
.add_all
(m
.redef_mclasses
)
605 all_mclasses
.add_all
(intro_mclasses
)
606 all_mclasses
.add_all
(redef_mclasses
)
608 var sorted
= new Array[MClass]
609 sorted
.add_all
(all_mclasses
)
610 var sorter
= new ComparableSorter[MClass]
612 open
("div").add_class
("module")
613 open
("article").add_class
("classes filterable")
614 add
("h2").text
("Classes")
617 var nclass
= mbuilder
.mclassdef2nclassdef
[c
.intro
].as(AStdClassdef)
618 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
619 open
("li").add_class
("redef")
620 add
("span").attr
("title", "refined in this module").text
("R ")
622 open
("li").add_class
("intro")
623 add
("span").attr
("title", "introduced in this module").text
("I ")
625 add_html
(c
.link
(nclass
))
634 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
635 var mpropdefs
= new HashSet[MPropDef]
636 for m
in mmodule
.in_nesting
.greaters
do
637 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
639 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
640 var sorted
= mpropdefs
.to_a
641 var sorter
= new ComparableSorter[MPropDef]
643 open
("article").add_class
("properties filterable")
644 add
("h2").text
("Properties")
647 if p
isa MAttributeDef then continue
648 if p
.mproperty
.visibility
<= none_visibility
then continue
649 if not mbuilder
.mpropdef2npropdef
.has_key
(p
) then continue
650 var nprop
= mbuilder
.mpropdef2npropdef
[p
]
652 open
("li").add_class
("intro")
653 add
("span").attr
("title", "introduction").text
("I")
655 open
("li").add_class
("redef")
656 add
("span").attr
("title", "redefinition").text
("R")
658 add_html
(" {p.link(nprop)} ({p.mclassdef.mclass.name})")
670 private var mclass
: MClass
671 private var mbuilder
: ModelBuilder
672 private var nitdoc
: Nitdoc
674 init(mclass
: MClass, nitdoc
: Nitdoc, dot_dir
: nullable String, source
: nullable String) do
676 self.mbuilder
= nitdoc
.modelbuilder
678 self.dot_dir
= dot_dir
684 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
685 if nclass
isa AStdClassdef then
686 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
688 add
("title").text
("{mclass.name} class")
694 add
("a").attr
("href", "index.html").text
("Overview")
697 var public_owner
= mclass
.public_owner
698 if public_owner
is null then
699 var am
= mbuilder
.mmodule2nmodule
[mclass
.intro_mmodule
]
700 add_html
(mclass
.intro_mmodule
.link
(am
))
702 var am
= mbuilder
.mmodule2nmodule
[public_owner
]
703 add_html
(public_owner
.link
(am
))
706 add
("li").add_class
("current").text
(mclass
.name
)
708 add
("a").attr
("href", "full-index.html").text
("Full Index")
713 open
("div").add_class
("menu")
717 open
("div").add_class
("content")
722 fun properties_column
do
723 var sorter
= new ComparableSorter[MPropDef]
724 open
("nav").add_class
("properties filterable")
725 add
("h3").text
("Properties")
727 var vtypes
= new HashSet[MVirtualTypeDef]
728 var consts
= new HashSet[MMethodDef]
729 var meths
= new HashSet[MMethodDef]
730 for mclassdef
in mclass
.mclassdefs
do
731 for mpropdef
in mclassdef
.mpropdefs
do
732 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
733 if mpropdef
.mproperty
.visibility
<= none_visibility
then continue
734 if mpropdef
isa MVirtualTypeDef then vtypes
.add
(mpropdef
)
735 if mpropdef
isa MMethodDef then
736 if mpropdef
.mproperty
.is_init
then
744 for mprop
in mclass
.inherited_methods
do
745 var mpropdef
= mprop
.intro
746 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
747 if mprop
.visibility
<= none_visibility
then continue
748 if mprop
.intro_mclassdef
.mclass
.name
== "Object" then continue
752 if vtypes
.length
> 0 then
753 var vts
= new Array[MVirtualTypeDef]
756 add
("h4").text
("Virtual Types")
757 display_mpropdef_list
(vts
)
759 if consts
.length
> 0 then
760 var cts
= new Array[MMethodDef]
763 add
("h4").text
("Constructors")
764 display_mpropdef_list
(cts
)
766 if meths
.length
> 0 then
767 var mts
= new Array[MMethodDef]
770 add
("h4").text
("Methods")
771 display_mpropdef_list
(mts
)
776 private fun display_mpropdef_list
(list
: Array[MPropDef]) do
779 var nprop
= mbuilder
.mpropdef2npropdef
[prop
]
780 if prop
.is_intro
and prop
.mproperty
.intro_mclassdef
.mclass
!= mclass
then
781 open
("li").add_class
("inherit")
782 add
("span").attr
("title", "Inherited").text
("H")
783 else if prop
.is_intro
then
784 open
("li").add_class
("intro")
785 add
("span").attr
("title", "Introduced").text
("I")
787 open
("li").add_class
("redef")
788 add
("span").attr
("title", "Redefined").text
("R")
790 add_html
(prop
.link
(nprop
))
796 fun inheritance_column
do
797 var sorted
= new Array[MClass]
798 var sorterp
= new ComparableSorter[MClass]
800 add
("h3").text
("Inheritance")
801 if mclass
.ancestors
.length
> 1 then
802 sorted
= mclass
.ancestors
.to_a
804 add
("h4").text
("Superclasses")
807 if sup
== mclass
then continue
809 add
("a").attr
("href", "{sup.name}.html").text
(sup
.name
)
815 if mclass
.descendants
.length
<= 1 then
816 add
("h4").text
("No Known Subclasses")
817 else if mclass
.descendants
.length
<= 100 then
818 sorted
= mclass
.descendants
.to_a
820 add
("h4").text
("Subclasses")
823 if sub
== mclass
then continue
825 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
829 else if mclass
.children
.length
<= 100 then
830 sorted
= mclass
.children
.to_a
832 add
("h4").text
("Direct Subclasses Only")
835 if sub
== mclass
then continue
837 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
842 add
("h4").text
("Too much Subclasses to list")
848 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
849 var sorted
= new Array[MModule]
850 sorted
.add_all
(mclass
.concerns
.keys
)
851 var sorterp
= new ComparableSorter[MModule]
852 var sorterprop
= new ComparableSorter[MProperty]
853 var sorterc
= new ComparableSorter[MClass]
856 var lmmodule
= new List[MModule]
857 # Insert the subtitle part
858 add
("h1").text
(mclass
.to_s
)
859 open
("div").add_class
("subtitle")
860 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
861 subtitle
+= "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}"
864 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
865 # We add the class description
866 open
("section").add_class
("description")
867 if nclass
isa AStdClassdef and not nclass
.comment
.is_empty
then add_html
("<pre class=\"text_label\
" title=\"122\
" name=\"\
" tag=\"{mclass.mclassdefs.first.location.to_s}\
" type=\"2\
">{nclass.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>")
870 open
("section").add_class
("concerns")
871 add
("h2").add_class
("section-header").text
("Concerns")
873 for owner
in sorted
do
874 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
875 var childs
= mclass
.concerns
[owner
]
877 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
878 if not childs
is null then
880 var sortedc
= childs
.to_a
881 var sorterpc
= new ComparableSorter[MModule]
882 sorterpc
.sort
(sortedc
)
883 for child
in sortedc
do
884 var nchild
= mbuilder
.mmodule2nmodule
[child
]
885 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
893 # Insert virtual types if there is almost one
894 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
895 open
("section").add_class
("types")
896 add
("h2").text
("Formal and Virtual Types")
897 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
898 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
899 for prop
in nclass
.n_formaldefs
do
900 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
901 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
902 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
904 add_html
("<div class=\"info\
">formal generic type</div>")
911 if mclass
.constructors
.length
> 0 then
912 var sortedc
= mclass
.constructors
.to_a
913 sorterprop
.sort
(sortedc
)
914 open
("section").add_class
("constructors")
915 add
("h2").add_class
("section-header").text
("Constructors")
916 for prop
in sortedc
do description
(prop
)
920 open
("section").add_class
("methods")
921 add
("h2").add_class
("section-header").text
("Methods")
922 for mmodule
, mmethods
in mclass
.all_methods
do
923 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
924 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
925 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
926 if mclass
.has_mmodule
(mmodule
) then
927 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
929 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in {mmodule.link(nmodule)}</h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
932 var sortedc
= mmethods
.to_a
933 sorterprop
.sort
(sortedc
)
934 for prop
in sortedc
do description
(prop
)
937 if mclass
.inherited_methods
.length
> 0 then
938 var sortedc
= new Array[MClass]
939 sortedc
.add_all
(mclass
.inherited
.keys
)
940 sorterc
.sort
(sortedc
)
941 add
("h3").text
("Inherited Methods")
942 for imclass
in sortedc
do
943 var inclass
= mbuilder
.mclassdef2nclassdef
[imclass
.intro
].as(AStdClassdef)
944 var sortedp
= mclass
.inherited
[imclass
].to_a
945 sorterprop
.sort
(sortedp
)
947 add_html
("Defined in {imclass.link(inclass)}: ")
948 for method
in sortedp
do
949 #TODO link to inherited propdef
950 add_html
("<a href=\"\
">{method.name}</a>")
951 if method
!= sortedp
.last
then add_html
(", ")
959 fun description
(prop
: MProperty) do
960 if not mbuilder
.mpropdef2npropdef
.has_key
(prop
.intro
) then return
961 var nprop
= mbuilder
.mpropdef2npropdef
[prop
.intro
]
962 if not nprop
isa AMethPropdef then return
963 var classes
= new Array[String]
964 if nprop
isa AInitPropdef then
969 if prop
.is_redef
then classes
.add
("redef")
970 if prop
.visibility
== none_visibility
then
971 classes
.add
("private")
972 else if prop
.visibility
== protected_visibility
then
973 classes
.add
("protected")
975 classes
.add
("public")
977 open
("article").add_classes
(classes
).attr
("id", "{prop.anchor}")
979 open
("h3").add_class
("signature")
980 add_html
("{prop.name}{nprop.signature}")
982 open
("div").add_class
("info")
983 add_html
("{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}</div><div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a>")
985 open
("div").add_class
("description")
986 if nprop
.comment
== "" then
987 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
989 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{nprop.comment}</pre>")
991 add_html
("<textarea id=\"fileContent\
" class=\"edit\
" cols=\"76\
" rows=\"1\
" style=\"display
: none
;\
"></textarea><a id=\"cancelBtn\
" style=\"display
: none
;\
">Cancel</a><a id=\"commitBtn\
" style=\"display
: none
;\
">Commit</a><pre id=\"preSave\
" class=\"text_label\
" type=\"2\
"></pre>")
993 if prop
.local_class
!= mclass
then
994 var mredef
= prop
.local_class
.intro_mmodule
995 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
996 add_html
("inherited from {mredef.link(nredef)} ")
998 #TODO display show code if doc github
999 var mintro
= prop
.intro_mclassdef
.mmodule
1000 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
1001 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
1003 for parent
in mclass
.parents
do
1004 var mparent
= parent
.intro_mmodule
1005 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
1006 if prop
isa MMethod then if parent
.constructors
.has
(prop
) then add_html
(" Previously defined by: {mparent.link(nparent)} for <a href=\"{parent.name}.html\
">{parent.name}</a>.")
1014 fun process_generate_dot
do
1015 var pe
= nitdoc
.class_hierarchy
[mclass
]
1016 var cla
= new HashSet[MClass]
1017 var sm
= new HashSet[MClass]
1018 var sm2
= new HashSet[MClass]
1020 while cla
.length
+ sm
.length
< 10 and sm
.length
> 0 do
1024 sm2
.add_all
(pe
.poset
[x
].direct_smallers
)
1030 cla
.add_all
(pe
.greaters
)
1033 var name
= "dep_{mclass.name}"
1034 op
.append
("digraph {name} \{ 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")
1037 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1039 op
.append
("\"{c.name}\
"[URL=\"{c.name}.html\
"];\n")
1041 for c2
in pe
.poset
[c
].direct_greaters
do
1042 if not cla
.has
(c2
) then continue
1043 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
1045 if not pe
.poset
[c
].direct_smallers
.is_empty
then
1047 for c2
in pe
.poset
[c
].direct_smallers
do
1048 if cla
.has
(c2
) then others
= false
1051 op
.append
("\"{c.name}...\
"[label=\"\
"];\n")
1052 op
.append
("\"{c.name}...\
"->\"{c.name}\
"[style=dotted];\n")
1057 generate_dot
(op
.to_s
, name
, "Dependency graph for class {mclass.name}")
1062 private fun comment
: String do
1064 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
1065 if n_moduledecl
.n_doc
is null then return ""
1066 for t
in n_moduledecl
.n_doc
.n_comment
do
1068 txt
= txt
.replace
("# ", "")
1069 txt
= txt
.replace
("#", "")
1075 private fun short_comment
: String do
1077 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
1078 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
1079 txt
= txt
.replace
("# ", "")
1080 txt
= txt
.replace
("\n", "")
1089 redef type OTHER: MModule
1090 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1092 # Get the list of all methods in a module
1093 fun imported_methods
: Set[MMethod] do
1094 var methods
= new HashSet[MMethod]
1095 for mclass
in imported_mclasses
do
1096 for method
in mclass
.intro_methods
do
1103 # Get the list aof all refined methods in a module
1104 fun redef_methods
: Set[MMethod] do
1105 var methods
= new HashSet[MMethod]
1106 for mclass
in redef_mclasses
do
1107 for method
in mclass
.intro_methods
do
1114 # Return a link (html a tag) to the nitdoc module page
1115 fun link
(amodule
: AModule): String do
1116 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1119 # Return the module namespace decorated with html
1120 fun namespace
(mbuilder
: ModelBuilder): String do
1121 var str
= new Buffer
1122 var mowner
= public_owner
1123 if mowner
!= null then
1124 var nowner
= mbuilder
.mmodule2nmodule
[mowner
]
1125 str
.append
(public_owner
.link
(nowner
))
1128 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1129 str
.append
(self.link
(nmodule
))
1133 redef class MPropDef
1135 redef type OTHER: MPropDef
1136 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1138 # Return a link (html a tag) to the nitdoc class page
1139 fun link
(nprop
: APropdef): String do
1140 return "<a href=\"{mclassdef.mclass.name}.html
#{mproperty.anchor}\" title=\"{nprop.short_comment}\">{mproperty}</a>"
1144 redef class MProperty
1146 redef type OTHER: MProperty
1147 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1150 var apropdef
: nullable APropdef
1152 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1158 fun local_class
: MClass do
1159 var classdef
= self.intro_mclassdef
1160 return classdef
.mclass
1163 fun anchor
: String do
1164 return "PROP_{c_name}"
1171 redef type OTHER: MClass
1172 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1174 # Add type parameters
1177 return "{name}[{intro.parameter_names.join(", ")}]"
1183 # Return a link (html a tag) to the nitdoc class page
1184 fun link
(aclass
: AStdClassdef): String do
1185 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1188 # Associate all MMethods to each MModule concerns
1189 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1190 var hm
= new HashMap[MModule, Set[MMethod]]
1191 for mmodule
, childs
in concerns
do
1192 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1193 for prop
in intro_methods
do
1194 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1195 prop
.is_redef
= false
1196 hm
[mmodule
].add
(prop
)
1199 for prop
in redef_methods
do
1200 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1201 prop
.is_redef
= true
1202 hm
[mmodule
].add
(prop
)
1206 if childs
!= null then
1207 for child
in childs
do
1208 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1209 for prop
in intro_methods
do
1210 if child
== prop
.intro_mclassdef
.mmodule
then
1211 prop
.is_redef
= false
1215 for prop
in redef_methods
do
1216 if child
== prop
.intro_mclassdef
.mmodule
then
1217 prop
.is_redef
= true
1227 fun public_owner
: MModule do
1228 var owner
= intro_mmodule
1229 if owner
.public_owner
is null then
1232 return owner
.public_owner
.as(not null)
1236 # Associate MClass to all MMethod include in 'inherited_methods'
1237 fun inherited
: HashMap[MClass, Set[MMethod]] do
1238 var hm
= new HashMap[MClass, Set[MMethod]]
1239 for method
in inherited_methods
do
1240 var mclass
= method
.intro_mclassdef
.mclass
1241 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1242 hm
[mclass
].add
(method
)
1247 # Return true if MModule concern contain subMModule
1248 fun has_mmodule
(sub
: MModule): Bool do
1249 for mmodule
, childs
in concerns
do
1250 if childs
is null then continue
1251 if childs
.has
(sub
) then return true
1256 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1257 for const
in constructors
do
1258 if mprop2npropdef
.has_key
(const
)then
1259 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1263 for intro
in intro_methods
do
1264 if mprop2npropdef
.has_key
(intro
)then
1265 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1269 for rd
in redef_methods
do
1270 if mprop2npropdef
.has_key
(rd
)then
1271 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1276 fun link_anchor
: String do
1277 return "{name}.html"
1282 redef class AStdClassdef
1283 private fun comment
: String do
1285 if n_doc
!= null then
1286 for t
in n_doc
.n_comment
do
1287 var txt
= t
.text
.replace
("# ", "")
1288 txt
= txt
.replace
("#", "")
1295 private fun short_comment
: String do
1297 if n_doc
!= null then
1298 var txt
= n_doc
.n_comment
.first
.text
1299 txt
= txt
.replace
("# ", "")
1300 txt
= txt
.replace
("\n", "")
1307 redef class ASignature
1311 if not n_params
.is_empty
then
1312 ret
= "{ret}({n_params.join(", ")})"
1314 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1321 var ret
= "{n_id.text}"
1322 if n_type
!= null then
1323 ret
= "{ret}: {n_type.to_s}"
1324 if n_dotdotdot
!= null then ret
= "{ret}..."
1332 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1333 if n_kwnullable
!= null then ret
= "nullable {ret}"
1334 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1339 redef class APropdef
1340 private fun short_comment
: String is abstract
1341 private fun signature
: String is abstract
1342 private fun comment
: String is abstract
1345 redef class AAttrPropdef
1346 redef fun short_comment
do
1348 if n_doc
!= null then
1349 var txt
= n_doc
.n_comment
.first
.text
1350 txt
= txt
.replace
("# ", "")
1351 txt
= txt
.replace
("\n", "")
1358 redef class AMethPropdef
1359 redef fun short_comment
do
1360 var ret
= new Buffer
1361 if n_doc
!= null then
1362 var txt
= n_doc
.n_comment
.first
.text
1363 txt
= txt
.replace
("# ", "")
1364 txt
= txt
.replace
("\n", "")
1370 redef fun signature
: String do
1372 if n_signature
!= null then sign
= "{n_signature.to_s}"
1376 redef private fun comment
: String do
1377 var ret
= new Buffer
1378 if n_doc
!= null then
1379 for t
in n_doc
.n_comment
do
1380 var txt
= t
.text
.replace
("# ", "")
1381 txt
= txt
.replace
("#", "")
1389 redef class MClassDef
1390 private fun namespace
(mclass
: MClass): String do
1392 if mmodule
.public_owner
is null then
1393 return "{mmodule.full_name}::{mclass.name}"
1394 else if mclass
is self.mclass
then
1395 return "{mmodule.public_owner.name}::{mclass.name}"
1397 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1404 return to_a
[length-1
]
1408 # Create a tool context to handle options and paths
1409 var toolcontext
= new ToolContext
1411 # Here we launch the nit index
1412 var nitdoc
= new Nitdoc(toolcontext
)