name
on the type mtype
visible in the module mmodule
.Visibility in modules is correctly handled.
Protected properties are returned (it is up to the caller to check and reject protected properties).
If no such a property exists, then null is returned.
If more than one property exists, then an error on anode
is displayed and null is returned.
FIXME: add a way to handle property name conflict
# Return a property named `name` on the type `mtype` visible in the module `mmodule`.
# Visibility in modules is correctly handled.
# Protected properties are returned (it is up to the caller to check and reject protected properties).
# If no such a property exists, then null is returned.
# If more than one property exists, then an error on `anode` is displayed and null is returned.
# FIXME: add a way to handle property name conflict
fun try_get_mproperty_by_name2(anode: nullable ANode, mmodule: MModule, mtype: MType, name: String): nullable MProperty
do
var props = self.model.get_mproperties_by_name(name)
if props == null then
return null
end
var cache = self.try_get_mproperty_by_name2_cache[mmodule, mtype, name]
if cache != null then return cache
var res: nullable MProperty = null
var ress: nullable Array[MProperty] = null
for mprop in props do
if not mtype.has_mproperty(mmodule, mprop) then continue
if not mmodule.is_visible(mprop.intro_mclassdef.mmodule, mprop.visibility) then continue
# new-factories are invisible outside of the class
if mprop isa MMethod and mprop.is_new and (not mtype isa MClassType or mprop.intro_mclassdef.mclass != mtype.mclass) then
continue
end
if res == null then
res = mprop
continue
end
# Two global properties?
# First, special case for init, keep the most specific ones
if res isa MMethod and mprop isa MMethod and res.is_init and mprop.is_init then
var restype = res.intro_mclassdef.bound_mtype
var mproptype = mprop.intro_mclassdef.bound_mtype
if mproptype.is_subtype(mmodule, null, restype) then
# found a most specific constructor, so keep it
res = mprop
continue
end
end
# Ok, just keep all prop in the ress table
if ress == null then
ress = new Array[MProperty]
ress.add(res)
end
ress.add(mprop)
end
# There is conflict?
if ress != null and res isa MMethod and res.is_init then
# special case forinit again
var restype = res.intro_mclassdef.bound_mtype
var ress2 = new Array[MProperty]
for mprop in ress do
var mproptype = mprop.intro_mclassdef.bound_mtype
if not restype.is_subtype(mmodule, null, mproptype) then
ress2.add(mprop)
else if not mprop isa MMethod or not mprop.is_init then
ress2.add(mprop)
end
end
if ress2.is_empty then
ress = null
else
ress = ress2
ress.add(res)
end
end
if ress != null then
assert ress.length > 1
var s = new Array[String]
for mprop in ress do s.add mprop.full_name
self.error(anode, "Error: ambiguous property name `{name}` for `{mtype}`; conflict between {s.join(" and ")}.")
end
self.try_get_mproperty_by_name2_cache[mmodule, mtype, name] = res
return res
end
src/modelbuilder_base.nit:124,2--206,4