X-Git-Url: http://nitlanguage.org diff --git a/src/doc/vim_autocomplete.nit b/src/doc/vim_autocomplete.nit index bcc9041..edbc126 100644 --- a/src/doc/vim_autocomplete.nit +++ b/src/doc/vim_autocomplete.nit @@ -14,8 +14,9 @@ # Generate files used by the Vim plugin to autocomplete with doc # -# There is 3 files generated, each with a different target: modules, classes, -# and properties. Each line describe a different entity, with 4 values: +# There is 3 files generated, each with a different target: modules, types, +# properties and constructors. Each line describe a different entity, +# with 4 values: # # 1. Short name to use in autocompletion # 2. Full signature @@ -23,13 +24,14 @@ # 4. Full doc with extra # # The priority with those files is for them to be analyzed efficiently, for -# this reason, the data is prepared in advant and some information may be +# this reason, the data is prepared in advance and some information may be # duplicated. module vim_autocomplete import modelbuilder import phase import modelize::modelize_class +import model_utils redef class ToolContext # Phase generating the files for the Vim plugin @@ -50,37 +52,47 @@ redef class MEntity private fun field_separator: String do return "#====#" private fun line_separator: String do return "#nnnn#" - private fun write_to_stream(stream: OStream) + private fun write_doc(mainmodule: MModule, stream: Writer) do # 1. Short name for autocompletion - stream.write name + stream.write complete_name stream.write field_separator # 2. Full signature - stream.write name + stream.write complete_name write_signature_to_stream(stream) stream.write field_separator # 3. Doc synopsis - var mdoc = mdoc + var mdoc = complete_mdoc if mdoc != null then stream.write mdoc.content.first end # 4. Full doc with extra stream.write field_separator + stream.write "# " + stream.write full_name + write_signature_to_stream(stream) if mdoc != null then - stream.write "# " - stream.write full_name - write_signature_to_stream(stream) for i in 2.times do stream.write line_separator stream.write mdoc.content.join(line_separator) end + write_extra_doc(mainmodule, stream) stream.write "\n" end - private fun write_signature_to_stream(stream: OStream) do end + private fun write_signature_to_stream(stream: Writer) do end + + # Actual name used in completion + private fun complete_name: String do return name + + # Doc to use in completion + private fun complete_mdoc: nullable MDoc do return mdoc + + # Extra auto documentation to append to the `stream` + private fun write_extra_doc(mainmodule: MModule, stream: Writer) do end end redef class MMethodDef @@ -103,6 +115,121 @@ redef class MAttributeDef end end +# Use `MClassDef` as anchor for its constructors only +redef class MClassDef + private var target_constructor: nullable MMethodDef = null + + redef fun complete_name + do + var target_constructor = target_constructor + assert target_constructor != null + + var params + var mparameters = mclass.mparameters + if not mparameters.is_empty then + params = "[{mparameters.join(", ")}]" + else + params = "" + end + + if target_constructor.name != "init" and target_constructor.name != "new" then + return name + params + "." + target_constructor.name + end + + return name + params + end + + redef fun complete_mdoc + do + var target_constructor = target_constructor + assert target_constructor != null + + if target_constructor.name != "init" and target_constructor.name != "new" then + return target_constructor.mdoc + end + + return mdoc + end +end + +redef class MClassType + redef fun write_extra_doc(mainmodule, stream) + do + # Super classes + stream.write line_separator*2 + stream.write "## Class hierarchy" + + var direct_supers = [for s in mclass.in_hierarchy(mainmodule).direct_greaters do s.name] + if not direct_supers.is_empty then + alpha_comparator.sort direct_supers + stream.write line_separator + stream.write "* Direct super classes: " + stream.write direct_supers.join(", ") + end + + var supers = [for s in mclass.in_hierarchy(mainmodule).greaters do s.name] + supers.remove mclass.name + if not supers.is_empty then + alpha_comparator.sort supers + stream.write line_separator + stream.write "* All super classes: " + stream.write supers.join(", ") + end + + var direct_subs = [for s in mclass.in_hierarchy(mainmodule).direct_smallers do s.name] + if not direct_subs.is_empty then + alpha_comparator.sort direct_subs + stream.write line_separator + stream.write "* Direct sub classes: " + stream.write direct_subs.join(", ") + end + + var subs = [for s in mclass.in_hierarchy(mainmodule).smallers do s.name] + subs.remove mclass.name + if not subs.is_empty then + alpha_comparator.sort subs + stream.write line_separator + stream.write "* All sub classes: " + stream.write subs.join(", ") + end + + # List other properties + stream.write line_separator*2 + stream.write "## Properties" + stream.write line_separator + var props = mclass.all_mproperties(mainmodule, protected_visibility).to_a + alpha_comparator.sort props + for prop in props do + if mclass.name == "Object" or prop.intro.mclassdef.mclass.name != "Object" then + + if prop.visibility == public_visibility then + stream.write "+ " + else stream.write "~ " # protected_visibility + + if prop isa MMethod then + if prop.is_init and prop.name != "init" then stream.write "init " + if prop.is_new and prop.name != "new" then stream.write "new " + end + + stream.write prop.name + + if prop isa MMethod then + stream.write prop.intro.msignature.to_s + end + + var mdoc = prop.intro.mdoc + if mdoc != null then + stream.write " # " + stream.write mdoc.content.first + end + stream.write line_separator + end + end + end + + redef fun complete_mdoc do return mclass.intro.mdoc +end + private class AutocompletePhase super Phase @@ -113,24 +240,41 @@ private class AutocompletePhase var compile_dir = "NIT_VIM_DIR".environ if compile_dir.is_empty then compile_dir = "HOME".environ / ".vim/nit" compile_dir.mkdir - var modules_stream = new OFStream.open(compile_dir / "modules.txt") - var classes_stream = new OFStream.open(compile_dir / "classes.txt") - var properties_stream = new OFStream.open(compile_dir / "properties.txt") + + var modules_stream = new FileWriter.open(compile_dir / "modules.txt") + var classes_stream = new FileWriter.open(compile_dir / "classes.txt") + var constructors_stream = new FileWriter.open(compile_dir / "constructors.txt") + var types_stream = new FileWriter.open(compile_dir / "types.txt") + var properties_stream = new FileWriter.open(compile_dir / "properties.txt") # Got all known modules var model = mainmodule.model for mmodule in model.mmodules do - mmodule.write_to_stream modules_stream + mmodule.write_doc(mainmodule, modules_stream) end # TODO list other modules from the Nit lib - # TODO list submodules # Get all known classes for mclass in model.mclasses do if not mainmodule.is_visible(mclass.intro_mmodule, public_visibility) then continue + var mclass_intro = mclass.intro + + # Can it be instantiated? + if mclass.kind != interface_kind and mclass.kind != abstract_kind then - mclass.intro.write_to_stream classes_stream + for prop in mclass.all_mproperties(mainmodule, public_visibility) do + if prop isa MMethod and prop.is_init then + mclass_intro.target_constructor = prop.intro + mclass_intro.write_doc(mainmodule, constructors_stream) + end + end + mclass_intro.target_constructor = null + end + + # Always add to types and classes + mclass.mclass_type.write_doc(mainmodule, classes_stream) + mclass.mclass_type.write_doc(mainmodule, types_stream) end # Get all known properties @@ -138,17 +282,24 @@ private class AutocompletePhase var intro_mmodule = mproperty.intro_mclassdef.mmodule if not mainmodule.is_visible(intro_mmodule, public_visibility) then continue + # Is it a virtual type? + if mproperty isa MVirtualTypeProp then + mproperty.intro.write_doc(mainmodule, types_stream) + continue + end + # Skip properties beginning with @ or _ var first_letter = mproperty.name.chars.first if first_letter == '@' or first_letter == '_' then continue - mproperty.intro.write_to_stream properties_stream + mproperty.intro.write_doc(mainmodule, properties_stream) end # Close streams - for stream in [modules_stream, classes_stream, properties_stream] do - stream.close + for stream in [modules_stream, classes_stream, properties_stream, + types_stream, constructors_stream] do + stream.close var error = stream.last_error if error != null then toolcontext.error(null, "Failed to write Vim autocomplete file: {error}")