1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Generate files used by the Vim plugin to autocomplete with doc
17 # There is 3 files generated, each with a different target: modules, types,
18 # properties and constructors. Each line describe a different entity,
21 # 1. Short name to use in autocompletion
24 # 4. Full doc with extra
26 # The priority with those files is for them to be analyzed efficiently, for
27 # this reason, the data is prepared in advance and some information may be
29 module vim_autocomplete
33 import modelize
::modelize_class
36 redef class ToolContext
37 # Phase generating the files for the Vim plugin
38 var autocomplete_phase
: Phase = new AutocompletePhase(self, [modelize_class_phase
])
40 # Shall we generate the files for the Vim plugin?
41 var opt_vim_autocomplete
= new OptionBool(
42 "Generate metadata files used by the Vim plugin for autocompletion", "--vim-autocomplete")
47 option_context
.add_option opt_vim_autocomplete
52 private fun field_separator
: String do return "#====#"
53 private fun line_separator
: String do return "#nnnn#"
55 private fun write_to_stream
(stream
: Writer)
57 # 1. Short name for autocompletion
58 stream
.write complete_name
59 stream
.write field_separator
62 stream
.write complete_name
63 write_signature_to_stream
(stream
)
64 stream
.write field_separator
67 var mdoc
= complete_mdoc
69 stream
.write mdoc
.content
.first
72 # 4. Full doc with extra
73 stream
.write field_separator
76 stream
.write full_name
77 write_signature_to_stream
(stream
)
78 for i
in 2.times
do stream
.write line_separator
79 stream
.write mdoc
.content
.join
(line_separator
)
85 private fun write_signature_to_stream
(stream
: Writer) do end
87 # Actual name used in completion
88 private fun complete_name
: String do return name
90 # Doc to use in completion
91 private fun complete_mdoc
: nullable MDoc do return mdoc
94 redef class MMethodDef
95 redef fun write_signature_to_stream
(stream
)
97 var msignature
= msignature
98 if msignature
!= null then
99 stream
.write msignature
.to_s
104 redef class MAttributeDef
105 redef fun write_signature_to_stream
(stream
)
107 var static_mtype
= static_mtype
108 if static_mtype
!= null then
109 stream
.write stream
.to_s
114 # Use `MClassDef` as anchor for its constructors only
115 redef class MClassDef
116 private var target_constructor
: nullable MMethodDef = null
118 redef fun complete_name
120 var target_constructor
= target_constructor
121 assert target_constructor
!= null
124 var mparameters
= mclass
.mparameters
125 if not mparameters
.is_empty
then
126 params
= "[{mparameters.join(", ")}]"
131 if target_constructor
.name
!= "init" and target_constructor
.name
!= "new" then
132 return name
+ params
+ "." + target_constructor
.name
138 redef fun complete_mdoc
140 var target_constructor
= target_constructor
141 assert target_constructor
!= null
143 if target_constructor
.name
!= "init" and target_constructor
.name
!= "new" then
144 return target_constructor
.mdoc
151 private class AutocompletePhase
154 redef fun process_mainmodule
(mainmodule
, given_mmodules
)
156 if not toolcontext
.opt_vim_autocomplete
.value
then return
158 var compile_dir
= "NIT_VIM_DIR".environ
159 if compile_dir
.is_empty
then compile_dir
= "HOME".environ
/ ".vim/nit"
162 var modules_stream
= new FileWriter.open
(compile_dir
/ "modules.txt")
163 var classes_stream
= new FileWriter.open
(compile_dir
/ "classes.txt")
164 var constructors_stream
= new FileWriter.open
(compile_dir
/ "constructors.txt")
165 var types_stream
= new FileWriter.open
(compile_dir
/ "types.txt")
166 var properties_stream
= new FileWriter.open
(compile_dir
/ "properties.txt")
168 # Got all known modules
169 var model
= mainmodule
.model
170 for mmodule
in model
.mmodules
do
171 mmodule
.write_to_stream modules_stream
174 # TODO list other modules from the Nit lib
176 # Get all known classes
177 for mclass
in model
.mclasses
do
178 if not mainmodule
.is_visible
(mclass
.intro_mmodule
, public_visibility
) then continue
179 var mclass_intro
= mclass
.intro
181 # Can it be instantiated?
182 if mclass
.kind
!= interface_kind
and mclass
.kind
!= abstract_kind
then
184 for prop
in mclass
.all_mproperties
(mainmodule
, public_visibility
) do
185 if prop
isa MMethod and prop
.is_init
then
186 mclass_intro
.target_constructor
= prop
.intro
187 mclass_intro
.write_to_stream constructors_stream
190 mclass_intro
.target_constructor
= null
193 # Always add to types and classes
194 mclass
.mclass_type
.write_to_stream classes_stream
195 mclass
.mclass_type
.write_to_stream types_stream
198 # Get all known properties
199 for mproperty
in model
.mproperties
do
200 var intro_mmodule
= mproperty
.intro_mclassdef
.mmodule
201 if not mainmodule
.is_visible
(intro_mmodule
, public_visibility
) then continue
203 # Is it a virtual type?
204 if mproperty
isa MVirtualTypeProp then
205 mproperty
.intro
.write_to_stream types_stream
209 # Skip properties beginning with @ or _
210 var first_letter
= mproperty
.name
.chars
.first
211 if first_letter
== '@' or first_letter
== '_' then continue
213 mproperty
.intro
.write_to_stream properties_stream
217 for stream
in [modules_stream
, classes_stream
, properties_stream
,
218 types_stream
, constructors_stream
] do
221 var error
= stream
.last_error
222 if error
!= null then
223 toolcontext
.error
(null, "Failed to write Vim autocomplete file: {error}")