/** * Some extra information is needed per variable inside the snippet to generate the parts. This * information is wrapped in an extra * * <p>Build the set of template wrappers for the input variables of the loop * * @return */ public List<TemplateInputVariable> getTemplateAccessesWrappers() { // TODO: Unit test for this if (templateAccessesWrappers != null) return templateAccessesWrappers; ArrayList<TemplateInputVariable> result = new ArrayList<>(); for (CtVariableAccess access : getAccesses()) { TemplateInputVariable var = new TemplateInputVariable(); var.initialize(this, access); if (printer instanceof DefaultJavaPrettyPrinter) { var.setPrinter(new DefaultJavaPrettyPrinter(astElement.getFactory().getEnvironment())); } else var.setPrinter(new AJMHPrettyPrinter(this)); result.add(var); } boolean canSerializeThiz = getPreconditions().checkTypeRef(getASTElement().getParent(CtClass.class).getReference()); if (canSerializeThiz && getMustSerializeThiz()) { // astElement.getFactory().Code().createVariableAccess() TemplateInputVariable thiz = new TemplateInputVariable(); thiz.initializeAsThiz(this); if (printer instanceof DefaultJavaPrettyPrinter) { thiz.setPrinter(new DefaultJavaPrettyPrinter(astElement.getFactory().getEnvironment())); } else thiz.setPrinter(new AJMHPrettyPrinter(this)); result.add(thiz); } templateAccessesWrappers = result; return result; }
@Override public <T extends CtBlock<R>> T insertBefore( Filter<? extends CtStatement> insertionPoints, CtStatementList statements) { for (CtStatement e : Query.getElements(this, insertionPoints)) { e.insertBefore(statements); } return (T) this; }
/** * Remove an statement * * @param statement */ private void remove(CtStatement statement) { if (statement.getParent() instanceof CtBlock) { ((CtBlock) statement.getParent()).removeStatement(statement); } else { CtCodeSnippetStatementImpl comment = new CtCodeSnippetStatementImpl(); comment.setValue("/*REMOVED*/"); statement.replace(comment); } }
@Override public <R> void visitCtBlock(CtBlock<R> block) { int i = 0; while (i < block.getStatements().size()) { int size = block.getStatements().size(); CtStatement s = block.getStatement(i); s.accept(this); if (block.getStatements().size() >= size) i++; } }
protected CtMethod apply(CtMethod method, List<Statement> statements, int index) { CtMethod cloned_method = AmplificationHelper.cloneMethodTest(method, "_cf", 1000); CtStatement stmt = getAssertStatement(cloned_method).get(index); statements .stream() .forEach( c -> { stmt.insertBefore((CtStatement) c.getCtCodeFragment()); c.getCtCodeFragment().setParent(stmt.getParent()); }); return cloned_method; }
@Override public <T extends CtStatementList> T addStatement(CtStatement statement) { ensureModifiableStatementsList(); statement.setParent(this); this.statements.add(statement); return (T) this; }
@Override public <T extends CtContinue> T setLabelledStatement(CtStatement labelledStatement) { if (labelledStatement != null) { labelledStatement.setParent(this); } this.labelledStatement = labelledStatement; return (T) this; }
@Override public void visitCtIf(CtIf ifElement) { // super.visitCtIf(ifElement); CtStatement ctThen = ifElement.getThenStatement(); CtStatement ctElse = ifElement.getElseStatement(); Mutability condMut = mutability(ifElement.getCondition()); if (ctThen != null) ifElement.getThenStatement().accept(this); if (ctElse != null) ifElement.getElseStatement().accept(this); if (condMut == Mutability.ERASABLE && isEmpty(ctThen)) { // if ( - ) { } else { } <- Remove the whole if if (ctElse == null || isEmpty(ctElse)) remove(ifElement); // else if case: if ( - ) { } else if { doSomething() } <-- pull the else if element up else if (ctElse instanceof CtIf) ctElse.setParent(ifElement.getParent()); } }
@Override public <T extends CtBlock<R>> T insertBegin(CtStatementList statements) { if (getParent() != null && getParent() instanceof CtConstructor && getStatements().size() > 0) { CtStatement first = getStatements().get(0); if (first instanceof CtInvocation && ((CtInvocation<?>) first).getExecutable().getSimpleName().startsWith("<init>")) { first.insertAfter(statements); return (T) this; } } if (this.statements == CtElementImpl.<CtStatement>emptyList()) { this.statements = new ArrayList<CtStatement>( statements.getStatements().size() + BLOCK_STATEMENTS_CONTAINER_DEFAULT_CAPACITY); } this.statements.addAll(0, statements.getStatements()); return (T) this; }
@Override public <T extends CtBlock<R>> T insertBegin(CtStatement statement) { try { if (getParent() != null && getParent() instanceof CtConstructor && getStatements().size() > 0) { CtStatement first = getStatements().get(0); if (first instanceof CtInvocation && ((CtInvocation<?>) first).getExecutable().getSimpleName().startsWith("<init>")) { first.insertAfter(statement); return (T) this; } } } catch (ParentNotInitializedException ignore) { // CtBlock hasn't a parent. So, it isn't in a constructor. } ensureModifiableStatementsList(); this.statements.add(0, statement); return (T) this; }
private void replace(CtElement e, CtElement op) { if (e instanceof CtStatement && op instanceof CtStatement) { ((CtStatement) e).replace((CtStatement) op); return; } if (e instanceof CtExpression && op instanceof CtExpression) { ((CtExpression) e).replace((CtExpression) op); return; } throw new IllegalArgumentException(e.getClass() + " " + op.getClass()); }
public Boolean getMustSerializeThiz() { if (mustSerializeThiz == null) { List<CtInvocation> invocations = astElement.getElements(new TypeFilter<CtInvocation>(CtInvocation.class)); for (CtInvocation inv : invocations) { if (isImplicitThiz(inv)) { mustSerializeThiz = true; return true; } } mustSerializeThiz = false; } return mustSerializeThiz; }
public String getCode() { if (astElement != null) { try { if (printer == null) return astElement.toString(); printer.reset(); printer.scan(astElement); return printer.toString(); } catch (NullPointerException ex) { throw new NullPointerException( "Unable to get the code. Code field was empty and astElement.toString() throw null"); } } return code; }
/** * Type of the benchmarks method for this snippet. This is 'void' by default. * * <p>The benchmark method type must be the same that the one */ public String getBenchMethodReturnType() { if (benchMethodReturnType == null) { if (astElement != null) { List<CtReturn> rets = astElement.getElements(new TypeFilter<CtReturn>(CtReturn.class)); if (rets != null && rets.size() > 0 && rets.get(0).getReturnedExpression() != null) { CtTypeReference t = rets.get(0).getReturnedExpression().getType(); if (t.isAnonymous() || t.getQualifiedName().equals("<nulltype>")) benchMethodReturnType = "Object"; else benchMethodReturnType = t.getQualifiedName(); } } } return benchMethodReturnType == null ? "void" : benchMethodReturnType; }
/** * Pretty print for the resulting degraded block * * @param clonedBody * @return */ public String prettyPrintBody(CtStatement clonedBody) { String result = ""; if (clonedBody instanceof CtBlock) { CtBlock block = (CtBlock) clonedBody; try { for (int i = 0; i < block.getStatements().size(); i++) { if (block.getStatement(i) instanceof CtBlock) result += prettyPrintBody(block.getStatement(i)); else if (block.getStatement(i) != null) result += block.getStatement(i).toString() + ";\n"; } } catch (NullPointerException ex) { log.error("Unable to print the degraded loop!"); } } else result = clonedBody.toString(); return result; }
@SuppressWarnings("unchecked") void enter(CtElement e, ASTNode node) { stack.push(new ASTPair(e, node)); if (!(e instanceof CtPackage) || (compilationUnitSpoon.getFile() != null && compilationUnitSpoon .getFile() .getName() .equals(DefaultJavaPrettyPrinter.JAVA_PACKAGE_DECLARATION))) { if (compilationunitdeclaration != null) { e.setPosition(this.jdtTreeBuilder.getPositionBuilder().buildPositionCtElement(e, node)); } } ASTPair pair = stack.peek(); CtElement current = pair.element; if (current instanceof CtExpression) { while (!casts.isEmpty()) { ((CtExpression<?>) current).addTypeCast(casts.remove(0)); } } if (current instanceof CtStatement && !this.label.isEmpty()) { ((CtStatement) current).setLabel(this.label.pop()); } try { if (e instanceof CtTypedElement && !(e instanceof CtConstructorCall) && node instanceof Expression) { if (((CtTypedElement<?>) e).getType() == null) { ((CtTypedElement<Object>) e) .setType( this.jdtTreeBuilder .getReferencesBuilder() .getTypeReference(((Expression) node).resolvedType)); } } } catch (UnsupportedOperationException ignore) { // For some element, we throw an UnsupportedOperationException when we call setType(). } }
protected List<CtLocalVariable> getLocalVarInScope(CtStatement stmt) { List<CtLocalVariable> vars = new ArrayList<>(); try { CtBlock parentBlock = stmt.getParent(CtBlock.class); if (parentBlock != null) { boolean beforeCurrentStmt = true; int i = 0; List<CtStatement> stmts = parentBlock.getStatements(); while (beforeCurrentStmt && i < stmts.size()) { CtStatement currentStatement = stmts.get(i); i++; beforeCurrentStmt = beforeCurrentStmt && currentStatement != stmt; if (currentStatement instanceof CtLocalVariable) { vars.add((CtLocalVariable) currentStatement); } } vars.addAll(getLocalVarInScope(parentBlock)); } } catch (Exception e) { throw new RuntimeException(e); } return vars; }
@Override public void process(CtConditional ctConditional) { CtStatement parent = ctConditional.getParent(CtStatement.class); while (!(parent.getParent() instanceof CtStatementList)) { parent = parent.getParent(CtStatement.class); } CtExpression condition = ctConditional.getCondition(); CtIf anIf = getFactory().Core().createIf(); anIf.setPosition(ctConditional.getPosition()); if (parent instanceof CtReturn) { if (!((CtReturn) parent).getReturnedExpression().equals(ctConditional)) { return; } CtReturn returnThen = (CtReturn) parent.clone(); CtReturn returnElse = (CtReturn) parent.clone(); returnThen.setReturnedExpression(ctConditional.getThenExpression()); returnElse.setReturnedExpression(ctConditional.getElseExpression()); List<CtTypeReference> typeCasts = ctConditional.getTypeCasts(); for (int i = 0; i < typeCasts.size(); i++) { CtTypeReference ctTypeReference = typeCasts.get(i); returnThen.getReturnedExpression().addTypeCast(ctTypeReference.clone()); returnElse.getReturnedExpression().addTypeCast(ctTypeReference.clone()); } anIf.setElseStatement(getFactory().Code().createCtBlock(returnElse)); anIf.setThenStatement(getFactory().Code().createCtBlock(returnThen)); } else if (parent instanceof CtAssignment) { CtAssignment assignment = (CtAssignment) parent; CtExpression ctExpression = assignment.getAssignment(); if (!ctExpression.equals(ctConditional)) { if (ctExpression instanceof CtBinaryOperator) { CtBinaryOperator ctBinaryOperator = (CtBinaryOperator) ctExpression; createAssignment(ctConditional, anIf, assignment); CtBinaryOperator cloneThen = ctBinaryOperator.clone(); CtBinaryOperator cloneElse = ctBinaryOperator.clone(); if (ctBinaryOperator.getLeftHandOperand().equals(ctConditional)) { cloneThen.setLeftHandOperand(ctConditional.getThenExpression()); ctConditional.getThenExpression().setParent(cloneThen); cloneElse.setLeftHandOperand(ctConditional.getElseExpression()); } else if (ctBinaryOperator.getRightHandOperand().equals(ctConditional)) { cloneThen.setRightHandOperand(ctConditional.getThenExpression()); cloneElse.setRightHandOperand(ctConditional.getElseExpression()); } cloneThen.getLeftHandOperand().setParent(cloneThen); cloneElse.getLeftHandOperand().setParent(cloneElse); ((CtAssignment) ((CtBlock) anIf.getThenStatement()).getStatement(0)) .setAssignment(cloneThen); ((CtAssignment) ((CtBlock) anIf.getElseStatement()).getStatement(0)) .setAssignment(cloneElse); } else { return; } } else { createAssignment(ctConditional, anIf, assignment); } } else if (parent instanceof CtLocalVariable) { CtLocalVariable localVariable = (CtLocalVariable) parent; if (!localVariable.getDefaultExpression().equals(ctConditional)) { return; } CtLocalVariable clone = localVariable.clone(); clone.setDefaultExpression(null); localVariable.insertBefore(clone); CtAssignment variableAssignment = getFactory() .Code() .createVariableAssignment(localVariable.getReference(), false, ctConditional); variableAssignment.setType(localVariable.getType().clone()); variableAssignment.setPosition(ctConditional.getPosition()); createAssignment(ctConditional, anIf, variableAssignment); } else if (parent instanceof CtInvocation) { CtInvocation invocation = (CtInvocation) parent; CtInvocation cloneThen = invocation.clone(); CtInvocation cloneElse = invocation.clone(); List arguments = cloneThen.getArguments(); boolean found = false; for (int i = 0; i < arguments.size(); i++) { Object o = arguments.get(i); if (o.equals(ctConditional)) { ctConditional.getThenExpression().setParent(invocation); arguments.set(i, ctConditional.getThenExpression()); ctConditional.getElseExpression().setParent(invocation); cloneElse.getArguments().set(i, ctConditional.getElseExpression()); found = true; break; } } if (!found) { return; } cloneThen.setParent(anIf); cloneElse.setParent(anIf); anIf.setElseStatement(getFactory().Code().createCtBlock(cloneElse)); anIf.setThenStatement(getFactory().Code().createCtBlock(cloneThen)); } else if (parent instanceof CtConstructorCall) { CtConstructorCall invocation = (CtConstructorCall) parent; CtConstructorCall cloneThen = invocation.clone(); CtConstructorCall cloneElse = invocation.clone(); List arguments = cloneThen.getArguments(); boolean found = false; for (int i = 0; i < arguments.size(); i++) { Object o = arguments.get(i); if (o.equals(ctConditional)) { arguments.set(i, ctConditional.getThenExpression()); cloneElse.getArguments().set(i, ctConditional.getElseExpression()); found = true; break; } } if (!found) { return; } cloneThen.setParent(anIf); cloneElse.setParent(anIf); anIf.setElseStatement(getFactory().Code().createCtBlock(cloneElse)); anIf.setThenStatement(getFactory().Code().createCtBlock(cloneThen)); } else if (parent instanceof CtIf) { CtIf elem = (CtIf) parent; if (!elem.getCondition().equals(ctConditional)) { return; } CtIf cloneThen = elem.clone(); cloneThen.setParent(anIf); CtIf cloneElse = elem.clone(); cloneElse.setParent(anIf); cloneThen.setCondition(ctConditional.getThenExpression()); ctConditional.getThenExpression().setParent(cloneThen); cloneElse.setCondition(ctConditional.getElseExpression()); ctConditional.getElseExpression().setParent(cloneElse); anIf.setElseStatement(getFactory().Code().createCtBlock(cloneElse)); anIf.setThenStatement(getFactory().Code().createCtBlock(cloneThen)); } else if (parent instanceof CtThrow) { return; } else if (parent instanceof CtLoop) { return; } else if (parent instanceof CtUnaryOperator) { return; } else { System.err.println(parent); throw new RuntimeException("Other " + parent.getClass()); } /*if(ctConditional.getThenExpression().getTypeCasts() == null || ctConditional.getThenExpression().getTypeCasts().isEmpty()) { ((CtExpression)anIf.getThenStatement()).setTypeCasts(ctConditional.getTypeCasts()); } if(ctConditional.getElseExpression().getTypeCasts() == null || ctConditional.getElseExpression().getTypeCasts().isEmpty()) { ((CtExpression) anIf.getElseStatement()) .setTypeCasts(ctConditional.getTypeCasts()); }*/ anIf.setCondition(condition); condition.setParent(anIf); parent.replace(anIf); }
public String getClassName() { if (astElement != null) className = astElement.getPosition().getCompilationUnit().getMainType().getQualifiedName(); return className; }
public int getLineNumber() { if (astElement != null) lineNumber = astElement.getPosition().getLine(); return lineNumber; }
/** * Resolves all the variables used by the snippet. The ones which are initialized and the ones * which are not * * @return True if the context was extracted successfully */ private boolean resolveDataContext(CtStatement statement) { needsInitialization = false; // Check some preconditions needed for the processor to run: // All variable access made inside the statement List<CtVariableAccess> access = statement.getElements(new TypeFilter<>(CtVariableAccess.class)); if (statement.getElements(new TypeFilter<>(CtThisAccess.class)).size() > 0) { mustSerializeThiz = new Preconditions().checkTypeRef(statement.getParent(CtClass.class).getReference()); } initialized = new HashSet<>(); // Get all THIZ field access from all invocations used in the element HashSet<CtInvocation> visited = new HashSet<>(); Stack<CtInvocation> invStack = new Stack<>(); invStack.addAll(statement.getElements(new TypeFilter<>(CtInvocation.class))); while (!invStack.empty()) { CtInvocation inv = invStack.pop(); if (!visited.contains(inv)) { visited.add(inv); CtBlock b; try { b = inv.getExecutable().getDeclaration().getBody(); } catch (NullPointerException ex) { b = null; } if (visibility(inv) != PUBLIC && b != null) { for (CtFieldAccess ta : b.getElements(new TypeFilter<CtFieldAccess>(CtFieldAccess.class))) { if (ta.getTarget() instanceof CtThisAccess || ta.getTarget() == null) { access.add(ta); // initialized.add(ta); } } for (CtInvocation i : b.getElements(new TypeFilter<CtInvocation>(CtInvocation.class))) { if (!visited.contains(i)) invStack.push(i); } } } } access = cleanRepeatedAccesses(access); setAccesses(access); // Find initialized variables of allowed types ControlFlowBuilder v = new ControlFlowBuilder(); CtMethod m = statement.getParent(CtMethod.class); if (m == null) return false; m.accept(v); ControlFlowGraph g = v.getResult(); g.simplify(); try { InitializedVariables vars = new InitializedVariables(); vars.run(ControlFlowBuilder.firstNode(g, statement)); for (CtVariableAccess a : access) { // A variable must be initialized if is local and is not a serializable field // Also if is not a constant. Constant get declared in the body of the microbenchmark if (isInitialized(a, statement, vars) && !isAConstant(a)) initialized.add(a); } } catch (NotFoundException e) { return false; } catch (StackOverflowError e) { System.out.print(g.toGraphVisText()); throw e; } needsInitialization = initialized.size() > 0; if (access.size() <= 0) return true; int i = 0; int replaced = 0; do { if (i == 0) replaced = 0; CtVariableAccess a = access.get(i); if (canBeReplacedByTarget(a)) { CtVariableAccess targetOfA = null; CtTargetedExpression ta = (CtTargetedExpression) a; if (ta.getTarget() != null) { if (ta.getTarget() instanceof CtVariableAccess) { targetOfA = (CtVariableAccess) ta.getTarget(); } else if (ta.getTarget() instanceof CtThisAccess) { mustSerializeThiz = true; } } else { mustSerializeThiz = true; } if (targetOfA != null) { if (!access.contains(targetOfA)) access.add(targetOfA); if (initialized.contains(a) && !initialized.contains(targetOfA)) initialized.add(targetOfA); } access.remove(a); if (initialized.contains(a)) initialized.remove(a); replaced++; } else i++; if (i >= access.size()) i = 0; } while (replaced > 0 || i != 0); return true; }
/** Sets the printer to be de default printer */ public void setPrinterToDefault() { this.printer = new DefaultJavaPrettyPrinter(astElement.getFactory().getEnvironment()); for (TemplateInputVariable v : getTemplateAccessesWrappers()) { v.setPrinter(new DefaultJavaPrettyPrinter(astElement.getFactory().getEnvironment())); } }