module annotation
import modelbuilder
-private import literal
+import literal
import model::mmodule_data
redef class Prod
var res = get_annotations(name)
if res.is_empty then return null
if res.length > 1 then
- modelbuilder.error(res[1], "Error: multiple annotation `{name}`. A previous one is defined line {res[0].location.line_start}")
+ modelbuilder.error(res[1], "Syntax Error: multiple `{name}`. A previous one is defined line {res[0].location.line_start}.")
end
return res.first
end
-
- # Return all its annotations of a given name in the order of their declaration
- # Retun an empty array if no such an annotation.
- fun get_annotations(name: String): Array[AAnnotation]
- do
- var res = new Array[AAnnotation]
- var nas = n_annotations
- if nas == null then return res
- for na in nas.n_items do
- if na.name != name then continue
- res.add(na)
- end
- return res
- end
end
redef class AAnnotation
- # The name of the annotation
- fun name: String
- do
- return n_atid.n_id.text
- end
-
# Get the single argument of `self` as a `String`.
# Raise error and return null on any inconsistency.
fun arg_as_string(modelbuilder: ModelBuilder): nullable String
if arg != null then return arg
end
- modelbuilder.error(self, "Annotation error: \"{name}\" expects a single String as argument.")
+ modelbuilder.error(self, "Syntax Error: `{name}` expects a single String as argument.")
return null
end
if arg != null then return arg
end
- modelbuilder.error(self, "Annotation error: \"{name}\" expects a single Int as argument.")
+ modelbuilder.error(self, "Syntax Error: `{name}` expects a single Int as argument.")
return null
end
if arg != null then return arg
end
- modelbuilder.error(self, "Annotation error: \"{name}\" expects a single identifier as argument.")
+ modelbuilder.error(self, "Syntax Error: `{name}` expects a single identifier as argument.")
return null
end
end
-redef class AAtArg
- # Get `self` as a `String`.
- # Return null if not a string.
- fun as_string: nullable String
- do
- if not self isa AExprAtArg then return null
- var nexpr = n_expr
- if not nexpr isa AStringFormExpr then return null
- return nexpr.value.as(not null)
- end
-
- # Get `self` as an `Int`.
- # Return null if not an integer.
- fun as_int: nullable Int
- do
- if not self isa AExprAtArg then return null
- var nexpr = n_expr
- if not nexpr isa AIntExpr then return null
- return nexpr.value.as(not null)
- end
-
- # Get `self` as a single identifier.
- # Return null if not a single identifier.
- fun as_id: nullable String
- do
- if not self isa AExprAtArg then return null
- var nexpr = n_expr
- if not nexpr isa ACallExpr then return null
- if not nexpr.n_expr isa AImplicitSelfExpr then return null
- if not nexpr.n_args.n_exprs.is_empty then return null
- return nexpr.n_id.text
- end
-end
-
redef class ModelBuilder
# Collect all annotations by `name` assocated to `mmodule` and its imported modules.
# Note that visibility is not considered.
do
var annotations = new Array[AAnnotation]
for mmod in mmodule.in_importation.greaters do
- if not mmodule2nmodule.keys.has(mmod) then continue
- var amod = mmodule2nmodule[mmod]
+ var amod = mmodule2node(mmod)
+ if amod == null then continue
var module_decl = amod.n_moduledecl
if module_decl == null then continue
var aas = module_decl.get_annotations(name)
# Obviously, if there is no ast associated to `mmodule`, then nothing is returned.
fun get_mmodule_annotation(name: String, mmodule: MModule): nullable AAnnotation
do
- if not mmodule2nmodule.keys.has(mmodule) then return null
- var amod = mmodule2nmodule[mmodule]
+ var amod = mmodule2node(mmodule)
+ if amod == null then return null
var module_decl = amod.n_moduledecl
if module_decl == null then return null
var res = module_decl.get_single_annotation(name, self)
for annot in annotations do locs.add(annot.location)
toolcontext.error(mmodule.location,
- "Priority conflict on annotation {name}, it has been defined in: {locs.join(", ")}")
+ "Error: priority conflict on annotation `{name}`, it has been defined in: {locs.join(", ")}.")
end
return annotations.first
end