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 # Simple visitor framework for Nit models.
17 # This module provides the `ModelVisitor` abstract class and
18 # refines the classes of the `MEntity` hierarchy to add visiting related methods.
20 # A standard approach on complex visitor is to dispatch the `ModelVisitor::visit` on the
21 # entities to do specific things.
26 # redef fun visit(e) do e.foo_visit(self)
31 # fun foo_vist(v: FooVisitor) do visit_all(v)
36 # redef fun foo_visit(v) do
46 # The abstract model visitor template.
48 # Specific visitor must implement the `visit` method to perform the work.
49 abstract class ModelVisitor
50 # Visit the entity `e`.
52 # This method setups `current_entity` and call `visit`.
53 # If `e` is null, nothing is done.
54 fun enter_visit
(e
: nullable MEntity) do
55 if e
== null then return
56 if not accept_mentity
(e
) then return
57 var old_entity
= current_entity
60 current_entity
= old_entity
63 # The current visited entity
64 var current_entity
: nullable MEntity = null
66 # Method to define in specific visitor.
68 # It should not be called directly but used by `enter_visit`
69 protected fun visit
(e
: MEntity) is abstract
71 # Filter classes and method on the visibility.
73 # If set, only the classes and method with at least the given
74 # visibility level will be visited.
75 var min_visibility
: nullable MVisibility = null is writable
77 # Can we accept this `mentity` in the view regarding its visibility?
78 fun accept_visibility
(mentity
: MEntity): Bool do
79 return mentity
.accept_visibility
(min_visibility
)
82 # Include fictive entities?
84 # By default, fictive entities (see `MEntity::is_fictive`) are not visited.
85 var include_fictive
= false is writable
87 # Can we accept this `mentity` in the view regarding its fictivity?
88 fun accept_fictive
(mentity
: MEntity): Bool do
89 if include_fictive
then return true
90 return not mentity
.is_fictive
93 # Should we accept mentities with empty documentation?
96 var include_empty_doc
= true is writable
98 # Can we accept this `mentity` regarding its documentation?
99 fun accept_empty_doc
(mentity
: MEntity): Bool do
100 if include_empty_doc
then return true
101 return mentity
.mdoc
!= null
104 # Should we accept nitunit test suites?
106 # Default is `false`.
107 var include_test
= false is writable
109 # Can we accept this `mentity` regarding its test suite status?
110 fun accept_test
(mentity
: MEntity): Bool do
111 if include_test
then return true
112 if mentity
isa MProperty then
113 if mentity
.is_before
or mentity
.is_before_all
then return false
114 if mentity
.is_after
or mentity
.is_after_all
then return false
116 if mentity
isa MPropDef then
117 if mentity
.is_before
or mentity
.is_before_all
then return false
118 if mentity
.is_after
or mentity
.is_after_all
then return false
120 return not mentity
.is_test
123 # Should we accept `MAttribute` instances?
126 var include_attribute
= true is writable
128 # Can we accept this `mentity` regarding its type?
129 fun accept_attribute
(mentity
: MEntity): Bool do
130 if include_attribute
then return true
131 if mentity
isa MAttribute then return false
132 if mentity
isa MAttributeDef then return false
136 # Should we accept this `mentity` from the view?
137 fun accept_mentity
(mentity
: MEntity): Bool do
138 if not accept_visibility
(mentity
) then return false
139 if not accept_fictive
(mentity
) then return false
140 if not accept_empty_doc
(mentity
) then return false
141 if not accept_test
(mentity
) then return false
142 if not accept_attribute
(mentity
) then return false
149 # Call `v.enter_visit` on all nested entities.
151 # See the specific implementation in the subclasses.
152 fun visit_all
(v
: ModelVisitor) do end
154 private fun accept_visibility
(min_visibility
: nullable MVisibility): Bool do
155 if min_visibility
== null then return true
156 return visibility
>= min_visibility
161 # Visit all the packages of the model.
162 redef fun visit_all
(v
) do
163 for x
in mpackages
do v
.enter_visit
(x
)
168 # Visit the root group of the package.
169 redef fun visit_all
(v
) do
175 # Visit all the subgroups and modules of the group.
176 redef fun visit_all
(v
) do
177 for x
in in_nesting
.direct_smallers
do v
.enter_visit
(x
)
178 for x
in mmodules
do v
.enter_visit
(x
)
183 # Visit all the classes and class definitions of the module.
185 # On class introduction, the `MClass` then the `MClassDef` are visited.
186 # On class refinement, only the `MClassDef` is visited (the `MClass` is visited in an imported module).
187 # On class importation, nothing is visited (the `MClass` and the `MClassDef` are visited in imported modules).
188 redef fun visit_all
(v
) do
189 for x
in mclassdefs
do
190 if x
.is_intro
then v
.enter_visit
(x
.mclass
)
196 redef class MClassDef
197 # Visit all the classes and class definitions of the module.
199 # On property introduction, the `MProperty` then the `MPropDef` are visited.
200 # On property redefinition, only the `MPropDef` is visited (the `MProperty` is visited in an inherited class).
201 # On property inheritance, nothing is visited (the `MProperty` and the `MPropDef` are visited in inherited classes).
202 redef fun visit_all
(v
) do
203 for x
in mpropdefs
do
204 if x
.is_intro
then v
.enter_visit
(x
.mproperty
)