model_views: introduce `mentities_by_name` in views
[nit.git] / src / model / model_views.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 module model_views
16
17 import model_visitor
18
19 # Provide a configurable view to a model.
20 #
21 # This can be useful when you need to filter some mentities from a model
22 # like private or fictive.
23 #
24 # TODO doc usage
25 class ModelView
26 super ModelVisitor
27
28 autoinit(model, mainmodule, filter)
29
30 # The model to view through `self`.
31 var model: Model
32
33 # MModule used to flatten mclass hierarchy
34 var mainmodule: MModule
35
36 # MPackages visible through `self`.
37 var mpackages: Set[MPackage] is lazy do
38 var mpackages = new HashSet[MPackage]
39 for mpackage in model.mpackages do
40 if not accept_mentity(mpackage) then continue
41 mpackages.add mpackage
42 end
43 return mpackages
44 end
45
46 # MGroups visible through `self`.
47 var mgroups: Set[MGroup] is lazy do
48 var mgroups = new HashSet[MGroup]
49 for mpackage in mpackages do
50 for mgroup in mpackage.mgroups do
51 if not accept_mentity(mgroup) then continue
52 mgroups.add mgroup
53 end
54 end
55 return mgroups
56 end
57
58 # MModules visible through `self`.
59 var mmodules: Set[MModule] is lazy do
60 var mmodules = new HashSet[MModule]
61 for mmodule in model.mmodules do
62 if not accept_mentity(mmodule) then continue
63 mmodules.add mmodule
64 end
65 return mmodules
66 end
67
68 # MClasses visible through `self`.
69 var mclasses: Set[MClass] is lazy do
70 var mclasses = new HashSet[MClass]
71 for mclass in model.mclasses do
72 if not accept_mentity(mclass) then continue
73 mclasses.add mclass
74 end
75 return mclasses
76 end
77
78 # MClassDefs visible through `self`.
79 var mclassdefs: Set[MClassDef] is lazy do
80 var mclassdefs = new HashSet[MClassDef]
81 for mclass in mclasses do
82 for mclassdef in mclass.mclassdefs do
83 if not accept_mentity(mclassdef) then continue
84 mclassdefs.add mclassdef
85 end
86 end
87 return mclassdefs
88 end
89
90 # MProperties visible through `self`.
91 var mproperties: Set[MProperty] is lazy do
92 var mproperties = new HashSet[MProperty]
93 for mproperty in model.mproperties do
94 if not accept_mentity(mproperty) then continue
95 mproperties.add mproperty
96 end
97 return mproperties
98 end
99
100 # MPropdefs visible through `self`.
101 var mpropdefs: Set[MPropDef] is lazy do
102 var mpropdefs = new HashSet[MPropDef]
103 for mproperty in mproperties do
104 for mpropdef in mproperty.mpropdefs do
105 if not accept_mentity(mpropdef) then continue
106 mpropdefs.add mpropdef
107 end
108 end
109 return mpropdefs
110 end
111
112 # Lists all MEntities visible through `self`.
113 var mentities: Set[MEntity] is lazy do
114 var res = new HashSet[MEntity]
115 res.add_all mpackages
116 res.add_all mgroups
117 res.add_all mmodules
118 res.add_all mclasses
119 res.add_all mclassdefs
120 res.add_all mproperties
121 res.add_all mpropdefs
122 return res
123 end
124
125 # Searches the MEntity that matches `full_name`.
126 fun mentity_by_full_name(full_name: String): nullable MEntity do
127 for mentity in mentities do
128 if mentity.full_name == full_name then return mentity
129 end
130 return null
131 end
132
133 # Searches the MEntities that matches `full_name`.
134 fun mentities_by_name(name: String): Array[MEntity] do
135 var res = new Array[MEntity]
136 for mentity in mentities do
137 if mentity.name == name then res.add mentity
138 end
139 return res
140 end
141
142 # Build an concerns tree with from `self`
143 fun to_tree: MEntityTree do
144 var v = new ModelTreeVisitor
145 v.filter = self.filter
146 for mpackage in mpackages do
147 v.enter_visit(mpackage)
148 end
149 return v.tree
150 end
151
152 # Build the POSet of `mmodules` importation.
153 fun mmodules_poset(mmodules: Set[MModule]): POSet[MModule] do
154 return model.mmodule_importation_hierarchy.sub(mmodules)
155 end
156
157 # Build the POSet of `mclasses` hierarchy.
158 fun mclasses_poset(mainmodule: MModule, mclasses: Set[MClass]): POSet[MClass] do
159 return mainmodule.flatten_mclass_hierarchy.sub(mclasses)
160 end
161 end
162
163 class LookupNamespaceVisitor
164 super ModelVisitor
165
166 var namespace: String
167
168 private var parts: Array[String] is lazy do return namespace.split_with("::")
169
170 var results = new Array[MEntity]
171
172 redef fun visit(mentity) do mentity.accept_namespace_visitor(self)
173 end
174
175 class ModelTreeVisitor
176 super ModelVisitor
177
178 var tree = new MEntityTree
179
180 redef fun visit(mentity) do mentity.accept_tree_visitor(self)
181 end
182
183 redef class MEntity
184 private fun accept_namespace_visitor(v: LookupNamespaceVisitor) do
185 if v.parts.is_empty then return
186 if name != v.parts.first then return
187 v.parts.shift
188 if v.parts.is_empty then
189 v.results.add self
190 return
191 end
192 visit_all(v)
193 end
194
195 private fun accept_tree_visitor(v: ModelTreeVisitor) do end
196 end
197
198 redef class MPackage
199 redef fun accept_tree_visitor(v) do
200 v.tree.add(null, self)
201 visit_all(v)
202 end
203 end
204
205 redef class MGroup
206 redef fun accept_tree_visitor(v) do
207 var parent = self.parent
208 if parent != null then
209 v.tree.add(parent, self)
210 else
211 v.tree.add(mpackage, self)
212 end
213 visit_all(v)
214 end
215 end
216
217 redef class MModule
218 redef fun accept_tree_visitor(v) do
219 v.tree.add(mgroup, self)
220 visit_all(v)
221 end
222 end
223
224 redef class MClass
225 # We don't want to collect classes from full namespace.
226 redef fun accept_namespace_visitor(v) do end
227 end
228
229 redef class MClassDef
230 redef fun accept_tree_visitor(v) do
231 v.tree.add(mmodule, self)
232 visit_all(v)
233 end
234 end
235
236 redef class MProperty
237 # We don't want to collect properties from full namespace.
238 redef fun accept_namespace_visitor(v) do end
239 end
240
241 redef class MPropDef
242 redef fun accept_tree_visitor(v) do
243 v.tree.add(mclassdef, self)
244 visit_all(v)
245 end
246 end