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