model/model_contract: Move contract model representation
[nit.git] / src / model / model_filters.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_filters
16
17 import model_examples
18 import parse_annotations
19
20 # A list of filters that can be applied on a MEntity
21 #
22 #
23 # By default ModelFilter accepts all mentity.
24 #
25 # ~~~nitish
26 # var filter = new ModelFilter
27 # assert filter.accept_mentity(my_mentity) == true
28 # ~~~
29 #
30 # To quickly configure the filters, options can be passed to the constructor:
31 # ~~~
32 # var filter = new ModelFilter(
33 # min_visibility = protected_visibility,
34 # accept_fictive = false,
35 # accept_test = false,
36 # accept_redef = false,
37 # accept_extern = false,
38 # accept_attribute = false,
39 # accept_empty_doc = false
40 # )
41 # ~~~
42 class ModelFilter
43
44 # Initialize `self` by copying the options from another `filter`
45 init from(filter: ModelFilter) do
46 init(
47 min_visibility = filter.min_visibility,
48 accept_fictive = filter.accept_fictive,
49 accept_test = filter.accept_test,
50 accept_redef = filter.accept_redef,
51 accept_extern = filter.accept_extern,
52 accept_example = filter.accept_example,
53 accept_attribute = filter.accept_attribute,
54 accept_empty_doc = filter.accept_empty_doc,
55 accept_inherited = filter.accept_inherited,
56 accept_full_name = filter.accept_full_name
57 )
58 end
59
60 # Accept `mentity` based on all the options from `self`?
61 #
62 # If one of the filter returns `false` then the `mentity` is not accepted.
63 fun accept_mentity(mentity: MEntity): Bool do
64 if not accept_mentity_broken(mentity) then return false
65 if not accept_mentity_visibility(mentity) then return false
66 if not accept_mentity_fictive(mentity) then return false
67 if not accept_mentity_generated(mentity) then return false
68 if not accept_mentity_test(mentity) then return false
69 if not accept_mentity_redef(mentity) then return false
70 if not accept_mentity_extern(mentity) then return false
71 if not accept_mentity_example(mentity) then return false
72 if not accept_mentity_attribute(mentity) then return false
73 if not accept_mentity_empty_doc(mentity) then return false
74 if not accept_mentity_inherited(mentity) then return false
75 if not accept_mentity_full_name(mentity) then return false
76 return true
77 end
78
79 # Minimum visibility an entity must have to be accepted
80 #
81 # Default is `private_visibility`.
82 var min_visibility: MVisibility = private_visibility is optional, writable
83
84 # Accept `mentity` if its visibility is above `min_visibility`
85 fun accept_mentity_visibility(mentity: MEntity): Bool do
86 return mentity.visibility >= min_visibility
87 end
88
89 # Accept fictive entities?
90 #
91 # Default is `true`.
92 var accept_fictive = true is optional, writable
93
94 # Accept only non-fictive entities
95 #
96 # See `MEntity::is_fictive`.
97 fun accept_mentity_fictive(mentity: MEntity): Bool do
98 if accept_fictive then return true
99 return not mentity.is_fictive
100 end
101
102 # Accept generated entities?
103 #
104 # Default is `true`.
105 var accept_generated = true is optional, writable
106
107 # Accept only non-generated entities
108 #
109 # See `MEntity::is_generated`.
110 fun accept_mentity_generated(mentity: MEntity): Bool do
111 if accept_generated then return true
112 if mentity isa MClass then mentity = mentity.intro
113 if mentity isa MProperty then mentity = mentity.intro
114 if mentity isa MModule then
115 return not mentity.has_annotation("generated")
116 else if mentity isa MClassDef then
117 return not mentity.has_annotation("generated")
118 else if mentity isa MPropDef then
119 return not mentity.has_annotation("generated")
120 end
121 return true
122 end
123
124 # Accept nitunit test suites?
125 #
126 # Default is `true`.
127 var accept_test = true is optional, writable
128
129 # Accept only entities that are not `nitunit` related
130 fun accept_mentity_test(mentity: MEntity): Bool do
131 if accept_test then return true
132 if mentity isa MProperty then return accept_mentity(mentity.intro)
133 if mentity isa MMethodDef then
134 if mentity.is_before then return false
135 if mentity.is_before_all then return false
136 if mentity.is_after then return false
137 if mentity.is_after_all then return false
138 end
139 return not mentity.is_test
140 end
141
142 # Accept redef classdefs and propdefs?
143 #
144 # Default is `true`.
145 var accept_redef = true is optional, writable
146
147 # Accept a MClassDefs and MPropeDefs onyl if they are an introduction
148 #
149 # See `MClassDef::is_intro` and `MPropDef::is_intro`.
150 fun accept_mentity_redef(mentity: MEntity): Bool do
151 if accept_redef then return true
152 if mentity isa MClassDef then
153 return mentity.is_intro
154 else if mentity isa MPropDef then
155 return mentity.is_intro
156 end
157 return true
158 end
159
160 # Accept extern entities?
161 #
162 # Default is `true`.
163 var accept_extern = true is optional, writable
164
165 # Accept only non- extern entities
166 #
167 # See `MEntity::is_extern`.
168 fun accept_mentity_extern(mentity: MEntity): Bool do
169 if accept_extern then return true
170 if mentity isa MMethodDef then
171 return not mentity.is_extern
172 end
173 return true
174 end
175
176 # Accept `MAttribute` and `MAttributeDef` instances?
177 #
178 # Default is `true`.
179 var accept_attribute = true is optional, writable
180
181 # Accept only entities that are not a `MAttribute` or `MAttributeDef`
182 fun accept_mentity_attribute(mentity: MEntity): Bool do
183 if accept_attribute then return true
184 if mentity isa MAttribute then return false
185 if mentity isa MAttributeDef then return false
186 return true
187 end
188
189 # Accept entities with empty documentation?
190 #
191 # Default is `true`.
192 var accept_empty_doc = true is optional, writable
193
194 # Accept only entities with documentation
195 fun accept_mentity_empty_doc(mentity: MEntity): Bool do
196 if accept_empty_doc then return true
197 return mentity.mdoc_or_fallback != null
198 end
199
200 # Accept examples?
201 #
202 # Default is `true`.
203 var accept_example = true is optional, writable
204
205 # Accept only entities that are not example related
206 fun accept_mentity_example(mentity: MEntity): Bool do
207 if accept_example then return true
208 return not mentity.is_example
209 end
210
211 # If set, accept only entities local to `accept_inherited`
212 var accept_inherited: nullable MEntity = null is optional, writable
213
214 # Accept only entities local to `accept_inherited`
215 #
216 # This means no imported or inherited entities.
217 fun accept_mentity_inherited(mentity: MEntity): Bool do
218 var context = accept_inherited
219 if context == null then return true
220 if context isa MPackage then
221 if mentity isa MGroup then return mentity.mpackage == context
222 if mentity isa MModule then return mentity.mpackage == context
223 end
224 if context isa MGroup then
225 if mentity isa MModule then return mentity.mgroup == context
226 end
227 if context isa MModule then
228 if mentity isa MClass then return mentity.intro.mmodule == context
229 if mentity isa MClassDef then return mentity.mmodule == context
230 end
231 if context isa MClass then
232 if mentity isa MProperty then return mentity.intro_mclassdef.mclass == context
233 if mentity isa MPropDef then return mentity.mclassdef.mclass == context
234 end
235 if context isa MClassDef then
236 if mentity isa MProperty then return mentity.intro_mclassdef == context
237 if mentity isa MPropDef then return mentity.mclassdef == context
238 end
239 return true
240 end
241
242 # If set, accept only entities where `MEntity::full_name` contains `string`
243 var accept_full_name: nullable String = null is optional, writable
244
245 # Accept only entities where `MEntity::full_name` contains `string`
246 fun accept_mentity_full_name(mentity: MEntity): Bool do
247 var string = accept_full_name
248 if string == null then return true
249 return mentity.full_name.has(string)
250 end
251
252 # Accept broken classes and properties?
253 #
254 # Default is `false`.
255 var accept_broken = false is optional, writable
256
257 # Accept only non broken entities
258 fun accept_mentity_broken(mentity: MEntity): Bool do
259 if accept_broken then return true
260 return not mentity.is_broken
261 end
262 end