Commit e6985539 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ added support for template variables

+ added support for altsteps
+ fixed handling of empty statement blocks in altsteps used in alt statements
+ added priority for data flow checks (normal)
+ generalised data flow helper
parent 9eacac55
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ package de.ugoe.cs.swe.validation;

import java.util.LinkedHashMap;

import de.ugoe.cs.swe.tTCN3.SingleVarInstance;
import org.eclipse.emf.ecore.EObject;

public class DataFlowHelper {
	
@@ -15,7 +15,7 @@ public class DataFlowHelper {
	}
	
	private DataFlowHelper parent;
	private LinkedHashMap<SingleVarInstance,STATUS> states = new LinkedHashMap<>();
	private LinkedHashMap<EObject,STATUS> states = new LinkedHashMap<>();
	
	public DataFlowHelper() {
		
@@ -41,7 +41,7 @@ public class DataFlowHelper {
		this.parent = parent;
	}

	public LinkedHashMap<SingleVarInstance,STATUS> getStates() {
	public LinkedHashMap<EObject,STATUS> getStates() {
		return states;
	}

@@ -49,7 +49,7 @@ public class DataFlowHelper {
//		this.states = states;
//	}
	
	public STATUS getState(SingleVarInstance v) {
	public STATUS getState(EObject v) {
		if (this.states.containsKey(v)) {
			return this.states.get(v);
		} else {
@@ -61,7 +61,7 @@ public class DataFlowHelper {
		} 
	}

	public void setState(SingleVarInstance v, STATUS s) {
	public void setState(EObject v, STATUS s) {
		this.states.put(v, s);
	}

+134 −21
Original line number Diff line number Diff line
@@ -4,20 +4,35 @@ import com.google.inject.Inject
import de.ugoe.cs.swe.TTCN3Configuration.QualityCheckProfile
import de.ugoe.cs.swe.common.ConfigTools
import de.ugoe.cs.swe.common.logging.LoggingInterface.MessageClass
import de.ugoe.cs.swe.tTCN3.AltConstruct
import de.ugoe.cs.swe.tTCN3.AltstepDef
import de.ugoe.cs.swe.tTCN3.AltstepLocalDef
import de.ugoe.cs.swe.tTCN3.Assignment
import de.ugoe.cs.swe.tTCN3.BasicStatements
import de.ugoe.cs.swe.tTCN3.BehaviourStatements
import de.ugoe.cs.swe.tTCN3.CallStatement
import de.ugoe.cs.swe.tTCN3.CommunicationStatements
import de.ugoe.cs.swe.tTCN3.ComponentDef
import de.ugoe.cs.swe.tTCN3.ComponentElementDef
import de.ugoe.cs.swe.tTCN3.ConditionalConstruct
import de.ugoe.cs.swe.tTCN3.ControlStatement
import de.ugoe.cs.swe.tTCN3.FunctionDef
import de.ugoe.cs.swe.tTCN3.FunctionDefList
import de.ugoe.cs.swe.tTCN3.FunctionLocalDef
import de.ugoe.cs.swe.tTCN3.FunctionLocalInst
import de.ugoe.cs.swe.tTCN3.FunctionStatement
import de.ugoe.cs.swe.tTCN3.FunctionStatementList
import de.ugoe.cs.swe.tTCN3.InterleavedConstruct
import de.ugoe.cs.swe.tTCN3.InterleavedGuardList
import de.ugoe.cs.swe.tTCN3.LoopConstruct
import de.ugoe.cs.swe.tTCN3.ModuleControlBody
import de.ugoe.cs.swe.tTCN3.ReferencedValue
import de.ugoe.cs.swe.tTCN3.SelectCaseConstruct
import de.ugoe.cs.swe.tTCN3.SingleTempVarInstance
import de.ugoe.cs.swe.tTCN3.SingleVarInstance
import de.ugoe.cs.swe.tTCN3.StatementBlock
import de.ugoe.cs.swe.tTCN3.TimerInstance
import de.ugoe.cs.swe.tTCN3.TimerStatements
import de.ugoe.cs.swe.tTCN3.Value
import de.ugoe.cs.swe.tTCN3.VarInstance
import de.ugoe.cs.swe.tTCN3.VariableRef
@@ -34,18 +49,6 @@ import org.eclipse.xtext.validation.EValidatorRegistrar

import static extension de.ugoe.cs.swe.common.TTCN3ScopeHelper.*
import static extension org.eclipse.xtext.EcoreUtil2.*
import de.ugoe.cs.swe.tTCN3.TimerStatements
import de.ugoe.cs.swe.tTCN3.CommunicationStatements
import de.ugoe.cs.swe.tTCN3.CallStatement
import de.ugoe.cs.swe.tTCN3.BehaviourStatements
import de.ugoe.cs.swe.tTCN3.InterleavedConstruct
import de.ugoe.cs.swe.tTCN3.AltConstruct
import de.ugoe.cs.swe.tTCN3.BasicStatements
import de.ugoe.cs.swe.tTCN3.ConditionalConstruct
import de.ugoe.cs.swe.tTCN3.SelectCaseConstruct
import de.ugoe.cs.swe.tTCN3.LoopConstruct
import de.ugoe.cs.swe.tTCN3.ModuleControlBody
import de.ugoe.cs.swe.tTCN3.ControlStatement

class DataFlowValidator extends AbstractDeclarativeValidator {
    val ConfigTools configTools = ConfigTools.getInstance;
@@ -58,7 +61,7 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
        // not needed for classes used as ComposedCheck
    }

    @Check
    @Check(NORMAL)
    def checkNoUninitialisedLocalDefinitions(StatementBlock block) {
        if (!activeProfile.checkNoUninitialisedVariables) {
            return
@@ -66,13 +69,18 @@ class DataFlowValidator extends AbstractDeclarativeValidator {

        var parentBlock = block.findDesiredParent(StatementBlock)
        var parentControl = block.findDesiredParent(ModuleControlBody)
        if (parentBlock === null && parentControl === null) { //top-level
        var parentAltstep = block.findDesiredParent(AltstepDef)
        if (parentBlock === null 
            && parentControl === null
            && parentAltstep === null
        ) { //top-level
            val DataFlowHelper dfh = new DataFlowHelper()
            
            //debugging
//            try {
//                block.traverseChildren(dfh)
//            } catch (Exception e) {
//                println(block.URI)
//                e.printStackTrace
//            }
            //live
@@ -81,7 +89,7 @@ class DataFlowValidator extends AbstractDeclarativeValidator {

    }

    @Check
    @Check(NORMAL)
    def checkNoUninitialisedLocalDefinitions(ModuleControlBody control) {
        if (!activeProfile.checkNoUninitialisedVariables) {
            return
@@ -93,6 +101,7 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
//        try {
//            control.traverseChildren(dfh)
//        } catch (Exception e) {
//            println(control.URI)
//            e.printStackTrace
//        }
        //live
@@ -100,6 +109,61 @@ class DataFlowValidator extends AbstractDeclarativeValidator {

    }

    @Check(NORMAL)
    def checkNoUninitialisedLocalDefinitions(AltstepDef altstep) {
        if (!activeProfile.checkNoUninitialisedVariables) {
            return
        }

        val DataFlowHelper dfh = new DataFlowHelper()
        
        //debugging
//        try {
//            altstep.traverseChildren(dfh)
//        } catch (Exception e) {
//            println(altstep.URI)
//            e.printStackTrace
//        }
        //live
         altstep.traverseChildren(dfh)

    }


    private def void traverseChildren(AltstepDef altstep, DataFlowHelper dfh) {
        //defs and statements in order
        for (cse : altstep.local.defs) {
            cse.processAltstepLocalDef(dfh)
        }
        for (b : altstep.guard.guardList) {
            dfh.checkVariableStatus(b.guard.eAllOfType(ReferencedValue))
            var bdfh = new DataFlowHelper(dfh)
            //op 
            if (b.op !== null) {
                val bValues = b.op.eAllOfType(ReferencedValue)
                dfh.checkVariableStatus(bValues.filter[eContainer instanceof Value])
                for (v : bValues.filter[eContainer instanceof VariableRef]) {
                    //valid only within -> bdfh for the branch, propagate if in all branches
                    bdfh.updateVariableStatus(v)
                }
            //step
            } else if (b.step !== null) {
                val bValues = b.step.eAllOfType(ReferencedValue)
                dfh.checkVariableStatus(bValues.filter[eContainer instanceof Value])
            }
            if (b.block !== null) {
                b.block.traverseChildren(bdfh)
            }
        }
                
        //else?
        for (b : altstep.guard.elseList) {
            var bdfh = new DataFlowHelper(dfh)
            b.block.traverseChildren(bdfh)
        }
    }


    private def traverseChildren(ModuleControlBody control, DataFlowHelper dfh) {
        //defs and statements in order
        for (c : NodeModelUtils.getNode(control.list).children.filter[hasDirectSemanticElement]) {
@@ -185,17 +249,45 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
            //variable=VarInstance 
            //timer=TimerInstance -> always defined
            if (inst.variable !== null) {
                for (target : inst.variable.list.variables) {
                inst.variable.processVarInstance(dfh)
            } else if (inst.timer !== null) {
                for (target : inst.timer.list.variables) {
                    dfh.checkVariableStatus(target.eAllOfType(ReferencedValue))
                    dfh.updateVariableStatus(target)
                }                               
            }
    }

    protected def void processAltstepLocalDef(AltstepLocalDef inst, DataFlowHelper dfh) {
            //variable=VarInstance 
            //timer=TimerInstance -> always defined
            if (inst.variable !== null) {
                inst.variable.processVarInstance(dfh)
            } else if (inst.timer !== null) {
                for (target : inst.timer.list.variables) {
                    dfh.checkVariableStatus(target.eAllOfType(ReferencedValue))
                }                               
            } else if (inst.const !== null) {
                dfh.checkVariableStatus(inst.const.eAllOfType(ReferencedValue))
            } else if (inst.template !== null) {
                dfh.checkVariableStatus(inst.template.eAllOfType(ReferencedValue))
            }
    }
    
    protected def void processVarInstance(VarInstance variable, DataFlowHelper dfh) {
        if (variable.list !== null) {
            for (target : variable.list.variables) {
                dfh.checkVariableStatus(target.eAllOfType(ReferencedValue))
                dfh.updateVariableStatus(target)
            }
        } else if (variable.tempList !== null) {
            for (target : variable.tempList.variables) {
                dfh.checkVariableStatus(target.eAllOfType(ReferencedValue))
                dfh.updateVariableStatus(target)
            }                    
        }
    }

    
    protected def void processFunctionStatement(FunctionStatement cse, DataFlowHelper dfh) {
        if (cse.basic !== null) {
            
@@ -399,8 +491,9 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
                val bValues = b.step.eAllOfType(ReferencedValue)
                dfh.checkVariableStatus(bValues.filter[eContainer instanceof Value])
            }
                
            if (b.block !== null) {
                b.block.traverseChildren(bdfh)
            }
            bdfhs.add(bdfh)
            bdfhkeys.addAll(bdfh.states.keySet)
        }
@@ -572,6 +665,21 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
        }
    }

    protected def void updateVariableStatus(DataFlowHelper dfh, SingleTempVarInstance target) {
        if (dfh.getState(target) === STATUS.UNDECLARED) {
            if (target.template !== null) {
                dfh.states.put(target,STATUS.INITIALISED)
            } else {
                dfh.states.put(target,STATUS.DECLARED)
            }
//            println("###     "+USE.DEFINE+"->"+dfh.states.get(target)+": "+target.name)
        } else {
//            println("###   ERROR: "+target.name+" already declared!")
        }
    }


    
    protected def void updateVariableStatus(DataFlowHelper dfh, ReferencedValue value) {
        val target = value.head.target
        if (target instanceof SingleVarInstance) {
@@ -648,6 +756,11 @@ class DataFlowValidator extends AbstractDeclarativeValidator {
        val parent = context.findDesiredParent(FunctionDef)
        if (parent !== null) {
            parentName = parent.name 
        } else {
            val asd = context.findDesiredParent(AltstepDef)
            if (asd !== null) {
                parentName = asd.name
            } 
        }            
        val message = "Local definition for \"" + target.name + "\" in definition of \"" + parentName +
            "\" is not "+status+"!"