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 # An index that contains Nit code
17 # Model entities are indexed by their ANode.
19 # Vectorization is based on model usage such as:
20 # * modules importation
21 # * classes spcialization and refinement
22 # * methods calls and refinements
27 # var index = new CodeIndex(toolcontext)
28 # for mentity in mentities do
29 # index.index_mentity(mentity)
32 # # Match a piece of code
33 # var matches = index.match_code("print \"Hello, World!\"")
34 # for match in matches do
48 redef type DOC: CodeDocument
50 # ToolContext used to parse pieces of code
51 var toolcontext
: ToolContext
54 fun index_mentity
(mentity
: MEntity) do
55 var terms
= vectorize_mentity
(mentity
)
56 var doc
= new CodeDocument(mentity
, terms
)
57 index_document
(doc
, false)
60 # Match `code` with the index
61 fun match_code
(code
: String): Array[IndexMatch[DOC]] do
62 var node
= parse_code
(code
)
63 if node
== null then return new Array[IndexMatch[DOC]]
64 return match_node
(node
)
67 # Match `node` with the index
68 fun match_node
(node
: ANode): Array[IndexMatch[DOC]] do
69 var vector
= vectorize_node
(node
)
70 return match_vector
(vector
)
73 # Parse a piece of code
74 private fun parse_code
(code
: String): nullable AModule do
76 var node
= toolcontext
.parse_something
(code
)
77 if not node
isa AModule then return null
79 # Load code into model
80 var mbuilder
= toolcontext
.modelbuilder
81 mbuilder
.load_rt_module
(null, node
, "tmp")
86 # Transform `node` in a Vector
87 private fun vectorize_node
(node
: ANode): Vector do
88 var visitor
= new CodeIndexVisitor
89 visitor
.enter_visit
(node
)
93 # Transform `mentity` in a Vector
94 private fun vectorize_mentity
(mentity
: MEntity): Vector do
95 var node
= toolcontext
.modelbuilder
.mentity2node
(mentity
)
96 if node
== null then return new Vector
97 return vectorize_node
(node
)
101 # A specific document for mentities code
104 autoinit
(mentity
, terms_count
)
106 # MEntity related to this document
109 redef var title
= mentity
.full_name
is lazy
111 redef var uri
= mentity
.location
.to_s
is lazy
116 # Used to build a VSM Vector from a Nit ANode.
117 private class CodeIndexVisitor
120 var vector
= new Vector
122 redef fun visit
(node
) do
123 node
.accept_code_index_visitor
(self)
128 private fun accept_code_index_visitor
(v
: CodeIndexVisitor) do
133 redef class AStdImport
134 redef fun accept_code_index_visitor
(v
) do
135 var mmodule
= self.mmodule
136 if mmodule
!= null then
137 v
.vector
.inc
"import#{mmodule.full_name}"
142 redef class AStdClassdef
143 redef fun accept_code_index_visitor
(v
) do
144 var mclassdef
= self.mclassdef
145 if mclassdef
!= null then
146 if not mclassdef
.is_intro
then
147 v
.vector
.inc
"redef#{mclassdef.full_name}"
148 v
.vector
.inc
"redef#{mclassdef.mclass.full_name}"
155 redef class ASuperPropdef
156 redef fun accept_code_index_visitor
(v
) do
157 var mtype
= self.n_type
.mtype
158 if mtype
isa MClassType then
159 v
.vector
.inc
"super#{mtype.mclass.intro.full_name}"
160 v
.vector
.inc
"super#{mtype.mclass.full_name}"
166 redef fun accept_code_index_visitor
(v
) do
167 var mpropdef
= self.mpropdef
168 if mpropdef
!= null then
169 if not mpropdef
.is_intro
then
170 v
.vector
.inc
"redef#{mpropdef.mproperty.intro.full_name}"
171 v
.vector
.inc
"redef#{mpropdef.mproperty.full_name}"
178 redef class ASendExpr
179 redef fun accept_code_index_visitor
(v
) do
180 var callsite
= self.callsite
181 if callsite
!= null then
182 var args
= callsite
.signaturemap
.as(not null).map
.length
183 v
.vector
.inc
"call#{callsite.mpropdef.full_name}({args})"
184 v
.vector
.inc
"call#{callsite.mpropdef.mproperty.full_name}({args})"
185 v
.vector
.inc
"call#{callsite.mpropdef.mclassdef.full_name}({args})"
186 v
.vector
.inc
"call#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"
193 redef fun accept_code_index_visitor
(v
) do
194 var callsite
= self.callsite
195 if callsite
!= null then
196 var args
= callsite
.signaturemap
.as(not null).map
.length
197 v
.vector
.inc
"call#{callsite.mpropdef.full_name}({args})"
198 v
.vector
.inc
"call#{callsite.mpropdef.mproperty.full_name}({args})"
199 v
.vector
.inc
"new#{callsite.mpropdef.mclassdef.full_name}({args})"
200 v
.vector
.inc
"new#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"