+ redef fun accept_class_visitor(v)
+ do
+ var n = node
+ while n != null do
+ v.enter_visit(n)
+ n = n.next_node
+ end
+ end
+
+ # Accept a class visitor (on class properties)
+ redef fun accept_properties_visitor(v)
+ do
+ var n = node
+ while n != null do
+ v.enter_visit(n)
+ n = n.next_node
+ end
+
+ for p in src_local_properties do
+ p.accept_property_visitor(v)
+ end
+ end
+
+ # Introduce or inherit default constructors
+ private fun process_default_constructors(v: PropertyBuilderVisitor)
+ do
+ # Is there already a constructor ?
+ for gp in global_properties do
+ if gp.is_init then
+ # Return if explicit constructor in the class
+ if gp.intro.local_class == self then return
+ end
+ end
+
+ # Collect visible constructors in super stateful classes
+ var super_inits = new ArraySet[MMLocalProperty]
+ var super_constructors = new ArraySet[MMGlobalProperty]
+ for sc in che.direct_greaters do
+ if sc.global.is_enum or sc.global.is_interface then continue
+ for gp in sc.global_properties do
+ if not gp.is_init then continue
+ super_constructors.add(gp)
+ end
+ var initname = once ("init".to_symbol)
+ if sc.has_global_property_by_name(initname) then
+ var gp = sc.get_property_by_name(initname)
+ super_inits.add(self[gp])
+ end
+ end
+
+ # Collect unassigned attributes
+ var unassigned_attributes = new Array[MMSrcAttribute]
+ for a in src_local_properties do
+ if a isa MMSrcAttribute then
+ var n = a.node
+ if n.n_expr == null then unassigned_attributes.add(a)
+ end
+ end
+
+ if not super_constructors.is_empty then
+ # Select most specific classes introducing inheritable constructors
+ # Mixin classes are skipped
+ var supers = new Array[MMLocalClass]
+ for gp in super_constructors do
+ var sc = gp.local_class
+ if supers.has(sc) then continue
+ if not sc.global.is_mixin then
+ supers.add(sc)
+ end
+ end
+ supers = che.order.select_smallests(supers)
+
+ # A mixin class can only have 0 or 1 most specific non-mixin superclass
+ var superclass: nullable MMLocalClass = null # This most specific non-mixin superclass (if any)
+
+ if supers.length > 1 then
+ v.error(node, "Error: Explicit constructor required in {self} since multiple inheritance of constructor is forbiden. Conflicting classes are {supers.join(", ")}. Costructors are {super_constructors.join(", ")}.")
+ return
+ else if supers.length == 1 then
+ superclass = supers.first
+ end
+
+ for gp in super_constructors do
+ # Inherit constructors : the one of the non-mixin super class or all from the all mixin super-classes
+ if superclass == null or gp.local_class == superclass then
+ make_visible_an_inherited_global_property(gp)
+ end
+ end
+ global.mixin_of = superclass.as(not null).global # FIXME Dear! this should break!
+ else
+ # v.error(nodes.first, "Error, constructor required in {self} since no anonimous init found in {sc}.")
+
+ # unassigned attributes, then implicit consructors are generated
+ var p = new MMImplicitInit(self, unassigned_attributes, super_inits.to_a)
+ add_src_local_property(v, p)
+ #print("Create implicit init {p} in {self} from {super_inits.join(", ")} + {unassigned_attributes.length} args")
+ end
+ end
+