This module provides the ModelVisitor abstract class and
refines the classes of the MEntity hierarchy to add visiting related methods.
A standard approach on complex visitor is to dispatch the ModelVisitor::visit on the
entities to do specific things.
class FooVisitor
  super ModelVisitor
  redef fun visit(e) do e.foo_visit(self)
end
redef class MEntity
do
  fun foo_vist(v: FooVisitor) do visit_all(v)
end
redef class MClass
do
  redef fun foo_visit(v) do
     print self
     super
  end
end
nitc :: model_visitor $ MClassDef
A definition (an introduction or a refinement) of a class in a modulenitc :: model_visitor $ MEntity
A named and possibly documented entity in the model.nitc :: model_visitor $ MModule
A Nit module is usually associated with a Nit source file.nitc :: model_visitor $ MClassDef
A definition (an introduction or a refinement) of a class in a modulenitc :: model_visitor $ MEntity
A named and possibly documented entity in the model.nitc :: model_visitor $ MModule
A Nit module is usually associated with a Nit source file.Serializable::inspect to show more useful information
			nitc :: modelbuilder
more_collections :: more_collections
Highly specific, but useful, collections-related classes.serialization :: serialization_core
Abstract services to serialize Nit objects to different formatsnitc :: toolcontext
Common command-line tool infrastructure than handle options and error messagescore :: union_find
union–find algorithm using an efficient disjoint-set data structure
# Simple visitor framework for Nit models.
#
# This module provides the `ModelVisitor` abstract class and
# refines the classes of the `MEntity` hierarchy to add visiting related methods.
#
# A standard approach on complex visitor is to dispatch the `ModelVisitor::visit` on the
# entities to do specific things.
#
# ~~~nitish
# class FooVisitor
#   super ModelVisitor
#   redef fun visit(e) do e.foo_visit(self)
# end
#
# redef class MEntity
# do
#   fun foo_vist(v: FooVisitor) do visit_all(v)
# end
#
# redef class MClass
# do
#   redef fun foo_visit(v) do
#      print self
#      super
#   end
# end
# ~~~
module model_visitor
import model_filters
# The abstract model visitor template.
#
# Specific visitor must implement the `visit` method to perform the work.
abstract class ModelVisitor
	# Visit the entity `e`.
	#
	# This method setups `current_entity` and call `visit`.
	# If `e` is null, nothing is done.
	fun enter_visit(e: nullable MEntity) do
		if e == null then return
		if not accept_mentity(e) then return
		var old_entity = current_entity
		current_entity = e
		visit(e)
		current_entity = old_entity
	end
	# The current visited entity
	var current_entity: nullable MEntity = null
	# Method to define in specific visitor.
	#
	# It should not be called directly but used by `enter_visit`
	protected fun visit(e: MEntity) is abstract
	# Filters to apply when visiting the model.
	#
	# See ModelFilters for configuration.
	var filter: ModelFilter is lazy, writable, optional do
		return new ModelFilter(
			min_visibility = protected_visibility,
			accept_fictive = false,
			accept_test = false,
			accept_example = false,
			accept_redef = true,
			accept_extern = true,
			accept_attribute = true,
			accept_empty_doc = true
		)
	end
	# Should we accept this `mentity` from the view?
	#
	# If no `override_filter` is passed then use `self.filter`.
	fun accept_mentity(mentity: MEntity, override_filter: nullable ModelFilter): Bool do
		if override_filter != null then
			return override_filter.accept_mentity(mentity)
		end
		return filter.accept_mentity(mentity)
	end
end
redef class MEntity
	# Call `v.enter_visit` on all nested entities.
	#
	# See the specific implementation in the subclasses.
	fun visit_all(v: ModelVisitor) do end
end
redef class Model
	# Visit all the packages of the model.
	redef fun visit_all(v) do
		for x in mpackages do v.enter_visit(x)
	end
end
redef class MPackage
	# Visit the root group of the package.
	redef fun visit_all(v) do
		v.enter_visit(root)
	end
end
redef class MGroup
	# Visit all the subgroups and modules of the group.
	redef fun visit_all(v) do
		for x in in_nesting.direct_smallers do v.enter_visit(x)
		for x in mmodules do v.enter_visit(x)
	end
end
redef class MModule
	# Visit all the classes and class definitions of the module.
	#
	# On class introduction, the `MClass` then the `MClassDef` are visited.
	# On class refinement, only the `MClassDef` is visited (the `MClass` is visited in an imported module).
	# On class importation, nothing is visited (the `MClass` and the `MClassDef` are visited in imported modules).
	redef fun visit_all(v) do
		for x in mclassdefs do
			if x.is_intro then v.enter_visit(x.mclass)
			v.enter_visit(x)
		end
	end
end
redef class MClassDef
	# Visit all the classes and class definitions of the module.
	#
	# On property introduction, the `MProperty` then the `MPropDef` are visited.
	# On property redefinition, only the `MPropDef` is visited (the `MProperty` is visited in an inherited class).
	# On property inheritance, nothing is visited (the `MProperty` and the `MPropDef` are visited in inherited classes).
	redef fun visit_all(v) do
		for x in mpropdefs do
			if x.is_intro then v.enter_visit(x.mproperty)
			v.enter_visit(x)
		end
	end
end
src/model/model_visitor.nit:15,1--154,3