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.name}.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")
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
("a").attr
("href", "{name}.html").text
(name
)
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
.name
)
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.name}"
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 i_mclass
in sortedc
do
920 var sortedp
= mclass
.inherited
[i_mclass
].to_a
921 sorterprop
.sort
(sortedp
)
923 add_html
("Defined in <a href=\"{i_mclass.name}.html\
">{i_mclass.name}</a>: ")
924 for method
in sortedp
do
925 add_html
("<a href=\"{method.link_anchor}\
">{method.name}</a>")
926 if method
!= sortedp
.last
then add_html
(", ")
934 # Insert description tags for 'prop'
935 fun description
(prop
: MProperty) do
936 open
("article").add_class
("fun public {if prop.is_redef then "redef" else ""}").attr
("id", "{prop.anchor}")
938 if prop
.apropdef
!= null then sign
+= prop
.apropdef
.signature
939 add_html
("<h3 class=\"signature\
">{sign}</h3>")
940 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>")
942 open
("div").add_class
("description")
943 if prop
.apropdef
is null or prop
.apropdef
.comment
== "" then
944 add_html
("<a class=\"newComment\
" title=\"32\
" tag=\"\
">New Comment</a>")
946 add_html
("<pre class=\"text_label\
" title=\"\
" name=\"\
" tag=\"\
" type=\"1\
">{prop.apropdef.comment}</pre>")
948 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>")
950 if prop
.local_class
!= mclass
then
951 var mredef
= prop
.local_class
.intro_mmodule
952 var nredef
= mbuilder
.mmodule2nmodule
[mredef
]
953 add_html
("inherited from {mredef.link(nredef)} ")
955 #TODO display show code if doc github
956 var mintro
= prop
.intro_mclassdef
.mmodule
957 var nintro
= mbuilder
.mmodule2nmodule
[mintro
]
958 add_html
("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
960 for parent
in mclass
.parents
do
961 var mparent
= parent
.intro_mmodule
962 var nparent
= mbuilder
.mmodule2nmodule
[mparent
]
963 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>.")
974 private fun comment
: String do
976 if n_moduledecl
is null or n_moduledecl
.n_doc
is null then ret
977 if n_moduledecl
.n_doc
is null then return ""
978 for t
in n_moduledecl
.n_doc
.n_comment
do
980 txt
= txt
.replace
("# ", "")
981 txt
= txt
.replace
("#", "")
987 private fun short_comment
: String do
989 if n_moduledecl
!= null and n_moduledecl
.n_doc
!= null then
990 var txt
= n_moduledecl
.n_doc
.n_comment
.first
.text
991 txt
= txt
.replace
("# ", "")
992 txt
= txt
.replace
("\n", "")
1001 redef type OTHER: MModule
1002 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1004 # Get the list of all methods in a module
1005 fun imported_methods
: Set[MMethod] do
1006 var methods
= new HashSet[MMethod]
1007 for mclass
in imported_mclasses
do
1008 for method
in mclass
.intro_methods
do
1015 # Get the list aof all refined methods in a module
1016 fun redef_methods
: Set[MMethod] do
1017 var methods
= new HashSet[MMethod]
1018 for mclass
in redef_mclasses
do
1019 for method
in mclass
.intro_methods
do
1026 # Return a link (html a tag) to the nitdoc module page
1027 fun link
(amodule
: AModule): String do
1028 return "<a href=\"{name}.html\
" title=\"{amodule.short_comment}\
">{name}</a>"
1031 redef class MPropDef
1033 redef type OTHER: MPropDef
1034 redef fun <(other
: OTHER): Bool do return self.mproperty
.name
< other
.mproperty
.name
1037 redef class MProperty
1039 redef type OTHER: MProperty
1040 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1043 var apropdef
: nullable APropdef
1045 redef init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1051 fun local_class
: MClass do
1052 var classdef
= self.intro_mclassdef
1053 return classdef
.mclass
1056 fun class_text
: String do
1057 return local_class
.name
1060 fun link_anchor
: String do
1061 return "{class_text}.html#{anchor}"
1064 fun anchor
: String do
1065 return "PROP_{c_name}"
1072 redef type OTHER: MClass
1073 redef fun <(other
: OTHER): Bool do return self.name
< other
.name
1075 # Associate all MMethods to each MModule concerns
1076 fun all_methods
: HashMap[MModule, Set[MMethod]] do
1077 var hm
= new HashMap[MModule, Set[MMethod]]
1078 for mmodule
, childs
in concerns
do
1079 if not hm
.has_key
(mmodule
) then hm
[mmodule
] = new HashSet[MMethod]
1080 for prop
in intro_methods
do
1081 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1082 prop
.is_redef
= false
1083 hm
[mmodule
].add
(prop
)
1086 for prop
in redef_methods
do
1087 if mmodule
== prop
.intro_mclassdef
.mmodule
then
1088 prop
.is_redef
= true
1089 hm
[mmodule
].add
(prop
)
1093 if childs
!= null then
1094 for child
in childs
do
1095 if not hm
.has_key
(child
) then hm
[child
] = new HashSet[MMethod]
1096 for prop
in intro_methods
do
1097 if child
== prop
.intro_mclassdef
.mmodule
then
1098 prop
.is_redef
= false
1102 for prop
in redef_methods
do
1103 if child
== prop
.intro_mclassdef
.mmodule
then
1104 prop
.is_redef
= true
1114 fun public_owner
: MModule do
1115 var owner
= intro_mmodule
1116 if owner
.public_owner
is null then
1119 return owner
.public_owner
.as(not null)
1123 # Associate MClass to all MMethod include in 'inherited_methods'
1124 fun inherited
: HashMap[MClass, Set[MMethod]] do
1125 var hm
= new HashMap[MClass, Set[MMethod]]
1126 for method
in inherited_methods
do
1127 var mclass
= method
.intro_mclassdef
.mclass
1128 if not hm
.has_key
(mclass
) then hm
[mclass
] = new HashSet[MMethod]
1129 hm
[mclass
].add
(method
)
1134 # Return true if MModule concern contain subMModule
1135 fun has_mmodule
(sub
: MModule): Bool do
1136 for mmodule
, childs
in concerns
do
1137 if childs
is null then continue
1138 if childs
.has
(sub
) then return true
1143 fun mmethod
(mprop2npropdef
: Map[MProperty, APropdef]) do
1144 for const
in constructors
do
1145 if mprop2npropdef
.has_key
(const
)then
1146 const
.apropdef
= mprop2npropdef
[const
].as(AMethPropdef)
1150 for intro
in intro_methods
do
1151 if mprop2npropdef
.has_key
(intro
)then
1152 if mprop2npropdef
[intro
] isa AMethPropdef then intro
.apropdef
= mprop2npropdef
[intro
].as(AMethPropdef)
1156 for rd
in redef_methods
do
1157 if mprop2npropdef
.has_key
(rd
)then
1158 if mprop2npropdef
[rd
] isa AMethPropdef then rd
.apropdef
= mprop2npropdef
[rd
].as(AMethPropdef)
1163 fun link_anchor
: String do
1164 return "{name}.html"
1169 redef class AStdClassdef
1170 private fun comment
: String do
1172 if n_doc
!= null then
1173 for t
in n_doc
.n_comment
do
1174 var txt
= t
.text
.replace
("# ", "")
1175 txt
= txt
.replace
("#", "")
1182 private fun short_comment
: String do
1184 if n_doc
!= null then
1185 var txt
= n_doc
.n_comment
.first
.text
1186 txt
= txt
.replace
("# ", "")
1187 txt
= txt
.replace
("\n", "")
1194 redef class ASignature
1198 if not n_params
.is_empty
then
1199 ret
= "{ret}({n_params.join(", ")})"
1201 if n_type
!= null and n_type
.to_s
!= "" then ret
+= " {n_type.to_s}"
1208 var ret
= "{n_id.text}"
1209 if n_type
!= null then
1210 ret
= "{ret}: {n_type.to_s}"
1211 if n_dotdotdot
!= null then ret
= "{ret}..."
1219 var ret
= "<a href=\"{n_id.text}.html\
">{n_id.text}</a>"
1220 if n_kwnullable
!= null then ret
= "nullable {ret}"
1221 if not n_types
.is_empty
then ret
= "{ret}[{n_types.join(", ")}]"
1226 redef class APropdef
1227 private fun short_comment
: String is abstract
1228 private fun signature
: String is abstract
1229 private fun comment
: String is abstract
1232 redef class AAttrPropdef
1233 redef fun short_comment
do
1235 if n_doc
!= null then
1236 var txt
= n_doc
.n_comment
.first
.text
1237 txt
= txt
.replace
("# ", "")
1238 txt
= txt
.replace
("\n", "")
1245 redef class AMethPropdef
1246 redef fun short_comment
do
1248 if n_doc
!= null then
1249 var txt
= n_doc
.n_comment
.first
.text
1250 txt
= txt
.replace
("# ", "")
1251 txt
= txt
.replace
("\n", "")
1257 redef fun signature
: String do
1259 if n_signature
!= null then sign
= " {n_signature.to_s}"
1263 redef private fun comment
: String do
1265 if n_doc
!= null then
1266 for t
in n_doc
.n_comment
do
1267 var txt
= t
.text
.replace
("# ", "")
1268 txt
= txt
.replace
("#", "")
1276 redef class MClassDef
1277 private fun namespace
(mclass
: MClass): String do
1279 if mmodule
.public_owner
is null then
1280 return "{mmodule.full_name}::{mclass.name}"
1281 else if mclass
is self.mclass
then
1282 return "{mmodule.public_owner.name}::{mclass.name}"
1284 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\
">{mclass.name}</a>"
1291 return to_a
[length-1
]
1295 # Create a tool context to handle options and paths
1296 var toolcontext
= new ToolContext
1298 # Here we launch the nit index
1299 var nitdoc
= new Nitdoc(toolcontext
)