diff --git a/src/main/java/spoon/support/visitor/ClassTypingContext.java b/src/main/java/spoon/support/visitor/ClassTypingContext.java index 26a3fcf2e6c..4f0665283f0 100644 --- a/src/main/java/spoon/support/visitor/ClassTypingContext.java +++ b/src/main/java/spoon/support/visitor/ClassTypingContext.java @@ -364,6 +364,10 @@ private CtTypeReference<?> getEnclosingType(CtTypeReference<?> typeRef) { if (declType == null) { return null; } + if (type.isInterface()) { + // Case: we have a declaring type and the inner type is an interface. So the nested interface is implicitly static. + return null; + } if (declType.isInterface()) { //nested types of interfaces are static return null; diff --git a/src/test/java/spoon/test/method/MethodTest.java b/src/test/java/spoon/test/method/MethodTest.java index b44d8a339fb..fe1b29b9a01 100644 --- a/src/test/java/spoon/test/method/MethodTest.java +++ b/src/test/java/spoon/test/method/MethodTest.java @@ -18,6 +18,7 @@ import org.junit.Test; import spoon.Launcher; +import spoon.reflect.CtModel; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtParameter; @@ -43,6 +44,7 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static spoon.testing.utils.ModelUtils.build; import static spoon.testing.utils.ModelUtils.buildClass; import static spoon.testing.utils.ModelUtils.createFactory; @@ -218,4 +220,16 @@ public void test_addFormalCtTypeParameterAt_throwsOutOfBoundsException_whenPosit assertThrows(IndexOutOfBoundsException.class, () -> method.addFormalCtTypeParameterAt(1, typeParam)); } + + @Test + public void testGetAllMethodsInnerClassExtended() { + // contract: implicit static nested interfaces are correct handled in getAllExecutables and dont throw an error. + Launcher launcher = new Launcher(); + launcher.addInputResource("src/test/resources/extendsStaticInnerType"); + CtModel model = launcher.buildModel(); + CtType<?> type = model.getAllTypes().stream().filter(v -> v.getSimpleName().contains("BarBaz")).findAny().get(); + assertDoesNotThrow(() -> type.getAllExecutables()); + // on jdk8 there are 14 types on newer 13 because a method in Object.java was removed + assertTrue(13 == type.getAllExecutables().size() || 14 == type.getAllExecutables().size()); + } } diff --git a/src/test/resources/extendsStaticInnerType/BarBaz.java b/src/test/resources/extendsStaticInnerType/BarBaz.java new file mode 100644 index 00000000000..e6cb6ed6dd5 --- /dev/null +++ b/src/test/resources/extendsStaticInnerType/BarBaz.java @@ -0,0 +1,10 @@ +package extendsStaticInnerType; + +public class BarBaz implements FooBar.Crashy { + + @Override + public String foo() { + return "bar!"; + } + +} \ No newline at end of file diff --git a/src/test/resources/extendsStaticInnerType/FooBar.java b/src/test/resources/extendsStaticInnerType/FooBar.java new file mode 100644 index 00000000000..c1259ea17a0 --- /dev/null +++ b/src/test/resources/extendsStaticInnerType/FooBar.java @@ -0,0 +1,9 @@ +package extendsStaticInnerType; + +public class FooBar { + + public interface Crashy { + + String foo(); + } +} \ No newline at end of file