model: better implementation of the two `intro` methods
authorJean Privat <jean@pryen.org>
Fri, 24 Oct 2014 00:37:53 +0000 (20:37 -0400)
committerJean Privat <jean@pryen.org>
Fri, 24 Oct 2014 00:37:53 +0000 (20:37 -0400)
MClass and MProperty have a `intro` method the get the introducing
definition.
The initial implementation was to return the first known definition, that
make sense for a model constructed from a source-code where introductions
are read before refinements and redefinitions.

However, for a better robustness of the model that allows to load the
model form a serialized form or allows a model partially loaded, the
first-read definition is not necessary the intro.

This new implementation uses a different approach: the introduction is
the definition in the introducing compound (module for classes and
classdefs for properties). The introducing compound is known since the
construction, thus this new implementation is trivial and does not change
the API.

Signed-off-by: Jean Privat <jean@pryen.org>

src/model/model.nit

index 64e82c7..d776cec 100644 (file)
@@ -417,15 +417,11 @@ class MClass
        # Alias for `name`
        redef fun to_s do return self.name
 
-       # The definition that introduced the class
-       # Warning: the introduction is the first `MClassDef` object associated
-       # to self.  If self is just created without having any associated
-       # definition, this method will abort
-       fun intro: MClassDef
-       do
-               assert has_a_first_definition: not mclassdefs.is_empty
-               return mclassdefs.first
-       end
+       # The definition that introduces the class.
+       #
+       # Warning: such a definition may not exist in the early life of the object.
+       # In this case, the method will abort.
+       var intro: MClassDef
 
        # Return the class `self` in the class hierarchy of the module `mmodule`.
        #
@@ -523,6 +519,10 @@ class MClassDef
                self.location = location
                mmodule.mclassdefs.add(self)
                mclass.mclassdefs.add(self)
+               if mclass.intro_mmodule == mmodule then
+                       assert not isset mclass._intro
+                       mclass.intro = self
+               end
                self.to_s = "{mmodule}#{mclass}"
        end
 
@@ -1646,11 +1646,11 @@ abstract class MProperty
        # The other are redefinitions (in refinements and in subclasses)
        var mpropdefs = new Array[MPROPDEF]
 
-       # The definition that introduced the property
-       # Warning: the introduction is the first `MPropDef` object
-       # associated to self. If self is just created without having any
-       # associated definition, this method will abort
-       fun intro: MPROPDEF do return mpropdefs.first
+       # The definition that introduces the property.
+       #
+       # Warning: such a definition may not exist in the early life of the object.
+       # In this case, the method will abort.
+       var intro: MPROPDEF
 
        redef fun model do return intro.model
 
@@ -1905,6 +1905,10 @@ abstract class MPropDef
                self.location = location
                mclassdef.mpropdefs.add(self)
                mproperty.mpropdefs.add(self)
+               if mproperty.intro_mclassdef == mclassdef then
+                       assert not isset mproperty._intro
+                       mproperty.intro = self
+               end
                self.to_s = "{mclassdef}#{mproperty}"
        end