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 destinationdir
: nullable String
30 private var sharedir
: nullable String
31 private var source
: nullable String
33 private var opt_dir
= new OptionString("Directory where doc is generated", "-d", "--dir")
34 private var opt_source
= new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
35 private var opt_sharedir
= new OptionString("Directory containing the nitdoc files", "--sharedir")
36 private var opt_nodot
= new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
38 init(toolcontext
: ToolContext) do
39 # We need a model to collect stufs
40 self.toolcontext
= toolcontext
41 self.arguments
= toolcontext
.option_context
.rest
42 toolcontext
.option_context
.options
.clear
43 toolcontext
.option_context
.add_option
(opt_dir
)
44 toolcontext
.option_context
.add_option
(opt_source
)
45 toolcontext
.option_context
.add_option
(opt_sharedir
)
46 toolcontext
.option_context
.add_option
(opt_nodot
)
47 toolcontext
.process_options
50 if arguments
.length
< 1 then
51 toolcontext
.option_context
.usage
56 modelbuilder
= new ModelBuilder(model
, toolcontext
)
58 # Here we load an process std modules
59 var mmodules
= modelbuilder
.parse_and_build
([arguments
.first
])
60 if mmodules
.is_empty
then return
61 modelbuilder
.full_propdef_semantic_analysis
62 assert mmodules
.length
== 1
63 self.mainmodule
= mmodules
.first
66 private fun process_options
do
67 if not opt_dir
.value
is null then
68 destinationdir
= opt_dir
.value
70 destinationdir
= "nitdoc_directory"
72 if not opt_sharedir
.value
is null then
73 sharedir
= opt_sharedir
.value
75 var dir
= "NIT_DIR".environ
77 dir
= "{sys.program_name.dirname}/../share/nitdoc"
79 dir
= "{dir}/share/nitdoc"
82 if sharedir
is null then
83 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
86 dir
= "{sharedir.to_s}/scripts/js-facilities.js"
87 if sharedir
is null then
88 print
"Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
92 if not opt_source
.value
is null then
95 source
= opt_source
.value
100 if arguments
.length
== 1 then
101 # Create destination dir if it's necessary
102 if not destinationdir
.file_exists
then destinationdir
.mkdir
103 sys
.system
("cp -r {sharedir.to_s}/* {destinationdir.to_s}/")
113 var overviewpage
= new NitdocOverview.with
(modelbuilder
, self.opt_nodot
.value
, destinationdir
.to_s
)
114 overviewpage
.save
("{destinationdir.to_s}/index.html")
118 var fullindex
= new NitdocFullindex.with
(model
.mmodules
)
119 fullindex
.save
("{destinationdir.to_s}/full-index.html")
123 for mmodule
in model
.mmodules
do
124 var modulepage
= new NitdocModule.with
(mmodule
, modelbuilder
)
125 modulepage
.save
("{destinationdir.to_s}/{mmodule.name}.html")
130 for mclass
in modelbuilder
.model
.mclasses
do
131 var classpage
= new NitdocClass.with
(mclass
, modelbuilder
, source
)
132 classpage
.save
("{destinationdir.to_s}/{mclass.name}.html")
136 # Generate QuickSearch file
137 fun quicksearch_list
do
138 var file
= new OFStream.open
("{destinationdir.to_s}/quicksearch-list.js")
139 var content
= new Buffer
140 content
.append
("var entries = \{ ")
141 for prop
in model
.mproperties
do
142 if not prop
isa MMethod then continue
143 content
.append
("\"{prop.name}\
": [")
144 for propdef
in prop
.mpropdefs
do
145 content
.append
("\{txt: \"{propdef.mproperty.full_name}\", url
:\
"{propdef.mproperty.anchor}\" \
}")
146 if not propdef is prop.mpropdefs.last then content.append(", ")
152 for mclass in model.mclasses do
153 content.append("\
"{mclass.name}\": [")
154 for mclassdef in mclass.mclassdefs do
155 content.append("\
{txt: \"{mclassdef.mclass.full_name}\
", url:\"{mclass.link_anchor}\
" \}")
156 if not mclassdef
is mclass
.mclassdefs
.last
then content
.append
(", ")
159 if not mclass
is model
.mclasses
.last
then content
.append
(", ")
162 content
.append
(" \};")
163 file
.write
(content
.to_s
)
170 abstract class NitdocPage
174 var destinationdir
: String
175 var source
: nullable String
178 add
("meta").attr
("charset", "utf-8")
179 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/jquery-1.7.1.min.js")
180 add
("script").attr
("type", "text/javascript").attr
("src", "quicksearch-list.js")
181 add
("script").attr
("type", "text/javascript").attr
("src", "scripts/js-facilities.js")
182 add
("link").attr
("rel", "stylesheet").attr
("href", "styles/main.css").attr
("type", "text/css").attr
("media", "screen")
187 open
("div").add_class
("page")
197 open
("nav").add_class
("main")
200 open
("li").attr
("id", "liGitHub")
201 open
("a").add_class
("btn").attr
("id", "logGitHub")
202 add
("img").attr
("id", "imgGitHub").attr
("src", "resources/icons/github-icon.png")
204 open
("div").add_class
("popover bottom")
205 add
("div").add_class
("arrow").text
(" ")
206 open
("div").add_class
("githubTitle")
207 add
("h3").text
("Github Sign In")
210 add
("label").attr
("id", "lbloginGit").text
("Username")
211 add
("input").attr
("id", "loginGit").attr
("name", "login").attr
("type", "text")
212 open
("label").attr
("id", "logginMessage").text
("Hello ")
213 open
("a").attr
("id", "githubAccount")
214 add
("strong").attr
("id", "nickName").text
(" ")
219 add
("label").attr
("id", "lbpasswordGit").text
("Password")
220 add
("input").attr
("id", "passwordGit").attr
("name", "password").attr
("type", "password")
221 open
("div").attr
("id", "listBranches")
222 add
("label").attr
("id", "lbBranches").text
("Branch")
223 add
("select").add_class
("dropdown").attr
("id", "dropBranches").attr
("name", "dropBranches").attr
("tabindex", "1").text
(" ")
227 add
("label").attr
("id", "lbrepositoryGit").text
("Repository")
228 add
("input").attr
("id", "repositoryGit").attr
("name", "repository").attr
("type", "text")
231 add
("label").attr
("id", "lbbranchGit").text
("Branch")
232 add
("input").attr
("id", "branchGit").attr
("name", "branch").attr
("type", "text")
235 add
("a").attr
("id", "signIn").text
("Sign In")
244 fun content
is abstract
247 add
("footer").text
("Nit standard library. Version jenkins-component=stdlib-19.")
250 # Generate a clickable graphviz image using a dot content
251 fun generate_dot
(dot
: String, name
: String, alt
: String) do
252 if opt_nodot
then return
253 var file
= new OFStream.open
("{self.destinationdir}/{name}.dot")
256 sys
.system
("\{ test -f {self.destinationdir}/{name}.png && test -f {self.destinationdir}/{name}.s.dot && diff {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot && dot -Tpng -o{self.destinationdir}/{name}.png -Tcmapx -o{self.destinationdir}/{name}.map {self.destinationdir}/{name}.s.dot ; \}")
257 open
("article").add_class
("graph")
258 add
("img").attr
("src", "{name}.png").attr
("usemap", "#{name}").attr
("style", "margin:auto").attr
("alt", "{alt}")
260 var fmap
= new IFStream.open
("{self.destinationdir}/{name}.map")
261 add_html
(fmap
.read_all
)
265 # Add a (source) link for a given location
266 fun show_source
(l
: Location): String
268 if source
== null then
269 return "({l.file.filename.simplify_path})"
271 # THIS IS JUST UGLY ! (but there is no replace yet)
272 var x
= source
.split_with
("%f")
273 source
= x
.join
(l
.file
.filename
.simplify_path
)
274 x
= source
.split_with
("%l")
275 source
= x
.join
(l
.line_start
.to_s
)
276 x
= source
.split_with
("%L")
277 source
= x
.join
(l
.line_end
.to_s
)
278 return " (<a href=\"{source.to_s}\
">show code</a>)"
287 private var mbuilder
: ModelBuilder
288 private var mmodules
= new Array[MModule]
290 init with
(mbuilder
: ModelBuilder, opt_nodot
: Bool, destination
: String) do
291 self.mbuilder
= mbuilder
292 self.opt_nodot
= opt_nodot
293 self.destinationdir
= destination
295 var mmodules
= new HashSet[MModule]
296 for mmodule
in mbuilder
.model
.mmodules
do
297 var owner
= mmodule
.public_owner
298 if owner
!= null then
301 mmodules
.add
(mmodule
)
305 var sorter
= new ComparableSorter[MModule]
306 self.mmodules
.add_all
(mmodules
)
307 sorter
.sort
(self.mmodules
)
312 add
("title").text
("Overview | Nit Standard Library")
316 add
("li").add_class
("current").text
("Overview")
318 add
("a").attr
("href", "full-index.html").text
("Full Index")
323 open
("div").add_class
("content fullpage")
324 add
("h1").text
("Nit Standard Library")
325 open
("article").add_class
("overview")
326 add_html
("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
328 open
("article").add_class
("overview")
330 add
("h2").text
("Modules")
332 for mmodule
in mmodules
do
333 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
335 add_html
("{mmodule.link(amodule)} {amodule.short_comment}")
345 fun process_generate_dot
do
347 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")
348 for mmodule
in mmodules
do
349 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
350 for imported
in mmodule
.in_importation
.direct_greaters
do
351 if imported
.direct_owner
== null then
352 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
357 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
361 # The full index page
362 class NitdocFullindex
365 var mmodules
: Array[MModule]
367 init with
(mmodules
: Array[MModule]) do
368 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})")
474 var mbuilder
: ModelBuilder
476 init with
(mmodule
: MModule, mbuilder
: ModelBuilder) do
477 self.mmodule
= mmodule
478 self.mbuilder
= mbuilder
485 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
486 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
491 add
("a").attr
("href", "index.html").text
("Overview")
493 add
("li").add_class
("current").text
(mmodule
.name
)
495 add
("a").attr
("href", "full-index.html").text
("Full Index")
501 open
("div").add_class
("content")
502 add
("h1").text
(mmodule
.name
)
503 add
("div").add_class
("subtitle")
504 add_html
("module {mmodule.namespace(mbuilder)}")
506 #process_generate_dot
512 # Insert module comment in the content
513 fun module_comment
do
514 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
515 var doc
= amodule
.comment
516 open
("div").attr
("id", "description")
517 add
("pre").add_class
("text_label").text
(doc
)
518 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
519 add
("a").attr
("id", "cancelBtn").text
("Cancel")
520 add
("a").attr
("id", "commitBtn").text
("Commit")
521 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
525 fun process_generate_dot
do
527 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")
528 for m
in mmodule
.in_importation
.smallers
do
529 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
530 for imported
in m
.in_importation
.direct_greaters
do
531 if imported
.direct_owner
== null then
532 op
.append
("\"{m.name}\
"->\"{imported.name}\
";\n")
537 generate_dot
(op
.to_s
, "dep_{mmodule.name}", "Modules hierarchy")
541 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
542 open
("div").add_class
("menu")
544 add
("h3").text
("Module Hierarchy")
545 var dependencies
= new Array[MModule]
546 for dep
in mmodule
.in_importation
.greaters
do
547 if dep
== mmodule
or dep
.public_owner
!= null then continue
548 dependencies
.add
(dep
)
550 if dependencies
.length
> 0 then
551 add
("h4").text
("All dependencies")
552 display_module_list
(dependencies
)
554 var clients
= new Array[MModule]
555 for dep
in mmodule
.in_importation
.smallers
do
556 if dep
== mmodule
or dep
.public_owner
!= null then continue
559 if clients
.length
> 0 then
560 add
("h4").text
("All clients")
561 display_module_list
(clients
)
564 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
566 add
("h3").text
("Nested Modules")
567 display_module_list
(mmodule
.in_nesting
.direct_greaters
.to_a
)
573 private fun display_module_list
(list
: Array[MModule]) do
575 var sorter
= new ComparableSorter[MModule]
578 var am
= mbuilder
.mmodule2nmodule
[m
]
587 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
588 var intro_mclasses
= mmodule
.intro_mclasses
589 var redef_mclasses
= mmodule
.redef_mclasses
590 var all_mclasses
= new HashSet[MClass]
591 for m
in mmodule
.in_nesting
.greaters
do
592 all_mclasses
.add_all
(m
.intro_mclasses
)
593 all_mclasses
.add_all
(m
.redef_mclasses
)
595 all_mclasses
.add_all
(intro_mclasses
)
596 all_mclasses
.add_all
(redef_mclasses
)
598 var sorted
= new Array[MClass]
599 sorted
.add_all
(all_mclasses
)
600 var sorter
= new ComparableSorter[MClass]
602 open
("div").add_class
("module")
603 open
("article").add_class
("classes filterable")
604 add
("h2").text
("Classes")
607 var nclass
= mbuilder
.mclassdef2nclassdef
[c
.intro
].as(AStdClassdef)
608 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
609 open
("li").add_class
("redef")
610 add
("span").attr
("title", "refined in this module").text
("R ")
612 open
("li").add_class
("intro")
613 add
("span").attr
("title", "introduced in this module").text
("I ")
615 add_html
(c
.link
(nclass
))
624 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
625 var mpropdefs
= new HashSet[MPropDef]
626 for m
in mmodule
.in_nesting
.greaters
do
627 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
629 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
630 var sorted
= mpropdefs
.to_a
631 var sorter
= new ComparableSorter[MPropDef]
633 open
("article").add_class
("properties filterable")
634 add
("h2").text
("Properties")
637 if p
isa MAttributeDef then continue
638 if p
.mproperty
.visibility
<= none_visibility
then continue
639 if not mbuilder
.mpropdef2npropdef
.has_key
(p
) then continue
640 var nprop
= mbuilder
.mpropdef2npropdef
[p
]
642 open
("li").add_class
("intro")
643 add
("span").attr
("title", "introduction").text
("I")
645 open
("li").add_class
("redef")
646 add
("span").attr
("title", "redefinition").text
("R")
648 add_html
(" {p.link(nprop)} ({p.mclassdef.mclass.name})")
661 var mbuilder
: ModelBuilder
663 init with
(mclass
: MClass, mbuilder
: ModelBuilder, source
: nullable String) do
665 self.mbuilder
= mbuilder
666 self.opt_nodot
= false
667 self.destinationdir
= ""
673 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
674 if nclass
isa AStdClassdef then
675 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
677 add
("title").text
("{mclass.name} class")
683 add
("a").attr
("href", "index.html").text
("Overview")
686 var public_owner
= mclass
.public_owner
687 if public_owner
is null then
688 var am
= mbuilder
.mmodule2nmodule
[mclass
.intro_mmodule
]
689 add_html
(mclass
.intro_mmodule
.link
(am
))
691 var am
= mbuilder
.mmodule2nmodule
[public_owner
]
692 add_html
(public_owner
.link
(am
))
695 add
("li").add_class
("current").text
(mclass
.name
)
697 add
("a").attr
("href", "full-index.html").text
("Full Index")
702 open
("div").add_class
("menu")
706 open
("div").add_class
("content")
711 fun properties_column
do
712 var sorter
= new ComparableSorter[MPropDef]
713 open
("nav").add_class
("properties filterable")
714 add
("h3").text
("Properties")
716 var vtypes
= new HashSet[MVirtualTypeDef]
717 var consts
= new HashSet[MMethodDef]
718 var meths
= new HashSet[MMethodDef]
719 for mclassdef
in mclass
.mclassdefs
do
720 for mpropdef
in mclassdef
.mpropdefs
do
721 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
722 if mpropdef
.mproperty
.visibility
<= none_visibility
then continue
723 if mpropdef
isa MVirtualTypeDef then vtypes
.add
(mpropdef
)
724 if mpropdef
isa MMethodDef then
725 if mpropdef
.mproperty
.is_init
then
733 for mprop
in mclass
.inherited_methods
do
734 var mpropdef
= mprop
.intro
735 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
736 if mprop
.visibility
<= none_visibility
then continue
737 if mprop
.intro_mclassdef
.mclass
.name
== "Object" then continue
741 if vtypes
.length
> 0 then
742 var vts
= new Array[MVirtualTypeDef]
745 add
("h4").text
("Virtual Types")
746 display_mpropdef_list
(vts
)
748 if consts
.length
> 0 then
749 var cts
= new Array[MMethodDef]
752 add
("h4").text
("Constructors")
753 display_mpropdef_list
(cts
)
755 if meths
.length
> 0 then
756 var mts
= new Array[MMethodDef]
759 add
("h4").text
("Methods")
760 display_mpropdef_list
(mts
)
765 private fun display_mpropdef_list
(list
: Array[MPropDef]) do
768 var nprop
= mbuilder
.mpropdef2npropdef
[prop
]
769 if prop
.is_intro
and prop
.mproperty
.intro_mclassdef
.mclass
!= mclass
then
770 open
("li").add_class
("inherit")
771 add
("span").attr
("title", "Inherited").text
("H")
772 else if prop
.is_intro
then
773 open
("li").add_class
("intro")
774 add
("span").attr
("title", "Introduced").text
("I")
776 open
("li").add_class
("redef")
777 add
("span").attr
("title", "Redefined").text
("R")
779 add_html
(prop
.link
(nprop
))
785 fun inheritance_column
do
786 var sorted
= new Array[MClass]
787 var sorterp
= new ComparableSorter[MClass]
789 add
("h3").text
("Inheritance")
790 if mclass
.ancestors
.length
> 1 then
791 sorted
= mclass
.ancestors
.to_a
793 add
("h4").text
("Superclasses")
796 if sup
== mclass
then continue
798 add
("a").attr
("href", "{sup.name}.html").text
(sup
.name
)
804 if mclass
.descendants
.length
<= 1 then
805 add
("h4").text
("No Known Subclasses")
806 else if mclass
.descendants
.length
<= 100 then
807 sorted
= mclass
.descendants
.to_a
809 add
("h4").text
("Subclasses")
812 if sub
== mclass
then continue
814 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
818 else if mclass
.children
.length
<= 100 then
819 sorted
= mclass
.children
.to_a
821 add
("h4").text
("Direct Subclasses Only")
824 if sub
== mclass
then continue
826 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
831 add
("h4").text
("Too much Subclasses to list")
837 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
838 var sorted
= new Array[MModule]
839 sorted
.add_all
(mclass
.concerns
.keys
)
840 var sorterp
= new ComparableSorter[MModule]
841 var sorterprop
= new ComparableSorter[MProperty]
842 var sorterc
= new ComparableSorter[MClass]
845 var lmmodule
= new List[MModule]
846 # Insert the subtitle part
847 add
("h1").text
(mclass
.to_s
)
848 open
("div").add_class
("subtitle")
849 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
850 subtitle
+= "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}"
853 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
854 # We add the class description
855 open
("section").add_class
("description")
856 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>")
858 open
("section").add_class
("concerns")
859 add
("h2").add_class
("section-header").text
("Concerns")
861 for owner
in sorted
do
862 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
863 var childs
= mclass
.concerns
[owner
]
865 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
866 if not childs
is null then
868 var sortedc
= childs
.to_a
869 var sorterpc
= new ComparableSorter[MModule]
870 sorterpc
.sort
(sortedc
)
871 for child
in sortedc
do
872 var nchild
= mbuilder
.mmodule2nmodule
[child
]
873 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
881 # Insert virtual types if there is almost one
882 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
883 open
("section").add_class
("types")
884 add
("h2").text
("Formal and Virtual Types")
885 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
886 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
887 for prop
in nclass
.n_formaldefs
do
888 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
889 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
890 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
892 add_html
("<div class=\"info\
">formal generic type</div>")
899 if mclass
.constructors
.length
> 0 then
900 var sortedc
= mclass
.constructors
.to_a
901 sorterprop
.sort
(sortedc
)
902 open
("section").add_class
("constructors")
903 add
("h2").add_class
("section-header").text
("Constructors")
904 for prop
in sortedc
do description
(prop
)
908 open
("section").add_class
("methods")
909 add
("h2").add_class
("section-header").text
("Methods")
910 for mmodule
, mmethods
in mclass
.all_methods
do
911 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
912 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
913 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
914 if mclass
.has_mmodule
(mmodule
) then
915 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
917 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in {mmodule.link(nmodule)}</h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
920 var sortedc
= mmethods
.to_a
921 sorterprop
.sort
(sortedc
)
922 for prop
in sortedc
do description
(prop
)
925 if mclass
.inherited_methods
.length
> 0 then
926 var sortedc
= new Array[MClass]
927 sortedc
.add_all
(mclass
.inherited
.keys
)
928 sorterc
.sort
(sortedc
)
929 add
("h3").text
("Inherited Methods")
930 for imclass
in sortedc
do
931 var inclass
= mbuilder
.mclassdef2nclassdef
[imclass
.intro
].as(AStdClassdef)
932 var sortedp
= mclass
.inherited
[imclass
].to_a
933 sorterprop
.sort
(sortedp
)
935 add_html
("Defined in {imclass.link(inclass)}: ")
936 for method
in sortedp
do
937 #TODO link to inherited propdef
938 add_html
("<a href=\"\
">{method.name}</a>")
939 if method
!= sortedp
.last
then add_html
(", ")
947 fun description
(prop
: MProperty) do
948 if not mbuilder
.mpropdef2npropdef
.has_key
(prop
.intro
) then return
949 var nprop
= mbuilder
.mpropdef2npropdef
[prop
.intro
]
950 if not nprop
isa AMethPropdef then return
951 var classes
= new Array[String]
952 if nprop
isa AInitPropdef then
957 if prop
.is_redef
then classes
.add
("redef")
958 if prop
.visibility
== none_visibility
then
959 classes
.add
("private")
960 else if prop
.visibility
== protected_visibility
then
961 classes
.add
("protected")
963 classes
.add
("public")
965 open
("article").add_classes
(classes
).attr
("id", "{prop.anchor}")
967 open
("h3").add_class
("signature")
968 add_html
("{prop.name}{nprop.signature}")
970 open
("div").add_class
("info")
971 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>")
973 open
("div").add_class
("description")
974 if nprop
.comment
== "" then
975 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
977 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{nprop.comment}</pre>")
979 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>")
981 if prop
.local_class
!= mclass
then
982 var mredef
= prop
.local_class
.intro_mmodule
983 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
984 add_html
("inherited from {mredef.link(nredef)} ")
986 #TODO display show code if doc github
987 var mintro
= prop
.intro_mclassdef
.mmodule
988 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
989 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
991 for parent
in mclass
.parents
do
992 var mparent
= parent
.intro_mmodule
993 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
994 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>.")
1005 private fun comment
: String do
1007 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
1008 if n_moduledecl
.n_doc
is null then return ""
1009 for t
in n_moduledecl
.n_doc
.n_comment
do
1011 txt
= txt
.replace
("# ", "")
1012 txt
= txt
.replace
("#", "")
1018 private fun short_comment
: String do
1020 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
1021 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
1022 txt
= txt
.replace
("# ", "")
1023 txt
= txt
.replace
("\n", "")
1032 redef type OTHER: MModule
1033 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1035 # Get the list of all methods in a module
1036 fun imported_methods
: Set[MMethod] do
1037 var methods
= new HashSet[MMethod]
1038 for mclass
in imported_mclasses
do
1039 for method
in mclass
.intro_methods
do
1046 # Get the list aof all refined methods in a module
1047 fun redef_methods
: Set[MMethod] do
1048 var methods
= new HashSet[MMethod]
1049 for mclass
in redef_mclasses
do
1050 for method
in mclass
.intro_methods
do
1057 # Return a link (html a tag) to the nitdoc module page
1058 fun link
(amodule
: AModule): String do
1059 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1062 # Return the module namespace decorated with html
1063 fun namespace
(mbuilder
: ModelBuilder): String do
1064 var str
= new Buffer
1065 var mowner
= public_owner
1066 if mowner
!= null then
1067 var nowner
= mbuilder
.mmodule2nmodule
[mowner
]
1068 str
.append
(public_owner
.link
(nowner
))
1070 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1071 str
.append
(self.link
(nmodule
))
1075 redef class MPropDef
1077 redef type OTHER: MPropDef
1078 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1080 # Return a link (html a tag) to the nitdoc class page
1081 fun link
(nprop
: APropdef): String do
1082 return "<a href=\"{mclassdef.mclass.name}.html
#{mproperty.anchor}\" title=\"{nprop.short_comment}\">{mproperty}</a>"
1086 redef class MProperty
1088 redef type OTHER: MProperty
1089 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1092 var apropdef
: nullable APropdef
1094 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1100 fun local_class
: MClass do
1101 var classdef
= self.intro_mclassdef
1102 return classdef
.mclass
1105 fun anchor
: String do
1106 return "PROP_{c_name}"
1113 redef type OTHER: MClass
1114 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1116 # Add type parameters
1119 return "{name}[{intro.parameter_names.join(", ")}]"
1125 # Return a link (html a tag) to the nitdoc class page
1126 fun link
(aclass
: AStdClassdef): String do
1127 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1130 # Associate all MMethods to each MModule concerns
1131 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1132 var hm
= new HashMap[MModule, Set[MMethod]]
1133 for mmodule
, childs
in concerns
do
1134 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1135 for prop
in intro_methods
do
1136 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1137 prop
.is_redef
= false
1138 hm
[mmodule
].add
(prop
)
1141 for prop
in redef_methods
do
1142 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1143 prop
.is_redef
= true
1144 hm
[mmodule
].add
(prop
)
1148 if childs
!= null then
1149 for child
in childs
do
1150 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1151 for prop
in intro_methods
do
1152 if child
== prop
.intro_mclassdef
.mmodule
then
1153 prop
.is_redef
= false
1157 for prop
in redef_methods
do
1158 if child
== prop
.intro_mclassdef
.mmodule
then
1159 prop
.is_redef
= true
1169 fun public_owner
: MModule do
1170 var owner
= intro_mmodule
1171 if owner
.public_owner
is null then
1174 return owner
.public_owner
.as(not null)
1178 # Associate MClass to all MMethod include in 'inherited_methods'
1179 fun inherited
: HashMap[MClass, Set[MMethod]] do
1180 var hm
= new HashMap[MClass, Set[MMethod]]
1181 for method
in inherited_methods
do
1182 var mclass
= method
.intro_mclassdef
.mclass
1183 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1184 hm
[mclass
].add
(method
)
1189 # Return true if MModule concern contain subMModule
1190 fun has_mmodule
(sub
: MModule): Bool do
1191 for mmodule
, childs
in concerns
do
1192 if childs
is null then continue
1193 if childs
.has
(sub
) then return true
1198 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1199 for const
in constructors
do
1200 if mprop2npropdef
.has_key
(const
)then
1201 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1205 for intro
in intro_methods
do
1206 if mprop2npropdef
.has_key
(intro
)then
1207 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1211 for rd
in redef_methods
do
1212 if mprop2npropdef
.has_key
(rd
)then
1213 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1218 fun link_anchor
: String do
1219 return "{name}.html"
1224 redef class AStdClassdef
1225 private fun comment
: String do
1227 if n_doc
!= null then
1228 for t
in n_doc
.n_comment
do
1229 var txt
= t
.text
.replace
("# ", "")
1230 txt
= txt
.replace
("#", "")
1237 private fun short_comment
: String do
1239 if n_doc
!= null then
1240 var txt
= n_doc
.n_comment
.first
.text
1241 txt
= txt
.replace
("# ", "")
1242 txt
= txt
.replace
("\n", "")
1249 redef class ASignature
1253 if not n_params
.is_empty
then
1254 ret
= "{ret}({n_params.join(", ")})"
1256 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1263 var ret
= "{n_id.text}"
1264 if n_type
!= null then
1265 ret
= "{ret}: {n_type.to_s}"
1266 if n_dotdotdot
!= null then ret
= "{ret}..."
1274 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1275 if n_kwnullable
!= null then ret
= "nullable {ret}"
1276 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1281 redef class APropdef
1282 private fun short_comment
: String is abstract
1283 private fun signature
: String is abstract
1284 private fun comment
: String is abstract
1287 redef class AAttrPropdef
1288 redef fun short_comment
do
1290 if n_doc
!= null then
1291 var txt
= n_doc
.n_comment
.first
.text
1292 txt
= txt
.replace
("# ", "")
1293 txt
= txt
.replace
("\n", "")
1300 redef class AMethPropdef
1301 redef fun short_comment
do
1302 var ret
= new Buffer
1303 if n_doc
!= null then
1304 var txt
= n_doc
.n_comment
.first
.text
1305 txt
= txt
.replace
("# ", "")
1306 txt
= txt
.replace
("\n", "")
1312 redef fun signature
: String do
1314 if n_signature
!= null then sign
= "{n_signature.to_s}"
1318 redef private fun comment
: String do
1319 var ret
= new Buffer
1320 if n_doc
!= null then
1321 for t
in n_doc
.n_comment
do
1322 var txt
= t
.text
.replace
("# ", "")
1323 txt
= txt
.replace
("#", "")
1331 redef class MClassDef
1332 private fun namespace
(mclass
: MClass): String do
1334 if mmodule
.public_owner
is null then
1335 return "{mmodule.full_name}::{mclass.name}"
1336 else if mclass
is self.mclass
then
1337 return "{mmodule.public_owner.name}::{mclass.name}"
1339 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1346 return to_a
[length-1
]
1350 # Create a tool context to handle options and paths
1351 var toolcontext
= new ToolContext
1353 # Here we launch the nit index
1354 var nitdoc
= new Nitdoc(toolcontext
)