Skip to content

Commit

Permalink
feat(snippet): add support for compiling statements with return
Browse files Browse the repository at this point in the history
  • Loading branch information
monperrus authored and tdurieux committed Nov 10, 2016
1 parent 904db11 commit 3fa4bc0
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/main/java/spoon/reflect/code/CtCodeSnippetStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package spoon.reflect.code;

import spoon.reflect.declaration.CtCodeSnippet;
import spoon.reflect.reference.CtTypeReference;
import spoon.support.compiler.SnippetCompilationError;

/**
Expand All @@ -31,6 +32,9 @@ public interface CtCodeSnippetStatement extends CtStatement, CtCodeSnippet {
* Compiles this statement code snippet to produce the corresponding AST
* statement.
*
* If you want to compile a non-void return or a snippet that uses a non-void return,
* use, {@link spoon.support.compiler.SnippetCompilationHelper#compileStatement(CtCodeSnippetStatement, CtTypeReference)}
*
* @return a statement
* @throws SnippetCompilationError
* when the current snippet is not valid Java code
Expand Down
19 changes: 11 additions & 8 deletions src/main/java/spoon/support/compiler/SnippetCompilationHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,18 @@ public static void compileAndReplaceSnippetsIn(CtType<?> c) {

public static CtStatement compileStatement(CtCodeSnippetStatement st)
throws SnippetCompilationError {
return internalCompileStatement(st);
return internalCompileStatement(st, st.getFactory().Type().VOID_PRIMITIVE);
}

private static CtStatement internalCompileStatement(CtElement st) {
public static CtStatement compileStatement(CtCodeSnippetStatement st, CtTypeReference returnType)
throws SnippetCompilationError {
return internalCompileStatement(st, returnType);
}

private static CtStatement internalCompileStatement(CtElement st, CtTypeReference returnType) {
Factory f = st.getFactory();

CtClass<?> w = createWrapper(st, f);
CtClass<?> w = createWrapper(st, f, returnType);

build(f, w);

Expand Down Expand Up @@ -97,7 +102,7 @@ private static CtStatement internalCompileStatement(CtElement st) {
public static <T> CtExpression<T> compileExpression(
CtCodeSnippetExpression<T> expr) throws SnippetCompilationError {

CtReturn<T> ret = (CtReturn<T>) internalCompileStatement(expr);
CtReturn<T> ret = (CtReturn<T>) internalCompileStatement(expr, expr.getFactory().Type().OBJECT);

return ret.getReturnedExpression();
}
Expand All @@ -119,22 +124,20 @@ private static void build(Factory f, String contents) {
}
}

private static CtClass<?> createWrapper(CtElement element, Factory f) {
private static CtClass<?> createWrapper(final CtElement element, final Factory f, final CtTypeReference returnType) {
CtClass<?> w = f.Class().create(WRAPPER_CLASS_NAME);

// Clean up (delete wrapper from factory)
w.getPackage().getTypes().remove(w);

CtBlock body = f.Core().createBlock();

CtTypeReference returnType = f.Type().VOID_PRIMITIVE;
;
if (element instanceof CtStatement) {
body.addStatement((CtStatement) element);
} else if (element instanceof CtExpression) {
CtReturn ret = f.Core().createReturn();
ret.setReturnedExpression((CtExpression) element);
body.addStatement(ret);
returnType = f.Type().OBJECT;
}

Set<ModifierKind> modifiers = EnumSet.of(ModifierKind.STATIC);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ protected boolean buildSources(JDTBuilder jdtBuilder) {

@Override
protected void report(Environment environment, CategorizedProblem problem) {
throw new SnippetCompilationError(problem.getMessage() + "at line " + problem.getSourceLineNumber());
if (problem.isError()) {
throw new SnippetCompilationError(problem.getMessage() + "at line " + problem.getSourceLineNumber());
}
}

/**
Expand Down
16 changes: 16 additions & 0 deletions src/test/java/spoon/test/snippets/SnippetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import spoon.reflect.code.CtBinaryOperator;
import spoon.reflect.code.CtCodeSnippetExpression;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtReturn;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.support.compiler.SnippetCompilationHelper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static spoon.support.compiler.SnippetCompilationHelper.compileStatement;
import static spoon.testing.utils.ModelUtils.createFactory;

public class SnippetTest {
Expand Down Expand Up @@ -76,4 +80,16 @@ public void testCompileSnippetWithContext() throws Exception {
fail();
}
}

@Test
public void testCompileStatementWithReturn() throws Exception {
// contract: a snippet with return can be compiled.
CtElement el = SnippetCompilationHelper.compileStatement(
factory.Code().createCodeSnippetStatement("return 3"),
factory.Type().INTEGER
);
assertTrue(CtReturn.class.isAssignableFrom(el.getClass()));
assertEquals("return 3", el.toString());
}

}

0 comments on commit 3fa4bc0

Please sign in to comment.