X-Git-Url: http://nitlanguage.org diff --git a/src/android_annotations.nit b/src/android_annotations.nit index 0e7170d..ec0d2dc 100644 --- a/src/android_annotations.nit +++ b/src/android_annotations.nit @@ -23,6 +23,7 @@ import modelbuilder import modelize_property import literal import typing +private import annotation # Metadata associated to an Android project class AndroidProject @@ -65,29 +66,47 @@ redef class ModelBuilder do var project = new AndroidProject - var annot = priority_annotation_on_modules("app_name", mmodule) + var annot = lookup_annotation_on_modules("app_name", mmodule) if annot != null then project.name = annot.arg_as_string(self) - annot = priority_annotation_on_modules("app_version", mmodule) + annot = lookup_annotation_on_modules("app_version", mmodule) if annot != null then project.version = annot.as_version(self) - annot = priority_annotation_on_modules("java_package", mmodule) + annot = lookup_annotation_on_modules("java_package", mmodule) if annot != null then project.java_package = annot.arg_as_string(self) var annots = collect_annotations_on_modules("min_api_version", mmodule) - for an in annots do project.min_api = an.arg_as_int(self) + if not annots.is_empty then + var i = annots.pop.arg_as_int(self) + if i == null then i = 0 + project.min_api = i + for an in annots do + i = an.arg_as_int(self) + if i == null then continue + project.min_api = project.min_api.max(i) + end + end annots = collect_annotations_on_modules("max_api_version", mmodule) - for an in annots do project.max_api = an.arg_as_int(self) + if not annots.is_empty then + var i = annots.pop.arg_as_int(self) + if i == null then i = 0 + project.max_api = i + for an in annots do + i = an.arg_as_int(self) + if i == null then continue + project.max_api = project.max_api.min(i) + end + end - annots = collect_annotations_on_modules("target_api_version", mmodule) - for an in annots do project.target_api = an.arg_as_int(self) + annot = lookup_annotation_on_modules("target_api_version", mmodule) + if annot != null then project.target_api = annot.arg_as_int(self) or else 0 annots = collect_annotations_on_modules("android_manifest", mmodule) - for an in annots do project.manifest_lines.add an.arg_as_string(self) + for an in annots do project.manifest_lines.add an.arg_as_string(self) or else "" annots = collect_annotations_on_modules("android_manifest_application", mmodule) - for an in annots do project.manifest_application_lines.add an.arg_as_string(self) + for an in annots do project.manifest_application_lines.add an.arg_as_string(self) or else "" # Get the date and time (down to the minute) as string var local_time = new Tm.localtime @@ -98,115 +117,9 @@ redef class ModelBuilder return project end - - # Recursively collect all annotations by name in `mmodule` and its importations (direct and indirect) - private fun collect_annotations_on_modules(name: String, mmodule: MModule): Array[AAnnotation] - 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 module_decl = amod.n_moduledecl - if module_decl == null then continue - var aas = module_decl.collect_annotations_by_name(name) - annotations.add_all aas - end - return annotations - end - - # Get an annotation by name from `mmodule` and its super modules. Will recursively search - # in imported module to find the "latest" declaration and detects priority conflicts. - private fun priority_annotation_on_modules(name: String, mmodule: MModule): nullable AAnnotation - do - if mmodule2nmodule.keys.has(mmodule) then - var amod = mmodule2nmodule[mmodule] - var module_decl = amod.n_moduledecl - if module_decl != null then - var annotations = module_decl.collect_annotations_by_name(name) - if annotations.length == 1 then - return annotations.first - else if annotations.length > 1 then - toolcontext.error(mmodule.location, - "Multiple declaration of annotation {name}, it must be defined only once.") - end - end - end - - var sources = new Array[MModule] - var annotations = null - for mmod in mmodule.in_importation.direct_greaters do - var res = priority_annotation_on_modules(name, mmod) - if res != null then - sources.add mmod - annotations = res - end - end - if sources.length > 1 then - toolcontext.error(mmodule.location, - "Priority conflict on annotation {name}, it has been defined in: {sources.join(", ")}") - return null - end - return annotations - end end redef class AAnnotation - # Get the single argument of `self` as a `String`. Raise error on any inconsistency. - private fun arg_as_string(modelbuilder: ModelBuilder): String - do - var annotation_name = n_atid.n_id.text - var format_error = "Annotation error: \"{annotation_name}\" expects a single String as argument." - - var args = n_args - var platform_name - if args.length != 1 then - modelbuilder.error(self, format_error) - return "" - else - var arg = args.first - - if not arg isa AExprAtArg then - modelbuilder.error(self, format_error) - return "" - end - - var expr = arg.n_expr - if not expr isa AStringFormExpr then - modelbuilder.error(self, format_error) - return "" - end - return expr.value.as(not null) - end - end - - # Get the single argument of `self` as an `Int`. Raise error on any inconsistency. - private fun arg_as_int(modelbuilder: ModelBuilder): nullable Int - do - var annotation_name = n_atid.n_id.text - var format_error = "Annotation error: \"{annotation_name}\" expects a single Int as argument." - - var args = n_args - var platform_name - if args.length != 1 then - modelbuilder.error(self, format_error) - return null - else - var arg = args.first - - if not arg isa AExprAtArg then - modelbuilder.error(self, format_error) - return null - end - - var expr = arg.n_expr - if not expr isa AIntExpr then - modelbuilder.error(self, format_error) - return null - end - return expr.value.as(not null) - end - end - # Returns a version string (example: "1.5.6b42a7c") from an annotation `version(1, 5, git_revision)`. # # The user can enter as many fields as needed. The call to `git_revision` will be replaced by the short @@ -219,33 +132,26 @@ redef class AAnnotation var args = n_args var platform_name if args.length < 1 then - modelbuilder.error(self, "Annotation error: \"{annotation_name}\" expects at least a single argument.") + modelbuilder.error(self, "Annotation error: \"{name}\" expects at least a single argument.") return "" else for arg in args do - var format_error = "Annotation error: \"{annotation_name}\" expects its arguments to be of type Int or a call to `git_revision`" + var format_error = "Annotation error: \"{name}\" expects its arguments to be of type Int or a call to `git_revision`" - if not arg isa AExprAtArg then - modelbuilder.error(self, format_error) - return "" + var value + value = arg.as_int + if value != null then + version_fields.add value + continue end - var expr = arg.n_expr - if expr isa AIntExpr then - var value = expr.value - assert value != null + value = arg.as_string + if value != null then version_fields.add value - else if expr isa AStringFormExpr then - version_fields.add expr.value.as(not null) - else if expr isa ACallExpr then - # We support calls to "git" only - var exec_args = expr.n_args.to_a - if expr.n_id.text != "git_revision" or not exec_args.is_empty then - modelbuilder.error(self, - "Annotation error: \"{annotation_name}\" accepts only calls to `git_revision` with the command as arguments.") - return "" - end + end + value = arg.as_id + if value == "git_revision" then # Get Git short revision var proc = new IProcess("git", "rev-parse", "--short", "HEAD") proc.wait @@ -261,10 +167,11 @@ redef class AAnnotation if dirty then revision += ".d" version_fields.add revision - else - modelbuilder.error(self, format_error) - return "" + continue end + + modelbuilder.error(self, format_error) + return "" end end