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
))
1127 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1128 str
.append
(self.link
(nmodule
))
1132 redef class MPropDef
1134 redef type OTHER: MPropDef
1135 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1137 # Return a link (html a tag) to the nitdoc class page
1138 fun link
(nprop
: APropdef): String do
1139 return "<a href=\"{mclassdef.mclass.name}.html
#{mproperty.anchor}\" title=\"{nprop.short_comment}\">{mproperty}</a>"
1143 redef class MProperty
1145 redef type OTHER: MProperty
1146 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1149 var apropdef
: nullable APropdef
1151 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1157 fun local_class
: MClass do
1158 var classdef
= self.intro_mclassdef
1159 return classdef
.mclass
1162 fun anchor
: String do
1163 return "PROP_{c_name}"
1170 redef type OTHER: MClass
1171 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1173 # Add type parameters
1176 return "{name}[{intro.parameter_names.join(", ")}]"
1182 # Return a link (html a tag) to the nitdoc class page
1183 fun link
(aclass
: AStdClassdef): String do
1184 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1187 # Associate all MMethods to each MModule concerns
1188 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1189 var hm
= new HashMap[MModule, Set[MMethod]]
1190 for mmodule
, childs
in concerns
do
1191 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1192 for prop
in intro_methods
do
1193 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1194 prop
.is_redef
= false
1195 hm
[mmodule
].add
(prop
)
1198 for prop
in redef_methods
do
1199 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1200 prop
.is_redef
= true
1201 hm
[mmodule
].add
(prop
)
1205 if childs
!= null then
1206 for child
in childs
do
1207 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1208 for prop
in intro_methods
do
1209 if child
== prop
.intro_mclassdef
.mmodule
then
1210 prop
.is_redef
= false
1214 for prop
in redef_methods
do
1215 if child
== prop
.intro_mclassdef
.mmodule
then
1216 prop
.is_redef
= true
1226 fun public_owner
: MModule do
1227 var owner
= intro_mmodule
1228 if owner
.public_owner
is null then
1231 return owner
.public_owner
.as(not null)
1235 # Associate MClass to all MMethod include in 'inherited_methods'
1236 fun inherited
: HashMap[MClass, Set[MMethod]] do
1237 var hm
= new HashMap[MClass, Set[MMethod]]
1238 for method
in inherited_methods
do
1239 var mclass
= method
.intro_mclassdef
.mclass
1240 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1241 hm
[mclass
].add
(method
)
1246 # Return true if MModule concern contain subMModule
1247 fun has_mmodule
(sub
: MModule): Bool do
1248 for mmodule
, childs
in concerns
do
1249 if childs
is null then continue
1250 if childs
.has
(sub
) then return true
1255 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1256 for const
in constructors
do
1257 if mprop2npropdef
.has_key
(const
)then
1258 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1262 for intro
in intro_methods
do
1263 if mprop2npropdef
.has_key
(intro
)then
1264 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1268 for rd
in redef_methods
do
1269 if mprop2npropdef
.has_key
(rd
)then
1270 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1275 fun link_anchor
: String do
1276 return "{name}.html"
1281 redef class AStdClassdef
1282 private fun comment
: String do
1284 if n_doc
!= null then
1285 for t
in n_doc
.n_comment
do
1286 var txt
= t
.text
.replace
("# ", "")
1287 txt
= txt
.replace
("#", "")
1294 private fun short_comment
: String do
1296 if n_doc
!= null then
1297 var txt
= n_doc
.n_comment
.first
.text
1298 txt
= txt
.replace
("# ", "")
1299 txt
= txt
.replace
("\n", "")
1306 redef class ASignature
1310 if not n_params
.is_empty
then
1311 ret
= "{ret}({n_params.join(", ")})"
1313 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1320 var ret
= "{n_id.text}"
1321 if n_type
!= null then
1322 ret
= "{ret}: {n_type.to_s}"
1323 if n_dotdotdot
!= null then ret
= "{ret}..."
1331 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1332 if n_kwnullable
!= null then ret
= "nullable {ret}"
1333 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1338 redef class APropdef
1339 private fun short_comment
: String is abstract
1340 private fun signature
: String is abstract
1341 private fun comment
: String is abstract
1344 redef class AAttrPropdef
1345 redef fun short_comment
do
1347 if n_doc
!= null then
1348 var txt
= n_doc
.n_comment
.first
.text
1349 txt
= txt
.replace
("# ", "")
1350 txt
= txt
.replace
("\n", "")
1357 redef class AMethPropdef
1358 redef fun short_comment
do
1359 var ret
= new Buffer
1360 if n_doc
!= null then
1361 var txt
= n_doc
.n_comment
.first
.text
1362 txt
= txt
.replace
("# ", "")
1363 txt
= txt
.replace
("\n", "")
1369 redef fun signature
: String do
1371 if n_signature
!= null then sign
= "{n_signature.to_s}"
1375 redef private fun comment
: String do
1376 var ret
= new Buffer
1377 if n_doc
!= null then
1378 for t
in n_doc
.n_comment
do
1379 var txt
= t
.text
.replace
("# ", "")
1380 txt
= txt
.replace
("#", "")
1388 redef class MClassDef
1389 private fun namespace
(mclass
: MClass): String do
1391 if mmodule
.public_owner
is null then
1392 return "{mmodule.full_name}::{mclass.name}"
1393 else if mclass
is self.mclass
then
1394 return "{mmodule.public_owner.name}::{mclass.name}"
1396 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1403 return to_a
[length-1
]
1407 # Create a tool context to handle options and paths
1408 var toolcontext
= new ToolContext
1410 # Here we launch the nit index
1411 var nitdoc
= new Nitdoc(toolcontext
)