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.namespace(mbuilder)}")
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 subtitle
+= "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}"
842 add_html
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
843 # We add the class description
844 open
("section").add_class
("description")
845 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>")
847 open
("section").add_class
("concerns")
848 add
("h2").add_class
("section-header").text
("Concerns")
850 for owner
in sorted
do
851 var nmodule
= mbuilder
.mmodule2nmodule
[owner
]
852 var childs
= mclass
.concerns
[owner
]
854 add_html
("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {nmodule.short_comment}")
855 if not childs
is null then
857 var sortedc
= childs
.to_a
858 var sorterpc
= new ComparableSorter[MModule]
859 sorterpc
.sort
(sortedc
)
860 for child
in sortedc
do
861 var nchild
= mbuilder
.mmodule2nmodule
[child
]
862 add_html
("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {nchild.short_comment} </li>")
870 # Insert virtual types if there is almost one
871 if mclass
.virtual_types
.length
> 0 or mclass
.arity
> 0 then
872 open
("section").add_class
("types")
873 add
("h2").text
("Formal and Virtual Types")
874 if mclass
.virtual_types
.length
> 0 then for prop
in mclass
.virtual_types
do description
(prop
)
875 if mclass
.arity
> 0 and nclass
isa AStdClassdef then
876 for prop
in nclass
.n_formaldefs
do
877 open
("article").attr
("id", "FT_Object_{prop.collect_text}")
878 open
("h3").add_class
("signature").text
("{prop.collect_text}: nullable ")
879 add_html
("<a title=\"The root of the
class hierarchy
.\
" href=\"Object.html\
">Object</a>")
881 add_html
("<div class=\"info\
">formal generic type</div>")
888 if mclass
.constructors
.length
> 0 then
889 var sortedc
= mclass
.constructors
.to_a
890 sorterprop
.sort
(sortedc
)
891 open
("section").add_class
("constructors")
892 add
("h2").add_class
("section-header").text
("Constructors")
893 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
)
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 fun description
(prop
: MProperty) do
936 if not mbuilder
.mpropdef2npropdef
.has_key
(prop
.intro
) then return
937 var nprop
= mbuilder
.mpropdef2npropdef
[prop
.intro
]
938 if not nprop
isa AMethPropdef then return
939 var classes
= new Array[String]
940 if nprop
isa AInitPropdef then
945 if prop
.is_redef
then classes
.add
("redef")
946 if prop
.visibility
== none_visibility
then
947 classes
.add
("private")
948 else if prop
.visibility
== protected_visibility
then
949 classes
.add
("protected")
951 classes
.add
("public")
953 open
("article").add_classes
(classes
).attr
("id", "{prop.anchor}")
955 open
("h3").add_class
("signature")
956 add_html
("{prop.name}{nprop.signature}")
958 open
("div").add_class
("info")
959 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>")
961 open
("div").add_class
("description")
962 if nprop
.comment
== "" then
963 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
965 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{nprop.comment}</pre>")
967 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>")
969 if prop
.local_class
!= mclass
then
970 var mredef
= prop
.local_class
.intro_mmodule
971 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
972 add_html
("inherited from {mredef.link(nredef)} ")
974 #TODO display show code if doc github
975 var mintro
= prop
.intro_mclassdef
.mmodule
976 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
977 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
979 for parent
in mclass
.parents
do
980 var mparent
= parent
.intro_mmodule
981 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
982 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>.")
993 private fun comment
: String do
995 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
996 if n_moduledecl
.n_doc
is null then return ""
997 for t
in n_moduledecl
.n_doc
.n_comment
do
999 txt
= txt
.replace
("# ", "")
1000 txt
= txt
.replace
("#", "")
1006 private fun short_comment
: String do
1008 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
1009 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
1010 txt
= txt
.replace
("# ", "")
1011 txt
= txt
.replace
("\n", "")
1020 redef type OTHER: MModule
1021 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1023 # Get the list of all methods in a module
1024 fun imported_methods
: Set[MMethod] do
1025 var methods
= new HashSet[MMethod]
1026 for mclass
in imported_mclasses
do
1027 for method
in mclass
.intro_methods
do
1034 # Get the list aof all refined methods in a module
1035 fun redef_methods
: Set[MMethod] do
1036 var methods
= new HashSet[MMethod]
1037 for mclass
in redef_mclasses
do
1038 for method
in mclass
.intro_methods
do
1045 # Return a link (html a tag) to the nitdoc module page
1046 fun link
(amodule
: AModule): String do
1047 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1050 # Return the module namespace decorated with html
1051 fun namespace
(mbuilder
: ModelBuilder): String do
1052 var str
= new Buffer
1053 var mowner
= public_owner
1054 if mowner
!= null then
1055 var nowner
= mbuilder
.mmodule2nmodule
[mowner
]
1056 str
.append
(public_owner
.link
(nowner
))
1058 var nmodule
= mbuilder
.mmodule2nmodule
[self]
1059 str
.append
(self.link
(nmodule
))
1063 redef class MPropDef
1065 redef type OTHER: MPropDef
1066 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1069 redef class MProperty
1071 redef type OTHER: MProperty
1072 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1075 var apropdef
: nullable APropdef
1077 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1083 fun local_class
: MClass do
1084 var classdef
= self.intro_mclassdef
1085 return classdef
.mclass
1088 fun class_text
: String do
1089 return local_class
.name
1092 fun link_anchor
: String do
1093 return "{class_text}.html#{anchor}"
1096 fun anchor
: String do
1097 return "PROP_{c_name}"
1104 redef type OTHER: MClass
1105 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1107 # Add type parameters
1110 return "{name}[{intro.parameter_names.join(", ")}]"
1116 # Return a link (html a tag) to the nitdoc class page
1117 fun link
(aclass
: AStdClassdef): String do
1118 return "<a href=\"{name}.html\
" title=\"{aclass.short_comment}\
">{self}</a>"
1121 # Associate all MMethods to each MModule concerns
1122 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1123 var hm
= new HashMap[MModule, Set[MMethod]]
1124 for mmodule
, childs
in concerns
do
1125 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1126 for prop
in intro_methods
do
1127 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1128 prop
.is_redef
= false
1129 hm
[mmodule
].add
(prop
)
1132 for prop
in redef_methods
do
1133 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1134 prop
.is_redef
= true
1135 hm
[mmodule
].add
(prop
)
1139 if childs
!= null then
1140 for child
in childs
do
1141 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1142 for prop
in intro_methods
do
1143 if child
== prop
.intro_mclassdef
.mmodule
then
1144 prop
.is_redef
= false
1148 for prop
in redef_methods
do
1149 if child
== prop
.intro_mclassdef
.mmodule
then
1150 prop
.is_redef
= true
1160 fun public_owner
: MModule do
1161 var owner
= intro_mmodule
1162 if owner
.public_owner
is null then
1165 return owner
.public_owner
.as(not null)
1169 # Associate MClass to all MMethod include in 'inherited_methods'
1170 fun inherited
: HashMap[MClass, Set[MMethod]] do
1171 var hm
= new HashMap[MClass, Set[MMethod]]
1172 for method
in inherited_methods
do
1173 var mclass
= method
.intro_mclassdef
.mclass
1174 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1175 hm
[mclass
].add
(method
)
1180 # Return true if MModule concern contain subMModule
1181 fun has_mmodule
(sub
: MModule): Bool do
1182 for mmodule
, childs
in concerns
do
1183 if childs
is null then continue
1184 if childs
.has
(sub
) then return true
1189 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1190 for const
in constructors
do
1191 if mprop2npropdef
.has_key
(const
)then
1192 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1196 for intro
in intro_methods
do
1197 if mprop2npropdef
.has_key
(intro
)then
1198 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1202 for rd
in redef_methods
do
1203 if mprop2npropdef
.has_key
(rd
)then
1204 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1209 fun link_anchor
: String do
1210 return "{name}.html"
1215 redef class AStdClassdef
1216 private fun comment
: String do
1218 if n_doc
!= null then
1219 for t
in n_doc
.n_comment
do
1220 var txt
= t
.text
.replace
("# ", "")
1221 txt
= txt
.replace
("#", "")
1228 private fun short_comment
: String do
1230 if n_doc
!= null then
1231 var txt
= n_doc
.n_comment
.first
.text
1232 txt
= txt
.replace
("# ", "")
1233 txt
= txt
.replace
("\n", "")
1240 redef class ASignature
1244 if not n_params
.is_empty
then
1245 ret
= "{ret}({n_params.join(", ")})"
1247 if n_type
!= null and n_type
.to_s
!= "" then ret
+= ": {n_type.to_s}"
1254 var ret
= "{n_id.text}"
1255 if n_type
!= null then
1256 ret
= "{ret}: {n_type.to_s}"
1257 if n_dotdotdot
!= null then ret
= "{ret}..."
1265 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1266 if n_kwnullable
!= null then ret
= "nullable {ret}"
1267 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1272 redef class APropdef
1273 private fun short_comment
: String is abstract
1274 private fun signature
: String is abstract
1275 private fun comment
: String is abstract
1278 redef class AAttrPropdef
1279 redef fun short_comment
do
1281 if n_doc
!= null then
1282 var txt
= n_doc
.n_comment
.first
.text
1283 txt
= txt
.replace
("# ", "")
1284 txt
= txt
.replace
("\n", "")
1291 redef class AMethPropdef
1292 redef fun short_comment
do
1293 var ret
= new Buffer
1294 if n_doc
!= null then
1295 var txt
= n_doc
.n_comment
.first
.text
1296 txt
= txt
.replace
("# ", "")
1297 txt
= txt
.replace
("\n", "")
1303 redef fun signature
: String do
1305 if n_signature
!= null then sign
= "{n_signature.to_s}"
1309 redef private fun comment
: String do
1310 var ret
= new Buffer
1311 if n_doc
!= null then
1312 for t
in n_doc
.n_comment
do
1313 var txt
= t
.text
.replace
("# ", "")
1314 txt
= txt
.replace
("#", "")
1322 redef class MClassDef
1323 private fun namespace
(mclass
: MClass): String do
1325 if mmodule
.public_owner
is null then
1326 return "{mmodule.full_name}::{mclass.name}"
1327 else if mclass
is self.mclass
then
1328 return "{mmodule.public_owner.name}::{mclass.name}"
1330 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1337 return to_a
[length-1
]
1341 # Create a tool context to handle options and paths
1342 var toolcontext
= new ToolContext
1344 # Here we launch the nit index
1345 var nitdoc
= new Nitdoc(toolcontext
)