if res == null then
res = mclass
else
- error(anode, "Ambigous class name '{name}'; conflict between {mclass.full_name} and {res.full_name}")
+ error(anode, "Error: ambiguous class name `{name}`; conflict between `{mclass.full_name}` and `{res.full_name}`.")
return null
end
end
return res
end
+ # Like `try_get_mclass_by_name` but display an error message when the class is not found
+ fun get_mclass_by_name(node: ANode, mmodule: MModule, name: String): nullable MClass
+ do
+ var mclass = try_get_mclass_by_name(node, mmodule, name)
+ if mclass == null then
+ error(node, "Type Error: missing primitive class `{name}'.")
+ end
+ return mclass
+ end
+
# 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).
assert ress.length > 1
var s = new Array[String]
for mprop in ress do s.add mprop.full_name
- self.error(anode, "Ambigous property name '{name}' for {mtype}; conflict between {s.join(" and ")}")
+ 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
# Helper function to display an error on a node.
# Alias for `self.toolcontext.error(n.hot_location, text)`
+ #
+ # This automatically sets `n.is_broken` to true.
fun error(n: nullable ANode, text: String)
do
var l = null
- if n != null then l = n.hot_location
+ if n != null then
+ l = n.hot_location
+ n.is_broken = true
+ end
self.toolcontext.error(l, text)
end
if res == null then
var l = null
if n != null then l = n.hot_location
- self.toolcontext.fatal_error(l, "Fatal Error: {recv} must have a property named {name}.")
+ self.toolcontext.fatal_error(l, "Fatal Error: `{recv}` must have a property named `{name}`.")
abort
end
return res
# FIXME: the name "resolve_mtype" is awful
fun resolve_mtype_unchecked(mmodule: MModule, mclassdef: nullable MClassDef, ntype: AType, with_virtual: Bool): nullable MType
do
- var name = ntype.n_id.text
+ var name = ntype.n_qid.n_id.text
var res: MType
# Check virtual type
var prop = try_get_mproperty_by_name(ntype, mclassdef, name).as(nullable MVirtualTypeProp)
if prop != null then
if not ntype.n_types.is_empty then
- error(ntype, "Type error: formal type {name} cannot have formal parameters.")
+ error(ntype, "Type Error: formal type `{name}` cannot have formal parameters.")
end
res = prop.mvirtualtype
if ntype.n_kwnullable != null then res = res.as_nullable
if p.name != name then continue
if not ntype.n_types.is_empty then
- error(ntype, "Type error: formal type {name} cannot have formal parameters.")
+ error(ntype, "Type Error: formal type `{name}` cannot have formal parameters.")
end
res = p
var arity = ntype.n_types.length
if arity != mclass.arity then
if arity == 0 then
- error(ntype, "Type error: '{name}' is a generic class.")
+ error(ntype, "Type Error: `{mclass.signature_to_s}` is a generic class.")
else if mclass.arity == 0 then
- error(ntype, "Type error: '{name}' is not a generic class.")
+ error(ntype, "Type Error: `{name}` is not a generic class.")
else
- error(ntype, "Type error: '{name}' has {mclass.arity} parameters ({arity} are provided).")
+ error(ntype, "Type Error: expected {mclass.arity} formal argument(s) for `{mclass.signature_to_s}`; got {arity}.")
end
return null
end
end
# If everything fail, then give up :(
- error(ntype, "Type error: class {name} not found in module {mmodule}.")
+ error(ntype, "Error: class `{name}` not found in module `{mmodule}`.")
return null
end
if mtype isa MGenericType then
var mclass = mtype.mclass
for i in [0..mclass.arity[ do
- var bound = mclass.intro.bound_mtype.arguments[i]
+ var intro = mclass.try_intro
+ if intro == null then return null # skip error
+ var bound = intro.bound_mtype.arguments[i]
var nt = ntype.n_types[i]
var mt = resolve_mtype(mmodule, mclassdef, nt)
if mt == null then return null # forward error
var anchor
if mclassdef != null then anchor = mclassdef.bound_mtype else anchor = null
if not check_subtype(nt, mmodule, anchor, mt, bound) then
- error(nt, "Type error: expected {bound}, got {mt}")
+ error(nt, "Type Error: expected `{bound}`, got `{mt}`.")
return null
end
end
end
end
+redef class ANode
+ # The indication that the node did not pass some semantic verifications.
+ #
+ # This simple flag is set by a given analysis to say that the node is broken and unusable in
+ # an execution.
+ # When a node status is set to broken, it is usually associated with a error message.
+ #
+ # If it is safe to do so, clients of the AST SHOULD just skip broken nodes in their processing.
+ # Clients that do not care about the executability (e.g. metrics) MAY still process the node or
+ # perform specific checks to determinate the validity of the node.
+ #
+ # Note that the broken status is not propagated to parent or children nodes.
+ # e.g. a broken expression used as argument does not make the whole call broken.
+ var is_broken = false is writable
+end
+
redef class AType
# The mtype associated to the node
var mtype: nullable MType = null
do
var res = mdoc_cache
if res != null then return res
- res = new MDoc
+ res = new MDoc(location)
for c in n_comment do
var text = c.text
if text.length < 2 then