Skip to content

Commit

Permalink
fix: CtCatchVariable#getType() in noclasspath mode may return null (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Egor18 authored and pvojtechovsky committed Apr 1, 2018
1 parent ec58744 commit 25ff47f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/main/java/spoon/reflect/code/CtCatchVariable.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public interface CtCatchVariable<T> extends CtVariable<T>, CtMultiTypedElement,
@UnsettableProperty
<C extends CtVariable<T>> C setDefaultExpression(CtExpression<T> assignedExpression);

/**
* Returns type reference of the exception variable in a catch.
* If type is unknown, or any of the types in a multi-catch is unknown, returns null.
*/
@Override
@DerivedProperty
CtTypeReference<T> getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public CtTypeReference<T> getType() {
.includingInterfaces(false)
.includingSelf(true)
.returnTypeReferences(true)).list();
if (superTypesOfFirst.isEmpty()) {
return null;
}
int commonSuperTypeIdx = 0;
//index of Throwable. Last is Object
int throwableIdx = superTypesOfFirst.size() - 2;
Expand Down
26 changes: 21 additions & 5 deletions src/test/java/spoon/test/trycatch/TryCatchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static spoon.testing.utils.ModelUtils.build;
Expand Down Expand Up @@ -218,7 +219,7 @@ public void testTryCatchVariableGetType() throws Exception {
CtTry tryStmt = (CtTry) clazz.getElements(new TypeFilter<>(CtTry.class)).get(0);
List<CtCatch> catchers = tryStmt.getCatchers();
assertEquals(1, catchers.size());

CtCatchVariable<?> catchVariable = catchers.get(0).getParameter();

assertEquals(
Expand All @@ -230,28 +231,28 @@ public void testTryCatchVariableGetType() throws Exception {
assertEquals(
RuntimeException.class,
catchVariable.getMultiTypes().get(0).getActualClass());

//contract: the manipulation with catch variable type is possible
catchVariable.setType((CtTypeReference)factory.Type().createReference(IllegalArgumentException.class));
assertEquals(IllegalArgumentException.class,catchVariable.getType().getActualClass());
//contract setType influences multitypes
assertEquals(1, catchVariable.getMultiTypes().size());
assertEquals(IllegalArgumentException.class, catchVariable.getMultiTypes().get(0).getActualClass());

catchVariable.setMultiTypes(Collections.singletonList((CtTypeReference)factory.Type().createReference(UnsupportedOperationException.class)));
assertEquals(UnsupportedOperationException.class,catchVariable.getType().getActualClass());
//contract setType influences multitypes
assertEquals(1, catchVariable.getMultiTypes().size());
assertEquals(UnsupportedOperationException.class, catchVariable.getMultiTypes().get(0).getActualClass());

catchVariable.setMultiTypes(Arrays.asList(
factory.Type().createReference(UnsupportedOperationException.class),
factory.Type().createReference(IllegalArgumentException.class)
));
assertEquals(2, catchVariable.getMultiTypes().size());
assertEquals(UnsupportedOperationException.class, catchVariable.getMultiTypes().get(0).getActualClass());
assertEquals(IllegalArgumentException.class, catchVariable.getMultiTypes().get(1).getActualClass());

//contract setMultiTypes influences types, which contains common super class of all multi types
assertEquals(RuntimeException.class,catchVariable.getType().getActualClass());
}
Expand Down Expand Up @@ -289,4 +290,19 @@ public void testCatchWithExplicitFinalVariable() throws IOException {

assertTrue(content.contains("catch (final java.lang.Exception e)"));
}

@Test
public void testCatchWithUnknownExceptions() {
// contract: unknown exception type in multicatch should not cause IndexOutOfBoundsException
String inputResource = "./src/test/resources/spoon/test/noclasspath/exceptions/Foo.java";
Launcher launcher = new Launcher();
launcher.addInputResource(inputResource);
launcher.getEnvironment().setNoClasspath(true);
CtModel model = launcher.buildModel();

List<CtCatch> catches = model.getElements(new TypeFilter<CtCatch>(CtCatch.class));
assertNotNull(catches.get(0).getParameter().getType()); // catch with single UnknownException
assertNull(catches.get(1).getParameter().getType()); // multicatch with UnknownException
assertNull(catches.get(2).getParameter().getType()); // multicatch with UnknownException
}
}
30 changes: 30 additions & 0 deletions src/test/resources/spoon/test/noclasspath/exceptions/Foo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

public class Foo {

void testCatchWithUnknownException(File file) {
try {
new FileReader(file);
}
catch (UnknownException e) {
System.out.println(e);
}
}

void testMultiCatchWithUnknownException1(File file) {
try {
new FileReader(file);
}
catch (UnknownException | FileNotFoundException e) {
System.out.println(e);
}
}

void testMultiCatchWithUnknownException2(File file) {
try {
new FileReader(file);
}
catch (FileNotFoundException | UnknownException e) {
System.out.println(e);
}
}
}

0 comments on commit 25ff47f

Please sign in to comment.