package spoon.test.intercession.insertBefore;
import org.junit.Before;
import org.junit.Test;
import spoon.Launcher;
import spoon.compiler.SpoonResourceHelper;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtCase;
import spoon.reflect.code.CtCodeSnippetStatement;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtSwitch;
import spoon.reflect.code.CtWhile;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.Query;
import spoon.reflect.visitor.filter.NameFilter;
import spoon.reflect.visitor.filter.TypeFilter;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class InsertMethodsTest {
Factory factory;
;
private CtClass<?> assignmentClass;
private CtClass<?> insertExampleClass;
@Before
public void setup() throws Exception {
Launcher spoon = new Launcher();
factory = spoon.createFactory();
spoon.createCompiler(factory, SpoonResourceHelper.resources("./src/test/java/spoon/test/intercession/insertBefore/InsertBeforeExample.java")).build();
assignmentClass = factory.Code().createCodeSnippetStatement(//
"class X {" //
+ "public void foo() {" //
+ " int x=0;" //
+ " int y=0;" //
+ " int z=x+y;" //
+ " }" //
+ "};").compile();
insertExampleClass = factory.Package().get("spoon.test.intercession.insertBefore").getType("InsertBeforeExample");
}
@Test
public void testInsertBefore() {
CtMethod<Void> foo = (CtMethod<Void>) assignmentClass.getMethods().toArray()[0];
CtBlock<?> body = foo.getBody();
assertEquals(3, body.getStatements().size());
CtStatement s = body.getStatements().get(2);
assertEquals("int z = x + y", s.toString());
// adding a new statement;
CtCodeSnippetStatement stmt = factory.Core().createCodeSnippetStatement();
stmt.setValue("System.out.println(x);");
s.insertBefore(stmt);
assertEquals(4, body.getStatements().size());
assertSame(stmt, body.getStatements().get(2));
assertEquals(s.getParent(), stmt.getParent());
}
@Test
public void testInsertAfter() throws Exception {
CtMethod<Void> foo = (CtMethod<Void>) assignmentClass.getMethods().toArray()[0];
CtBlock<?> body = foo.getBody();
assertEquals(3, body.getStatements().size());
CtStatement s = body.getStatements().get(2);
assertEquals("int z = x + y", s.toString());
// adding a new statement;
CtCodeSnippetStatement stmt = factory.Core().createCodeSnippetStatement();
stmt.setValue("System.out.println(x);");
s.insertAfter(stmt);
assertEquals(4, body.getStatements().size());
assertSame(stmt, body.getStatements().get(3));
assertEquals(body, stmt.getParent());
}
@Test
public void testInsertBeforeWithoutBrace() throws Exception {
CtMethod<?> ifWithoutBraces_m = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("ifWithoutBraces")).get(0);
// replace the return
CtCodeSnippetStatement s = factory.Code().createCodeSnippetStatement("return 2");
CtIf ifWithoutBraces = ifWithoutBraces_m.getElements(new TypeFilter<>(CtIf.class)).get(0);
// Inserts a s before the then statement
ifWithoutBraces.getThenStatement().insertBefore(s);
assertTrue(ifWithoutBraces.getThenStatement() instanceof CtBlock);
assertEquals(s, ((CtBlock<?>) ifWithoutBraces.getThenStatement()).getStatement(0));
assertEquals(ifWithoutBraces.getThenStatement(), s.getParent());
}
@Test
public void testInsertBeforeWithBrace() throws Exception {
CtMethod<?> ifWithBraces_m = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("ifWithBraces")).get(0);
// replace the return
CtCodeSnippetStatement s = factory.Code().createCodeSnippetStatement("return 2");
CtIf ifWithBraces = ifWithBraces_m.getElements(new TypeFilter<CtIf>(CtIf.class)).get(0);
// Inserts a s before the then statement
ifWithBraces.getThenStatement().insertBefore(s);
assertTrue(ifWithBraces.getThenStatement() instanceof CtBlock);
assertEquals(s, ((CtBlock<?>) ifWithBraces.getThenStatement()).getStatement(0));
assertEquals(ifWithBraces.getThenStatement(), s.getParent());
}
@Test
public void testInsertAfterWithoutBrace() throws Exception {
CtMethod<?> ifWithoutBraces_m = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("ifWithoutBraces")).get(0);
// replace the return
CtCodeSnippetStatement s = factory.Code().createCodeSnippetStatement("return 2");
CtIf ifWithoutBraces = ifWithoutBraces_m.getElements(new TypeFilter<>(CtIf.class)).get(0);
// Inserts a s before the then statement
ifWithoutBraces.getThenStatement().insertAfter(s);
assertTrue(ifWithoutBraces.getThenStatement() instanceof CtBlock);
assertEquals(s, ((CtBlock<?>) ifWithoutBraces.getThenStatement()).getStatement(1));
assertEquals(ifWithoutBraces.getThenStatement(), s.getParent());
}
@Test
public void testInsertAfterWithBrace() throws Exception {
CtMethod<?> ifWithBraces_m = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("ifWithBraces")).get(0);
// replace the return
CtCodeSnippetStatement s = factory.Code().createCodeSnippetStatement("return 2");
CtIf ifWithBraces = ifWithBraces_m.getElements(new TypeFilter<CtIf>(CtIf.class)).get(0);
// Inserts a s before the then statement
ifWithBraces.getThenStatement().insertAfter(s);
assertTrue(ifWithBraces.getThenStatement() instanceof CtBlock);
assertEquals(s, ((CtBlock<?>) ifWithBraces.getThenStatement()).getStatement(1));
assertEquals(ifWithBraces.getThenStatement(), s.getParent());
}
@Test
public void testInsertBeforeSwitchCase() throws Exception {
CtMethod<?> sm = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("switchMethod")).get(0);
// Adds a new snippet in a case.
CtSwitch<?> sw = sm.getElements(new TypeFilter<CtSwitch<?>>(CtSwitch.class)).get(0);
CtCase<?> ctCase1 = sw.getCases().get(2);
CtCase<?> ctCase2 = sw.getCases().get(3);
CtCodeSnippetStatement snippet = factory.Code().createCodeSnippetStatement("System.out.println(\"foo\")");
ctCase1.getStatements().get(0).insertBefore(snippet);
assertEquals(snippet, ctCase1.getStatements().get(0));
assertEquals(ctCase1, snippet.getParent());
CtCodeSnippetStatement snippet2 = snippet.clone();
ctCase2.getStatements().get(1).insertBefore(snippet2);
assertEquals(snippet2, ctCase2.getStatements().get(1));
assertEquals(ctCase2, snippet2.getParent());
// Creates a new case.
CtCase<Object> caseElem = factory.Core().createCase();
CtLiteral<Object> literal = factory.Core().createLiteral();
literal.setValue(1);
caseElem.setCaseExpression(literal);
// here we may call either insertBefore(CtStatement) or insertBefore(CtStatementList)
// ctCase.insertBefore(caseElem);
// so force the correct insert
CtCase<?> ctCase = sw.getCases().get(1);
ctCase.insertBefore((CtStatement) caseElem);
assertEquals(5, sw.getCases().size());
assertEquals(caseElem, sw.getCases().get(1));
assertEquals(ctCase, sw.getCases().get(2));
assertEquals(sw, caseElem.getParent());
}
@Test
public void testInsertAfterSwitchCase() throws Exception {
CtMethod<?> sm = insertExampleClass.getElements(new NameFilter<CtMethod<?>>("switchMethod")).get(0);
// Adds a new snippet in a case.
CtSwitch<?> sw = sm.getElements(new TypeFilter<CtSwitch<?>>(CtSwitch.class)).get(0);
CtCase<?> ctCase1 = sw.getCases().get(2);
CtCase<?> ctCase2 = sw.getCases().get(3);
CtCodeSnippetStatement snippet = factory.Code().createCodeSnippetStatement("System.out.println(\"foo\")");
ctCase1.getStatements().get(0).insertAfter(snippet);
assertEquals(snippet, ctCase1.getStatements().get(1));
assertEquals(ctCase1, snippet.getParent());
CtCodeSnippetStatement snippet2 = snippet.clone();
ctCase2.getStatements().get(1).insertAfter(snippet2);
assertEquals(snippet2, ctCase2.getStatements().get(2));
assertEquals(ctCase2, snippet2.getParent());
// Creates a new case.
CtCase<Object> caseElem = factory.Core().createCase();
CtLiteral<Object> literal = factory.Core().createLiteral();
literal.setValue(1);
caseElem.setCaseExpression(literal);
// here we may call either insertAfter(CtStatement) or insertAfter(CtStatementList)
// ctCase.insertAfter(caseElem);
// so force the correct insert
CtCase<?> ctCase = sw.getCases().get(1);
ctCase.insertAfter((CtStatement) caseElem);
assertEquals(5, sw.getCases().size());
assertEquals(caseElem, sw.getCases().get(2));
assertEquals(ctCase, sw.getCases().get(1));
assertEquals(sw, caseElem.getParent());
}
@Test
public void insertBeforeAndUpdateParent() throws Exception {
/**
* if (condition)
* while (loop_condition)
*
* In this case the 'while' is inside an implicit block, but
* when we insert a new statement
*
* if (condition) {
* newStatement
* while (loop_condition)
* ...
* }
*
* Now the while is inside an explicit block.
*/
Launcher spoon = new Launcher();
Factory factory = spoon.createFactory();
spoon.createCompiler(factory, SpoonResourceHelper.resources("./src/test/resources/spoon/test/intercession/insertBefore/InsertBeforeExample2.java")).build();
// Get the 'while'
List<CtWhile> elements = Query.getElements(factory, new TypeFilter<CtWhile>(CtWhile.class));
assertTrue(1 == elements.size());
CtWhile theWhile = elements.get(0);
// We make sure the parent of the while is the CtIf and not the block
CtElement parent = theWhile.getParent();
assertTrue(parent instanceof CtBlock);
assertTrue(parent.isImplicit());
CtIf ifParent = (CtIf) parent.getParent();
// Create a new statement to be inserted before the while
CtStatement insert = factory.Code().createCodeSnippetStatement("System.out.println()");
// Insertion of the new statement
theWhile.insertBefore(insert);
// We make sure the parent of the while is updated
CtElement newParent = theWhile.getParent();
assertTrue(newParent != ifParent);
assertTrue(newParent instanceof CtBlock);
assertFalse(newParent.isImplicit());
}
}