X-Git-Url: http://nitlanguage.org diff --git a/src/ni_nitdoc.nit b/src/ni_nitdoc.nit index e58f273..6ad2eb2 100644 --- a/src/ni_nitdoc.nit +++ b/src/ni_nitdoc.nit @@ -1,7 +1,5 @@ # This file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2008 Jean Privat -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,15 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Documentation generator for the nit language. +# Generate API documentation in HTML format from nit source code. module ni_nitdoc import model_utils -import abstract_compiler +# The NitdocContext contains all the knowledge used for doc generation class NitdocContext - private var toolcontext: ToolContext + + private var toolcontext = new ToolContext private var model: Model - private var modelbuilder: ModelBuilder + private var mbuilder: ModelBuilder private var mainmodule: MModule private var class_hierarchy: POSet[MClass] private var arguments: Array[String] @@ -43,9 +44,7 @@ class NitdocContext private var opt_custom_overview_text: OptionString = new OptionString("Text displayed as introduction of Overview page before the modules list", "--custom-overview-text") private var opt_custom_footer_text: OptionString = new OptionString("Text displayed as footer of all pages", "--custom-footer-text") - init(toolcontext: ToolContext) do - # We need a model to collect stufs - self.toolcontext = toolcontext + init do self.arguments = toolcontext.option_context.rest toolcontext.option_context.options.clear toolcontext.option_context.add_option(opt_dir) @@ -58,7 +57,6 @@ class NitdocContext toolcontext.option_context.add_option(opt_custom_overview_text) toolcontext.option_context.add_option(opt_custom_menu_items) toolcontext.process_options - process_options if arguments.length < 1 then toolcontext.option_context.usage @@ -66,10 +64,9 @@ class NitdocContext end model = new Model - modelbuilder = new ModelBuilder(model, toolcontext) + mbuilder = new ModelBuilder(model, toolcontext) # Here we load an process all modules passed on the command line - var mmodules = modelbuilder.parse_and_build(arguments) - modelbuilder.full_propdef_semantic_analysis + var mmodules = mbuilder.parse_and_build(arguments) if mmodules.is_empty then return if mmodules.length == 1 then @@ -80,6 +77,7 @@ class NitdocContext mainmodule.set_imported_mmodules(mmodules) end self.class_hierarchy = mainmodule.flatten_mclass_hierarchy + self.process_options end private fun process_options do @@ -117,7 +115,7 @@ class NitdocContext source = opt_source.value end - fun start do + fun generate_nitdoc do # Create destination dir if it's necessary if not output_dir.file_exists then output_dir.mkdir sys.system("cp -r {share_dir.to_s}/* {output_dir.to_s}/") @@ -130,17 +128,17 @@ class NitdocContext quicksearch_list end - fun overview do + private fun overview do var overviewpage = new NitdocOverview(self, dot_dir) overviewpage.save("{output_dir.to_s}/index.html") end - fun fullindex do + private fun fullindex do var fullindex = new NitdocFullindex(self) fullindex.save("{output_dir.to_s}/full-index.html") end - fun modules do + private fun modules do for mmodule in model.mmodules do if mmodule.name == "
" then continue var modulepage = new NitdocModule(mmodule, self, dot_dir) @@ -148,15 +146,14 @@ class NitdocContext end end - fun classes do - for mclass in modelbuilder.model.mclasses do + private fun classes do + for mclass in mbuilder.model.mclasses do var classpage = new NitdocClass(mclass, self, dot_dir, source) classpage.save("{output_dir.to_s}/{mclass.url}") end end - # Generate QuickSearch file - fun quicksearch_list do + private fun quicksearch_list do var file = new OFStream.open("{output_dir.to_s}/quicksearch-list.js") var content = new Buffer content.append("var entries = \{ ") @@ -196,19 +193,18 @@ end # Nitdoc base page abstract class NitdocPage + super Buffer var dot_dir: nullable String var source: nullable String var ctx: NitdocContext init(ctx: NitdocContext) do + super self.ctx = ctx end - fun append(str: String) do html.append(str) - var html = new Buffer - - fun head do + protected fun head do append("") append("") append("") @@ -221,15 +217,15 @@ abstract class NitdocPage append("{self.title}{title}") end - fun menu do + protected fun menu do if ctx.opt_custom_menu_items.value != null then append(ctx.opt_custom_menu_items.value.to_s) end end - fun title: String is abstract + protected fun title: String is abstract - fun header do + protected fun header do append("
") append("
") end - fun content is abstract + protected fun content is abstract - fun footer do + protected fun footer do if ctx.opt_custom_footer_text.value != null then append("
{ctx.opt_custom_footer_text.value.to_s}
") end end # Generate a clickable graphviz image using a dot content - fun generate_dot(dot: String, name: String, alt: String) do + protected fun generate_dot(dot: String, name: String, alt: String) do var output_dir = dot_dir if output_dir == null then return var file = new OFStream.open("{output_dir}/{name}.dot") @@ -301,7 +297,7 @@ abstract class NitdocPage end # Add a (source) link for a given location - fun show_source(l: Location): String + protected fun show_source(l: Location): String do if source == null then return "({l.file.filename.simplify_path})" @@ -330,7 +326,7 @@ abstract class NitdocPage append("") footer append("") - return html.to_s + return to_s end # Save html page in the specified file @@ -349,7 +345,7 @@ class NitdocOverview init(ctx: NitdocContext, dot_dir: nullable String) do super(ctx) - self.mbuilder = ctx.modelbuilder + self.mbuilder = ctx.mbuilder self.dot_dir = dot_dir # get modules var mmodules = new HashSet[MModule] @@ -363,7 +359,7 @@ class NitdocOverview end end # sort modules - var sorter = new ComparableSorter[MModule] + var sorter = new MModuleNameSorter self.mmodules.add_all(mmodules) sorter.sort(self.mmodules) end @@ -395,7 +391,9 @@ class NitdocOverview for mmodule in mmodules do if mbuilder.mmodule2nmodule.has_key(mmodule) then var amodule = mbuilder.mmodule2nmodule[mmodule] - append("
  • {mmodule.link(mbuilder)} {amodule.short_comment}
  • ") + append("
  • ") + mmodule.html_link(self) + append(" {amodule.short_comment}
  • ") end end append("") @@ -405,15 +403,26 @@ class NitdocOverview append("") end - fun process_generate_dot do + private fun process_generate_dot do + # build poset with public owners + var poset = new POSet[MModule] + for mmodule in mmodules do + poset.add_node(mmodule) + for omodule in mmodules do + if mmodule == omodule then continue + if mmodule.in_importation < omodule then + poset.add_node(omodule) + poset.add_edge(mmodule, omodule) + end + end + end + # build graph var op = new Buffer 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") - for mmodule in mmodules do + for mmodule in poset do op.append("\"{mmodule.name}\"[URL=\"{mmodule.url}\"];\n") - for imported in mmodule.in_importation.direct_greaters do - if imported.direct_owner == null then - op.append("\"{mmodule.name}\"->\"{imported.name}\";\n") - end + for omodule in poset[mmodule].direct_greaters do + op.append("\"{mmodule.name}\"->\"{omodule.name}\";\n") end end op.append("\}\n") @@ -448,43 +457,44 @@ class NitdocFullindex end # Add to content modules column - fun module_column do - var sorter = new ComparableSorter[MModule] - var sorted = new Array[MModule] - for mmodule in ctx.modelbuilder.model.mmodule_importation_hierarchy do - sorted.add(mmodule) - end + private fun module_column do + var sorted = ctx.mbuilder.model.mmodule_importation_hierarchy.to_a + var sorter = new MModuleNameSorter sorter.sort(sorted) append("
    ") append("

    Modules

    ") append("
      ") for mmodule in sorted do - append("
    • {mmodule.link(ctx.modelbuilder)}
    • ") + append("
    • ") + mmodule.html_link(self) + append("
    • ") end append("
    ") append("
    ") end # Add to content classes modules - fun classes_column do - var sorted = ctx.modelbuilder.model.mclasses - var sorter = new ComparableSorter[MClass] + private fun classes_column do + var sorted = ctx.mbuilder.model.mclasses + var sorter = new MClassNameSorter sorter.sort(sorted) append("
    ") append("

    Classes

    ") append("
      ") for mclass in sorted do if mclass.visibility < ctx.min_visibility then continue - append("
    • {mclass.link(ctx.modelbuilder)}
    • ") + append("
    • ") + mclass.html_link(self) + append("
    • ") end append("
    ") append("
    ") end # Insert the properties column of fullindex page - fun properties_column do - var sorted = ctx.modelbuilder.model.mproperties - var sorter = new ComparableSorter[MProperty] + private fun properties_column do + var sorted = ctx.mbuilder.model.mproperties + var sorter = new MPropertyNameSorter sorter.sort(sorted) append("
    ") append("

    Properties

    ") @@ -492,7 +502,11 @@ class NitdocFullindex for mproperty in sorted do if mproperty.visibility < ctx.min_visibility then continue if mproperty isa MAttribute then continue - append("
  • {mproperty.intro.link(ctx.modelbuilder)} ({mproperty.intro.mclassdef.mclass.link(ctx.modelbuilder)})
  • ") + append("
  • ") + mproperty.intro.html_link(self) + append(" (") + mproperty.intro.mclassdef.mclass.html_link(self) + append(")
  • ") end append("") append("
    ") @@ -510,7 +524,7 @@ class NitdocModule init(mmodule: MModule, ctx: NitdocContext, dot_dir: nullable String) do super(ctx) self.mmodule = mmodule - self.mbuilder = ctx.modelbuilder + self.mbuilder = ctx.mbuilder self.dot_dir = dot_dir end @@ -534,41 +548,53 @@ class NitdocModule sidebar append("
    ") append("

    {mmodule.name}

    ") - append("
    {mmodule.html_signature(mbuilder)}
    ") - append(mmodule.html_full_comment(mbuilder)) + append("
    ") + mmodule.html_signature(self) + append("
    ") + mmodule.html_full_comment(self) process_generate_dot classes properties append("
    ") end - fun process_generate_dot do - var name = "dep_{mmodule.name}" + private fun process_generate_dot do + # build poset with public owners + var poset = new POSet[MModule] + for mmodule in self.mmodule.in_importation.poset do + if mmodule.name == "
    " then continue + if mmodule.public_owner != null then continue + if not mmodule.in_importation < self.mmodule and not self.mmodule.in_importation < mmodule and mmodule != self.mmodule then continue + poset.add_node(mmodule) + for omodule in mmodule.in_importation.poset do + if mmodule == omodule then continue + if omodule.name == "
    " then continue + if omodule.public_owner != null then continue + if mmodule.in_importation < omodule then + poset.add_node(omodule) + poset.add_edge(mmodule, omodule) + end + end + end + # build graph var op = new Buffer + var name = "dep_{mmodule.name}" op.append("digraph {name} \{ 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") - for m in mmodule.in_importation.poset do - if m.name == "
    " then continue - var public_owner = m.public_owner - if public_owner == null then - public_owner = m - if m == mmodule then - op.append("\"{m.name}\"[shape=box,margin=0.03];\n") - else - op.append("\"{m.name}\"[URL=\"{m.url}\"];\n") - end + for mmodule in poset do + if mmodule == self.mmodule then + op.append("\"{mmodule.name}\"[shape=box,margin=0.03];\n") + else + op.append("\"{mmodule.name}\"[URL=\"{mmodule.url}\"];\n") end - for imported in m.in_importation.direct_greaters do - if imported.name == "
    " then continue - if imported.public_owner == null then - op.append("\"{public_owner.name}\"->\"{imported.name}\";\n") - end + for omodule in poset[mmodule].direct_greaters do + op.append("\"{mmodule.name}\"->\"{omodule.name}\";\n") end end op.append("\}\n") generate_dot(op.to_s, name, "Dependency graph for module {mmodule.name}") end - fun sidebar do + private fun sidebar do append("") end private fun display_module_list(list: Array[MModule]) do append("
      ") - var sorter = new ComparableSorter[MModule] + var sorter = new MModuleNameSorter sorter.sort(list) - for m in list do append("
    • {m.link(mbuilder)}
    • ") + for m in list do + append("
    • ") + m.html_link(self) + append("
    • ") + end append("
    ") end # display the class column - fun classes do + private fun classes do var intro_mclasses = mmodule.intro_mclasses var redef_mclasses = mmodule.redef_mclasses var all_mclasses = new HashSet[MClass] @@ -622,7 +655,7 @@ class NitdocModule var sorted = new Array[MClass] sorted.add_all(all_mclasses) - var sorter = new ComparableSorter[MClass] + var sorter = new MClassNameSorter sorter.sort(sorted) append("
    ") append("
    ") @@ -637,7 +670,7 @@ class NitdocModule append("
  • ") append("I ") end - append(c.link(mbuilder)) + c.html_link(self) append("
  • ") end append("") @@ -646,7 +679,7 @@ class NitdocModule end # display the property column - fun properties do + private fun properties do # get properties var mpropdefs = new HashSet[MPropDef] for m in mmodule.in_nesting.greaters do @@ -654,7 +687,7 @@ class NitdocModule end for c in mmodule.mclassdefs do mpropdefs.add_all(c.mpropdefs) var sorted = mpropdefs.to_a - var sorter = new ComparableSorter[MPropDef] + var sorter = new MPropDefNameSorter sorter.sort(sorted) # display properties in one column append("
    ") @@ -663,7 +696,7 @@ class NitdocModule for mprop in sorted do if mprop isa MAttributeDef then continue if mprop.mproperty.visibility < ctx.min_visibility then continue - append(mprop.html_list_item(mbuilder)) + mprop.html_list_item(self) end append("") append("
    ") @@ -675,7 +708,6 @@ class NitdocClass super NitdocPage private var mclass: MClass - private var mbuilder: ModelBuilder private var vtypes = new HashSet[MVirtualTypeDef] private var consts = new HashSet[MMethodDef] private var meths = new HashSet[MMethodDef] @@ -684,7 +716,6 @@ class NitdocClass init(mclass: MClass, ctx: NitdocContext, dot_dir: nullable String, source: nullable String) do super(ctx) self.mclass = mclass - self.mbuilder = ctx.modelbuilder self.dot_dir = dot_dir self.source = source # load properties @@ -718,7 +749,7 @@ class NitdocClass end redef fun title do - var nclass = mbuilder.mclassdef2nclassdef[mclass.intro] + var nclass = ctx.mbuilder.mclassdef2nclassdef[mclass.intro] if nclass isa AStdClassdef then return "{mclass.name} class | {nclass.short_comment}" else @@ -731,9 +762,13 @@ class NitdocClass append("
  • Overview
  • ") var public_owner = mclass.public_owner if public_owner is null then - append("
  • {mclass.intro_mmodule.link(mbuilder)}
  • ") + append("
  • ") + mclass.intro_mmodule.html_link(self) + append("
  • ") else - append("
  • {public_owner.link(mbuilder)}
  • ") + append("
  • ") + public_owner.html_link(self) + append("
  • ") end append("
  • {mclass.name}
  • ") append("
  • Full Index
  • ") @@ -749,8 +784,8 @@ class NitdocClass append("
    ") end - fun properties_column do - var sorter = new ComparableSorter[MPropDef] + private fun properties_column do + var sorter = new MPropDefNameSorter append("") end - fun inheritance_column do + private fun inheritance_column do var sorted = new Array[MClass] - var sorterp = new ComparableSorter[MClass] + var sorterp = new MClassNameSorter append("") end - fun class_doc do + private fun class_doc do # title - append("

    {mclass.html_signature}

    ") - append("
    {mclass.html_full_signature(mbuilder)}") - + append("

    {mclass.signature}

    ") + append("
    ") + mclass.html_full_signature(self) append("
    ") # comment - var nclass = mbuilder.mclassdef2nclassdef[mclass.intro] + var nclass = ctx.mbuilder.mclassdef2nclassdef[mclass.intro] append("
    ") append("
    ") - if nclass isa AStdClassdef and not nclass.comment.is_empty then append("
    {nclass.comment}
    CancelCommit
    ")
    +		if nclass isa AStdClassdef and not nclass.full_comment.is_empty then append("
    {nclass.full_comment}
    CancelCommit
    ")
     		process_generate_dot
     		append("
    ") # concerns @@ -877,7 +918,7 @@ class NitdocClass append("

    Concerns

    ") append("
      ") for owner, mmodules in sections do - var nowner = mbuilder.mmodule2nmodule[owner] + var nowner = ctx.mbuilder.mmodule2nmodule[owner] append("
    • ") if nowner.short_comment.is_empty then append("{owner.name}") @@ -887,7 +928,7 @@ class NitdocClass if not mmodules.is_empty then append("
        ") for mmodule in mmodules do - var nmodule = mbuilder.mmodule2nmodule[mmodule] + var nmodule = ctx.mbuilder.mmodule2nmodule[mmodule] if nmodule.short_comment.is_empty then append("
      • {mmodule.name}
      • ") else @@ -901,9 +942,7 @@ class NitdocClass append("
      ") append("") # properties - var prop_sorter = new ComparableSorter[MPropDef] - var sorterprop = new ComparableSorter[MProperty] - var sorterc = new ComparableSorter[MClass] + var prop_sorter = new MPropDefNameSorter var lmmodule = new List[MModule] # virtual and formal types var local_vtypes = new Array[MVirtualTypeDef] @@ -915,14 +954,16 @@ class NitdocClass if mclass.arity > 0 and nclass isa AStdClassdef then for ft, bound in mclass.parameter_types do append("
      ") - append("

      {ft}: {bound.link(mbuilder)}

      ") + append("

      {ft}: ") + bound.html_link(self) + append("

      ") append("
      formal generic type
      ") append("
      ") end end # virtual types prop_sorter.sort(local_vtypes) - for prop in local_vtypes do append(prop.html_full_desc(self)) + for prop in local_vtypes do prop.html_full_desc(self) append("") end # constructors @@ -932,7 +973,7 @@ class NitdocClass if local_consts.length > 0 then append("
      ") append("

      Constructors

      ") - for prop in local_consts do append(prop.html_full_desc(self)) + for prop in local_consts do prop.html_full_desc(self) append("
      ") end # methods @@ -942,32 +983,36 @@ class NitdocClass for owner, mmodules in sections do append("") if owner != mclass.intro_mmodule and owner != mclass.public_owner then - var nowner = mbuilder.mmodule2nmodule[owner] - append("

      Methods refined in {owner.link(mbuilder)}

      ") - if nowner.short_comment.is_empty then - append("

      {owner.link(mbuilder)}

      ") - else - append("

      {owner.link(mbuilder)}: {nowner.short_comment}

      ") + var nowner = ctx.mbuilder.mmodule2nmodule[owner] + append("

      Methods refined in ") + owner.html_link(self) + append("

      ") + append("

      ") + owner.html_link(self) + if not nowner.short_comment.is_empty then + append(": {nowner.short_comment}") end + append("

      ") end if concern2meths.has_key(owner) then var mmethods = concern2meths[owner] prop_sorter.sort(mmethods) - for prop in mmethods do append(prop.html_full_desc(self)) + for prop in mmethods do prop.html_full_desc(self) end for mmodule in mmodules do append("") - var nmodule = mbuilder.mmodule2nmodule[mmodule] + var nmodule = ctx.mbuilder.mmodule2nmodule[mmodule] if mmodule != mclass.intro_mmodule and mmodule != mclass.public_owner then - if nmodule.short_comment.is_empty then - append("

      {mmodule.link(mbuilder)}

      ") - else - append("

      {mmodule.link(mbuilder)}: {nmodule.short_comment}

      ") + append("

      ") + mmodule.html_link(self) + if not nmodule.short_comment.is_empty then + append(": {nmodule.short_comment}") end + append("

      ") end var mmethods = concern2meths[mmodule] prop_sorter.sort(mmethods) - for prop in mmethods do append(prop.html_full_desc(self)) + for prop in mmethods do prop.html_full_desc(self) end end end @@ -985,10 +1030,12 @@ class NitdocClass append("

      Inherited Properties

      ") for c, mmethods in classes do prop_sorter.sort(mmethods) - append("

      Defined in {c.link(mbuilder)}: ") + append("

      Defined in ") + c.html_link(self) + append(": ") for i in [0..mmethods.length[ do var mmethod = mmethods[i] - append(mmethod.link(mbuilder)) + mmethod.html_link(self) if i <= mmethods.length - 1 then append(", ") end append("

      ") @@ -997,7 +1044,7 @@ class NitdocClass append("") end - fun process_generate_dot do + private fun process_generate_dot do var pe = ctx.class_hierarchy[mclass] var cla = new HashSet[MClass] var sm = new HashSet[MClass] @@ -1049,32 +1096,6 @@ end # redef class MModule - super Comparable - redef type OTHER: MModule - redef fun <(other: OTHER): Bool do return self.name < other.name - - # Get the list of all methods in a module - fun imported_methods: Set[MMethod] do - var methods = new HashSet[MMethod] - for mclass in imported_mclasses do - for method in mclass.intro_methods do - methods.add(method) - end - end - return methods - end - - # Get the list aof all refined methods in a module - fun redef_methods: Set[MMethod] do - var methods = new HashSet[MMethod] - for mclass in redef_mclasses do - for method in mclass.intro_methods do - methods.add(method) - end - end - return methods - end - # URL to nitdoc page fun url: String do var res = new Buffer @@ -1100,78 +1121,70 @@ redef class MModule end # Return a link (html a tag) to the nitdoc module page - fun link(mbuilder: ModelBuilder): String do - if mbuilder.mmodule2nmodule.has_key(self) then - return "{name}" + fun html_link(page: NitdocPage) do + if page.ctx.mbuilder.mmodule2nmodule.has_key(self) then + page.append("{name}") else - return "{name}" + page.append("{name}") end end # Return the module signature decorated with html - fun html_signature(mbuilder: ModelBuilder): String do - return "module {html_full_namespace(mbuilder)}" + fun html_signature(page: NitdocPage) do + page.append("module ") + html_full_namespace(page) + page.append("") end # Return the module full namespace decorated with html - fun html_full_namespace(mbuilder: ModelBuilder): String do - var res = new Buffer - res.append("") + fun html_full_namespace(page: NitdocPage) do + page.append("") var mowner = public_owner if mowner != null then - res.append(public_owner.html_namespace(mbuilder)) - res.append("::") + public_owner.html_namespace(page) + page.append("::") end - res.append(self.link(mbuilder)) - res.append("") - return res.to_s + html_link(page) + page.append("") end # Return the module full namespace decorated with html - fun html_namespace(mbuilder: ModelBuilder): String do - var res = new Buffer - res.append("") + fun html_namespace(page: NitdocPage) do + page.append("") var mowner = public_owner if mowner != null then - res.append(public_owner.html_namespace(mbuilder)) + public_owner.html_namespace(page) else - res.append(self.link(mbuilder)) + html_link(page) end - res.append("") - return res.to_s + page.append("") end # Return the full comment of the module decorated with html - fun html_full_comment(mbuilder: ModelBuilder): String do - var res = new Buffer - if mbuilder.mmodule2nmodule.has_key(self) then - res.append("
      ") - res.append("
      {mbuilder.mmodule2nmodule[self].comment}
      ") - res.append("") - res.append("Cancel") - res.append("Commit") - res.append("
      ")
      -			res.append("
      ") + fun html_full_comment(page: NitdocPage) do + if page.ctx.mbuilder.mmodule2nmodule.has_key(self) then + page.append("
      ") + page.append("
      {page.ctx.mbuilder.mmodule2nmodule[self].full_comment}
      ") + page.append("") + page.append("Cancel") + page.append("Commit") + page.append("
      ")
      +			page.append("
      ") end - return res.to_s end end redef class MClass - super Comparable - redef type OTHER: MClass - redef fun <(other: OTHER): Bool do return self.name < other.name - # Return the module signature decorated with html - fun html_full_signature(mbuilder: ModelBuilder): String do - var res = new Buffer - if visibility < public_visibility then res.append("{visibility.to_s} ") - res.append("{kind} {html_namespace(mbuilder)}") - return res.to_s + fun html_full_signature(page: NitdocPage) do + if visibility < public_visibility then page.append("{visibility.to_s} ") + page.append("{kind} ") + html_namespace(page) end - # Add type parameters - fun html_signature: String do + # name with formal parameter + # Foo[A, B] + private fun signature: String do if arity > 0 then return "{name}[{intro.parameter_names.join(", ")}]" else @@ -1180,29 +1193,27 @@ redef class MClass end # Return a link (html a tag) to the nitdoc class page - fun link(mbuilder: ModelBuilder): String do - if mbuilder.mclassdef2nclassdef.has_key(intro) then - var nclass = mbuilder.mclassdef2nclassdef[intro] + fun html_link(page: NitdocPage) do + page.append("{html_signature}" - else - return "{html_signature}" + page.append(" title=\"{nclass.short_comment}\"") end - else - return "{html_signature}" end + page.append(">{signature}") end # Return the class namespace decorated with html - fun html_namespace(mbuilder: ModelBuilder): String do - var res = new Buffer - res.append(intro_mmodule.html_namespace(mbuilder)) - res.append("::{self.link(mbuilder)}") - return res.to_s + fun html_namespace(page: NitdocPage) do + intro_mmodule.html_namespace(page) + page.append("::") + html_link(page) + page.append("") end fun url: String do - return "class_{public_owner}_{c_name}.html" + return "class_{public_owner}_{name}.html" end # Escape name for html output @@ -1210,13 +1221,12 @@ redef class MClass end redef class MProperty - super Comparable - redef type OTHER: MProperty - redef fun <(other: OTHER): Bool do return self.name < other.name - # Return the property namespace decorated with html - fun html_namespace(mbuilder: ModelBuilder): String do - return "{intro_mclassdef.mclass.html_namespace(mbuilder)}::{intro.link(mbuilder)}" + fun html_namespace(page: NitdocPage) do + intro_mclassdef.mclass.html_namespace(page) + page.append("::") + intro.html_link(page) + page.append("") end # Escape name for html output @@ -1224,113 +1234,108 @@ redef class MProperty end redef class MType - fun link(mbuilder: ModelBuilder): String is abstract + fun html_link(page: NitdocPage) is abstract end redef class MClassType - redef fun link(mbuilder) do return mclass.link(mbuilder) + redef fun html_link(page) do mclass.html_link(page) end redef class MNullableType - redef fun link(mbuilder) do return "nullable {mtype.link(mbuilder)}" + redef fun html_link(page) do + page.append("nullable ") + mtype.html_link(page) + end end redef class MGenericType - redef fun link(mbuilder) do - var res = new Buffer - res.append("{mclass.name}[") + redef fun html_link(page) do + page.append("{mclass.name}[") for i in [0..arguments.length[ do - res.append(arguments[i].link(mbuilder)) - if i < arguments.length - 1 then res.append(", ") + arguments[i].html_link(page) + if i < arguments.length - 1 then page.append(", ") end - res.append("]") - return res.to_s + page.append("]") end end redef class MParameterType - redef fun link(mbuilder) do + redef fun html_link(page) do var name = mclass.intro.parameter_names[rank] - return "{name}" + page.append("{name}") end end redef class MVirtualType - redef fun link(mbuilder) do return mproperty.intro.link(mbuilder) + redef fun html_link(page) do mproperty.intro.html_link(page) end redef class MClassDef # Return the classdef namespace decorated with html - fun html_namespace(mbuilder: ModelBuilder): String do - var res = new Buffer - res.append(mmodule.html_full_namespace(mbuilder)) - res.append("::{self.mclass.link(mbuilder)}") - return res.to_s + fun html_namespace(page: NitdocPage) do + mmodule.html_full_namespace(page) + page.append("::") + mclass.html_link(page) + page.append("") end end redef class MPropDef - super Comparable - redef type OTHER: MPropDef - redef fun <(other: OTHER): Bool do return self.mproperty.name < other.mproperty.name - fun url: String do return "{mclassdef.mclass.url}#{anchor}" - fun anchor: String do return "PROP_{mclassdef.mclass.public_owner.name}_{c_name}" + fun anchor: String do return "PROP_{mclassdef.mclass.public_owner.name}_{mproperty.name}" # Return a link (html a tag) to the nitdoc class page - fun link(mbuilder: ModelBuilder): String do - if mbuilder.mpropdef2npropdef.has_key(self) then - var nprop = mbuilder.mpropdef2npropdef[self] - return "{mproperty.name}" + fun html_link(page: NitdocPage) do + if page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then + var nprop = page.ctx.mbuilder.mpropdef2npropdef[self] + page.append("{mproperty.name}") else - return "{mproperty.name}" + page.append("{mproperty.name}") end end # Return a list item for the mpropdef - fun html_list_item(mbuilder: ModelBuilder): String do - var res = new Buffer + private fun html_list_item(page: NitdocPage) do if is_intro then - res.append("
    • ") - res.append("I {link(mbuilder)} ({mclassdef.mclass.link(mbuilder)})") - res.append("
    • ") + page.append("
    • ") + page.append("I ") else - res.append("
    • ") - res.append("R {link(mbuilder)} ({mclassdef.mclass.link(mbuilder)})") - res.append("
    • ") + page.append("
    • ") + page.append("R ") end - return res.to_s + html_link(page) + page.append("(") + mclassdef.mclass.html_link(page) + page.append(")") + page.append("
    • ") end # Return a list item for the mpropdef - fun html_sidebar_item(page: NitdocClass): String do - var res = new Buffer + private fun html_sidebar_item(page: NitdocClass) do if is_intro and mclassdef.mclass == page.mclass then - res.append("
    • ") - res.append("I") + page.append("
    • ") + page.append("I") else if is_intro and mclassdef.mclass != page.mclass then - res.append("
    • ") - res.append("H") + page.append("
    • ") + page.append("H") else - res.append("
    • ") - res.append("R") + page.append("
    • ") + page.append("R") end - res.append(link(page.mbuilder)) - res.append("
    • ") - return res.to_s + html_link(page) + page.append("") end - fun html_full_desc(page: NitdocClass): String is abstract - fun html_info(page: NitdocClass): String is abstract + private fun html_full_desc(page: NitdocClass) is abstract + private fun html_info(page: NitdocClass) is abstract fun full_name: String do return "{mclassdef.mclass.public_owner.name}::{mclassdef.mclass.name}::{mproperty.name}" end - fun html_inheritance(page: NitdocClass): String do - var res = new Buffer + private fun html_inheritance(page: NitdocClass) do # definitions block - res.append("

      ") + page.append("

      ") page.ctx.mainmodule.linearize_mpropdefs(mproperty.mpropdefs) var previous_defs = new Array[MPropDef] var next_defs = new Array[MPropDef] @@ -1341,282 +1346,225 @@ redef class MPropDef continue end if not self_passed then - if not page.mclass.ancestors.has(def.mclassdef.mclass) then continue + if def.mclassdef.mclass.in_hierarchy(page.ctx.mainmodule) < page.mclass then continue if def.is_intro then continue previous_defs.add(def) else - if not page.mclass.descendants.has(def.mclassdef.mclass) then continue + if page.mclass.in_hierarchy(page.ctx.mainmodule) < def.mclassdef.mclass then continue next_defs.add(def) end end - var source = "" - if page.mbuilder.mpropdef2npropdef.has_key(self) then - source = " {page.show_source(page.mbuilder.mpropdef2npropdef[self].location)}" + page.append("defined by ") + mclassdef.mmodule.html_full_namespace(page) + if page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then + page.append(" {page.show_source(page.ctx.mbuilder.mpropdef2npropdef[self].location)}") end - res.append("defined by {mclassdef.mmodule.html_full_namespace(page.mbuilder)}{source}") if not is_intro then - source = "" - if page.mbuilder.mpropdef2npropdef.has_key(mproperty.intro) then - source = " {page.show_source(page.mbuilder.mpropdef2npropdef[mproperty.intro].location)}" + page.append(", introduced by ") + mproperty.intro.mclassdef.mclass.html_link(page) + if page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then + page.append(" {page.show_source(page.ctx.mbuilder.mpropdef2npropdef[self].location)}") end - res.append(", introduced by {mproperty.intro.mclassdef.mclass.link(page.mbuilder)}{source}") end if not previous_defs.is_empty then - res.append(", inherited from ") + page.append(", inherited from ") for i in [0..previous_defs.length[ do var def = previous_defs[i] - source = "" - if page.mbuilder.mpropdef2npropdef.has_key(def) then - source = " {page.show_source(page.mbuilder.mpropdef2npropdef[def].location)}" + def.mclassdef.mclass.html_link(page) + if page.ctx.mbuilder.mpropdef2npropdef.has_key(def) then + page.append(" {page.show_source(page.ctx.mbuilder.mpropdef2npropdef[def].location)}") end - res.append("{def.mclassdef.mclass.link(page.mbuilder)}{source}") - if i < previous_defs.length - 1 then res.append(", ") + + if i < previous_defs.length - 1 then page.append(", ") end end if not next_defs.is_empty then - res.append(", redefined by ") + page.append(", redefined by ") for i in [0..next_defs.length[ do var def = next_defs[i] - source = "" - if page.mbuilder.mpropdef2npropdef.has_key(def) then - source = " {page.show_source(page.mbuilder.mpropdef2npropdef[def].location)}" + def.mclassdef.mclass.html_link(page) + if page.ctx.mbuilder.mpropdef2npropdef.has_key(def) then + page.append(" {page.show_source(page.ctx.mbuilder.mpropdef2npropdef[def].location)}") end - res.append("{def.mclassdef.mclass.link(page.mbuilder)}{source}") - if i < next_defs.length - 1 then res.append(", ") + if i < next_defs.length - 1 then page.append(", ") end end - res.append(".

      ") - return res.to_s + page.append(".

      ") + end + + private fun html_comment(page: NitdocClass) do + if not page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then return + var nprop = page.ctx.mbuilder.mpropdef2npropdef[self] + page.append("
      ") + if not is_intro then + var intro_nprop = page.ctx.mbuilder.mpropdef2npropdef[mproperty.intro] + page.append("

      from ") + mproperty.html_namespace(page) + page.append("

      ") + if intro_nprop.full_comment == "" then + page.append("New Comment") + else + page.append("
      {intro_nprop.full_comment}
      ") + end + page.append("

      from ") + mclassdef.html_namespace(page) + page.append("

      ") + end + if nprop.full_comment == "" then + page.append("New Comment") + else + page.append("
      {nprop.full_comment}
      ") + end + page.append("CancelCommit
      ")
      +		html_inheritance(page)
      +		page.append("
      ") end end redef class MMethodDef redef fun html_full_desc(page) do - if not page.mbuilder.mpropdef2npropdef.has_key(self) then - return "" - end - var res = new Buffer - var mprop = mproperty - var nprop = page.mbuilder.mpropdef2npropdef[self] var classes = new Array[String] - var is_redef = mprop.intro_mclassdef.mclass != page.mclass - classes.add("fun") - if mprop.is_init then classes.add("init") - if is_redef then classes.add("redef") - classes.add(mproperty.visibility.to_s) - res.append("
      ") - if nprop isa AAttrPropdef then - if nprop.mreadpropdef == self then - res.append("

      {mprop.name}: {nprop.html_signature(page.mbuilder)}

      ") - else - res.append("

      {mprop.name}(value: {nprop.html_signature(page.mbuilder)})

      ") - end + var is_redef = mproperty.intro_mclassdef.mclass != page.mclass + if mproperty.is_init then + classes.add("init") else - var intro_nprop = page.mbuilder.mpropdef2npropdef[mprop.intro] - res.append("

      {mprop.name}{intro_nprop.html_signature(page.mbuilder)}

      ") + classes.add("fun") end - res.append(html_info(page)) - res.append("
      ") - if nprop.comment == "" then - res.append("New Comment") + if is_redef then classes.add("redef") + classes.add(mproperty.visibility.to_s) + page.append("
      ") + if page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then + page.append("

      {mproperty.name}") + msignature.html_signature(page) + page.append("

      ") else - res.append("
      {nprop.comment}
      ") + page.append("

      init") + msignature.html_signature(page) + page.append("

      ") end - res.append("CancelCommit
      ")
      -		res.append(html_inheritance(page))
      -		res.append("
      ") - res.append("
      ") - return res.to_s + html_info(page) + html_comment(page) + page.append("") end redef fun html_info(page) do - var res = new Buffer - res.append("
      ") - if mproperty.visibility < public_visibility then res.append("{mproperty.visibility.to_s} ") - if mproperty.intro_mclassdef.mclass != page.mclass then res.append("redef ") - res.append("fun {mproperty.html_namespace(page.mbuilder)}") - res.append("
      ") - res.append("
      ") - return res.to_s + page.append("
      ") + if mproperty.visibility < public_visibility then page.append("{mproperty.visibility.to_s} ") + if mproperty.intro_mclassdef.mclass != page.mclass then page.append("redef ") + if mproperty.is_init then + page.append("init ") + else + page.append("fun ") + end + mproperty.html_namespace(page) + page.append("
      ") + page.append("
      ") end end redef class MVirtualTypeDef redef fun html_full_desc(page) do - var res = new Buffer - var mprop = mproperty - var is_redef = mprop.intro_mclassdef.mclass != page.mclass + var is_redef = mproperty.intro_mclassdef.mclass != page.mclass var classes = new Array[String] classes.add("type") if is_redef then classes.add("redef") classes.add(mproperty.visibility.to_s) - res.append("
      ") - res.append("

      {mprop.name}: {bound.link(page.mbuilder)}

      ") - res.append(html_info(page)) - res.append("
      ") - - if page.mbuilder.mpropdef2npropdef.has_key(self) and page.mbuilder.mpropdef2npropdef[self].comment != "" then - var nprop = page.mbuilder.mpropdef2npropdef[self] - res.append("
      {nprop.comment}
      ") - else - res.append("New Comment") - end - res.append("CancelCommit
      ")
      -		res.append(html_inheritance(page))
      -		res.append("
      ") - res.append("
      ") - return res.to_s + page.append("
      ") + page.append("

      {mproperty.name}: ") + bound.html_link(page) + page.append("

      ") + html_info(page) + html_comment(page) + page.append("
      ") end redef fun html_info(page) do - var res = new Buffer - res.append("
      ") - if mproperty.intro_mclassdef.mclass != page.mclass then res.append("redef ") - res.append("type {mproperty.html_namespace(page.mbuilder)}") - res.append("
      ") - res.append("
      ") - return res.to_s + page.append("
      ") + if mproperty.intro_mclassdef.mclass != page.mclass then page.append("redef ") + page.append("type ") + mproperty.html_namespace(page) + page.append("
      ") + page.append("
      ") end end -# -# Nodes redefs -# - -redef class AModule - private fun comment: String do - var ret = new Buffer - if n_moduledecl == null or n_moduledecl.n_doc == null then return "" - for t in n_moduledecl.n_doc.n_comment do - ret.append(t.text.substring_from(1)) +redef class MSignature + private fun html_signature(page: NitdocPage) do + if not mparameters.is_empty then + page.append("(") + for i in [0..mparameters.length[ do + mparameters[i].html_link(page) + if i < mparameters.length - 1 then page.append(", ") + end + page.append(")") end - return ret.to_s.html_escape - end - - private fun short_comment: String do - var ret = new Buffer - if n_moduledecl != null and n_moduledecl.n_doc != null then - ret.append(n_moduledecl.n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) + if return_mtype != null then + page.append(": ") + return_mtype.html_link(page) end - return ret.to_s.html_escape end end -redef class AStdClassdef - private fun comment: String do - var ret = new Buffer - if n_doc != null then - for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) - end - return ret.to_s.html_escape - end - - private fun short_comment: String do - var ret = new Buffer - if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s.html_escape +redef class MParameter + private fun html_link(page: NitdocPage) do + page.append("{name}: ") + mtype.html_link(page) + if is_vararg then page.append("...") end end -redef class APropdef - private fun short_comment: String is abstract - private fun html_signature(mbuilder: ModelBuilder): String is abstract - private fun comment: String is abstract -end - -redef class AAttrPropdef - redef fun short_comment do - var ret = new Buffer - if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s.html_escape - end +# +# Nodes redefs +# - redef private fun comment: String do - var ret = new Buffer - if n_doc != null then - for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) +redef class AModule + private fun short_comment: String do + if n_moduledecl != null and n_moduledecl.n_doc != null then + return n_moduledecl.n_doc.n_comment.first.text.substring_from(2).replace("\n", "").html_escape end - return ret.to_s.html_escape - end - - redef fun html_signature(mbuilder) do - if n_type != null then return n_type.mtype.link(mbuilder) return "" end -end - -redef class AMethPropdef - redef fun short_comment do - var ret = new Buffer - if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s.html_escape - end - redef private fun comment: String do - var ret = new Buffer - if n_doc != null then - for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) + private fun full_comment: String do + var res = new Buffer + if n_moduledecl != null and n_moduledecl.n_doc != null then + for t in n_moduledecl.n_doc.n_comment do + res.append(t.text.substring_from(1).html_escape) + end end - return ret.to_s.html_escape - end - - redef fun html_signature(mbuilder) do - if n_signature != null then return n_signature.to_html(mbuilder) - return "" + return res.to_s end end -redef class ATypePropdef - redef fun short_comment do - var ret = new Buffer - if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s.html_escape +redef class AStdClassdef + private fun short_comment: String do + if n_doc != null then return n_doc.n_comment.first.text.substring_from(2).replace("\n", "").html_escape + return "" end - redef private fun comment: String do - var ret = new Buffer + private fun full_comment: String do + var res = new Buffer if n_doc != null then - for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) + for t in n_doc.n_comment do res.append(t.text.substring_from(1).html_escape) end - return ret.to_s.html_escape + return res.to_s end +end - redef fun html_signature(mbuilder) do - return mpropdef.bound.link(mbuilder) +redef class APropdef + private fun short_comment: String do + if n_doc != null then return n_doc.n_comment.first.text.substring_from(2).replace("\n", "").html_escape + return "" end -end -redef class ASignature - fun to_html(mbuilder: ModelBuilder): String do - #TODO closures + private fun full_comment: String do var res = new Buffer - if not n_params.is_empty then - res.append("(") - for i in [0..n_params.length[ do - res.append(n_params[i].to_html(mbuilder)) - if i < n_params.length - 1 then res.append(", ") - end - res.append(")") + if n_doc != null then + for t in n_doc.n_comment do res.append(t.text.substring_from(1).html_escape) end - if n_type != null and n_type.mtype.link(mbuilder) != "" then res.append(": {n_type.mtype.link(mbuilder)}") return res.to_s end end -redef class AParam - fun to_html(mbuilder: ModelBuilder): String do - var ret = "{n_id.text}" - if n_type != null then - ret = "{ret}: {n_type.mtype.link(mbuilder)}" - if n_dotdotdot != null then ret = "{ret}..." - end - return ret - end -end - -# Create a tool context to handle options and paths -var toolcontext = new ToolContext - -# Here we launch the nit index -var nitdoc = new NitdocContext(toolcontext) -nitdoc.start +var nitdoc = new NitdocContext +nitdoc.generate_nitdoc