Skip to content

Commit

Permalink
refactors CtCase: now extends CtStatementList
Browse files Browse the repository at this point in the history
one can thus write:
for (CtStatement s : case) {
 l.add(s);
}
  • Loading branch information
monperrus committed Aug 1, 2014
1 parent 7b7dd96 commit eab464a
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 60 deletions.
33 changes: 1 addition & 32 deletions src/main/java/spoon/reflect/code/CtCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package spoon.reflect.code;

import java.util.List;

/**
* This code element defines a <code>case</code> within a <code>switch</code>.
Expand All @@ -26,7 +25,7 @@
* This type must be assignable from the switch type
* @see spoon.reflect.code.CtSwitch
*/
public interface CtCase<S> extends CtStatement {
public interface CtCase<S> extends CtStatement, CtStatementList {
/**
* Gets the case expression.
*/
Expand All @@ -36,34 +35,4 @@ public interface CtCase<S> extends CtStatement {
* Sets the case expression.
*/
void setCaseExpression(CtExpression<S> caseExpression);

/**
* Gets the list of statements that defines the case body.
*/
List<CtStatement> getStatements();

/**
* Adds a statement to the case.
*/
boolean addStatement(CtStatement statement);

/**
* Adds a statement to the case at the ith position.
*/
void addStatement(int i, CtStatement statement);

/**
* Removes a statement from the case.
*/
boolean removeStatement(CtStatement statement);

/**
* Removes the ith statement from the case.
*/
void removeStatement(int i);

/**
* Sets the list of statements that defines the case body.
*/
void setStatements(List<CtStatement> statements);
}
32 changes: 15 additions & 17 deletions src/main/java/spoon/support/reflect/code/CtCaseImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package spoon.support.reflect.code;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import spoon.reflect.code.CtCase;
Expand Down Expand Up @@ -54,35 +55,32 @@ public void setStatements(List<CtStatement> statements) {
}

@Override
public boolean addStatement(CtStatement statement) {
public void addStatement(CtStatement statement) {
if (statements == CtElementImpl.<CtStatement> EMPTY_LIST()) {
statements = new ArrayList<CtStatement>();
}
return statements.add(statement);
statements.add(statement);
}

@Override
public void addStatement(int i, CtStatement statement) {
public void removeStatement(CtStatement statement) {
if (statements == CtElementImpl.<CtStatement> EMPTY_LIST()) {
statements = new ArrayList<CtStatement>();
return;
}
statements.add(i, statement);
statements.remove(statement);
}

@Override
public boolean removeStatement(CtStatement statement) {
if (statements == CtElementImpl.<CtStatement> EMPTY_LIST()) {
return false;
}
return statements.remove(statement);
public Iterator<CtStatement> iterator() {
return getStatements().iterator();
}

@Override
public void removeStatement(int i) {
if (statements == CtElementImpl.<CtStatement> EMPTY_LIST()) {
return;
}
statements.remove(i);
}
// adds all those elements before the current case
// @Override
// public void insertBefore(CtStatementList statements)
// throws ParentNotInitializedException {
//
// throw new SpoonException("");
// }

}
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
package spoon.test.intercession.insertBefore;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import spoon.Launcher;
import spoon.compiler.SpoonResourceHelper;
import spoon.reflect.code.*;
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.declaration.CtClass;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.filter.NameFilter;
import spoon.reflect.visitor.filter.TypeFilter;

import static org.junit.Assert.*;

public class InsertBeforeTest {

Factory factory;
Expand Down Expand Up @@ -105,29 +113,34 @@ public void testInsertBeforeSwitchCase() throws Exception {
CtMethod<?> sm = (CtMethod)foo.getElements(
new NameFilter("switchMethod")).get(0);

CtCase s = factory.Core().createCase();
CtCase caseElem = factory.Core().createCase();
CtLiteral<Object> literal = factory.Core().createLiteral();
literal.setValue(1);
s.setCaseExpression(literal);
caseElem.setCaseExpression(literal);

CtSwitch sw = sm.getElements(
new TypeFilter<CtSwitch>(CtSwitch.class)).get(0);

CtCase ctCase1 = (CtCase) sw.getCases().get(2);
CtCase ctCase2= (CtCase) sw.getCases().get(3);
CtCodeSnippetStatement snippet = factory.Code().createCodeSnippetStatement("System.out.println(\"foo\")");
((CtStatement)ctCase1.getStatements().get(0)).insertBefore(snippet);
((CtStatement)ctCase2.getStatements().get(1)).insertBefore(snippet);
ctCase1.getStatements().get(0).insertBefore(snippet);
ctCase2.getStatements().get(1).insertBefore(snippet);
assertEquals(snippet, ctCase1.getStatements().get(0));
assertEquals(snippet, ctCase2.getStatements().get(1));

CtCase ctCase = (CtCase) sw.getCases().get(1);
ctCase.insertBefore(s);

// here we may call either insertBefore(CtStatement) or insertBefore(CtStatementList)
// ctCase.insertBefore(caseElem);
// so force the correct insert
CtStatement stmt = caseElem;
ctCase.insertBefore(stmt);

assertEquals(5, sw.getCases().size());
assertEquals(s, sw.getCases().get(1));
assertEquals(caseElem, sw.getCases().get(1));
assertEquals(ctCase, sw.getCases().get(2));

}
}

Expand Down
57 changes: 57 additions & 0 deletions src/test/java/spoon/test/model/SwitchCaseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package spoon.test.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import spoon.reflect.code.CtCase;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtSwitch;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.filter.TypeFilter;
import spoon.test.TestUtils;

public class SwitchCaseTest {

@Test
public void testIterationStatements() {
Factory factory = TestUtils.createFactory();
CtClass<?> clazz = factory
.Code()
.createCodeSnippetStatement(
"" + "class X {" + "public void foo() {" + " int x=0;" +
"switch(x) {"
+ "case 0: x=x+1;break;"
+ "case 1: x=0;"
+ "default: x=-1;"
+ "}"
+ "}};")
.compile();
CtMethod<?> foo = (CtMethod<?>) clazz.getMethods().toArray()[0];

CtSwitch sw = foo.getElements(new TypeFilter<CtSwitch>(CtSwitch.class)).get(0);

assertEquals(3, sw.getCases().size());

CtCase c = (CtCase) sw.getCases().get(0);

assertEquals(0, ((CtLiteral)c.getCaseExpression()).getValue());
assertEquals(2, c.getStatements().size());

List l = new ArrayList();

// this compiles (thanks to the new CtCase extends CtStatementList)
for (CtStatement s : c) {
l.add(s);
}
assertTrue(c.getStatements().equals(l));
}

}

4 comments on commit eab464a

@pschichtel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not compile for me on Oracle JDK 1.7 (Windows), Oracle JDK 1.8 (Windows) and OpenJDK 1.7 (Debian). It seems like the compiler fails to detect the generic type of the Iterable implementation. Which compiler did you use to build this?

@pschichtel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The offending line is line 51: The compiler detects Iterable even though it's Iterable

@pschichtel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the only compiler that is able to handle this is the Eclipse compiler. Probably not a good idea to depend in that.

@monperrus
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's strange. Fixed but I don't understand the deep causes of the problem.

Please sign in to comment.