package ru.csu.stan.java.cfg.automaton; import java.math.BigInteger; import ru.csu.stan.java.cfg.automaton.base.ContextBase; import ru.csu.stan.java.cfg.automaton.base.FlowCursor; import ru.csu.stan.java.cfg.automaton.base.IClassInsidePart; import ru.csu.stan.java.cfg.jaxb.Block; import ru.csu.stan.java.cfg.jaxb.Flow; import ru.csu.stan.java.cfg.jaxb.Method; import ru.csu.stan.java.cfg.jaxb.Project; import ru.csu.stan.java.cfg.util.scope.VariableScope; import ru.csu.stan.java.classgen.automaton.IContext; import ru.csu.stan.java.classgen.handlers.NodeAttributes; import ru.csu.stan.java.classgen.util.CompilationUnit; /** * * @author mz * */ public class ControlFlowContext extends ContextBase implements IClassInsidePart{ private Method method; private final FlowCursor cursor; private CompilationUnit compilationUnit; private Block block; private String startTag = ""; private VariableScope scope = new VariableScope(); public ControlFlowContext(ContextBase previousState, Method method, final FlowCursor cursor, CompilationUnit compilationUnit){ super(previousState); this.method = method; this.cursor = cursor; this.compilationUnit = compilationUnit; } @Override public IContext<Project> getPreviousState(String eventName){ if ("block".equals(eventName)) return getUpperState(); if (startTag.equals(eventName)) return getUpperState(); return this; } @Override public IContext<Project> getNextState(IContext<Project> context, String eventName){ if ("class".equals(eventName)) return new ClassContext(this, compilationUnit); if ("if".equals(eventName)){ block = null; return new IfContext(this, cursor, compilationUnit, method); } if ("while_loop".equals(eventName) || "do_while_loop".equals(eventName)){ block = null; return new WhileContext(this, cursor, compilationUnit, method); } if ("for_loop".equals(eventName) || "enhanced_for_loop".equals(eventName)){ block = null; return new ForContext(this, cursor, compilationUnit, method); } if ("try".equals(eventName)){ block = null; return new TryCatchContext(this, cursor, compilationUnit, method); } if ("method_invocation".equals(eventName)){ return new MethodInvocationContext(this, block, getClassName(), compilationUnit); } if ("new_class".equals(eventName)){ return new NewClassContext(this, block, getClassName(), compilationUnit); } if ("variable".equals(eventName)) return new VariableContext(this, scope, block, compilationUnit); return this; } @Override public void processTag(String name, NodeAttributes attrs){ // if ("body".equals(name)) // return; if (startTag == null || "".equals(startTag)) startTag = name; if (block == null && isNotOpeningTag(name)){ makeFlowsToCurrent(); block = getObjectFactory().createBlock(); block.setId(BigInteger.valueOf(cursor.getCurrentId())); if (attrs.isAttributeExist(NodeAttributes.LINE_ATTRIBUTE)) block.setFromlineno(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.LINE_ATTRIBUTE))); if (attrs.isAttributeExist(NodeAttributes.COL_ATTRIBUTE)) block.setColOffset(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.COL_ATTRIBUTE))); method.getTryExceptOrTryFinallyOrWith().add(block); cursor.clearParentIds(); cursor.addParentId(cursor.getCurrentId()); cursor.incrementCurrentId(); } if ("return".equals(name)){ cursor.clearParentIds(); cursor.addParentId(-1 * block.getId().intValue()); } if ("throw".equals(name)){ cursor.clearParentIds(); cursor.addParentId(-1 * block.getId().intValue()); } } private void makeFlowsToCurrent(){ for (Integer parent: cursor.getParentIds()){ if (parent.intValue() > 0){ Flow flow = getObjectFactory().createFlow(); flow.setFromId(BigInteger.valueOf(parent.longValue())); flow.setToId(cursor.getCurrentIdBigInteger()); method.getTryExceptOrTryFinallyOrWith().add(flow); } } } @Override public void finish(String eventName){ if ("block".equals(eventName) || startTag.equals(eventName)){ this.scope.setName(method.getName()); this.scope.setParentScope(getVariableScope()); } } private boolean isNotOpeningTag(String tag){ return !("block".equals(tag) || "body".equals(tag) || "nodename.statements".equals(tag) || "then_part".equals(tag) || "else_part".equals(tag) || "finally".equals(tag) || "catch".equals(tag) || "modifier".equals(tag)); } @Override public String getClassName() { return findParentClassNameHolder().getClassName(); } @Override public int getNextInnerCount() { return findParentClassNameHolder().getNextInnerCount(); } private IClassInsidePart findParentClassNameHolder(){ ContextBase ctx = this.getUpperState(); while (!(ctx instanceof IClassInsidePart) && ctx != null) ctx = ctx.getUpperState(); return (IClassInsidePart) ctx; } @Override public VariableScope getVariableScope() { return findParentClassNameHolder().getVariableScope(); } }