From ddf4db5b7c5bb76db613ce66b3e5af8ca5e42880 Mon Sep 17 00:00:00 2001 From: Pavel Vojtechovsky Date: Sat, 26 Nov 2016 14:24:21 +0100 Subject: [PATCH] feature(API): add CtTypeMember.getTopLevelType() (#1004) --- .../reflect/declaration/CtTypeMember.java | 6 +++ .../CtAnonymousExecutableImpl.java | 6 --- .../reflect/declaration/CtExecutableImpl.java | 9 ++++ .../reflect/declaration/CtFieldImpl.java | 5 ++ .../reflect/declaration/CtMethodImpl.java | 6 --- .../reflect/declaration/CtTypeImpl.java | 14 ++++++ .../spoon/test/parent/TopLevelTypeTest.java | 46 +++++++++++++++++++ 7 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 src/test/java/spoon/test/parent/TopLevelTypeTest.java diff --git a/src/main/java/spoon/reflect/declaration/CtTypeMember.java b/src/main/java/spoon/reflect/declaration/CtTypeMember.java index 71eb53bb605..ef02a07e8d2 100644 --- a/src/main/java/spoon/reflect/declaration/CtTypeMember.java +++ b/src/main/java/spoon/reflect/declaration/CtTypeMember.java @@ -32,4 +32,10 @@ public interface CtTypeMember extends CtModifiable { @DerivedProperty CtType getDeclaringType(); + /** + * Returns the top level type declaring this type if an inner type or type member. + * If this is already a top-level type, then returns itself. + */ + @DerivedProperty + CtType getTopLevelType(); } diff --git a/src/main/java/spoon/support/reflect/declaration/CtAnonymousExecutableImpl.java b/src/main/java/spoon/support/reflect/declaration/CtAnonymousExecutableImpl.java index 01dc7c20de6..67430b6e348 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtAnonymousExecutableImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtAnonymousExecutableImpl.java @@ -17,7 +17,6 @@ package spoon.support.reflect.declaration; import spoon.reflect.declaration.CtAnonymousExecutable; -import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtModifiable; import spoon.reflect.declaration.CtNamedElement; @@ -61,11 +60,6 @@ public Set getModifiers() { return modifiers; } - @Override - public CtClass getDeclaringType() { - return (CtClass) parent; - } - @Override public ModifierKind getVisibility() { if (getModifiers().contains(ModifierKind.PUBLIC)) { diff --git a/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java b/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java index 8bd936fc976..354aed706fa 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java @@ -27,6 +27,7 @@ import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtType; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; import spoon.support.util.QualifiedNameBasedSortedSet; @@ -50,6 +51,14 @@ public CtExecutableImpl() { super(); } + public CtType getDeclaringType() { + return (CtType) parent; + } + + public CtType getTopLevelType() { + return getDeclaringType().getTopLevelType(); + } + @Override @SuppressWarnings("unchecked") public CtBlock getBody() { diff --git a/src/main/java/spoon/support/reflect/declaration/CtFieldImpl.java b/src/main/java/spoon/support/reflect/declaration/CtFieldImpl.java index bdd9d7a3e10..bdbbe154e73 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtFieldImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtFieldImpl.java @@ -61,6 +61,11 @@ public CtType getDeclaringType() { return (CtType) parent; } + @Override + public CtType getTopLevelType() { + return getDeclaringType().getTopLevelType(); + } + @Override public CtExpression getDefaultExpression() { return defaultExpression; diff --git a/src/main/java/spoon/support/reflect/declaration/CtMethodImpl.java b/src/main/java/spoon/support/reflect/declaration/CtMethodImpl.java index bb9378ba323..d1fcc3a9371 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtMethodImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtMethodImpl.java @@ -21,7 +21,6 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtModifiable; import spoon.reflect.declaration.CtShadowable; -import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.CtTypedElement; import spoon.reflect.declaration.ModifierKind; @@ -77,11 +76,6 @@ public C setType(CtTypeReference type) { return (C) this; } - @Override - public CtType getDeclaringType() { - return (CtType) parent; - } - @Override public boolean isDefaultMethod() { return defaultMethod; diff --git a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java index 0f08add31c1..dc43024219f 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java @@ -298,6 +298,20 @@ public CtType getDeclaringType() { } } + @SuppressWarnings("unchecked") + @Override + public CtType getTopLevelType() { + CtType top = this; + + while (true) { + CtType nextTop = top.getDeclaringType(); + if (nextTop == null) { + return (CtType) top; + } + top = nextTop; + } + } + @Override @SuppressWarnings("unchecked") public > N getNestedType(final String name) { diff --git a/src/test/java/spoon/test/parent/TopLevelTypeTest.java b/src/test/java/spoon/test/parent/TopLevelTypeTest.java new file mode 100644 index 00000000000..431e14925e7 --- /dev/null +++ b/src/test/java/spoon/test/parent/TopLevelTypeTest.java @@ -0,0 +1,46 @@ +package spoon.test.parent; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import spoon.Launcher; +import spoon.compiler.SpoonResourceHelper; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.factory.Factory; + +public class TopLevelTypeTest +{ + Factory factory; + + @Before + public void setup() throws Exception { + Launcher spoon = new Launcher(); + spoon.setArgs(new String[] {"--output-type", "nooutput" }); + factory = spoon.createFactory(); + spoon.createCompiler( + factory, + SpoonResourceHelper + .resources("./src/test/java/spoon/test/parent/Foo.java")) + .build(); + } + + + @Test + public void testTopLevelType() throws Exception { + CtClass foo = factory.Class().get(Foo.class); + assertEquals(foo, foo.getTopLevelType()); + CtMethod internalClassMethod = foo.getMethod("internalClass"); + assertEquals(foo, internalClassMethod.getDeclaringType()); + assertEquals(foo, internalClassMethod.getTopLevelType()); + CtClass internalClass = (CtClass)internalClassMethod.getBody().getStatement(0); + assertEquals(foo, internalClassMethod.getDeclaringType()); + assertEquals(foo, internalClassMethod.getTopLevelType()); + CtMethod mm = internalClass.getMethod("m"); + assertEquals(internalClass, mm.getDeclaringType()); + assertEquals(foo, mm.getTopLevelType()); + } + +}