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.IClassInsidePart; import ru.csu.stan.java.cfg.jaxb.Block; import ru.csu.stan.java.cfg.jaxb.Call; import ru.csu.stan.java.cfg.jaxb.Direct; import ru.csu.stan.java.cfg.jaxb.Getattr; import ru.csu.stan.java.cfg.jaxb.Project; import ru.csu.stan.java.cfg.jaxb.Target; import ru.csu.stan.java.cfg.jaxb.TargetClass; 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 MethodInvocationContext extends ContextBase implements IClassInsidePart { private Block block; private String name; private String label; private Call call; private boolean hasInternalCall; private String className; private CompilationUnit compilationUnit; MethodInvocationContext(ContextBase previousState, Block block, String className, CompilationUnit compilationUnit) { super(previousState); this.block = block; this.className = className; this.compilationUnit = compilationUnit; } @Override public IContext<Project> getPreviousState(String eventName) { if ("method_invocation".equals(eventName)) return getUpperState(); else return this; } @Override public IContext<Project> getNextState(IContext<Project> context, String eventName) { if ("method_invocation".equals(eventName)){ hasInternalCall = true; return new MethodInvocationContext(this, block, className, compilationUnit); } if ("new_class".equals(eventName)){ hasInternalCall = true; return new NewClassContext(this, block, className, compilationUnit); } if ("arguments".equals(eventName)) return new MethodArgumentsContext(this, block, className, compilationUnit); return this; } @Override public void processTag(String name, NodeAttributes attrs) { if ("method_invocation".equals(name)){ call = getObjectFactory().createCall(); if (attrs.isAttributeExist(NodeAttributes.LINE_ATTRIBUTE)) call.setFromlineno(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.LINE_ATTRIBUTE))); if (attrs.isAttributeExist(NodeAttributes.COL_ATTRIBUTE)) call.setColOffset(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.COL_ATTRIBUTE))); } if ("member_select".equals(name)){ if (this.name == null || this.name.isEmpty()) this.name = attrs.getNameAttribute(); else this.name = attrs.getNameAttribute() + '.' + this.name; } if ("identifier".equals(name)){ label = attrs.getNameAttribute(); } if (name.endsWith("literal")){ label = "\"" + attrs.getStringAttribute("value") + "\""; } } @Override public void finish(String eventName) { if ("method_invocation".equals(eventName)){ if (!hasInternalCall){ if (name == null || name.isEmpty()){ Direct direct = getObjectFactory().createDirect(); direct.setName(label); Target target = getObjectFactory().createTarget(); target.setType("method"); TargetClass tc = getObjectFactory().createTargetClass(); tc.setLabel(className); direct.setTarget(target); call.setDirect(direct); } else{ Getattr getattr = getObjectFactory().createGetattr(); getattr.setName(name); getattr.setLabel(label); call.setGetattr(getattr); } block.getCall().add(call); } } } public void setInternalCall(){ this.hasInternalCall = true; } @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(); } }