package fr.inria.diversify.sosie.logger.processor;
import fr.inria.diversify.transformation.Transformation;
import spoon.reflect.code.*;
import spoon.reflect.cu.CompilationUnit;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.*;
import spoon.reflect.reference.CtExecutableReference;
import spoon.reflect.reference.CtTypeReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* User: Simon
* Date: 25/02/14
* Time: 11:32
*/
@Deprecated
public class AssertInstrumenter extends AbstractLoggingInstrumenter<CtInvocation<?>> {
protected static Map<CtExecutable, Integer> count = new HashMap();
protected static Map<Integer,String> idMap = new HashMap();
public AssertInstrumenter() {
super(new ArrayList<Transformation>());
}
@Override
public boolean isToBeProcessed(CtInvocation<?> candidate) {
try {
return candidate.getExecutable().getSimpleName().startsWith("assert");
} catch (NullPointerException e) {
return false;
}
}
//Obtains a proper argument type string... yes, is not as simple as toString some very special times
private String buildTypedArgumentString(CtTypeReference typedElement) {
String result = "";
if (typedElement.getDeclaringType() != null && !typedElement.getDeclaringType().toString().equals("null")) {
//A declaring type must be a class so it must have a package
result += typedElement.getDeclaringType().getPackage().getSimpleName() + ".";
result += typedElement.getDeclaringType().getSimpleName() + ".";
} else if (typedElement.getPackage() != null && !typedElement.getPackage().toString().equals("null")) {
//If not declaring type, validate for packages
result += typedElement.getPackage().getSimpleName() + ".";
}
result += typedElement.getSimpleName();
//Build elements inside the "<>" diamond
List<CtTypeReference<?>> r = typedElement.getActualTypeArguments();
if (r.size() > 0) {
result += "<";
for (int i = 0; i < r.size(); i++) {
result += buildTypedArgumentString(r.get(i));
result += i + 1 >= r.size() ? ">" : ",";
}
}
return result;
}
public void process(CtInvocation<?> invocation) {
CtExecutableReference<?> executable = invocation.getExecutable();
SourcePosition sp = invocation.getPosition();
CompilationUnit compileUnit = sp.getCompilationUnit();
String snippet = "";
List<String> assertVar = new ArrayList();
List<String> types = new ArrayList();
for (CtExpression expression : invocation.getArguments()) {
String var = "asssertVar_" + getCount(invocation);
String type;
assertVar.add(var);
if (expression.getTypeCasts().size() != 0)
type = expression.getTypeCasts().get(0).toString();
else if (expression.getType().toString().equals("?") || expression.getType().toString().equals("<nulltype>"))
type = "Object";
else if (expression.toString().endsWith(".class"))
type = "java.lang.Class<?>";
else if (expression.getType().getActualTypeArguments().size() > 0)
//On typed argument expressions the expression.getType().toString() is not good
//since produces bad syntax code. So a more complex analysis must be made
type = buildTypedArgumentString(expression.getType());
else
type = expression.getType().toString();
types.add(type);
snippet += type + " " + var + " = " + expression + ";\n";
}
snippet += getLogName() + ".writeAssert(" + sp.getSourceStart() + ",Thread.currentThread(),\"" +
getClass(invocation).getQualifiedName() + "\",\"" + getMethod(invocation).getSignature() + "\",\"" +
executable.getSimpleName() + "\"";
for (int i = 0; i < assertVar.size(); i++) {
snippet += ", \"" + types.get(i) + "\", " + assertVar.get(i);
}
snippet += ");\n";
if (assertVar.size() != 0) {
if (executable.isStatic())
snippet += executable.getDeclaringType().getPackage() + "." + executable.getDeclaringType().getSimpleName() + "." + executable.getSimpleName() + "(" + assertVar.get(0);
else
snippet += executable.getSimpleName() + "(" + assertVar.get(0);
for (int i = 1; i < assertVar.size(); i++)
snippet += ", " + assertVar.get(i);
snippet += ");\n";
}
// compileUnit.addSourceCodeFragment(new SourceCodeFragment(sp.getSourceStart(), "/**", 0));
// compileUnit.addSourceCodeFragment(new SourceCodeFragment(sp.getSourceEnd() + 1, "**/\n" + snippet, 0));
}
protected int getCount(CtInvocation stmt) {
CtExecutable parent = stmt.getParent(CtExecutable.class);
if (count.containsKey(parent))
count.put(parent, count.get(parent) + 1);
else
count.put(parent, 0);
return count.get(parent);
}
protected CtType<?> getClass(CtStatement stmt) {
return stmt.getParent(CtType.class);
}
protected CtExecutable<?> getMethod(CtStatement stmt) {
CtExecutable<?> ret = stmt.getParent(CtMethod.class);
if (ret == null)
ret = stmt.getParent(CtConstructor.class);
return ret;
}
}