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 arguments
: Array[String]
29 private var output_dir
: nullable String
30 private var dot_dir
: nullable String
31 private var share_dir
: nullable String
32 private var source
: nullable String
34 private var opt_dir
= new OptionString("Directory where doc is generated", "-d", "--dir")
35 private var opt_source
= new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
36 private var opt_sharedir
= new OptionString("Directory containing the nitdoc files", "--sharedir")
37 private var opt_nodot
= new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
39 init(toolcontext
: ToolContext) do
40 # We need a model to collect stufs
41 self.toolcontext
= toolcontext
42 self.arguments
= toolcontext
.option_context
.rest
43 toolcontext
.option_context
.options
.clear
44 toolcontext
.option_context
.add_option
(opt_dir
)
45 toolcontext
.option_context
.add_option
(opt_source
)
46 toolcontext
.option_context
.add_option
(opt_sharedir
)
47 toolcontext
.option_context
.add_option
(opt_nodot
)
48 toolcontext
.process_options
51 if arguments
.length
< 1 then
52 toolcontext
.option_context
.usage
57 modelbuilder
= new ModelBuilder(model
, toolcontext
)
59 # Here we load an process std modules
60 var mmodules
= modelbuilder
.parse_and_build
([arguments
.first
])
61 if mmodules
.is_empty
then return
62 modelbuilder
.full_propdef_semantic_analysis
63 assert mmodules
.length
== 1
64 self.mainmodule
= mmodules
.first
67 private fun process_options
do
68 if not opt_dir
.value
is null then
69 output_dir
= opt_dir
.value
73 if not opt_sharedir
.value
is null then
74 share_dir
= opt_sharedir
.value
76 var dir
= "NIT_DIR".environ
78 dir
= "{sys.program_name.dirname}/../share/nitdoc"
80 dir
= "{dir}/share/nitdoc"
83 if share_dir
is null then
84 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
87 dir
= "{share_dir.to_s}/scripts/js-facilities.js"
88 if share_dir
is null then
89 print
"Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
93 if not opt_source
.value
is null then
96 source
= opt_source
.value
101 if arguments
.length
== 1 then
102 # Create destination dir if it's necessary
103 if not output_dir
.file_exists
then output_dir
.mkdir
104 sys
.system
("cp -r {share_dir.to_s}/* {output_dir.to_s}/")
106 if not opt_nodot
.value
then self.dot_dir
= output_dir
.to_s
116 var overviewpage
= new NitdocOverview(modelbuilder
, dot_dir
)
117 overviewpage
.save
("{output_dir.to_s}/index.html")
121 var fullindex
= new NitdocFullindex(model
.mmodules
)
122 fullindex
.save
("{output_dir.to_s}/full-index.html")
126 for mmodule
in model
.mmodules
do
127 var modulepage
= new NitdocModule(mmodule
, modelbuilder
, dot_dir
)
128 modulepage
.save
("{output_dir.to_s}/{mmodule.name}.html")
133 for mclass
in modelbuilder
.model
.mclasses
do
134 var classpage
= new NitdocClass(mclass
, modelbuilder
, dot_dir
, source
)
135 classpage
.save
("{output_dir.to_s}/{mclass.name}.html")
139 # Generate QuickSearch file
140 fun quicksearch_list
do
141 var file
= new OFStream.open
("{output_dir.to_s}/quicksearch-list.js")
142 var content
= new Buffer
143 content
.append
("var entries = \{ ")
144 for prop
in model
.mproperties
do
145 if not prop
isa MMethod then continue
146 content
.append
("\"{prop.name}\
": [")
147 for propdef
in prop
.mpropdefs
do
148 content
.append
("\{txt: \"{propdef.mproperty.full_name}\", url
:\
"{propdef.mproperty.anchor}\" \
}")
149 if not propdef is prop.mpropdefs.last then content.append(", ")
155 for mclass in model.mclasses do
156 content.append("\
"{mclass.name}\": [")
157 for mclassdef in mclass.mclassdefs do
158 content.append("\
{txt: \"{mclassdef.mclass.full_name}\
", url:\"{mclass.link_anchor}\
" \}")
159 if not mclassdef
is mclass
.mclassdefs
.last
then content
.append
(", ")
162 if not mclass
is model
.mclasses
.last
then content
.append
(", ")
165 content
.append
(" \};")
166 file
.write
(content
.to_s
)
173 abstract class NitdocPage
176 var dot_dir
: nullable String
177 var source
: nullable String
180 add
("meta").attr
("charset", "utf-8")
181 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/jquery-1.7.1.min.js")
182 add
("script").attr
("type", "text/javascript").attr
("src", "quicksearch-list.js")
183 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/js-facilities.js")
184 add
("link").attr
("rel", "stylesheet").attr
("href", "styles/main.css").attr
("type", "text/css").attr
("media", "screen")
189 open
("div").add_class
("page")
199 open
("nav").add_class
("main")
202 open
("li").attr
("id", "liGitHub")
203 open
("a").add_class
("btn").attr
("id", "logGitHub")
204 add
("img").attr
("id", "imgGitHub").attr
("src", "resources/icons/github-icon.png")
206 open
("div").add_class
("popover bottom")
207 add
("div").add_class
("arrow").text
(" ")
208 open
("div").add_class
("githubTitle")
209 add
("h3").text
("Github Sign In")
212 add
("label").attr
("id", "lbloginGit").text
("Username")
213 add
("input").attr
("id", "loginGit").attr
("name", "login").attr
("type", "text")
214 open
("label").attr
("id", "logginMessage").text
("Hello ")
215 open
("a").attr
("id", "githubAccount")
216 add
("strong").attr
("id", "nickName").text
(" ")
221 add
("label").attr
("id", "lbpasswordGit").text
("Password")
222 add
("input").attr
("id", "passwordGit").attr
("name", "password").attr
("type", "password")
223 open
("div").attr
("id", "listBranches")
224 add
("label").attr
("id", "lbBranches").text
("Branch")
225 add
("select").add_class
("dropdown").attr
("id", "dropBranches").attr
("name", "dropBranches").attr
("tabindex", "1").text
(" ")
229 add
("label").attr
("id", "lbrepositoryGit").text
("Repository")
230 add
("input").attr
("id", "repositoryGit").attr
("name", "repository").attr
("type", "text")
233 add
("label").attr
("id", "lbbranchGit").text
("Branch")
234 add
("input").attr
("id", "branchGit").attr
("name", "branch").attr
("type", "text")
237 add
("a").attr
("id", "signIn").text
("Sign In")
246 fun content
is abstract
249 add
("footer").text
("Nit standard library. Version jenkins-component=stdlib-19.")
252 # Generate a clickable graphviz image using a dot content
253 fun generate_dot
(dot
: String, name
: String, alt
: String) do
254 var output_dir
= dot_dir
255 if output_dir
== null then return
256 var file
= new OFStream.open
("{output_dir}/{name}.dot")
259 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 ; \}")
260 open
("article").add_class
("graph")
261 add
("img").attr
("src", "{name}.png").attr
("usemap", "#{name}").attr
("style", "margin:auto").attr
("alt", "{alt}")
263 var fmap
= new IFStream.open
("{output_dir}/{name}.map")
264 add_html
(fmap
.read_all
)
268 # Add a (source) link for a given location
269 fun show_source
(l
: Location): String
271 if source
== null then
272 return "({l.file.filename.simplify_path})"
274 # THIS IS JUST UGLY ! (but there is no replace yet)
275 var x
= source
.split_with
("%f")
276 source
= x
.join
(l
.file
.filename
.simplify_path
)
277 x
= source
.split_with
("%l")
278 source
= x
.join
(l
.line_start
.to_s
)
279 x
= source
.split_with
("%L")
280 source
= x
.join
(l
.line_end
.to_s
)
281 return " (<a href=\"{source.to_s}\
">show code</a>)"
289 private var mbuilder
: ModelBuilder
290 private var mmodules
= new Array[MModule]
292 init(mbuilder
: ModelBuilder, dot_dir
: nullable String) do
293 self.mbuilder
= mbuilder
294 self.dot_dir
= dot_dir
296 var mmodules
= new HashSet[MModule]
297 for mmodule
in mbuilder
.model
.mmodules
do
298 var owner
= mmodule
.public_owner
299 if owner
!= null then
302 mmodules
.add
(mmodule
)
306 var sorter
= new ComparableSorter[MModule]
307 self.mmodules
.add_all
(mmodules
)
308 sorter
.sort
(self.mmodules
)
313 add
("title").text
("Overview | Nit Standard Library")
317 add
("li").add_class
("current").text
("Overview")
319 add
("a").attr
("href", "full-index.html").text
("Full Index")
324 open
("div").add_class
("content fullpage")
325 add
("h1").text
("Nit Standard Library")
326 open
("article").add_class
("overview")
327 add_html
("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
329 open
("article").add_class
("overview")
331 add
("h2").text
("Modules")
333 for mmodule
in mmodules
do
334 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
336 add_html
("{mmodule.link(amodule)} {amodule.short_comment}")
346 fun process_generate_dot
do
348 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")
349 for mmodule
in mmodules
do
350 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
351 for imported
in mmodule
.in_importation
.direct_greaters
do
352 if imported
.direct_owner
== null then
353 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
358 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
362 # The full index page
363 class NitdocFullindex
366 private var mmodules
: Array[MModule]
368 init(mmodules
: Array[MModule]) do
369 self.mmodules
= mmodules
375 add
("title").text
("Full Index | Nit Standard Library")
380 add
("a").attr
("href", "index.html").text
("Overview")
382 add
("li").add_class
("current").text
("Full Index")
386 open
("div").add_class
("content fullpage")
387 add
("h1").text
("Full Index")
394 # Add to content modules column
396 var ls
= new List[nullable MModule]
397 var sorted
= mmodules
398 var sorterp
= new ComparableSorter[MModule]
400 open
("article").add_class
("modules filterable")
401 add
("h2").text
("Modules")
403 for mmodule
in sorted
do
404 if mmodule
.public_owner
!= null and not ls
.has
(mmodule
.public_owner
) then
405 ls
.add
(mmodule
.public_owner
)
407 add
("a").attr
("href", "{mmodule.public_owner.name}.html").text
(mmodule
.public_owner
.name
)
415 # Add to content classes modules
416 fun classes_column
do
417 var sorted
= mmodules
.first
.imported_mclasses
.to_a
418 var sorterp
= new ComparableSorter[MClass]
420 open
("article").add_class
("classes filterable")
421 add
("h2").text
("Classes")
424 for mclass
in sorted
do
426 add
("a").attr
("href", "{mclass}.html").text
(mclass
.name
)
434 # Insert the properties column of fullindex page
435 fun properties_column
do
436 open
("article").add_class
("properties filterable")
437 add
("h2").text
("Properties")
439 var sorted_imported
= mmodules
.first
.imported_methods
.to_a
440 var sorted_redef
= mmodules
.first
.redef_methods
.to_a
441 var sorterp
= new ComparableSorter[MProperty]
442 sorterp
.sort
(sorted_imported
)
443 sorterp
.sort
(sorted_redef
)
445 for method
in sorted_imported
do
446 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
447 open
("li").add_class
("intro")
448 add
("span").attr
("title", "introduction").text
("I")
450 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
454 for method
in sorted_redef
do
455 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
456 open
("li").add_class
("redef")
457 add
("span").attr
("title", "redefinition").text
("R")
459 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
473 private var mmodule
: MModule
474 private var mbuilder
: ModelBuilder
476 init(mmodule
: MModule, mbuilder
: ModelBuilder, dot_dir
: nullable String) do
477 self.mmodule
= mmodule
478 self.mbuilder
= mbuilder
479 self.dot_dir
= dot_dir
484 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
485 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
490 add
("a").attr
("href", "index.html").text
("Overview")
492 add
("li").add_class
("current").text
(mmodule
.name
)
494 add
("a").attr
("href", "full-index.html").text
("Full Index")
500 open
("div").add_class
("content")
501 add
("h1").text
(mmodule
.name
)
502 add
("div").add_class
("subtitle")
503 add_html
("module {mmodule.namespace(mbuilder)}")
505 #process_generate_dot
511 # Insert module comment in the content
512 fun module_comment
do
513 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
514 var doc
= amodule
.comment
515 open
("div").attr
("id", "description")
516 add
("pre").add_class
("text_label").text
(doc
)
517 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
518 add
("a").attr
("id", "cancelBtn").text
("Cancel")
519 add
("a").attr
("id", "commitBtn").text
("Commit")
520 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
524 fun process_generate_dot
do
526 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")
527 for m
in mmodule
.in_importation
.smallers
do
528 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
529 for imported
in m
.in_importation
.direct_greaters
do
530 if imported
.direct_owner
== null then
531 op
.append
("\"{m.name}\
"->\"{imported.name}\
";\n")
536 generate_dot
(op
.to_s
, "dep_{mmodule.name}", "Modules hierarchy")
540 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
541 open
("div").add_class
("menu")
543 add
("h3").text
("Module Hierarchy")
544 var dependencies
= new Array[MModule]
545 for dep
in mmodule
.in_importation
.greaters
do
546 if dep
== mmodule
or dep
.public_owner
!= null then continue
547 dependencies
.add
(dep
)
549 if dependencies
.length
> 0 then
550 add
("h4").text
("All dependencies")
551 display_module_list
(dependencies
)
553 var clients
= new Array[MModule]
554 for dep
in mmodule
.in_importation
.smallers
do
555 if dep
== mmodule
or dep
.public_owner
!= null then continue
558 if clients
.length
> 0 then
559 add
("h4").text
("All clients")
560 display_module_list
(clients
)
563 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
565 add
("h3").text
("Nested Modules")
566 display_module_list
(mmodule
.in_nesting
.direct_greaters
.to_a
)
572 private fun display_module_list
(list
: Array[MModule]) do
574 var sorter
= new ComparableSorter[MModule]
577 var am
= mbuilder
.mmodule2nmodule
[m
]
586 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
587 var intro_mclasses
= mmodule
.intro_mclasses
588 var redef_mclasses
= mmodule
.redef_mclasses
589 var all_mclasses
= new HashSet[MClass]
590 for m
in mmodule
.in_nesting
.greaters
do
591 all_mclasses
.add_all
(m
.intro_mclasses
)
592 all_mclasses
.add_all
(m
.redef_mclasses
)
594 all_mclasses
.add_all
(intro_mclasses
)
595 all_mclasses
.add_all
(redef_mclasses
)
597 var sorted
= new Array[MClass]
598 sorted
.add_all
(all_mclasses
)
599 var sorter
= new ComparableSorter[MClass]
601 open
("div").add_class
("module")
602 open
("article").add_class
("classes filterable")
603 add
("h2").text
("Classes")
606 var nclass
= mbuilder
.mclassdef2nclassdef
[c
.intro
].as(AStdClassdef)
607 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
608 open
("li").add_class
("redef")
609 add
("span").attr
("title", "refined in this module").text
("R ")
611 open
("li").add_class
("intro")
612 add
("span").attr
("title", "introduced in this module").text
("I ")
614 add_html
(c
.link
(nclass
))
623 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
624 var mpropdefs
= new HashSet[MPropDef]
625 for m
in mmodule
.in_nesting
.greaters
do
626 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
628 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
629 var sorted
= mpropdefs
.to_a
630 var sorter
= new ComparableSorter[MPropDef]
632 open
("article").add_class
("properties filterable")
633 add
("h2").text
("Properties")
636 if p
isa MAttributeDef then continue
637 if p
.mproperty
.visibility
<= none_visibility
then continue
638 if not mbuilder
.mpropdef2npropdef
.has_key
(p
) then continue
639 var nprop
= mbuilder
.mpropdef2npropdef
[p
]
641 open
("li").add_class
("intro")
642 add
("span").attr
("title", "introduction").text
("I")
644 open
("li").add_class
("redef")
645 add
("span").attr
("title", "redefinition").text
("R")
647 add_html
(" {p.link(nprop)} ({p.mclassdef.mclass.name})")
659 private var mclass
: MClass
660 private var mbuilder
: ModelBuilder
662 init(mclass
: MClass, mbuilder
: ModelBuilder, dot_dir
: nullable String, source
: nullable String) do
664 self.mbuilder
= mbuilder
665 self.dot_dir
= dot_dir
671 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
672 if nclass
isa AStdClassdef then
673 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
675 add
("title").text
("{mclass.name} class")
681 add
("a").attr
("href", "index.html").text
("Overview")
684 var public_owner
= mclass
.public_owner
685 if public_owner
is null then
686 var am
= mbuilder
.mmodule2nmodule
[mclass
.intro_mmodule
]
687 add_html
(mclass
.intro_mmodule
.link
(am
))
689 var am
= mbuilder
.mmodule2nmodule
[public_owner
]
690 add_html
(public_owner
.link
(am
))
693 add
("li").add_class
("current").text
(mclass
.name
)
695 add
("a").attr
("href", "full-index.html").text
("Full Index")
700 open
("div").add_class
("menu")
704 open
("div").add_class
("content")
709 fun properties_column
do
710 var sorter
= new ComparableSorter[MPropDef]
711 open
("nav").add_class
("properties filterable")
712 add
("h3").text
("Properties")
714 var vtypes
= new HashSet[MVirtualTypeDef]
715 var consts
= new HashSet[MMethodDef]
716 var meths
= new HashSet[MMethodDef]
717 for mclassdef
in mclass
.mclassdefs
do
718 for mpropdef
in mclassdef
.mpropdefs
do
719 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
720 if mpropdef
.mproperty
.visibility
<= none_visibility
then continue
721 if mpropdef
isa MVirtualTypeDef then vtypes
.add
(mpropdef
)
722 if mpropdef
isa MMethodDef then
723 if mpropdef
.mproperty
.is_init
then
731 for mprop
in mclass
.inherited_methods
do
732 var mpropdef
= mprop
.intro
733 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
734 if mprop
.visibility
<= none_visibility
then continue
735 if mprop
.intro_mclassdef
.mclass
.name
== "Object" then continue
739 if vtypes
.length
> 0 then
740 var vts
= new Array[MVirtualTypeDef]
743 add
("h4").text
("Virtual Types")
744 display_mpropdef_list
(vts
)
746 if consts
.length
> 0 then
747 var cts
= new Array[MMethodDef]
750 add
("h4").text
("Constructors")
751 display_mpropdef_list
(cts
)
753 if meths
.length
> 0 then
754 var mts
= new Array[MMethodDef]
757 add
("h4").text
("Methods")
758 display_mpropdef_list
(mts
)
763 private fun display_mpropdef_list
(list
: Array[MPropDef]) do
766 var nprop
= mbuilder
.mpropdef2npropdef
[prop
]
767 if prop
.is_intro
and prop
.mproperty
.intro_mclassdef
.mclass
!= mclass
then
768 open
("li").add_class
("inherit")
769 add
("span").attr
("title", "Inherited").text
("H")
770 else if prop
.is_intro
then
771 open
("li").add_class
("intro")
772 add
("span").attr
("title", "Introduced").text
("I")
774 open
("li").add_class
("redef")
775 add
("span").attr
("title", "Redefined").text
("R")
777 add_html
(prop
.link
(nprop
))
783 fun inheritance_column
do
784 var sorted
= new Array[MClass]
785 var sorterp
= new ComparableSorter[MClass]
787 add
("h3").text
("Inheritance")
788 if mclass
.ancestors
.length
> 1 then
789 sorted
= mclass
.ancestors
.to_a
791 add
("h4").text
("Superclasses")
794 if sup
== mclass
then continue
796 add
("a").attr
("href", "{sup.name}.html").text
(sup
.name
)
802 if mclass
.descendants
.length
<= 1 then
803 add
("h4").text
("No Known Subclasses")
804 else if mclass
.descendants
.length
<= 100 then
805 sorted
= mclass
.descendants
.to_a
807 add
("h4").text
("Subclasses")
810 if sub
== mclass
then continue
812 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
816 else if mclass
.children
.length
<= 100 then
817 sorted
= mclass
.children
.to_a
819 add
("h4").text
("Direct Subclasses Only")
822 if sub
== mclass
then continue
824 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
829 add
("h4").text
("Too much Subclasses to list")
835 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
836 var sorted
= new Array[MModule]
837 sorted
.add_all
(mclass
.concerns
.keys
)
838 var sorterp
= new ComparableSorter[MModule]
839 var sorterprop
= new ComparableSorter[MProperty]
840 var sorterc
= new ComparableSorter[MClass]
843 var lmmodule
= new List[MModule]
844 # Insert the subtitle part
845 add
("h1").text
(mclass
.to_s
)
846 open
("div").add_class
("subtitle")
847 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
848 subtitle
+= "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}"
851 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
852 # We add the class description
853 open
("section").add_class
("description")
854 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>")
856 open
("section").add_class
("concerns")
857 add
("h2").add_class
("section-header").text
("Concerns")
859 for owner
in sorted
do
860 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
861 var childs
= mclass
.concerns
[owner
]
863 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
864 if not childs
is null then
866 var sortedc
= childs
.to_a
867 var sorterpc
= new ComparableSorter[MModule]
868 sorterpc
.sort
(sortedc
)
869 for child
in sortedc
do
870 var nchild
= mbuilder
.mmodule2nmodule
[child
]
871 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
879 # Insert virtual types if there is almost one
880 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
881 open
("section").add_class
("types")
882 add
("h2").text
("Formal and Virtual Types")
883 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
884 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
885 for prop
in nclass
.n_formaldefs
do
886 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
887 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
888 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
890 add_html
("<div class=\"info\
">formal generic type</div>")
897 if mclass
.constructors
.length
> 0 then
898 var sortedc
= mclass
.constructors
.to_a
899 sorterprop
.sort
(sortedc
)
900 open
("section").add_class
("constructors")
901 add
("h2").add_class
("section-header").text
("Constructors")
902 for prop
in sortedc
do description
(prop
)
906 open
("section").add_class
("methods")
907 add
("h2").add_class
("section-header").text
("Methods")
908 for mmodule
, mmethods
in mclass
.all_methods
do
909 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
910 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
911 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
912 if mclass
.has_mmodule
(mmodule
) then
913 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
915 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in {mmodule.link(nmodule)}</h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
918 var sortedc
= mmethods
.to_a
919 sorterprop
.sort
(sortedc
)
920 for prop
in sortedc
do description
(prop
)
923 if mclass
.inherited_methods
.length
> 0 then
924 var sortedc
= new Array[MClass]
925 sortedc
.add_all
(mclass
.inherited
.keys
)
926 sorterc
.sort
(sortedc
)
927 add
("h3").text
("Inherited Methods")
928 for imclass
in sortedc
do
929 var inclass
= mbuilder
.mclassdef2nclassdef
[imclass
.intro
].as(AStdClassdef)
930 var sortedp
= mclass
.inherited
[imclass
].to_a
931 sorterprop
.sort
(sortedp
)
933 add_html
("Defined in {imclass.link(inclass)}: ")
934 for method
in sortedp
do
935 #TODO link to inherited propdef
936 add_html
("<a href=\"\
">{method.name}</a>")
937 if method
!= sortedp
.last
then add_html
(", ")
945 fun description
(prop
: MProperty) do
946 if not mbuilder
.mpropdef2npropdef
.has_key
(prop
.intro
) then return
947 var nprop
= mbuilder
.mpropdef2npropdef
[prop
.intro
]
948 if not nprop
isa AMethPropdef then return
949 var classes
= new Array[String]
950 if nprop
isa AInitPropdef then
955 if prop
.is_redef
then classes
.add
("redef")
956 if prop
.visibility
== none_visibility
then
957 classes
.add
("private")
958 else if prop
.visibility
== protected_visibility
then
959 classes
.add
("protected")
961 classes
.add
("public")
963 open
("article").add_classes
(classes
).attr
("id", "{prop.anchor}")
965 open
("h3").add_class
("signature")
966 add_html
("{prop.name}{nprop.signature}")
968 open
("div").add_class
("info")
969 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>")
971 open
("div").add_class
("description")
972 if nprop
.comment
== "" then
973 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
975 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{nprop.comment}</pre>")
977 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>")
979 if prop
.local_class
!= mclass
then
980 var mredef
= prop
.local_class
.intro_mmodule
981 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
982 add_html
("inherited from {mredef.link(nredef)} ")
984 #TODO display show code if doc github
985 var mintro
= prop
.intro_mclassdef
.mmodule
986 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
987 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
989 for parent
in mclass
.parents
do
990 var mparent
= parent
.intro_mmodule
991 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
992 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>.")
1003 private fun comment
: String do
1005 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
1006 if n_moduledecl
.n_doc
is null then return ""
1007 for t
in n_moduledecl
.n_doc
.n_comment
do
1009 txt
= txt
.replace
("# ", "")
1010 txt
= txt
.replace
("#", "")
1016 private fun short_comment
: String do
1018 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
1019 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
1020 txt
= txt
.replace
("# ", "")
1021 txt
= txt
.replace
("\n", "")
1030 redef type OTHER: MModule
1031 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1033 # Get the list of all methods in a module
1034 fun imported_methods
: Set[MMethod] do
1035 var methods
= new HashSet[MMethod]
1036 for mclass
in imported_mclasses
do
1037 for method
in mclass
.intro_methods
do
1044 # Get the list aof all refined methods in a module
1045 fun redef_methods
: Set[MMethod] do
1046 var methods
= new HashSet[MMethod]
1047 for mclass
in redef_mclasses
do
1048 for method
in mclass
.intro_methods
do
1055 # Return a link (html a tag) to the nitdoc module page
1056 fun link
(amodule
: AModule): String do
1057 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1060 # Return the module namespace decorated with html
1061 fun namespace
(mbuilder
: ModelBuilder): String do
1062 var str
= new Buffer
1063 var mowner
= public_owner
1064 if mowner
!= null then
1065 var nowner
= mbuilder
.mmodule2nmodule
[mowner
]
1066 str
.append
(public_owner
.link
(nowner
))
1068 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1069 str
.append
(self.link
(nmodule
))
1073 redef class MPropDef
1075 redef type OTHER: MPropDef
1076 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1078 # Return a link (html a tag) to the nitdoc class page
1079 fun link
(nprop
: APropdef): String do
1080 return "<a href=\"{mclassdef.mclass.name}.html
#{mproperty.anchor}\" title=\"{nprop.short_comment}\">{mproperty}</a>"
1084 redef class MProperty
1086 redef type OTHER: MProperty
1087 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1090 var apropdef
: nullable APropdef
1092 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1098 fun local_class
: MClass do
1099 var classdef
= self.intro_mclassdef
1100 return classdef
.mclass
1103 fun anchor
: String do
1104 return "PROP_{c_name}"
1111 redef type OTHER: MClass
1112 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1114 # Add type parameters
1117 return "{name}[{intro.parameter_names.join(", ")}]"
1123 # Return a link (html a tag) to the nitdoc class page
1124 fun link
(aclass
: AStdClassdef): String do
1125 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1128 # Associate all MMethods to each MModule concerns
1129 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1130 var hm
= new HashMap[MModule, Set[MMethod]]
1131 for mmodule
, childs
in concerns
do
1132 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1133 for prop
in intro_methods
do
1134 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1135 prop
.is_redef
= false
1136 hm
[mmodule
].add
(prop
)
1139 for prop
in redef_methods
do
1140 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1141 prop
.is_redef
= true
1142 hm
[mmodule
].add
(prop
)
1146 if childs
!= null then
1147 for child
in childs
do
1148 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1149 for prop
in intro_methods
do
1150 if child
== prop
.intro_mclassdef
.mmodule
then
1151 prop
.is_redef
= false
1155 for prop
in redef_methods
do
1156 if child
== prop
.intro_mclassdef
.mmodule
then
1157 prop
.is_redef
= true
1167 fun public_owner
: MModule do
1168 var owner
= intro_mmodule
1169 if owner
.public_owner
is null then
1172 return owner
.public_owner
.as(not null)
1176 # Associate MClass to all MMethod include in 'inherited_methods'
1177 fun inherited
: HashMap[MClass, Set[MMethod]] do
1178 var hm
= new HashMap[MClass, Set[MMethod]]
1179 for method
in inherited_methods
do
1180 var mclass
= method
.intro_mclassdef
.mclass
1181 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1182 hm
[mclass
].add
(method
)
1187 # Return true if MModule concern contain subMModule
1188 fun has_mmodule
(sub
: MModule): Bool do
1189 for mmodule
, childs
in concerns
do
1190 if childs
is null then continue
1191 if childs
.has
(sub
) then return true
1196 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1197 for const
in constructors
do
1198 if mprop2npropdef
.has_key
(const
)then
1199 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1203 for intro
in intro_methods
do
1204 if mprop2npropdef
.has_key
(intro
)then
1205 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1209 for rd
in redef_methods
do
1210 if mprop2npropdef
.has_key
(rd
)then
1211 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1216 fun link_anchor
: String do
1217 return "{name}.html"
1222 redef class AStdClassdef
1223 private fun comment
: String do
1225 if n_doc
!= null then
1226 for t
in n_doc
.n_comment
do
1227 var txt
= t
.text
.replace
("# ", "")
1228 txt
= txt
.replace
("#", "")
1235 private fun short_comment
: String do
1237 if n_doc
!= null then
1238 var txt
= n_doc
.n_comment
.first
.text
1239 txt
= txt
.replace
("# ", "")
1240 txt
= txt
.replace
("\n", "")
1247 redef class ASignature
1251 if not n_params
.is_empty
then
1252 ret
= "{ret}({n_params.join(", ")})"
1254 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1261 var ret
= "{n_id.text}"
1262 if n_type
!= null then
1263 ret
= "{ret}: {n_type.to_s}"
1264 if n_dotdotdot
!= null then ret
= "{ret}..."
1272 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1273 if n_kwnullable
!= null then ret
= "nullable {ret}"
1274 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1279 redef class APropdef
1280 private fun short_comment
: String is abstract
1281 private fun signature
: String is abstract
1282 private fun comment
: String is abstract
1285 redef class AAttrPropdef
1286 redef fun short_comment
do
1288 if n_doc
!= null then
1289 var txt
= n_doc
.n_comment
.first
.text
1290 txt
= txt
.replace
("# ", "")
1291 txt
= txt
.replace
("\n", "")
1298 redef class AMethPropdef
1299 redef fun short_comment
do
1300 var ret
= new Buffer
1301 if n_doc
!= null then
1302 var txt
= n_doc
.n_comment
.first
.text
1303 txt
= txt
.replace
("# ", "")
1304 txt
= txt
.replace
("\n", "")
1310 redef fun signature
: String do
1312 if n_signature
!= null then sign
= "{n_signature.to_s}"
1316 redef private fun comment
: String do
1317 var ret
= new Buffer
1318 if n_doc
!= null then
1319 for t
in n_doc
.n_comment
do
1320 var txt
= t
.text
.replace
("# ", "")
1321 txt
= txt
.replace
("#", "")
1329 redef class MClassDef
1330 private fun namespace
(mclass
: MClass): String do
1332 if mmodule
.public_owner
is null then
1333 return "{mmodule.full_name}::{mclass.name}"
1334 else if mclass
is self.mclass
then
1335 return "{mmodule.public_owner.name}::{mclass.name}"
1337 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1344 return to_a
[length-1
]
1348 # Create a tool context to handle options and paths
1349 var toolcontext
= new ToolContext
1351 # Here we launch the nit index
1352 var nitdoc
= new Nitdoc(toolcontext
)