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.link_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")
195 open
("nav").add_class
("main")
198 open
("li").attr
("id", "liGitHub")
199 open
("a").add_class
("btn").attr
("id", "logGitHub")
200 add
("img").attr
("id", "imgGitHub").attr
("src", "resources/icons/github-icon.png")
202 open
("div").add_class
("popover bottom")
203 add
("div").add_class
("arrow").text
(" ")
204 open
("div").add_class
("githubTitle")
205 add
("h3").text
("Github Sign In")
208 add
("label").attr
("id", "lbloginGit").text
("Username")
209 add
("input").attr
("id", "loginGit").attr
("name", "login").attr
("type", "text")
210 open
("label").attr
("id", "logginMessage").text
("Hello ")
211 open
("a").attr
("id", "githubAccount")
212 add
("strong").attr
("id", "nickName").text
(" ")
217 add
("label").attr
("id", "lbpasswordGit").text
("Password")
218 add
("input").attr
("id", "passwordGit").attr
("name", "password").attr
("type", "password")
219 open
("div").attr
("id", "listBranches")
220 add
("label").attr
("id", "lbBranches").text
("Branch")
221 add
("select").add_class
("dropdown").attr
("id", "dropBranches").attr
("name", "dropBranches").attr
("tabindex", "1").text
(" ")
225 add
("label").attr
("id", "lbrepositoryGit").text
("Repository")
226 add
("input").attr
("id", "repositoryGit").attr
("name", "repository").attr
("type", "text")
229 add
("label").attr
("id", "lbbranchGit").text
("Branch")
230 add
("input").attr
("id", "branchGit").attr
("name", "branch").attr
("type", "text")
233 add
("a").attr
("id", "signIn").text
("Sign In")
242 fun content
is abstract
245 add
("footer").text
("Nit standard library. Version jenkins-component=stdlib-19.")
248 # Generate a clickable graphviz image using a dot content
249 fun generate_dot
(dot
: String, name
: String, alt
: String) do
250 if opt_nodot
then return
251 var file
= new OFStream.open
("{self.destinationdir}/{name}.dot")
254 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 ; \}")
255 open
("article").add_class
("graph")
256 add
("img").attr
("src", "{name}.png").attr
("usemap", "#{name}").attr
("style", "margin:auto").attr
("alt", "{alt}")
258 var fmap
= new IFStream.open
("{self.destinationdir}/{name}.map")
259 add_html
(fmap
.read_all
)
263 # Add a (source) link for a given location
264 fun show_source
(l
: Location): String
266 if source
== null then
267 return "({l.file.filename.simplify_path})"
269 # THIS IS JUST UGLY ! (but there is no replace yet)
270 var x
= source
.split_with
("%f")
271 source
= x
.join
(l
.file
.filename
.simplify_path
)
272 x
= source
.split_with
("%l")
273 source
= x
.join
(l
.line_start
.to_s
)
274 x
= source
.split_with
("%L")
275 source
= x
.join
(l
.line_end
.to_s
)
276 return " (<a href=\"{source.to_s}\
">show code</a>)"
286 var mbuilder
: ModelBuilder
288 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
289 # opt_nodot to inform about the graph gen
290 # destination: to know where will be saved dot files
291 init with
(mbuilder
: ModelBuilder, opt_nodot
: Bool, destination
: String) do
292 self.mbuilder
= mbuilder
293 self.opt_nodot
= opt_nodot
294 self.destinationdir
= destination
299 add
("title").text
("Overview | Nit Standard Library")
303 add
("li").add_class
("current").text
("Overview")
305 add_html
("<a href=\"full-index
.html\
">Full Index</a>")
310 open
("div").add_class
("page")
311 open
("div").add_class
("content fullpage")
312 add
("h1").text
("Nit Standard Library")
313 open
("article").add_class
("overview")
314 add_html
("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
316 open
("article").add_class
("overview")
317 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
("a").attr
("href", "{mmodule.name}.html").text
("{mmodule.to_s} ")
336 add_html
(amodule
.short_comment
)
341 fun process_generate_dot
do
343 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")
344 for mmodule
in list_mmodules
do
345 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
346 for imported
in mmodule
.in_importation
.direct_greaters
do
347 if imported
.direct_owner
== null then
348 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
353 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
356 private fun list_mmodules
: Set[MModule] do
357 var mmodules
= new HashSet[MModule]
358 for mmodule
in mbuilder
.model
.mmodules
do
359 var owner
= mmodule
.public_owner
360 if owner
!= null then
363 mmodules
.add
(mmodule
)
370 # The full index page
371 class NitdocFullindex
374 var mmodules
: Array[MModule]
376 init with
(mmodules
: Array[MModule]) do
377 self.mmodules
= mmodules
384 add
("title").text
("Full Index | Nit Standard Library")
389 add_html
("<a href=\"index
.html\
">Overview</a>")
391 add
("li").add_class
("current").text
("Full Index")
395 open
("div").add_class
("page")
396 open
("div").add_class
("content fullpage")
397 add
("h1").text
("Full Index")
405 # Add to content modules column
407 var ls
= new List[nullable MModule]
408 var sorted
= mmodules
409 var sorterp
= new ComparableSorter[MModule]
411 open
("article").add_class
("modules filterable")
412 add
("h2").text
("Modules")
414 for mmodule
in sorted
do
415 if mmodule
.public_owner
!= null and not ls
.has
(mmodule
.public_owner
) then
416 ls
.add
(mmodule
.public_owner
)
418 add
("a").attr
("href", "{mmodule.public_owner.name}.html").text
(mmodule
.public_owner
.name
)
426 # Add to content classes modules
427 fun classes_column
do
428 var sorted
= mmodules
.first
.imported_mclasses
.to_a
429 var sorterp
= new ComparableSorter[MClass]
431 open
("article").add_class
("classes filterable")
432 add
("h2").text
("Classes")
435 for mclass
in sorted
do
437 add
("a").attr
("href", "{mclass.name}.html").text
(mclass
.name
)
445 # Insert the properties column of fullindex page
446 fun properties_column
do
447 open
("article").add_class
("properties filterable")
448 add
("h2").text
("Properties")
450 var sorted_imported
= mmodules
.first
.imported_methods
.to_a
451 var sorted_redef
= mmodules
.first
.redef_methods
.to_a
452 var sorterp
= new ComparableSorter[MProperty]
453 sorterp
.sort
(sorted_imported
)
454 sorterp
.sort
(sorted_redef
)
456 for method
in sorted_imported
do
457 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
458 open
("li").add_class
("intro")
459 add
("span").attr
("title", "introduction").text
("I")
461 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
465 for method
in sorted_redef
do
466 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
467 open
("li").add_class
("redef")
468 add
("span").attr
("title", "redefinition").text
("R")
470 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
485 var mbuilder
: ModelBuilder
487 init with
(mmodule
: MModule, mbuilder
: ModelBuilder) do
488 self.mmodule
= mmodule
489 self.mbuilder
= mbuilder
496 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
497 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
502 add_html
("<a href=\"index
.html\
">Overview</a>")
504 add
("li").add_class
("current").text
(mmodule
.name
)
506 add_html
("<a href=\"full-index
.html\
" >Full Index</a>")
511 open
("div").add_class
("page")
513 open
("div").add_class
("content")
514 add
("h1").text
(mmodule
.name
)
515 add
("div").add_class
("subtitle").text
("module {mmodule.name}")
517 #process_generate_dot
524 # Insert module comment in the content
525 fun module_comment
do
526 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
527 var doc
= amodule
.comment
528 open
("div").attr
("id", "description")
529 add
("pre").add_class
("text_label").text
(doc
)
530 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
531 add
("a").attr
("id", "cancelBtn").text
("Cancel")
532 add
("a").attr
("id", "commitBtn").text
("Commit")
533 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
537 fun process_generate_dot
do
539 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")
540 for m
in mmodule
.in_importation
.smallers
do
541 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
542 for imported
in m
.in_importation
.direct_greaters
do
543 if imported
.direct_owner
== null then
544 op
.append
("\"{m.name}\
"->\"{imported.name}\
";\n")
549 generate_dot
(op
.to_s
, "dep_{mmodule.name}", "Modules hierarchy")
553 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
554 open
("div").add_class
("menu")
556 add
("h3").text
("Module Hierarchy").attr
("style","cursor: pointer;")
557 if mmodule
.in_importation
.greaters
.length
> 0 then
558 add_html
("<h4>All dependencies</h4><ul>")
559 var sorted
= mmodule
.in_importation
.greaters
.to_a
560 var sorter
= new ComparableSorter[MModule]
563 if m
== mmodule
or m
.public_owner
!= null then continue
565 add
("a").attr
("href", "{m.name}.html").text
(m
.name
)
570 if mmodule
.in_importation
.smallers
.length
> 0 then
571 add_html
("<h4>All clients</h4><ul>")
572 var sorted
= mmodule
.in_importation
.smallers
.to_a
573 var sorter
= new ComparableSorter[MModule]
576 if m
== mmodule
or m
.public_owner
!= null then continue
578 add
("a").attr
("href", "{m.name}.html").text
(m
.name
)
584 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
585 var sorted
= mmodule
.in_nesting
.direct_greaters
.to_a
586 var sorter
= new ComparableSorter[MModule]
589 add
("h3").text
("Nested Modules").attr
("style","cursor: pointer;")
593 add
("a").attr
("href", "{m.name}.html").text
(m
.name
)
604 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
605 var intro_mclasses
= mmodule
.intro_mclasses
606 var redef_mclasses
= mmodule
.redef_mclasses
607 var all_mclasses
= new HashSet[MClass]
608 for m
in mmodule
.in_nesting
.greaters
do
609 all_mclasses
.add_all
(m
.intro_mclasses
)
610 all_mclasses
.add_all
(m
.redef_mclasses
)
612 all_mclasses
.add_all
(intro_mclasses
)
613 all_mclasses
.add_all
(redef_mclasses
)
615 var sorted
= new Array[MClass]
616 sorted
.add_all
(all_mclasses
)
617 var sorter
= new ComparableSorter[MClass]
619 open
("div").add_class
("module")
620 open
("article").add_class
("classes filterable")
621 add
("h2").text
("Classes")
625 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
626 open
("li").add_class
("redef")
627 add
("span").attr
("title", "refined in this module").text
("R ")
629 open
("li").add_class
("intro")
630 add
("span").attr
("title", "introduced in this module").text
("I ")
632 add
("a").attr
("href", "{name}.html").text
(name
)
641 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
642 var mpropdefs
= new HashSet[MPropDef]
643 for m
in mmodule
.in_nesting
.greaters
do
644 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
646 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
647 var sorted
= mpropdefs
.to_a
648 var sorter
= new ComparableSorter[MPropDef]
650 open
("article").add_class
("properties filterable")
651 add_html
("<h2>Properties</h2>")
654 if p
.mproperty
.visibility
<= none_visibility
then continue
656 open
("li").add_class
("intro")
657 add
("span").attr
("title", "introduction").text
("I")
659 open
("li").add_class
("redef")
660 add
("span").attr
("title", "redefinition").text
("R")
663 add
("a").attr
("href", "{p.mclassdef.mclass.name}.html").attr
("title", "").text
("{p.mproperty.name} ({p.mclassdef.mclass.name})")
676 var mbuilder
: ModelBuilder
678 init with
(mclass
: MClass, mbuilder
: ModelBuilder, source
: nullable String) do
680 self.mbuilder
= mbuilder
681 self.opt_nodot
= false
682 self.destinationdir
= ""
688 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
689 if nclass
isa AStdClassdef then
690 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
692 add
("title").text
("{mclass.name} class")
698 add_html
("<a href=\"index
.html\
">Overview</a>")
701 var public_owner
= mclass
.public_owner
702 if public_owner
is null then
703 add_html
("<a href=\"{mclass.intro_mmodule.name}.html\
">{mclass.intro_mmodule.name}</a>")
705 add_html
("<a href=\"{public_owner.name}.html\
">{public_owner.name}</a>")
708 add
("li").add_class
("current").text
(mclass
.name
)
710 add_html
("<a href=\"full-index
.html\
" >Full Index</a>")
715 open
("div").add_class
("page")
716 open
("div").add_class
("menu")
720 open
("div").add_class
("content")
726 fun properties_column
do
727 var sorted
= new Array[MProperty]
728 var sorter
= new ComparableSorter[MProperty]
729 open
("nav").add_class
("properties filterable")
730 add
("h3").text
("Properties")
732 if mclass
.virtual_types
.length
> 0 then
733 add
("h4").text
("Virtual Types")
735 sorted
= mclass
.virtual_types
.to_a
737 for prop
in sorted
do
738 add_html
("<li class=\"redef\
"><span title=\"Redefined\
">R</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
742 if mclass
.constructors
.length
> 0 then
743 sorted
= mclass
.constructors
.to_a
745 add
("h4").text
("Constructors")
747 for prop
in sorted
do
748 add_html
("<li class=\"intro\
"><span title=\"Introduced\
">I</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
752 add
("h4").text
("Methods")
754 var mmethods
= new HashSet[MMethod]
755 var redef_methods
= mclass
.redef_methods
756 mmethods
.add_all
(mclass
.intro_methods
)
757 mmethods
.add_all
(mclass
.inherited_methods
)
758 mmethods
.add_all
(redef_methods
)
759 sorted
= mmethods
.to_a
761 for prop
in sorted
do
762 if prop
.visibility
<= none_visibility
then continue
763 if prop
.intro_mclassdef
.mclass
== mclass
then
764 add_html
("<li class=\"intro\
"><span title=\"Introduced\
">I</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
765 else if redef_methods
.has
(prop
) then
766 add_html
("<li class=\"redef\
"><span title=\"Refined\
">R</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
768 add_html
("<li class=\"inherit\
"><span title=\"Inherited\
">H</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
775 fun inheritance_column
do
776 var sorted
= new Array[MClass]
777 var sorterp
= new ComparableSorter[MClass]
779 add
("h3").text
("Inheritance")
780 if mclass
.ancestors
.length
> 1 then
781 sorted
= mclass
.ancestors
.to_a
783 add
("h4").text
("Superclasses")
786 if sup
== mclass
then continue
787 add_html
("<li><a href=\"{sup.name}.html\
">{sup.name}</a></li>")
792 if mclass
.descendants
.length
<= 1 then
793 add
("h4").text
("No Known Subclasses")
794 else if mclass
.descendants
.length
<= 100 then
795 sorted
= mclass
.descendants
.to_a
797 add
("h4").text
("Subclasses")
800 if sub
== mclass
then continue
801 add_html
("<li><a href=\"{sub.name}\
">{sub.name}</a></li>")
804 else if mclass
.children
.length
<= 100 then
805 sorted
= mclass
.children
.to_a
807 add
("h4").text
("Direct Subclasses Only")
810 if sub
== mclass
then continue
811 add_html
("<li><a href=\"{sub.name}\
">{sub.name}</a></li>")
815 add
("h4").text
("Too much Subclasses to list")
821 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
822 var sorted
= new Array[MModule]
823 sorted
.add_all
(mclass
.concerns
.keys
)
824 var sorterp
= new ComparableSorter[MModule]
825 var sorterprop
= new ComparableSorter[MProperty]
826 var sorterc
= new ComparableSorter[MClass]
829 var lmmodule
= new List[MModule]
830 # Insert the subtitle part
831 add
("h1").text
(mclass
.name
)
832 open
("div").add_class
("subtitle")
833 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
834 subtitle
+= "{mclass.kind} <a href=\"{mclass.public_owner.name}.html\
">{mclass.public_owner.name}</a>::{mclass.name}"
837 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
838 # We add the class description
839 open
("section").add_class
("description")
840 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>")
842 open
("section").add_class
("concerns")
843 add
("h2").add_class
("section-header").text
("Concerns")
845 for owner
in sorted
do
846 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
847 var childs
= mclass
.concerns
[owner
]
849 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
850 if not childs
is null then
852 var sortedc
= childs
.to_a
853 var sorterpc
= new ComparableSorter[MModule]
854 sorterpc
.sort
(sortedc
)
855 for child
in sortedc
do
856 var nchild
= mbuilder
.mmodule2nmodule
[child
]
857 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
865 # Insert virtual types if there is almost one
866 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
867 open
("section").add_class
("types")
868 add
("h2").text
("Formal and Virtual Types")
869 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
870 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
871 for prop
in nclass
.n_formaldefs
do
872 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
873 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
874 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
876 add_html
("<div class=\"info\
">formal generic type</div>")
882 # Insert constructors if there is almost one
883 if mclass
.constructors
.length
> 0 then
884 var sortedc
= mclass
.constructors
.to_a
885 sorterprop
.sort
(sortedc
)
886 open
("section").add_class
("constructors")
887 add
("h2").add_class
("section-header").text
("Constructors")
888 for prop
in sortedc
do description
(prop
)
891 open
("section").add_class
("methods")
892 add
("h2").add_class
("section-header").text
("Methods")
893 for mmodule
, mmethods
in mclass
.all_methods
do
894 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
895 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
896 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
897 if mclass
.has_mmodule
(mmodule
) then
898 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
900 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in <a href=\"{mmodule.name}.html\
">{mmodule.name}</a></h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
903 var sortedc
= mmethods
.to_a
904 sorterprop
.sort
(sortedc
)
905 for prop
in sortedc
do description
(prop
)
907 # Insert inherited methods
908 if mclass
.inherited_methods
.length
> 0 then
909 var sortedc
= new Array[MClass]
910 sortedc
.add_all
(mclass
.inherited
.keys
)
911 sorterc
.sort
(sortedc
)
912 add
("h3").text
("Inherited Methods")
913 for i_mclass
in sortedc
do
914 var sortedp
= mclass
.inherited
[i_mclass
].to_a
915 sorterprop
.sort
(sortedp
)
917 add_html
("Defined in <a href=\"{i_mclass.name}.html\
">{i_mclass.name}</a>: ")
918 for method
in sortedp
do
919 add_html
("<a href=\"{method.link_anchor}\
">{method.name}</a>")
920 if method
!= sortedp
.last
then add_html
(", ")
928 # Insert description tags for 'prop'
929 fun description
(prop
: MProperty) do
930 open
("article").add_class
("fun public {if prop.is_redef then "redef" else ""}").attr
("id", "{prop.anchor}")
932 if prop
.apropdef
!= null then sign
+= prop
.apropdef
.signature
933 add_html
("<h3 class=\"signature\
">{sign}</h3>")
934 add_html
("<div class=\"info\
">{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}</div><div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
936 open
("div").add_class
("description")
937 if prop
.apropdef
is null or prop
.apropdef
.comment
== "" then
938 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
940 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{prop.apropdef.comment}</pre>")
942 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>")
944 if prop
.local_class
!= mclass
then add_html
("inherited from {prop.local_class.intro_mmodule.name} ")
945 #TODO display show code if doc github
946 add_html
("defined by the module <a href=\"{prop.intro_mclassdef.mmodule.name}.html\
">{prop.intro_mclassdef.mmodule.name}</a> {if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
948 for parent
in mclass
.parents
do
949 if prop
isa MMethod then if parent
.constructors
.has
(prop
) then add_html
(" Previously defined by: <a href=\"{parent.intro_mmodule.name}.html\
">{parent.intro_mmodule.name}</a> for <a href=\"{parent.name}.html\
">{parent.name}</a>.")
960 private fun comment
: String do
962 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
963 if n_moduledecl
.n_doc
is null then return ""
964 for t
in n_moduledecl
.n_doc
.n_comment
do
966 txt
= txt
.replace
("# ", "")
967 txt
= txt
.replace
("#", "")
973 private fun short_comment
: String do
975 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
976 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
977 txt
= txt
.replace
("# ", "")
978 txt
= txt
.replace
("\n", "")
987 redef type OTHER: MModule
988 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
990 var amodule
: nullable AModule
992 # Get the list of all methods in a module
993 fun imported_methods
: Set[MMethod] do
994 var methods
= new HashSet[MMethod]
995 for mclass
in imported_mclasses
do
996 for method
in mclass
.intro_methods
do
1003 # Get the list aof all refined methods in a module
1004 fun redef_methods
: Set[MMethod] do
1005 var methods
= new HashSet[MMethod]
1006 for mclass
in redef_mclasses
do
1007 for method
in mclass
.intro_methods
do
1014 redef class MPropDef
1016 redef type OTHER: MPropDef
1017 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1020 redef class MProperty
1022 redef type OTHER: MProperty
1023 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1026 var apropdef
: nullable APropdef
1028 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1034 fun local_class
: MClass do
1035 var classdef
= self.intro_mclassdef
1036 return classdef
.mclass
1039 fun class_text
: String do
1040 return local_class
.name
1043 fun link_anchor
: String do
1044 return "{class_text}.html#{anchor}"
1047 fun anchor
: String do
1048 return "PROP_{c_name}"
1055 redef type OTHER: MClass
1056 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1058 # Associate all MMethods to each MModule concerns
1059 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1060 var hm
= new HashMap[MModule, Set[MMethod]]
1061 for mmodule
, childs
in concerns
do
1062 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1063 for prop
in intro_methods
do
1064 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1065 prop
.is_redef
= false
1066 hm
[mmodule
].add
(prop
)
1069 for prop
in redef_methods
do
1070 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1071 prop
.is_redef
= true
1072 hm
[mmodule
].add
(prop
)
1076 if childs
!= null then
1077 for child
in childs
do
1078 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1079 for prop
in intro_methods
do
1080 if child
== prop
.intro_mclassdef
.mmodule
then
1081 prop
.is_redef
= false
1085 for prop
in redef_methods
do
1086 if child
== prop
.intro_mclassdef
.mmodule
then
1087 prop
.is_redef
= true
1097 fun public_owner
: MModule do
1098 var owner
= intro_mmodule
1099 if owner
.public_owner
is null then
1102 return owner
.public_owner
.as(not null)
1106 # Associate Amodule to all MModule concern by 'self'
1107 fun amodule
(amodules
: HashMap[MModule, AModule]) do
1108 for owner
, childs
in concerns
do
1109 if childs
!= null then for child
in childs
do child
.amodule
= amodules
[child
]
1110 owner
.amodule
= amodules
[owner
]
1114 # Associate MClass to all MMethod include in 'inherited_methods'
1115 fun inherited
: HashMap[MClass, Set[MMethod]] do
1116 var hm
= new HashMap[MClass, Set[MMethod]]
1117 for method
in inherited_methods
do
1118 var mclass
= method
.intro_mclassdef
.mclass
1119 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1120 hm
[mclass
].add
(method
)
1125 # Return true if MModule concern contain subMModule
1126 fun has_mmodule
(sub
: MModule): Bool do
1127 for mmodule
, childs
in concerns
do
1128 if childs
is null then continue
1129 if childs
.has
(sub
) then return true
1134 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1135 for const
in constructors
do
1136 if mprop2npropdef
.has_key
(const
)then
1137 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1141 for intro
in intro_methods
do
1142 if mprop2npropdef
.has_key
(intro
)then
1143 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1147 for rd
in redef_methods
do
1148 if mprop2npropdef
.has_key
(rd
)then
1149 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1154 fun link_anchor
: String do
1155 return "{name}.html"
1160 redef class AStdClassdef
1161 private fun comment
: String do
1163 if n_doc
!= null then
1164 for t
in n_doc
.n_comment
do
1165 var txt
= t
.text
.replace
("# ", "")
1166 txt
= txt
.replace
("#", "")
1173 private fun short_comment
: String do
1175 if n_doc
!= null then
1176 var txt
= n_doc
.n_comment
.first
.text
1177 txt
= txt
.replace
("# ", "")
1178 txt
= txt
.replace
("\n", "")
1185 redef class ASignature
1189 if not n_params
.is_empty
then
1190 ret
= "{ret}({n_params.join(", ")})"
1192 if n_type
!= null and n_type
.to_s
!= "" then ret
+= " {n_type.to_s}"
1199 var ret
= "{n_id.text}"
1200 if n_type
!= null then
1201 ret
= "{ret}: {n_type.to_s}"
1202 if n_dotdotdot
!= null then ret
= "{ret}..."
1210 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1211 if n_kwnullable
!= null then ret
= "nullable {ret}"
1212 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1217 redef class APropdef
1218 private fun short_comment
: String is abstract
1219 private fun signature
: String is abstract
1220 private fun comment
: String is abstract
1223 redef class AAttrPropdef
1224 redef fun short_comment
do
1226 if n_doc
!= null then
1227 var txt
= n_doc
.n_comment
.first
.text
1228 txt
= txt
.replace
("# ", "")
1229 txt
= txt
.replace
("\n", "")
1236 redef class AMethPropdef
1237 redef fun short_comment
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", "")
1248 redef fun signature
: String do
1250 if n_signature
!= null then sign
= " {n_signature.to_s}"
1254 redef private fun comment
: String do
1256 if n_doc
!= null then
1257 for t
in n_doc
.n_comment
do
1258 var txt
= t
.text
.replace
("# ", "")
1259 txt
= txt
.replace
("#", "")
1267 redef class MClassDef
1268 private fun namespace
(mclass
: MClass): String do
1270 if mmodule
.public_owner
is null then
1271 return "{mmodule.full_name}::{mclass.name}"
1272 else if mclass
is self.mclass
then
1273 return "{mmodule.public_owner.name}::{mclass.name}"
1275 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1282 return to_a
[length-1
]
1286 # Create a tool context to handle options and paths
1287 var toolcontext
= new ToolContext
1289 # Here we launch the nit index
1290 var nitdoc
= new Nitdoc(toolcontext
)