update NOTICE and LICENSE
[nit.git] / src / nitdoc.nit
index cac3298..205caca 100644 (file)
@@ -83,6 +83,8 @@ class DocContext
        readable var _opt_dir: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
        readable var _opt_source: OptionString = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
        readable var _opt_public: OptionBool = new OptionBool("Generate only the public API", "--public")
+       readable var _opt_private: OptionBool = new OptionBool("Generate the private API", "--private")
+       readable var _opt_nodot: OptionBool = new OptionBool("Do not generate graphes with graphviz", "--no-dot")
 
        fun public_only: Bool
        do
@@ -90,6 +92,12 @@ class DocContext
                return false
        end
 
+       fun with_private: Bool
+       do
+               if self._opt_private.value == true then return true
+               return false
+       end
+
        # The current processed filename
        var filename: String
 
@@ -261,6 +269,7 @@ class DocContext
        # `name' must also match the name of the graph in the dot content (eg. digraph NAME {...)
        fun gen_dot(dot: String,  name: String, alt: String)
        do
+               if opt_nodot.value then return
                var f = new OFStream.open("{self.dir}/{name}.dot")
                f.write(dot)
                f.close
@@ -277,8 +286,10 @@ class DocContext
                super("nitdoc")
                filename = "-unset-"
                option_context.add_option(opt_public)
+               option_context.add_option(opt_private)
                option_context.add_option(opt_dir)
                option_context.add_option(opt_source)
+               option_context.add_option(opt_nodot)
        end
 
        redef fun process_options
@@ -286,6 +297,15 @@ class DocContext
                super
                var d = opt_dir.value
                if d != null then dir = d
+
+               if not opt_nodot.value then
+                       # Test if dot is runable
+                       var res = sys.system("sh -c dot </dev/null >/dev/null 2>&1")
+                       if res != 0 then
+                               stderr.write "--no-dot implied since `dot' is not available. Try to install graphviz.\n"
+                               opt_nodot.value = true
+                       end
+               end
        end
 
        redef fun handle_property_conflict(lc, impls)
@@ -299,6 +319,23 @@ class DocContext
 end
 
 redef class String
+       # Replace all occurence of pattern ith string
+       fun replace(p: Pattern, string: String): String
+       do
+               return self.split_with(p).join(string)
+       end
+
+       # Escape the following characters < > & and " with their html counterpart
+       fun html_escape: String
+       do
+               var ret = self
+               if ret.has('&') then ret = ret.replace('&', "&amp;")
+               if ret.has('<') then ret = ret.replace('<', "&lt;")
+               if ret.has('>') then ret = ret.replace('>', "&gt;")
+               if ret.has('"') then ret = ret.replace('"', "&quot;")
+               return ret
+       end
+
        # Remove "/./", "//" and "bla/../"
        fun simplify_path: String
        do
@@ -600,6 +637,7 @@ redef class MMModule
                                end
                                if not keep then continue
                                clas.add(self[g])
+                               lc.compute_super_classes
                                for gp in lc.global_properties do
                                        if self.visibility_for(gp.intro.local_class.mmmodule) <= 1 then continue # private import or invisible import
                                        var lp = lc[gp]
@@ -649,16 +687,16 @@ redef class MMModule
                        var lpi = self[gp.intro.local_class.global][gp]
                
                        if lps.has(lpi) then
-                               dctx.add("<li class='intro'><span title='introduction in an other module'>I</span>&nbsp;{lpi.html_open_link(dctx)}{lpi}&nbsp;({lpi.local_class})</a></li>\n")
+                               dctx.add("<li class='intro'><span title='introduction in an other module'>I</span>&nbsp;{lpi.html_open_link(dctx)}{lpi.html_name}&nbsp;({lpi.local_class})</a></li>\n")
                                lps.remove(lpi)
                        else
-                               dctx.add("<li class='intro'><span title='introduction in this module'>I</span>&nbsp;{lpi}")
+                               dctx.add("<li class='intro'><span title='introduction in this module'>I</span>&nbsp;{lpi.html_name}")
                                dctx.add("&nbsp;({lpi.local_class})</li>\n")
                        end
                        if lps.length >= 1 then
                                dctx.sort(lps)
                                for lp in lps do
-                                       dctx.add("<li class='redef'><span title='redefinition'>R</span>&nbsp;{lp.html_open_link(dctx)}{lp}&nbsp;({lp.local_class})</a></li>")
+                                       dctx.add("<li class='redef'><span title='redefinition'>R</span>&nbsp;{lp.html_open_link(dctx)}{lp.html_name}&nbsp;({lp.local_class})</a></li>")
                                end
                        end
                end
@@ -735,11 +773,11 @@ redef class MMModule
                        var lpi = self[gp.intro.local_class.global][gp]
                        
                        lps.remove(lpi)
-                               dctx.add("<li class='intro'><span title='introduction'>I</span>&nbsp;{lpi.html_open_link(dctx)}{lpi}&nbsp;({lpi.local_class})</a></li>\n")
+                               dctx.add("<li class='intro'><span title='introduction'>I</span>&nbsp;{lpi.html_open_link(dctx)}{lpi.html_name}&nbsp;({lpi.local_class})</a></li>\n")
                        if lps.length >= 1 then
                                dctx.sort(lps)
                                for lp in lps do
-                                       dctx.add("<li class='redef'><span title='redefinition'>R</span>&nbsp;{lp.html_open_link(dctx)}{lp}&nbsp;({lp.local_class})</a></li>\n")
+                                       dctx.add("<li class='redef'><span title='redefinition'>R</span>&nbsp;{lp.html_open_link(dctx)}{lp.html_name}&nbsp;({lp.local_class})</a></li>\n")
                                end
                        end
                end
@@ -759,31 +797,36 @@ redef class MMLocalProperty
        fun html_open_link(dctx: DocContext): String
        do
                if not require_doc(dctx) then print "not required {self}"
-               var title = "{name}{signature.to_s}"
+               var title = "{html_name}{signature.to_s}"
                if short_doc != "&nbsp;" then
                        title += " #{short_doc}"
                end
                return "<a href=\"{local_class.html_name}.html#{html_anchor}\" title=\"{title}\">"
        end
 
+       fun html_name: String
+       do
+               return self.name.to_s.html_escape
+       end
+
        redef fun html_link(dctx)
        do
                if not require_doc(dctx) then print "not required {self}"
-               var title = "{name}{signature.to_s}"
+               var title = "{html_name}{signature.to_s}"
                if short_doc != "&nbsp;" then
                        title += " #{short_doc}"
                end
-               return "<a href=\"{local_class.html_name}.html#{html_anchor}\" title=\"{title}\">{self}</a>"
+               return "<a href=\"{local_class.html_name}.html#{html_anchor}\" title=\"{title}\">{html_name}</a>"
        end
 
        fun html_link_special(dctx: DocContext, lc: MMLocalClass): String
        do
                if not require_doc(dctx) then print "not required {self}"
-               var title = "{name}{signature_for(lc.get_type)}"
+               var title = "{html_name}{signature_for(lc.get_type)}"
                if short_doc != "&nbsp;" then
                        title += " #{short_doc}"
                end
-               return "<a href=\"{lc.html_name}.html#{html_anchor}\" title=\"{title}\">{self}</a>"
+               return "<a href=\"{lc.html_name}.html#{html_anchor}\" title=\"{title}\">{html_name}</a>"
        end
 
        # Kind of property (fun, attr, etc.)
@@ -837,10 +880,10 @@ redef class MMLocalProperty
                return m == m.toplevel_owner
        end
 
-       # Return true if the global class must be documented according to the visibility configured
+       # Return true if the global property must be documented according to the visibility configured
        fun require_doc(dctx: DocContext): Bool
        do
-               if global.visibility_level == 3 then return false # Private
+               if global.visibility_level == 3 and not dctx.with_private then return false # Private
                if dctx.public_only then
                        var m = intro_module
                        if m != m.toplevel_owner then return false # Unexported
@@ -866,7 +909,7 @@ redef class MMLocalProperty
                var is_redef = local_class.global != intro_class.global or local_class.mmmodule.toplevel_owner != intro_class.mmmodule.toplevel_owner
 
                dctx.add("<article id=\"{html_anchor}\" class=\"{kind} {visibility} {if is_redef then "redef" else ""}\">\n")
-               dctx.add("<h3 class=\"signature\">{name}{signature.to_html(dctx, true)}</h3>\n")
+               dctx.add("<h3 class=\"signature\">{html_name}{signature.to_html(dctx, true)}</h3>\n")
                dctx.add("<div class=\"info\">\n")
                #dctx.add("<p>LP: {self.mmmodule.html_link(dctx)}::{self.local_class.html_link(dctx)}::{self.html_link(dctx)}</p>")
 
@@ -891,7 +934,7 @@ redef class MMLocalProperty
                if is_redef then
                        dctx.add("::{mmmodule[intro_class.global][global].html_link(dctx)}")
                else
-                       dctx.add("::{name}")
+                       dctx.add("::{html_name}")
                end
                dctx.add("</div>")
 
@@ -999,42 +1042,6 @@ redef class MMTypeProperty
        redef fun kind do return "type"
 end
 
-redef class Symbol
-       # Replace < and > with html entities
-       redef fun to_s
-       do
-               var ret = super.to_s
-
-               if(ret.has('<')) then
-                       var parts = ret.split_with("<")
-                       ret = ""
-
-                       for i in [0..parts.length[ do
-                               ret += parts[i]
-
-                               if(i < parts.length - 1) then
-                                       ret += "&lt;"
-                               end
-                       end
-               end
-
-               if(ret.has('>')) then
-                       var parts = ret.split_with(">")
-                       ret = ""
-
-                       for i in [0..parts.length[ do
-                               ret += parts[i]
-
-                               if(i < parts.length - 1) then
-                                       ret += "&gt;"
-                               end
-                       end
-               end
-               
-               return ret
-       end
-end
-
 redef class MMSrcModule
        redef fun short_doc
        do
@@ -1073,13 +1080,13 @@ redef class ADoc
                for c in n_comment do
                        res.append(c.text.substring_from(1))
                end
-               return res.to_s
+               return res.to_s.html_escape
        end
 
        # Oneliner transcription of the doc
        fun short: String
        do
-               return n_comment.first.text.substring_from(1)
+               return n_comment.first.text.substring_from(1).html_escape
        end
 end
 
@@ -1145,7 +1152,7 @@ redef class MMLocalClass
        # Return true if the global class must be documented according to the visibility configured
        fun require_doc(dctx: DocContext): Bool
        do
-               if global.visibility_level == 3 then return false # Private
+               if global.visibility_level == 3 and not dctx.with_private then return false # Private
                if dctx.public_only then
                        var m = intro_module
                        if m != m.toplevel_owner then return false # Unexported