X-Git-Url: http://nitlanguage.org diff --git a/src/nitx.nit b/src/nitx.nit index 4b5183f..69b34e7 100644 --- a/src/nitx.nit +++ b/src/nitx.nit @@ -16,19 +16,18 @@ module nitx import model_utils -import modelize_property -import frontend +import modelize # Main class of the nit index tool # NitIndex build the model using the toolcontext argument # then wait for query on std in to display documentation class NitIndex private var toolcontext: ToolContext - private var model: Model - private var mbuilder: ModelBuilder - private var mainmodule: MModule - private var arguments: Array[String] - private var renderer: PagerMatchesRenderer + private var model: Model is noinit + private var mbuilder: ModelBuilder is noinit + private var mainmodule: MModule is noinit + private var arguments: Array[String] is noinit + private var renderer: PagerMatchesRenderer is noinit # New constructor to use the pre-calculated model when interpreting a module init with_infos(mbuilder: ModelBuilder, mmodule: MModule) do @@ -43,24 +42,18 @@ class NitIndex renderer = new PagerMatchesRenderer(self) end - init(toolcontext: ToolContext) do + init do # We need a model to collect stufs - self.toolcontext = toolcontext - self.toolcontext.option_context.options.clear self.arguments = toolcontext.option_context.rest - if arguments.is_empty or arguments.length > 2 then - print "usage: ni path/to/module.nit [expression]" - toolcontext.option_context.usage + if arguments.length > 2 then + print toolcontext.tooldescription exit(1) end model = new Model mbuilder = new ModelBuilder(model, toolcontext) - # Here we load an process std modules - #var dir = "NIT_DIR".environ - #var mmodules = modelbuilder.parse_and_build(["{dir}/lib/standard/standard.nit"]) var mmodules = mbuilder.parse([arguments.first]) if mmodules.is_empty then return mbuilder.run_phases @@ -85,7 +78,7 @@ class NitIndex print "Loaded modules:" var mmodules = new Array[MModule] mmodules.add_all(model.mmodules) - var sorter = new MModuleNameSorter + var sorter = new MEntityNameSorter sorter.sort(mmodules) for m in mmodules do print "\t{m.name}" @@ -107,7 +100,7 @@ class NitIndex fun prompt do printn ">> " - search(stdin.read_line) + search(sys.stdin.read_line) end fun search(entry: String) do @@ -159,7 +152,7 @@ class NitIndex else var category = parts[0] var keyword = parts[1] - if keyword.first == ' ' then keyword = keyword.substring_from(1) + if keyword.chars.first == ' ' then keyword = keyword.substring_from(1) return new IndexQueryPair(str, keyword, category) end end @@ -240,19 +233,11 @@ end private class IndexQuery var string: String var keyword: String - init(string: String, keyword: String) do - self.string = string - self.keyword = keyword - end end private class IndexQueryPair super IndexQuery var category: String - init(string: String, keyword: String, category: String) do - super(string, keyword) - self.category = category - end end # A match to a query in the nit index @@ -265,7 +250,7 @@ end # Code Analysis redef class ToolContext - private var nitx_phase: NitxPhase = new NitxPhase(self, [typing_phase]) + private var nitx_phase: NitxPhase = new NitxPhase(self, [modelize_property_phase]) end # Compiler phase for nitx @@ -304,7 +289,6 @@ end private class PagerMatchesRenderer var index: NitIndex - init(index: NitIndex) do self.index = index fun render_matches(query: IndexQuery, matches: Collection[IndexMatch]) do var pager = new Pager @@ -326,7 +310,7 @@ private class PagerMatchesRenderer pager.render end - private fun props_fulldoc(pager: Pager, raw_mprops: List[MProperty]) do + fun props_fulldoc(pager: Pager, raw_mprops: List[MProperty]) do # group by module var cats = new HashMap[MModule, Array[MProperty]] for mprop in raw_mprops do @@ -336,7 +320,7 @@ private class PagerMatchesRenderer cats[key].add(mprop) end #sort groups - var sorter = new MModuleNameSorter + var sorter = new MEntityNameSorter var sorted = new Array[MModule] sorted.add_all(cats.keys) sorter.sort(sorted) @@ -344,8 +328,7 @@ private class PagerMatchesRenderer for mmodule in sorted do var mprops = cats[mmodule] pager.add("# matches in module {mmodule.namespace.bold}") - var sorterp = new MPropertyNameSorter - sorterp.sort(mprops) + sorter.sort(mprops) for mprop in mprops do end @@ -355,7 +338,7 @@ private class PagerMatchesRenderer end private class Pager - var content = new Buffer + var content = new FlatBuffer var indent = 0 fun add(text: String) do add_indent @@ -364,51 +347,47 @@ private class Pager fun add_indent do addn(" " * indent) fun addn(text: String) do content.append(text.escape) fun add_rule do add("\n---\n") - fun render do sys.system("echo \"{content}\" | pager -r") + fun render do sys.system("echo \"{content}\" | less -r") end redef class MModule super IndexMatch # prototype of the module - # module ownername::name + # module name private fun prototype: String do return "module {name.bold}" # namespace of the module - # ownername::name + # project::name private fun namespace: String do - if public_owner == null then + if mgroup == null or mgroup.mproject.name == self.name then return self.name else - return "{public_owner.namespace}::{self.name}" + return "{mgroup.mproject}::{self.name}" end end redef fun preview(index, pager) do - if index.mbuilder.mmodule2nmodule.has_key(self) then - var node = index.mbuilder.mmodule2nmodule[self] - if node.n_moduledecl != null and not node.n_moduledecl.n_doc == null and not node.n_moduledecl.n_doc.short_comment.is_empty then - pager.add(node.n_moduledecl.n_doc.short_comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + pager.add(mdoc.short_comment.green) end pager.add(prototype) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) end redef fun content(index, pager) do - if index.mbuilder.mmodule2nmodule.has_key(self) then - var node = index.mbuilder.mmodule2nmodule[self] - if node.n_moduledecl != null and not node.n_moduledecl.n_doc == null and not node.n_moduledecl.n_doc.comment.is_empty then - for comment in node.n_moduledecl.n_doc.comment do pager.add(comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + for comment in mdoc.content do pager.add(comment.green) end pager.add(prototype) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) pager.indent = pager.indent + 1 - var sorter = new MModuleNameSorter + var sorter = new MEntityNameSorter # imported modules var imports = new Array[MModule] for mmodule in in_importation.direct_greaters.to_a do - if not in_nesting.direct_greaters.has(mmodule) then imports.add(mmodule) + imports.add(mmodule) end if not imports.is_empty then sorter.sort(imports) @@ -421,21 +400,7 @@ redef class MModule end pager.indent = pager.indent - 1 end - # nested modules - var nested = in_nesting.direct_greaters.to_a - if not nested.is_empty then - sorter.sort(nested) - pager.add("") - pager.add("== nested modules".bold) - pager.indent = pager.indent + 1 - for mmodule in nested do - pager.add("") - mmodule.preview(index, pager) - end - pager.indent = pager.indent - 1 - end # mclassdefs - var csorter = new MClassDefNameSorter var intros = new Array[MClassDef] var redefs = new Array[MClassDef] for mclassdef in mclassdefs do @@ -447,7 +412,7 @@ redef class MModule end # introductions if not intros.is_empty then - csorter.sort(intros) + sorter.sort(intros) pager.add("") pager.add("== introduced classes".bold) pager.indent = pager.indent + 1 @@ -459,7 +424,7 @@ redef class MModule end # refinements if not redefs.is_empty then - csorter.sort(redefs) + sorter.sort(redefs) pager.add("") pager.add("== refined classes".bold) pager.indent = pager.indent + 1 @@ -478,12 +443,12 @@ redef class MClass # return the generic signature of the class # [E, F] private fun signature: String do - var res = new Buffer + var res = new FlatBuffer if arity > 0 then res.append("[") - for i in [0..intro.parameter_names.length[ do - res.append(intro.parameter_names[i]) - if i < intro.parameter_names.length - 1 then res.append(", ") + for i in [0..mparameters.length[ do + res.append(mparameters[i].name) + if i < mparameters.length - 1 then res.append(", ") end res.append("]") end @@ -494,7 +459,7 @@ redef class MClass # class name is displayed with colors depending on visibility # abstract interface Foo[E] private fun prototype: String do - var res = new Buffer + var res = new FlatBuffer res.append("{kind} ") if visibility.to_s == "public" then res.append("{name}{signature}".bold.green) if visibility.to_s == "private" then res.append("{name}{signature}".bold.red) @@ -512,11 +477,10 @@ redef class MClass redef fun content(index, pager) do # intro comment - if index.mbuilder.mclassdef2nclassdef.has_key(intro) then - var node = index.mbuilder.mclassdef2nclassdef[intro] - if node isa AStdClassdef and not node.n_doc == null and not node.n_doc.comment.is_empty then - for comment in node.n_doc.comment do pager.add(comment.green) - end + var sorter = new MEntityNameSorter + var mdoc = intro.mdoc + if mdoc != null then + for comment in mdoc.content do pager.add(comment.green) end pager.add(intro.to_console) pager.add("{intro.namespace}".bold.gray + " (lines {intro.location.lines})".gray) @@ -524,8 +488,7 @@ redef class MClass # parents var supers = self.in_hierarchy(index.mainmodule).direct_greaters.to_a if not supers.is_empty then - var csorter = new MClassNameSorter - csorter.sort(supers) + sorter.sort(supers) pager.add("") pager.add("== supers".bold) pager.indent = pager.indent + 1 @@ -547,13 +510,12 @@ redef class MClass pager.indent = pager.indent - 1 end # intro mproperties - var psorter = new MPropDefNameSorter var mpropdefs = intro.mpropdefs index.mainmodule.linearize_mpropdefs(mpropdefs) for cat in intro.cats2mpropdefs.keys do var defs = intro.cats2mpropdefs[cat].to_a if defs.is_empty then continue - psorter.sort(defs) + sorter.sort(defs) pager.add("") pager.add("== {cat}".bold) pager.indent = pager.indent + 1 @@ -590,39 +552,35 @@ redef class MClassDef end fun to_console: String do - var res = new Buffer + var res = new FlatBuffer if not is_intro then res.append("redef ") res.append(mclass.prototype) return res.to_s end redef fun preview(index, pager) do - if index.mbuilder.mclassdef2nclassdef.has_key(self) then - var node = index.mbuilder.mclassdef2nclassdef[self] - if node isa AStdClassdef and not node.n_doc == null and not node.n_doc.short_comment.is_empty then - pager.add(node.n_doc.short_comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + pager.add(mdoc.short_comment.green) end pager.add(to_console) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) end redef fun content(index, pager) do - if index.mbuilder.mclassdef2nclassdef.has_key(self) then - var node = index.mbuilder.mclassdef2nclassdef[self] - if node isa AStdClassdef and not node.n_doc == null and not node.n_doc.comment.is_empty then - for comment in node.n_doc.comment do pager.add(comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + for comment in mdoc.content do pager.add(comment.green) end pager.add(to_console) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) pager.indent = pager.indent + 1 var mpropdefs = self.mpropdefs - var psorter = new MPropDefNameSorter + var sorter = new MEntityNameSorter index.mainmodule.linearize_mpropdefs(mpropdefs) for cat in cats2mpropdefs.keys do var defs = cats2mpropdefs[cat].to_a - psorter.sort(defs) + sorter.sort(defs) if defs.is_empty then continue pager.add("") pager.add("== {cat}".bold) @@ -698,22 +656,18 @@ redef class MPropDef end redef fun preview(index, pager) do - if index.mbuilder.mpropdef2npropdef.has_key(self) then - var nprop = index.mbuilder.mpropdef2npropdef[self] - if not nprop.n_doc == null and not nprop.n_doc.short_comment.is_empty then - pager.add(nprop.n_doc.short_comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + pager.add(mdoc.short_comment.green) end pager.add(to_console) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) end redef fun content(index, pager) do - if index.mbuilder.mpropdef2npropdef.has_key(self) then - var nprop = index.mbuilder.mpropdef2npropdef[self] - if not nprop.n_doc == null and not nprop.n_doc.comment.is_empty then - for comment in nprop.n_doc.comment do pager.add(comment.green) - end + var mdoc = self.mdoc + if mdoc != null then + for comment in mdoc.content do pager.add(comment.green) end pager.add(to_console) pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray) @@ -722,22 +676,21 @@ end redef class MMethodDef redef fun to_console do - var res = new Buffer + var res = new FlatBuffer if not is_intro then res.append("redef ") if not mproperty.is_init then res.append("fun ") res.append(mproperty.to_console.bold) if msignature != null then res.append(msignature.to_console) - # FIXME: modifiers should be accessible via the model - #if self isa ADeferredMethPropdef then ret = "{ret} is abstract" - #if self isa AInternMethPropdef then ret = "{ret} is intern" - #if self isa AExternMethPropdef then ret = "{ret} is extern" + if is_abstract then res.append " is abstract" + if is_intern then res.append " is intern" + if is_extern then res.append " is extern" return res.to_s end end redef class MVirtualTypeDef redef fun to_console do - var res = new Buffer + var res = new FlatBuffer res.append("type ") res.append(mproperty.to_console.bold) res.append(": {bound.to_console}") @@ -747,7 +700,7 @@ end redef class MAttributeDef redef fun to_console do - var res = new Buffer + var res = new FlatBuffer res.append("var ") res.append(mproperty.to_console.bold) res.append(": {static_mtype.to_console}") @@ -757,7 +710,7 @@ end redef class MSignature redef fun to_console do - var res = new Buffer + var res = new FlatBuffer if not mparameters.is_empty then res.append("(") for i in [0..mparameters.length[ do @@ -775,7 +728,7 @@ end redef class MParameter fun to_console: String do - var res = new Buffer + var res = new FlatBuffer res.append("{name}: {mtype.to_console}") if is_vararg then res.append("...") return res.to_s @@ -792,7 +745,7 @@ end redef class MGenericType redef fun to_console do - var res = new Buffer + var res = new FlatBuffer res.append("{mclass.name}[") for i in [0..arguments.length[ do res.append(arguments[i].to_console) @@ -804,53 +757,16 @@ redef class MGenericType end redef class MParameterType - redef fun to_console do return mclass.intro.parameter_names[rank] + redef fun to_console do return name end redef class MVirtualType redef fun to_console do return mproperty.name end -redef class ADoc - private fun comment: List[String] do - var res = new List[String] - for t in n_comment do - res.add(t.text.replace("\n", "")) - end - return res - end - +redef class MDoc private fun short_comment: String do - return n_comment.first.text.replace("\n", "") - end -end - -redef class AAttrPropdef - private fun read_accessor: String do - var ret = "fun " - #FIXME bug with standard::stream::FDStream::fd - var name = mreadpropdef.mproperty.name - if mpropdef.mproperty.visibility.to_s == "public" then ret = "{ret}{name.green}" - if mpropdef.mproperty.visibility.to_s == "private" then ret = "{ret}{name.red}" - if mpropdef.mproperty.visibility.to_s == "protected" then ret = "{ret}{name.yellow}" - ret = "{ret}: {n_type.to_s}" - if n_kwredef != null then ret = "redef {ret}" - return ret - end - - private fun write_accessor: String do - var ret = "fun " - var name = "{mreadpropdef.mproperty.name}=" - if n_readable != null and n_readable.n_visibility != null then - if n_readable.n_visibility isa APublicVisibility then ret = "{ret}{name.green}" - if n_readable.n_visibility isa APrivateVisibility then ret = "{ret}{name.red}" - if n_readable.n_visibility isa AProtectedVisibility then ret = "{ret}{name.yellow}" - else - ret = "{ret}{name.red}" - end - ret = "{ret}({mreadpropdef.mproperty.name}: {n_type.to_s})" - if n_kwredef != null then ret = "redef {ret}" - return ret + return content.first end end @@ -875,8 +791,8 @@ redef class String private fun escape: String do - var b = new Buffer - for c in self do + var b = new FlatBuffer + for c in self.chars do if c == '\n' then b.append("\\n") else if c == '\0' then @@ -905,7 +821,8 @@ end # Create a tool context to handle options and paths var toolcontext = new ToolContext -toolcontext.process_options +toolcontext.tooldescription = "Usage: nitx [OPTION]... [query]\nDisplays specific pieces of API information from Nit source files." +toolcontext.process_options(args) # Here we launch the nit index var ni = new NitIndex(toolcontext)