Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / contracts.nit
index 3d300ff..f732065 100644 (file)
@@ -35,33 +35,35 @@ end
 private class ContractsPhase
        super Phase
 
-       # The entry point of the contract phase
-       # In reality, the contract phase is executed on each module
-       # FIXME: Actually all method is checked to add method if any contract is inherited
        redef fun process_nmodule(nmodule)do
                # Check if the contracts are disabled
                if toolcontext.opt_no_contract.value then return
                nmodule.do_contracts(self.toolcontext)
        end
+
+       redef fun process_mainmodule(mainmodule: MModule, given_mmodules: SequenceRead[MModule]) do
+               # Visit all loaded modules `toolcontext.nmodules` to do contract weaving
+               for nmodule in toolcontext.modelbuilder.nmodules do
+                       nmodule.do_weaving_contracts(self.toolcontext)
+               end
+       end
 end
 
 redef class AModule
-       # Compile all contracts
-       #
-       # The implementation of the contracts is done in two visits.
-       #
-       # - First step, the visitor analyzes and constructs the contracts
-       #   for each class (invariant) and method (expect, ensure).
-       #
-       # - Second step the visitor analyzes each `ASendExpr` to see
-       #   if the callsite calls a method with a contract. If this is
-       #       the case the callsite is replaced by another callsite to the contract method.
+
+       # Entry point to generate the entire contract infrastructure.
+       # Once this method is called we must call the `do_weaving_contracts` method (see it for more information).
        fun do_contracts(toolcontext: ToolContext) do
                var ast_builder = new ASTBuilder(mmodule.as(not null))
                #
                var contract_visitor = new ContractsVisitor(toolcontext, toolcontext.modelbuilder.identified_modules.first, self, ast_builder)
                contract_visitor.enter_visit(self)
-               #
+       end
+
+       # Entry point to execute the weaving in order to redirect the calls to the contract sides if it's needed.
+       fun do_weaving_contracts(toolcontext: ToolContext)
+       do
+               var ast_builder = new ASTBuilder(mmodule.as(not null))
                var callsite_visitor = new CallSiteVisitor(toolcontext, ast_builder)
                callsite_visitor.enter_visit(self)
        end
@@ -585,7 +587,9 @@ redef class MMethod
                if not exist_contract_facet then
                        # If has no contract facet in intro just create it
                        if classdef != intro_mclassdef then
-                               create_facet(v, intro_mclassdef, contract_facet, self)
+                               var n_intro_face = create_facet(v, intro_mclassdef, contract_facet, self)
+                               n_intro_face.location = self.intro.location
+                               n_intro_face.do_all(v.toolcontext)
                        end
                        n_contract_facet = create_facet(v, classdef, contract_facet, self)
                else
@@ -832,6 +836,8 @@ redef class ASendExpr
                var actual_callsite = callsite
                if actual_callsite != null then
                        callsite = v.drive_callsite_to_contract(actual_callsite)
+                       # Set the signature mapping with the old value, this avoids having to re-check the callsite.
+                       callsite.signaturemap = actual_callsite.signaturemap
                end
        end
 end
@@ -842,6 +848,8 @@ redef class ANewExpr
                var actual_callsite = callsite
                if actual_callsite != null then
                        callsite = v.drive_callsite_to_contract(actual_callsite)
+                       # Set the signature mapping with the old value, this avoids having to re-check the callsite
+                       callsite.signaturemap = actual_callsite.signaturemap
                end
        end
 end