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_html
(mmodule
.link
(amodule
))
337 add_html
(amodule
.short_comment
)
342 fun process_generate_dot
do
344 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")
345 for mmodule
in list_mmodules
do
346 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.name}.html\
"];\n")
347 for imported
in mmodule
.in_importation
.direct_greaters
do
348 if imported
.direct_owner
== null then
349 op
.append
("\"{mmodule.name}\
"->\"{imported.name}\
";\n")
354 generate_dot
(op
.to_s
, "dep", "Modules hierarchy")
357 private fun list_mmodules
: Set[MModule] do
358 var mmodules
= new HashSet[MModule]
359 for mmodule
in mbuilder
.model
.mmodules
do
360 var owner
= mmodule
.public_owner
361 if owner
!= null then
364 mmodules
.add
(mmodule
)
371 # The full index page
372 class NitdocFullindex
375 var mmodules
: Array[MModule]
377 init with
(mmodules
: Array[MModule]) do
378 self.mmodules
= mmodules
385 add
("title").text
("Full Index | Nit Standard Library")
390 add_html
("<a href=\"index
.html\
">Overview</a>")
392 add
("li").add_class
("current").text
("Full Index")
396 open
("div").add_class
("page")
397 open
("div").add_class
("content fullpage")
398 add
("h1").text
("Full Index")
406 # Add to content modules column
408 var ls
= new List[nullable MModule]
409 var sorted
= mmodules
410 var sorterp
= new ComparableSorter[MModule]
412 open
("article").add_class
("modules filterable")
413 add
("h2").text
("Modules")
415 for mmodule
in sorted
do
416 if mmodule
.public_owner
!= null and not ls
.has
(mmodule
.public_owner
) then
417 ls
.add
(mmodule
.public_owner
)
419 add
("a").attr
("href", "{mmodule.public_owner.name}.html").text
(mmodule
.public_owner
.name
)
427 # Add to content classes modules
428 fun classes_column
do
429 var sorted
= mmodules
.first
.imported_mclasses
.to_a
430 var sorterp
= new ComparableSorter[MClass]
432 open
("article").add_class
("classes filterable")
433 add
("h2").text
("Classes")
436 for mclass
in sorted
do
438 add
("a").attr
("href", "{mclass}.html").text
(mclass
.name
)
446 # Insert the properties column of fullindex page
447 fun properties_column
do
448 open
("article").add_class
("properties filterable")
449 add
("h2").text
("Properties")
451 var sorted_imported
= mmodules
.first
.imported_methods
.to_a
452 var sorted_redef
= mmodules
.first
.redef_methods
.to_a
453 var sorterp
= new ComparableSorter[MProperty]
454 sorterp
.sort
(sorted_imported
)
455 sorterp
.sort
(sorted_redef
)
457 for method
in sorted_imported
do
458 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
459 open
("li").add_class
("intro")
460 add
("span").attr
("title", "introduction").text
("I")
462 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
466 for method
in sorted_redef
do
467 if method
.visibility
is none_visibility
or method
.visibility
is intrude_visibility
then continue
468 open
("li").add_class
("redef")
469 add
("span").attr
("title", "redefinition").text
("R")
471 add
("a").attr
("href", "{method.local_class.name}.html").attr
("title", "").text
("{method.name} ({method.local_class.name})")
486 var mbuilder
: ModelBuilder
488 init with
(mmodule
: MModule, mbuilder
: ModelBuilder) do
489 self.mmodule
= mmodule
490 self.mbuilder
= mbuilder
497 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
498 add
("title").text
("{mmodule.name} module | {amodule.short_comment}")
503 add_html
("<a href=\"index
.html\
">Overview</a>")
505 add
("li").add_class
("current").text
(mmodule
.name
)
507 add_html
("<a href=\"full-index
.html\
" >Full Index</a>")
512 open
("div").add_class
("page")
514 open
("div").add_class
("content")
515 add
("h1").text
(mmodule
.name
)
516 add
("div").add_class
("subtitle").text
("module {mmodule.name}")
518 #process_generate_dot
525 # Insert module comment in the content
526 fun module_comment
do
527 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
528 var doc
= amodule
.comment
529 open
("div").attr
("id", "description")
530 add
("pre").add_class
("text_label").text
(doc
)
531 add
("textarea").add_class
("edit").attr
("rows", "1").attr
("cols", "76").attr
("id", "fileContent").text
(" ")
532 add
("a").attr
("id", "cancelBtn").text
("Cancel")
533 add
("a").attr
("id", "commitBtn").text
("Commit")
534 add
("pre").add_class
("text_label").attr
("id", "preSave").attr
("type", "2")
538 fun process_generate_dot
do
540 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")
541 for m
in mmodule
.in_importation
.smallers
do
542 op
.append
("\"{m.name}\
"[URL=\"{m.name}.html\
"];\n")
543 for imported
in m
.in_importation
.direct_greaters
do
544 if imported
.direct_owner
== null then
545 op
.append
("\"{m.name}\
"->\"{imported.name}\
";\n")
550 generate_dot
(op
.to_s
, "dep_{mmodule.name}", "Modules hierarchy")
554 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
555 open
("div").add_class
("menu")
557 add
("h3").text
("Module Hierarchy").attr
("style","cursor: pointer;")
558 if mmodule
.in_importation
.greaters
.length
> 0 then
559 add_html
("<h4>All dependencies</h4><ul>")
560 var sorted
= mmodule
.in_importation
.greaters
.to_a
561 var sorter
= new ComparableSorter[MModule]
564 if m
== mmodule
or m
.public_owner
!= null then continue
565 var am
= mbuilder
.mmodule2nmodule
[m
]
572 if mmodule
.in_importation
.smallers
.length
> 0 then
573 add_html
("<h4>All clients</h4><ul>")
574 var sorted
= mmodule
.in_importation
.smallers
.to_a
575 var sorter
= new ComparableSorter[MModule]
578 if m
== mmodule
or m
.public_owner
!= null then continue
579 var am
= mbuilder
.mmodule2nmodule
[m
]
587 if mmodule
.in_nesting
.direct_greaters
.length
> 0 then
588 var sorted
= mmodule
.in_nesting
.direct_greaters
.to_a
589 var sorter
= new ComparableSorter[MModule]
592 add
("h3").text
("Nested Modules").attr
("style","cursor: pointer;")
595 var am
= mbuilder
.mmodule2nmodule
[m
]
607 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
608 var intro_mclasses
= mmodule
.intro_mclasses
609 var redef_mclasses
= mmodule
.redef_mclasses
610 var all_mclasses
= new HashSet[MClass]
611 for m
in mmodule
.in_nesting
.greaters
do
612 all_mclasses
.add_all
(m
.intro_mclasses
)
613 all_mclasses
.add_all
(m
.redef_mclasses
)
615 all_mclasses
.add_all
(intro_mclasses
)
616 all_mclasses
.add_all
(redef_mclasses
)
618 var sorted
= new Array[MClass]
619 sorted
.add_all
(all_mclasses
)
620 var sorter
= new ComparableSorter[MClass]
622 open
("div").add_class
("module")
623 open
("article").add_class
("classes filterable")
624 add
("h2").text
("Classes")
627 var nclass
= mbuilder
.mclassdef2nclassdef
[c
.intro
].as(AStdClassdef)
628 if redef_mclasses
.has
(c
) and c
.intro_mmodule
.public_owner
!= mmodule
then
629 open
("li").add_class
("redef")
630 add
("span").attr
("title", "refined in this module").text
("R ")
632 open
("li").add_class
("intro")
633 add
("span").attr
("title", "introduced in this module").text
("I ")
635 add_html
(c
.link
(nclass
))
644 var amodule
= mbuilder
.mmodule2nmodule
[mmodule
]
645 var mpropdefs
= new HashSet[MPropDef]
646 for m
in mmodule
.in_nesting
.greaters
do
647 for c
in m
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
649 for c
in mmodule
.mclassdefs
do mpropdefs
.add_all
(c
.mpropdefs
)
650 var sorted
= mpropdefs
.to_a
651 var sorter
= new ComparableSorter[MPropDef]
653 open
("article").add_class
("properties filterable")
654 add_html
("<h2>Properties</h2>")
657 if p
.mproperty
.visibility
<= none_visibility
then continue
659 open
("li").add_class
("intro")
660 add
("span").attr
("title", "introduction").text
("I")
662 open
("li").add_class
("redef")
663 add
("span").attr
("title", "redefinition").text
("R")
666 add
("a").attr
("href", "{p.mclassdef.mclass.name}.html").attr
("title", "").text
("{p.mproperty.name} ({p.mclassdef.mclass.name})")
679 var mbuilder
: ModelBuilder
681 init with
(mclass
: MClass, mbuilder
: ModelBuilder, source
: nullable String) do
683 self.mbuilder
= mbuilder
684 self.opt_nodot
= false
685 self.destinationdir
= ""
691 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
692 if nclass
isa AStdClassdef then
693 add
("title").text
("{mclass.name} class | {nclass.short_comment}")
695 add
("title").text
("{mclass.name} class")
701 add_html
("<a href=\"index
.html\
">Overview</a>")
704 var public_owner
= mclass
.public_owner
705 if public_owner
is null then
706 var am
= mbuilder
.mmodule2nmodule
[mclass
.intro_mmodule
]
707 add_html
(mclass
.intro_mmodule
.link
(am
))
709 var am
= mbuilder
.mmodule2nmodule
[public_owner
]
710 add_html
(public_owner
.link
(am
))
713 add
("li").add_class
("current").text
(mclass
.name
)
715 add_html
("<a href=\"full-index
.html\
" >Full Index</a>")
720 open
("div").add_class
("page")
721 open
("div").add_class
("menu")
725 open
("div").add_class
("content")
731 fun properties_column
do
732 var sorted
= new Array[MProperty]
733 var sorter
= new ComparableSorter[MProperty]
734 open
("nav").add_class
("properties filterable")
735 add
("h3").text
("Properties")
737 if mclass
.virtual_types
.length
> 0 then
738 add
("h4").text
("Virtual Types")
740 sorted
= mclass
.virtual_types
.to_a
742 for prop
in sorted
do
743 add_html
("<li class=\"redef\
"><span title=\"Redefined\
">R</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
747 if mclass
.constructors
.length
> 0 then
748 sorted
= mclass
.constructors
.to_a
750 add
("h4").text
("Constructors")
752 for prop
in sorted
do
753 add_html
("<li class=\"intro\
"><span title=\"Introduced\
">I</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
757 add
("h4").text
("Methods")
759 var mmethods
= new HashSet[MMethod]
760 var redef_methods
= mclass
.redef_methods
761 mmethods
.add_all
(mclass
.intro_methods
)
762 mmethods
.add_all
(mclass
.inherited_methods
)
763 mmethods
.add_all
(redef_methods
)
764 sorted
= mmethods
.to_a
766 for prop
in sorted
do
767 if prop
.visibility
<= none_visibility
then continue
768 if prop
.intro_mclassdef
.mclass
== mclass
then
769 add_html
("<li class=\"intro\
"><span title=\"Introduced\
">I</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
770 else if redef_methods
.has
(prop
) then
771 add_html
("<li class=\"redef\
"><span title=\"Refined\
">R</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
773 add_html
("<li class=\"inherit\
"><span title=\"Inherited\
">H</span><a href=\"{prop.link_anchor}\
">{prop.name}</a></li>")
780 fun inheritance_column
do
781 var sorted
= new Array[MClass]
782 var sorterp
= new ComparableSorter[MClass]
784 add
("h3").text
("Inheritance")
785 if mclass
.ancestors
.length
> 1 then
786 sorted
= mclass
.ancestors
.to_a
788 add
("h4").text
("Superclasses")
791 if sup
== mclass
then continue
792 add_html
("<li><a href=\"{sup.name}.html\
">{sup.name}</a></li>")
797 if mclass
.descendants
.length
<= 1 then
798 add
("h4").text
("No Known Subclasses")
799 else if mclass
.descendants
.length
<= 100 then
800 sorted
= mclass
.descendants
.to_a
802 add
("h4").text
("Subclasses")
805 if sub
== mclass
then continue
806 add_html
("<li><a href=\"{sub.name}\
">{sub.name}</a></li>")
809 else if mclass
.children
.length
<= 100 then
810 sorted
= mclass
.children
.to_a
812 add
("h4").text
("Direct Subclasses Only")
815 if sub
== mclass
then continue
816 add_html
("<li><a href=\"{sub.name}\
">{sub.name}</a></li>")
820 add
("h4").text
("Too much Subclasses to list")
826 var nclass
= mbuilder
.mclassdef2nclassdef
[mclass
.intro
]
827 var sorted
= new Array[MModule]
828 sorted
.add_all
(mclass
.concerns
.keys
)
829 var sorterp
= new ComparableSorter[MModule]
830 var sorterprop
= new ComparableSorter[MProperty]
831 var sorterc
= new ComparableSorter[MClass]
834 var lmmodule
= new List[MModule]
835 # Insert the subtitle part
836 add
("h1").text
(mclass
.to_s
)
837 open
("div").add_class
("subtitle")
838 if mclass
.visibility
is none_visibility
then subtitle
+= "private "
839 var nowner
= mbuilder
.mmodule2nmodule
[mclass
.public_owner
]
840 subtitle
+= "{mclass.kind} {mclass.public_owner.link(nowner)}::{mclass}"
843 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
844 # We add the class description
845 open
("section").add_class
("description")
846 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>")
848 open
("section").add_class
("concerns")
849 add
("h2").add_class
("section-header").text
("Concerns")
851 for owner
in sorted
do
852 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
853 var childs
= mclass
.concerns
[owner
]
855 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
856 if not childs
is null then
858 var sortedc
= childs
.to_a
859 var sorterpc
= new ComparableSorter[MModule]
860 sorterpc
.sort
(sortedc
)
861 for child
in sortedc
do
862 var nchild
= mbuilder
.mmodule2nmodule
[child
]
863 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
871 # Insert virtual types if there is almost one
872 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
873 open
("section").add_class
("types")
874 add
("h2").text
("Formal and Virtual Types")
875 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
876 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
877 for prop
in nclass
.n_formaldefs
do
878 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
879 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
880 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
882 add_html
("<div class=\"info\
">formal generic type</div>")
888 # Insert constructors if there is almost one
889 if mclass
.constructors
.length
> 0 then
890 var sortedc
= mclass
.constructors
.to_a
891 sorterprop
.sort
(sortedc
)
892 open
("section").add_class
("constructors")
893 add
("h2").add_class
("section-header").text
("Constructors")
894 for prop
in sortedc
do description
(prop
)
897 open
("section").add_class
("methods")
898 add
("h2").add_class
("section-header").text
("Methods")
899 for mmodule
, mmethods
in mclass
.all_methods
do
900 var nmodule
= mbuilder
.mmodule2nmodule
[mmodule
]
901 add_html
("<a id=\"MOD_{mmodule.name}\
"></a>")
902 if mmodule
!= mclass
.intro_mmodule
and mmodule
!= mclass
.public_owner
then
903 if mclass
.has_mmodule
(mmodule
) then
904 add_html
("<p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
906 add_html
("<h3 class=\"concern-toplevel\
">Methods refined in {mmodule.link(nmodule)}</h3><p class=\"concern-doc\
">{mmodule.name}: {nmodule.short_comment}</p>")
909 var sortedc
= mmethods
.to_a
910 sorterprop
.sort
(sortedc
)
911 for prop
in sortedc
do description
(prop
)
913 # Insert inherited methods
914 if mclass
.inherited_methods
.length
> 0 then
915 var sortedc
= new Array[MClass]
916 sortedc
.add_all
(mclass
.inherited
.keys
)
917 sorterc
.sort
(sortedc
)
918 add
("h3").text
("Inherited Methods")
919 for imclass
in sortedc
do
920 var inclass
= mbuilder
.mclassdef2nclassdef
[imclass
.intro
].as(AStdClassdef)
921 var sortedp
= mclass
.inherited
[imclass
].to_a
922 sorterprop
.sort
(sortedp
)
924 add_html
("Defined in {imclass.link(inclass)}: ")
925 for method
in sortedp
do
926 add_html
("<a href=\"{method.link_anchor}\
">{method.name}</a>")
927 if method
!= sortedp
.last
then add_html
(", ")
935 # Insert description tags for 'prop'
936 fun description
(prop
: MProperty) do
937 open
("article").add_class
("fun public {if prop.is_redef then "redef" else ""}").attr
("id", "{prop.anchor}")
939 if prop
.apropdef
!= null then sign
+= prop
.apropdef
.signature
940 add_html
("<h3 class=\"signature\
">{sign}</h3>")
941 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>")
943 open
("div").add_class
("description")
944 if prop
.apropdef
is null or prop
.apropdef
.comment
== "" then
945 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
947 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{prop.apropdef.comment}</pre>")
949 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>")
951 if prop
.local_class
!= mclass
then
952 var mredef
= prop
.local_class
.intro_mmodule
953 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
954 add_html
("inherited from {mredef.link(nredef)} ")
956 #TODO display show code if doc github
957 var mintro
= prop
.intro_mclassdef
.mmodule
958 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
959 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
961 for parent
in mclass
.parents
do
962 var mparent
= parent
.intro_mmodule
963 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
964 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>.")
975 private fun comment
: String do
977 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
978 if n_moduledecl
.n_doc
is null then return ""
979 for t
in n_moduledecl
.n_doc
.n_comment
do
981 txt
= txt
.replace
("# ", "")
982 txt
= txt
.replace
("#", "")
988 private fun short_comment
: String do
990 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
991 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
992 txt
= txt
.replace
("# ", "")
993 txt
= txt
.replace
("\n", "")
1002 redef type OTHER: MModule
1003 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1005 # Get the list of all methods in a module
1006 fun imported_methods
: Set[MMethod] do
1007 var methods
= new HashSet[MMethod]
1008 for mclass
in imported_mclasses
do
1009 for method
in mclass
.intro_methods
do
1016 # Get the list aof all refined methods in a module
1017 fun redef_methods
: Set[MMethod] do
1018 var methods
= new HashSet[MMethod]
1019 for mclass
in redef_mclasses
do
1020 for method
in mclass
.intro_methods
do
1027 # Return a link (html a tag) to the nitdoc module page
1028 fun link
(amodule
: AModule): String do
1029 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1032 redef class MPropDef
1034 redef type OTHER: MPropDef
1035 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1038 redef class MProperty
1040 redef type OTHER: MProperty
1041 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1044 var apropdef
: nullable APropdef
1046 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1052 fun local_class
: MClass do
1053 var classdef
= self.intro_mclassdef
1054 return classdef
.mclass
1057 fun class_text
: String do
1058 return local_class
.name
1061 fun link_anchor
: String do
1062 return "{class_text}.html#{anchor}"
1065 fun anchor
: String do
1066 return "PROP_{c_name}"
1073 redef type OTHER: MClass
1074 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1076 # Add type parameters
1079 return "{name}[{intro.parameter_names.join(", ")}]"
1085 # Return a link (html a tag) to the nitdoc class page
1086 fun link
(aclass
: AStdClassdef): String do
1087 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1090 # Associate all MMethods to each MModule concerns
1091 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1092 var hm
= new HashMap[MModule, Set[MMethod]]
1093 for mmodule
, childs
in concerns
do
1094 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1095 for prop
in intro_methods
do
1096 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1097 prop
.is_redef
= false
1098 hm
[mmodule
].add
(prop
)
1101 for prop
in redef_methods
do
1102 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1103 prop
.is_redef
= true
1104 hm
[mmodule
].add
(prop
)
1108 if childs
!= null then
1109 for child
in childs
do
1110 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1111 for prop
in intro_methods
do
1112 if child
== prop
.intro_mclassdef
.mmodule
then
1113 prop
.is_redef
= false
1117 for prop
in redef_methods
do
1118 if child
== prop
.intro_mclassdef
.mmodule
then
1119 prop
.is_redef
= true
1129 fun public_owner
: MModule do
1130 var owner
= intro_mmodule
1131 if owner
.public_owner
is null then
1134 return owner
.public_owner
.as(not null)
1138 # Associate MClass to all MMethod include in 'inherited_methods'
1139 fun inherited
: HashMap[MClass, Set[MMethod]] do
1140 var hm
= new HashMap[MClass, Set[MMethod]]
1141 for method
in inherited_methods
do
1142 var mclass
= method
.intro_mclassdef
.mclass
1143 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1144 hm
[mclass
].add
(method
)
1149 # Return true if MModule concern contain subMModule
1150 fun has_mmodule
(sub
: MModule): Bool do
1151 for mmodule
, childs
in concerns
do
1152 if childs
is null then continue
1153 if childs
.has
(sub
) then return true
1158 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1159 for const
in constructors
do
1160 if mprop2npropdef
.has_key
(const
)then
1161 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1165 for intro
in intro_methods
do
1166 if mprop2npropdef
.has_key
(intro
)then
1167 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1171 for rd
in redef_methods
do
1172 if mprop2npropdef
.has_key
(rd
)then
1173 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1178 fun link_anchor
: String do
1179 return "{name}.html"
1184 redef class AStdClassdef
1185 private fun comment
: String do
1187 if n_doc
!= null then
1188 for t
in n_doc
.n_comment
do
1189 var txt
= t
.text
.replace
("# ", "")
1190 txt
= txt
.replace
("#", "")
1197 private fun short_comment
: String do
1199 if n_doc
!= null then
1200 var txt
= n_doc
.n_comment
.first
.text
1201 txt
= txt
.replace
("# ", "")
1202 txt
= txt
.replace
("\n", "")
1209 redef class ASignature
1213 if not n_params
.is_empty
then
1214 ret
= "{ret}({n_params.join(", ")})"
1216 if n_type
!= null and n_type
.to_s
!= "" then ret
+= " {n_type.to_s}"
1223 var ret
= "{n_id.text}"
1224 if n_type
!= null then
1225 ret
= "{ret}: {n_type.to_s}"
1226 if n_dotdotdot
!= null then ret
= "{ret}..."
1234 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1235 if n_kwnullable
!= null then ret
= "nullable {ret}"
1236 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1241 redef class APropdef
1242 private fun short_comment
: String is abstract
1243 private fun signature
: String is abstract
1244 private fun comment
: String is abstract
1247 redef class AAttrPropdef
1248 redef fun short_comment
do
1250 if n_doc
!= null then
1251 var txt
= n_doc
.n_comment
.first
.text
1252 txt
= txt
.replace
("# ", "")
1253 txt
= txt
.replace
("\n", "")
1260 redef class AMethPropdef
1261 redef fun short_comment
do
1263 if n_doc
!= null then
1264 var txt
= n_doc
.n_comment
.first
.text
1265 txt
= txt
.replace
("# ", "")
1266 txt
= txt
.replace
("\n", "")
1272 redef fun signature
: String do
1274 if n_signature
!= null then sign
= " {n_signature.to_s}"
1278 redef private fun comment
: String do
1280 if n_doc
!= null then
1281 for t
in n_doc
.n_comment
do
1282 var txt
= t
.text
.replace
("# ", "")
1283 txt
= txt
.replace
("#", "")
1291 redef class MClassDef
1292 private fun namespace
(mclass
: MClass): String do
1294 if mmodule
.public_owner
is null then
1295 return "{mmodule.full_name}::{mclass.name}"
1296 else if mclass
is self.mclass
then
1297 return "{mmodule.public_owner.name}::{mclass.name}"
1299 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1306 return to_a
[length-1
]
1310 # Create a tool context to handle options and paths
1311 var toolcontext
= new ToolContext
1313 # Here we launch the nit index
1314 var nitdoc
= new Nitdoc(toolcontext
)