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>)"
288 var mbuilder
: ModelBuilder
290 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
291 # opt_nodot to inform about the graph gen
292 # destination: to know where will be saved dot files
293 init with
(mbuilder
: ModelBuilder, opt_nodot
: Bool, destination
: String) do
294 self.mbuilder
= mbuilder
295 self.opt_nodot
= opt_nodot
296 self.destinationdir
= destination
301 add
("title").text
("Overview | Nit Standard Library")
305 add
("li").add_class
("current").text
("Overview")
307 add
("a").attr
("href", "full-index.html").text
("Full Index")
312 open
("div").add_class
("content fullpage")
313 add
("h1").text
("Nit Standard Library")
314 open
("article").add_class
("overview")
315 add_html
("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
317 open
("article").add_class
("overview")
318 add
("h2").text
("Modules")
328 var mmodules
= list_mmodules
329 var sorted
= new Array[MModule].from
(mmodules
)
330 var sorter
= new ComparableSorter[MModule]
332 for mmodule
in sorted
do
333 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
335 add_html
("{mmodule.link(amodule)} {amodule.short_comment}")
340 fun process_generate_dot
do
342 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")
343 for mmodule
in list_mmodules
do
344 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
345 for imported
in mmodule
.in_importation
.direct_greaters
do
346 if imported
.direct_owner
== null then
347 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
352 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
355 private fun list_mmodules
: Set[MModule] do
356 var mmodules
= new HashSet[MModule]
357 for mmodule
in mbuilder
.model
.mmodules
do
358 var owner
= mmodule
.public_owner
359 if owner
!= null then
362 mmodules
.add
(mmodule
)
369 # The full index page
370 class NitdocFullindex
373 var mmodules
: Array[MModule]
375 init with
(mmodules
: Array[MModule]) do
376 self.mmodules
= mmodules
383 add
("title").text
("Full Index | Nit Standard Library")
388 add
("a").attr
("href", "index.html").text
("Overview")
390 add
("li").add_class
("current").text
("Full Index")
394 open
("div").add_class
("content fullpage")
395 add
("h1").text
("Full Index")
402 # Add to content modules column
404 var ls
= new List[nullable MModule]
405 var sorted
= mmodules
406 var sorterp
= new ComparableSorter[MModule]
408 open
("article").add_class
("modules filterable")
409 add
("h2").text
("Modules")
411 for mmodule
in sorted
do
412 if mmodule
.public_owner
!= null and not ls
.has
(mmodule
.public_owner
) then
413 ls
.add
(mmodule
.public_owner
)
415 add
("a").attr
("href", "{mmodule.public_owner.name}.html").text
(mmodule
.public_owner
.name
)
423 # Add to content classes modules
424 fun classes_column
do
425 var sorted
= mmodules
.first
.imported_mclasses
.to_a
426 var sorterp
= new ComparableSorter[MClass]
428 open
("article").add_class
("classes filterable")
429 add
("h2").text
("Classes")
432 for mclass
in sorted
do
434 add
("a").attr
("href", "{mclass}.html").text
(mclass
.name
)
442 # Insert the properties column of fullindex page
443 fun properties_column
do
444 open
("article").add_class
("properties filterable")
445 add
("h2").text
("Properties")
447 var sorted_imported
= mmodules
.first
.imported_methods
.to_a
448 var sorted_redef
= mmodules
.first
.redef_methods
.to_a
449 var sorterp
= new ComparableSorter[MProperty]
450 sorterp
.sort
(sorted_imported
)
451 sorterp
.sort
(sorted_redef
)
453 for method
in sorted_imported
do
454 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
455 open
("li").add_class
("intro")
456 add
("span").attr
("title", "introduction").text
("I")
458 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
462 for method
in sorted_redef
do
463 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
464 open
("li").add_class
("redef")
465 add
("span").attr
("title", "redefinition").text
("R")
467 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
482 var mbuilder
: ModelBuilder
484 init with
(mmodule
: MModule, mbuilder
: ModelBuilder) do
485 self.mmodule
= mmodule
486 self.mbuilder
= mbuilder
493 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
494 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
499 add
("a").attr
("href", "index.html").text
("Overview")
501 add
("li").add_class
("current").text
(mmodule
.name
)
503 add
("a").attr
("href", "full-index.html").text
("Full Index")
509 open
("div").add_class
("content")
510 add
("h1").text
(mmodule
.name
)
511 add
("div").add_class
("subtitle")
512 add_html
("module {mmodule.namespace(mbuilder)}")
514 #process_generate_dot
520 # Insert module comment in the content
521 fun module_comment
do
522 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
523 var doc
= amodule
.comment
524 open
("div").attr
("id", "description")
525 add
("pre").add_class
("text_label").text
(doc
)
526 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
527 add
("a").attr
("id", "cancelBtn").text
("Cancel")
528 add
("a").attr
("id", "commitBtn").text
("Commit")
529 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
533 fun process_generate_dot
do
535 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")
536 for m
in mmodule
.in_importation
.smallers
do
537 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
538 for imported
in m
.in_importation
.direct_greaters
do
539 if imported
.direct_owner
== null then
540 op
.append
("\"{m.name}\
"->\"{imported.name}\
";\n")
545 generate_dot
(op
.to_s
, "dep_{mmodule.name}", "Modules hierarchy")
549 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
550 open
("div").add_class
("menu")
552 add
("h3").text
("Module Hierarchy")
553 var dependencies
= new Array[MModule]
554 for dep
in mmodule
.in_importation
.greaters
do
555 if dep
== mmodule
or dep
.public_owner
!= null then continue
556 dependencies
.add
(dep
)
558 if dependencies
.length
> 0 then
559 add
("h4").text
("All dependencies")
560 display_module_list
(dependencies
)
562 var clients
= new Array[MModule]
563 for dep
in mmodule
.in_importation
.smallers
do
564 if dep
== mmodule
or dep
.public_owner
!= null then continue
567 if clients
.length
> 0 then
568 add
("h4").text
("All clients")
569 display_module_list
(clients
)
572 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
574 add
("h3").text
("Nested Modules")
575 display_module_list
(mmodule
.in_nesting
.direct_greaters
.to_a
)
581 private fun display_module_list
(list
: Array[MModule]) do
583 var sorter
= new ComparableSorter[MModule]
586 var am
= mbuilder
.mmodule2nmodule
[m
]
595 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
596 var intro_mclasses
= mmodule
.intro_mclasses
597 var redef_mclasses
= mmodule
.redef_mclasses
598 var all_mclasses
= new HashSet[MClass]
599 for m
in mmodule
.in_nesting
.greaters
do
600 all_mclasses
.add_all
(m
.intro_mclasses
)
601 all_mclasses
.add_all
(m
.redef_mclasses
)
603 all_mclasses
.add_all
(intro_mclasses
)
604 all_mclasses
.add_all
(redef_mclasses
)
606 var sorted
= new Array[MClass]
607 sorted
.add_all
(all_mclasses
)
608 var sorter
= new ComparableSorter[MClass]
610 open
("div").add_class
("module")
611 open
("article").add_class
("classes filterable")
612 add
("h2").text
("Classes")
615 var nclass
= mbuilder
.mclassdef2nclassdef
[c
.intro
].as(AStdClassdef)
616 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
617 open
("li").add_class
("redef")
618 add
("span").attr
("title", "refined in this module").text
("R ")
620 open
("li").add_class
("intro")
621 add
("span").attr
("title", "introduced in this module").text
("I ")
623 add_html
(c
.link
(nclass
))
632 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
633 var mpropdefs
= new HashSet[MPropDef]
634 for m
in mmodule
.in_nesting
.greaters
do
635 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
637 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
638 var sorted
= mpropdefs
.to_a
639 var sorter
= new ComparableSorter[MPropDef]
641 open
("article").add_class
("properties filterable")
642 add
("h2").text
("Properties")
645 if p
isa MAttributeDef then continue
646 if p
.mproperty
.visibility
<= none_visibility
then continue
647 if not mbuilder
.mpropdef2npropdef
.has_key
(p
) then continue
648 var nprop
= mbuilder
.mpropdef2npropdef
[p
]
650 open
("li").add_class
("intro")
651 add
("span").attr
("title", "introduction").text
("I")
653 open
("li").add_class
("redef")
654 add
("span").attr
("title", "redefinition").text
("R")
656 add_html
(" {p.link(nprop)} ({p.mclassdef.mclass.name})")
669 var mbuilder
: ModelBuilder
671 init with
(mclass
: MClass, mbuilder
: ModelBuilder, source
: nullable String) do
673 self.mbuilder
= mbuilder
674 self.opt_nodot
= false
675 self.destinationdir
= ""
681 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
682 if nclass
isa AStdClassdef then
683 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
685 add
("title").text
("{mclass.name} class")
691 add
("a").attr
("href", "index.html").text
("Overview")
694 var public_owner
= mclass
.public_owner
695 if public_owner
is null then
696 var am
= mbuilder
.mmodule2nmodule
[mclass
.intro_mmodule
]
697 add_html
(mclass
.intro_mmodule
.link
(am
))
699 var am
= mbuilder
.mmodule2nmodule
[public_owner
]
700 add_html
(public_owner
.link
(am
))
703 add
("li").add_class
("current").text
(mclass
.name
)
705 add
("a").attr
("href", "full-index.html").text
("Full Index")
710 open
("div").add_class
("menu")
714 open
("div").add_class
("content")
719 fun properties_column
do
720 var sorter
= new ComparableSorter[MPropDef]
721 open
("nav").add_class
("properties filterable")
722 add
("h3").text
("Properties")
724 var vtypes
= new HashSet[MVirtualTypeDef]
725 var consts
= new HashSet[MMethodDef]
726 var meths
= new HashSet[MMethodDef]
727 for mclassdef
in mclass
.mclassdefs
do
728 for mpropdef
in mclassdef
.mpropdefs
do
729 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
730 if mpropdef
.mproperty
.visibility
<= none_visibility
then continue
731 if mpropdef
isa MVirtualTypeDef then vtypes
.add
(mpropdef
)
732 if mpropdef
isa MMethodDef then
733 if mpropdef
.mproperty
.is_init
then
741 for mprop
in mclass
.inherited_methods
do
742 var mpropdef
= mprop
.intro
743 if not mbuilder
.mpropdef2npropdef
.has_key
(mpropdef
) then continue
744 if mprop
.visibility
<= none_visibility
then continue
745 if mprop
.intro_mclassdef
.mclass
.name
== "Object" then continue
749 if vtypes
.length
> 0 then
750 var vts
= new Array[MVirtualTypeDef]
753 add
("h4").text
("Virtual Types")
754 display_mpropdef_list
(vts
)
756 if consts
.length
> 0 then
757 var cts
= new Array[MMethodDef]
760 add
("h4").text
("Constructors")
761 display_mpropdef_list
(cts
)
763 if meths
.length
> 0 then
764 var mts
= new Array[MMethodDef]
767 add
("h4").text
("Methods")
768 display_mpropdef_list
(mts
)
773 private fun display_mpropdef_list
(list
: Array[MPropDef]) do
776 var nprop
= mbuilder
.mpropdef2npropdef
[prop
]
777 if prop
.is_intro
and prop
.mproperty
.intro_mclassdef
.mclass
!= mclass
then
778 open
("li").add_class
("inherit")
779 add
("span").attr
("title", "Inherited").text
("H")
780 else if prop
.is_intro
then
781 open
("li").add_class
("intro")
782 add
("span").attr
("title", "Introduced").text
("I")
784 open
("li").add_class
("redef")
785 add
("span").attr
("title", "Redefined").text
("R")
787 add_html
(prop
.link
(nprop
))
793 fun inheritance_column
do
794 var sorted
= new Array[MClass]
795 var sorterp
= new ComparableSorter[MClass]
797 add
("h3").text
("Inheritance")
798 if mclass
.ancestors
.length
> 1 then
799 sorted
= mclass
.ancestors
.to_a
801 add
("h4").text
("Superclasses")
804 if sup
== mclass
then continue
806 add
("a").attr
("href", "{sup.name}.html").text
(sup
.name
)
812 if mclass
.descendants
.length
<= 1 then
813 add
("h4").text
("No Known Subclasses")
814 else if mclass
.descendants
.length
<= 100 then
815 sorted
= mclass
.descendants
.to_a
817 add
("h4").text
("Subclasses")
820 if sub
== mclass
then continue
822 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
826 else if mclass
.children
.length
<= 100 then
827 sorted
= mclass
.children
.to_a
829 add
("h4").text
("Direct Subclasses Only")
832 if sub
== mclass
then continue
834 add
("a").attr
("href", "{sub.name}.html").text
(sub
.name
)
839 add
("h4").text
("Too much Subclasses to list")
845 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
846 var sorted
= new Array[MModule]
847 sorted
.add_all
(mclass
.concerns
.keys
)
848 var sorterp
= new ComparableSorter[MModule]
849 var sorterprop
= new ComparableSorter[MProperty]
850 var sorterc
= new ComparableSorter[MClass]
853 var lmmodule
= new List[MModule]
854 # Insert the subtitle part
855 add
("h1").text
(mclass
.to_s
)
856 open
("div").add_class
("subtitle")
857 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
858 subtitle
+= "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}"
861 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
862 # We add the class description
863 open
("section").add_class
("description")
864 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>")
866 open
("section").add_class
("concerns")
867 add
("h2").add_class
("section-header").text
("Concerns")
869 for owner
in sorted
do
870 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
871 var childs
= mclass
.concerns
[owner
]
873 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
874 if not childs
is null then
876 var sortedc
= childs
.to_a
877 var sorterpc
= new ComparableSorter[MModule]
878 sorterpc
.sort
(sortedc
)
879 for child
in sortedc
do
880 var nchild
= mbuilder
.mmodule2nmodule
[child
]
881 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
889 # Insert virtual types if there is almost one
890 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
891 open
("section").add_class
("types")
892 add
("h2").text
("Formal and Virtual Types")
893 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
894 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
895 for prop
in nclass
.n_formaldefs
do
896 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
897 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
898 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
900 add_html
("<div class=\"info\
">formal generic type</div>")
907 if mclass
.constructors
.length
> 0 then
908 var sortedc
= mclass
.constructors
.to_a
909 sorterprop
.sort
(sortedc
)
910 open
("section").add_class
("constructors")
911 add
("h2").add_class
("section-header").text
("Constructors")
912 for prop
in sortedc
do description
(prop
)
916 open
("section").add_class
("methods")
917 add
("h2").add_class
("section-header").text
("Methods")
918 for mmodule
, mmethods
in mclass
.all_methods
do
919 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
920 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
921 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
922 if mclass
.has_mmodule
(mmodule
) then
923 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
925 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in {mmodule.link(nmodule)}</h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
928 var sortedc
= mmethods
.to_a
929 sorterprop
.sort
(sortedc
)
930 for prop
in sortedc
do description
(prop
)
933 if mclass
.inherited_methods
.length
> 0 then
934 var sortedc
= new Array[MClass]
935 sortedc
.add_all
(mclass
.inherited
.keys
)
936 sorterc
.sort
(sortedc
)
937 add
("h3").text
("Inherited Methods")
938 for imclass
in sortedc
do
939 var inclass
= mbuilder
.mclassdef2nclassdef
[imclass
.intro
].as(AStdClassdef)
940 var sortedp
= mclass
.inherited
[imclass
].to_a
941 sorterprop
.sort
(sortedp
)
943 add_html
("Defined in {imclass.link(inclass)}: ")
944 for method
in sortedp
do
945 #TODO link to inherited propdef
946 add_html
("<a href=\"\
">{method.name}</a>")
947 if method
!= sortedp
.last
then add_html
(", ")
955 fun description
(prop
: MProperty) do
956 if not mbuilder
.mpropdef2npropdef
.has_key
(prop
.intro
) then return
957 var nprop
= mbuilder
.mpropdef2npropdef
[prop
.intro
]
958 if not nprop
isa AMethPropdef then return
959 var classes
= new Array[String]
960 if nprop
isa AInitPropdef then
965 if prop
.is_redef
then classes
.add
("redef")
966 if prop
.visibility
== none_visibility
then
967 classes
.add
("private")
968 else if prop
.visibility
== protected_visibility
then
969 classes
.add
("protected")
971 classes
.add
("public")
973 open
("article").add_classes
(classes
).attr
("id", "{prop.anchor}")
975 open
("h3").add_class
("signature")
976 add_html
("{prop.name}{nprop.signature}")
978 open
("div").add_class
("info")
979 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>")
981 open
("div").add_class
("description")
982 if nprop
.comment
== "" then
983 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
985 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{nprop.comment}</pre>")
987 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>")
989 if prop
.local_class
!= mclass
then
990 var mredef
= prop
.local_class
.intro_mmodule
991 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
992 add_html
("inherited from {mredef.link(nredef)} ")
994 #TODO display show code if doc github
995 var mintro
= prop
.intro_mclassdef
.mmodule
996 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
997 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
999 for parent
in mclass
.parents
do
1000 var mparent
= parent
.intro_mmodule
1001 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
1002 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>.")
1013 private fun comment
: String do
1015 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
1016 if n_moduledecl
.n_doc
is null then return ""
1017 for t
in n_moduledecl
.n_doc
.n_comment
do
1019 txt
= txt
.replace
("# ", "")
1020 txt
= txt
.replace
("#", "")
1026 private fun short_comment
: String do
1028 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
1029 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
1030 txt
= txt
.replace
("# ", "")
1031 txt
= txt
.replace
("\n", "")
1040 redef type OTHER: MModule
1041 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1043 # Get the list of all methods in a module
1044 fun imported_methods
: Set[MMethod] do
1045 var methods
= new HashSet[MMethod]
1046 for mclass
in imported_mclasses
do
1047 for method
in mclass
.intro_methods
do
1054 # Get the list aof all refined methods in a module
1055 fun redef_methods
: Set[MMethod] do
1056 var methods
= new HashSet[MMethod]
1057 for mclass
in redef_mclasses
do
1058 for method
in mclass
.intro_methods
do
1065 # Return a link (html a tag) to the nitdoc module page
1066 fun link
(amodule
: AModule): String do
1067 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1070 # Return the module namespace decorated with html
1071 fun namespace
(mbuilder
: ModelBuilder): String do
1072 var str
= new Buffer
1073 var mowner
= public_owner
1074 if mowner
!= null then
1075 var nowner
= mbuilder
.mmodule2nmodule
[mowner
]
1076 str
.append
(public_owner
.link
(nowner
))
1078 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1079 str
.append
(self.link
(nmodule
))
1083 redef class MPropDef
1085 redef type OTHER: MPropDef
1086 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1088 # Return a link (html a tag) to the nitdoc class page
1089 fun link
(nprop
: APropdef): String do
1090 return "<a href=\"{mclassdef.mclass.name}.html
#{mproperty.anchor}\" title=\"{nprop.short_comment}\">{mproperty}</a>"
1094 redef class MProperty
1096 redef type OTHER: MProperty
1097 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1100 var apropdef
: nullable APropdef
1102 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1108 fun local_class
: MClass do
1109 var classdef
= self.intro_mclassdef
1110 return classdef
.mclass
1113 fun anchor
: String do
1114 return "PROP_{c_name}"
1121 redef type OTHER: MClass
1122 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1124 # Add type parameters
1127 return "{name}[{intro.parameter_names.join(", ")}]"
1133 # Return a link (html a tag) to the nitdoc class page
1134 fun link
(aclass
: AStdClassdef): String do
1135 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1138 # Associate all MMethods to each MModule concerns
1139 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1140 var hm
= new HashMap[MModule, Set[MMethod]]
1141 for mmodule
, childs
in concerns
do
1142 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1143 for prop
in intro_methods
do
1144 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1145 prop
.is_redef
= false
1146 hm
[mmodule
].add
(prop
)
1149 for prop
in redef_methods
do
1150 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1151 prop
.is_redef
= true
1152 hm
[mmodule
].add
(prop
)
1156 if childs
!= null then
1157 for child
in childs
do
1158 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1159 for prop
in intro_methods
do
1160 if child
== prop
.intro_mclassdef
.mmodule
then
1161 prop
.is_redef
= false
1165 for prop
in redef_methods
do
1166 if child
== prop
.intro_mclassdef
.mmodule
then
1167 prop
.is_redef
= true
1177 fun public_owner
: MModule do
1178 var owner
= intro_mmodule
1179 if owner
.public_owner
is null then
1182 return owner
.public_owner
.as(not null)
1186 # Associate MClass to all MMethod include in 'inherited_methods'
1187 fun inherited
: HashMap[MClass, Set[MMethod]] do
1188 var hm
= new HashMap[MClass, Set[MMethod]]
1189 for method
in inherited_methods
do
1190 var mclass
= method
.intro_mclassdef
.mclass
1191 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1192 hm
[mclass
].add
(method
)
1197 # Return true if MModule concern contain subMModule
1198 fun has_mmodule
(sub
: MModule): Bool do
1199 for mmodule
, childs
in concerns
do
1200 if childs
is null then continue
1201 if childs
.has
(sub
) then return true
1206 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1207 for const
in constructors
do
1208 if mprop2npropdef
.has_key
(const
)then
1209 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1213 for intro
in intro_methods
do
1214 if mprop2npropdef
.has_key
(intro
)then
1215 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1219 for rd
in redef_methods
do
1220 if mprop2npropdef
.has_key
(rd
)then
1221 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1226 fun link_anchor
: String do
1227 return "{name}.html"
1232 redef class AStdClassdef
1233 private fun comment
: String do
1235 if n_doc
!= null then
1236 for t
in n_doc
.n_comment
do
1237 var txt
= t
.text
.replace
("# ", "")
1238 txt
= txt
.replace
("#", "")
1245 private fun short_comment
: String do
1247 if n_doc
!= null then
1248 var txt
= n_doc
.n_comment
.first
.text
1249 txt
= txt
.replace
("# ", "")
1250 txt
= txt
.replace
("\n", "")
1257 redef class ASignature
1261 if not n_params
.is_empty
then
1262 ret
= "{ret}({n_params.join(", ")})"
1264 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1271 var ret
= "{n_id.text}"
1272 if n_type
!= null then
1273 ret
= "{ret}: {n_type.to_s}"
1274 if n_dotdotdot
!= null then ret
= "{ret}..."
1282 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1283 if n_kwnullable
!= null then ret
= "nullable {ret}"
1284 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1289 redef class APropdef
1290 private fun short_comment
: String is abstract
1291 private fun signature
: String is abstract
1292 private fun comment
: String is abstract
1295 redef class AAttrPropdef
1296 redef fun short_comment
do
1298 if n_doc
!= null then
1299 var txt
= n_doc
.n_comment
.first
.text
1300 txt
= txt
.replace
("# ", "")
1301 txt
= txt
.replace
("\n", "")
1308 redef class AMethPropdef
1309 redef fun short_comment
do
1310 var ret
= new Buffer
1311 if n_doc
!= null then
1312 var txt
= n_doc
.n_comment
.first
.text
1313 txt
= txt
.replace
("# ", "")
1314 txt
= txt
.replace
("\n", "")
1320 redef fun signature
: String do
1322 if n_signature
!= null then sign
= "{n_signature.to_s}"
1326 redef private fun comment
: String do
1327 var ret
= new Buffer
1328 if n_doc
!= null then
1329 for t
in n_doc
.n_comment
do
1330 var txt
= t
.text
.replace
("# ", "")
1331 txt
= txt
.replace
("#", "")
1339 redef class MClassDef
1340 private fun namespace
(mclass
: MClass): String do
1342 if mmodule
.public_owner
is null then
1343 return "{mmodule.full_name}::{mclass.name}"
1344 else if mclass
is self.mclass
then
1345 return "{mmodule.public_owner.name}::{mclass.name}"
1347 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1354 return to_a
[length-1
]
1358 # Create a tool context to handle options and paths
1359 var toolcontext
= new ToolContext
1361 # Here we launch the nit index
1362 var nitdoc
= new Nitdoc(toolcontext
)