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.MethodRegistryItem; 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; /** * Состояние анализа метода. * Создает методы - основные единицы CFG и добавляет их в результат. * * @author mzubov * */ class MethodContext extends ContextBase implements IClassInsidePart { private String className; private String name; private CompilationUnit compilationUnit; private Method method; private FlowCursor innerCursor = new FlowCursor(); private MethodRegistryItem registryItem = new MethodRegistryItem(); private final int id; MethodContext(ContextBase previousState, String className, CompilationUnit compilationUnit, int id) { super(previousState); this.className = className; this.compilationUnit = compilationUnit; this.id = id; } @Override public IContext<Project> getPreviousState(String eventName) { if ("method".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 ("block".equals(eventName)) return new ControlFlowContext(this, method, innerCursor, compilationUnit); if ("variable".equals(eventName)) return new ArgContext(this, this.registryItem); return this; } @Override public void processTag(String name, NodeAttributes attrs) { if ("method".equals(name)) { String nameAttr = attrs.getNameAttribute(); if ("<init>".equals(nameAttr)) nameAttr = className.substring(className.lastIndexOf('.')+1); this.name = nameAttr; method = getObjectFactory().createMethod(); method.setParentClass(className); method.setName(this.name); } } @Override public void finish(String eventName) { if ("method".equals(eventName)){ for (Integer parent: innerCursor.getParentIds()){ int flowParent = parent.intValue() > 0 ? parent.intValue() : (-1) * parent.intValue(); Flow flow = getObjectFactory().createFlow(); flow.setFromId(BigInteger.valueOf(flowParent)); flow.setToId(innerCursor.getCurrentIdBigInteger()); method.getTryExceptOrTryFinallyOrWith().add(flow); } Block exitBlock = getObjectFactory().createBlock(); exitBlock.setType("<<Exit>>"); exitBlock.setId(innerCursor.getCurrentIdBigInteger()); method.getTryExceptOrTryFinallyOrWith().add(exitBlock); method.setUcrMethodId(BigInteger.valueOf(id)); getResultRoot().getMethodOrFunction().add(method); registryItem.setName(name); registryItem.setId(id); getMethodRegistry().addMethodToRegistry(className, registryItem); } } @Override public String getClassName() { return className; } @Override public int getNextInnerCount() { if (getUpperState() instanceof IClassInsidePart) return ((IClassInsidePart)getUpperState()).getNextInnerCount(); else return 0; } @Override public VariableScope getVariableScope() { if (getUpperState() instanceof IClassInsidePart) return ((IClassInsidePart)getUpperState()).getVariableScope(); else return null; } }