package fr.inria.diversify.sosie.logger.processor;
import fr.inria.diversify.transformation.Transformation;
import spoon.processing.AbstractProcessor;
import spoon.processing.ProcessingManager;
import spoon.reflect.code.*;
import spoon.reflect.declaration.*;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.QueryVisitor;
import spoon.reflect.visitor.filter.TypeFilter;
import spoon.support.QueueProcessingManager;
import spoon.support.reflect.code.CtCodeSnippetStatementImpl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* User: Simon
* Date: 06/01/14
* Time: 10:04
*/
@Deprecated
public class MethodLoggingInstrumenter extends AbstractLoggingInstrumenter<CtMethod> {
protected List<CtMethod> methods;
public MethodLoggingInstrumenter(List<Transformation> transformations) {
super(transformations);
}
@Override
public boolean isToBeProcessed(CtMethod candidate) {
return !candidate.isImplicit()
&& candidate.getBody() != null
&& candidate.getBody().getStatements().size() != 0
// && hasCall(candidate)
&& !containsGoto(candidate);
}
@Override
public void process(CtMethod candidate) {
String id = idFor(getClass(candidate).getQualifiedName() + "." + candidate.getSignature());
Factory factory = candidate.getFactory();
CtTry ctTry = factory.Core().createTry();
ctTry.setBody(candidate.getBody());
String snippet;
if (containsTransformation(candidate)) {
snippet = getLogName()+".startLogging(Thread.currentThread(),\""+id+"\");\n\t" + getLogName() + ".methodCall(Thread.currentThread(),\"" +
id + "\")";
} else {
snippet = getLogName() + ".methodCall(Thread.currentThread(),\"" +
id + "\")";
}
CtCodeSnippetStatement beginStmt = new CtCodeSnippetStatementImpl();
beginStmt.setValue(snippet);
ctTry.getBody().insertBegin(beginStmt);
CtCodeSnippetStatement stmt = new CtCodeSnippetStatementImpl();
stmt.setValue(getLogName()+".methodOut(Thread.currentThread())");
CtBlock finalizerBlock = factory.Core().createBlock();
finalizerBlock.addStatement(stmt);
ctTry.setFinalizer(finalizerBlock);
CtBlock methodBlock = factory.Core().createBlock();
methodBlock.addStatement(ctTry);
candidate.setBody(methodBlock);
}
protected boolean hasCall(CtMethod method) {
QueryVisitor query = new QueryVisitor(new TypeFilter(CtInvocation.class));
method.accept(query);
for(Object o : query.getResult()) {
CtInvocation target = (CtInvocation) o;
if(target.getExecutable() != null && target.getExecutable().getDeclaration() != null)
if (getAllMethod(method.getFactory()).contains(target.getExecutable().getDeclaration())) {
return true;
}
}
return false;
}
protected List<CtMethod> getAllMethod(Factory factory) {
if(methods == null) {
QueryVisitor query = new QueryVisitor(new TypeFilter(CtMethod.class));
Set<CtElement> roots = getRoots(factory);
roots.stream().flatMap(root -> {
root.accept(query);
return query.getResult().stream();
}).collect(Collectors.toList());
methods = query.getResult();
}
return methods;
}
protected Set<CtElement> getRoots(Factory factory) {
Set<CtElement> roots = new HashSet<>();
ProcessingManager pm = new QueueProcessingManager(factory);
AbstractProcessor<CtPackage> processor = new AbstractProcessor<CtPackage>() {
@Override
public void process(CtPackage element) {
CtElement root = element;
while (root.getParent() != null) {
root = root.getParent();
}
roots.add(root);
}
};
pm.addProcessor(processor);
pm.process();
return roots;
}
}