From 72b19e5d9eabb76874f065f2107ac1616d763d6c Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Tue, 6 Oct 2015 15:00:21 -0400 Subject: [PATCH] model: add `MEntity::is_broken` Signed-off-by: Jean Privat --- src/loader.nit | 7 +++++++ src/model/model_base.nit | 14 ++++++++++++++ src/modelize/modelize_class.nit | 3 +++ src/modelize/modelize_property.nit | 29 ++++++++++++++++++++++------- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/loader.nit b/src/loader.nit index a59ccf0..f5b7be1 100644 --- a/src/loader.nit +++ b/src/loader.nit @@ -811,11 +811,13 @@ redef class ModelBuilder # Load the imported module var suppath = seach_module_by_amodule_name(aimport.n_name, mmodule.mgroup) if suppath == null then + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module continue # Skip error end var sup = load_module_path(suppath) if sup == null then + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module continue # Skip error end @@ -824,16 +826,20 @@ redef class ModelBuilder imported_modules.add(sup) var mvisibility = aimport.n_visibility.mvisibility if mvisibility == protected_visibility then + mmodule.is_broken = true error(aimport.n_visibility, "Error: only properties can be protected.") + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module return end if sup == mmodule then error(aimport.n_name, "Error: dependency loop in module {mmodule}.") + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module end if sup.in_importation < mmodule then error(aimport.n_name, "Error: dependency loop between modules {mmodule} and {sup}.") + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module return end @@ -843,6 +849,7 @@ redef class ModelBuilder var mod_name = "core" var sup = self.get_mmodule_by_name(nmodule, null, mod_name) if sup == null then + mmodule.is_broken = true nmodule.mmodule = null # invalidate the module else # Skip error imported_modules.add(sup) diff --git a/src/model/model_base.nit b/src/model/model_base.nit index 396d5e1..8b33f15 100644 --- a/src/model/model_base.nit +++ b/src/model/model_base.nit @@ -64,6 +64,20 @@ abstract class MEntity # A Model Entity has a direct link to its model fun model: Model is abstract + + # The indication that the entity did not pass some semantic verifications. + # + # This simple flag is set by a given analysis to say that the entity is broken and unusable in + # an execution. + # When an entity status is set to broken, it is usually associated with a error message. + # + # If it is safe to do so, clients of the model SHOULD just skip broken entities in their processing. + # Clients that do not care about the executability (e.g. metrics) MAY still process the entity or + # perform specific checks to determinate the validity of the entity. + # + # Note that the broken status is not propagated to enclosing and enclosed entities. + # e.g. a broken method does not make the whole module broken. + var is_broken = false is writable end # Something that represents a concern diff --git a/src/modelize/modelize_class.nit b/src/modelize/modelize_class.nit index 14c8e94..b3ab0bb 100644 --- a/src/modelize/modelize_class.nit +++ b/src/modelize/modelize_class.nit @@ -116,12 +116,15 @@ redef class ModelBuilder #print "new class {mclass}" else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then error(nclassdef, "Error: a class `{name}` is already defined at line {nmodule.mclass2nclassdef[mclass].location.line_start}.") + mclass.is_broken = true return else if nclassdef isa AStdClassdef and nclassdef.n_kwredef == null then error(nclassdef, "Redef Error: `{name}` is an imported class. Add the `redef` keyword to refine it.") + mclass.is_broken = true return else if arity != 0 and mclass.arity != arity then error(nclassdef, "Redef Error: expected {mclass.arity} formal parameter(s) for {mclass.signature_to_s}; got {arity}.") + mclass.is_broken = true return else if nkind != null and mkind != concrete_kind and mclass.kind != mkind then error(nkind, "Redef Error: refinement changed the kind from `{mclass.kind}` to `{mkind}`.") diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index eec36f4..e3f5ea1 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -110,6 +110,7 @@ redef class ModelBuilder if mpropdef.bound == null then continue if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then # Invalidate the bound + mpropdef.is_broken = true mpropdef.bound = mclassdef.mmodule.model.null_type end end @@ -720,6 +721,7 @@ redef class ASignature res = false end end + if not res then is_broken = true return res end end @@ -831,8 +833,14 @@ redef class AMethPropdef mprop.is_new = n_kwnew != null if mprop.is_new then mclassdef.mclass.has_new_factory = true if name == "sys" then mprop.is_toplevel = true # special case for sys allowed in `new` factories - self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then + mprop.is_broken = true + return + end else + if mprop.is_broken then + return + end if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) end @@ -841,7 +849,10 @@ redef class AMethPropdef if is_init then for p, n in mclassdef.mprop2npropdef do if p != mprop and p isa MMethod and p.name == name then - check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, p) + if not check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, p) then + mprop.is_broken = true + return + end break end end @@ -993,13 +1004,14 @@ redef class AMethPropdef var mclassdef = mpropdef.mclassdef var mmodule = mclassdef.mmodule var nsig = self.n_signature - var mysignature = self.mpropdef.msignature + var mysignature = mpropdef.msignature if mysignature == null then return # Error thus skiped # Check if nsig != null then if not nsig.check_signature(modelbuilder, mclassdef) then - self.mpropdef.msignature = null # invalidate + mpropdef.msignature = null # invalidate + mpropdef.is_broken = true return # Forward error end end @@ -1014,7 +1026,8 @@ redef class AMethPropdef var ret_type = mysignature.return_mtype if ret_type != null and precursor_ret_type == null then modelbuilder.error(nsig.n_type.as(not null), "Redef Error: `{mpropdef.mproperty}` is a procedure, not a function.") - self.mpropdef.msignature = null + mpropdef.msignature = null + mpropdef.is_broken = true return end @@ -1026,7 +1039,8 @@ redef class AMethPropdef var node = nsig.n_params[i] if not modelbuilder.check_sametype(node, mmodule, mclassdef.bound_mtype, myt, prt) then modelbuilder.error(node, "Redef Error: expected `{prt}` for parameter `{mysignature.mparameters[i].name}'; got `{myt}`.") - self.mpropdef.msignature = null + mpropdef.msignature = null + mpropdef.is_broken = true end end end @@ -1039,7 +1053,8 @@ redef class AMethPropdef ret_type = precursor_ret_type else if not modelbuilder.check_subtype(node, mmodule, mclassdef.bound_mtype, ret_type, precursor_ret_type) then modelbuilder.error(node, "Redef Error: expected `{precursor_ret_type}` for return type; got `{ret_type}`.") - self.mpropdef.msignature = null + mpropdef.msignature = null + mpropdef.is_broken = true end end end -- 1.7.9.5