Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for https://github.com/INRIA/spoon/issues/793 #794

Merged
merged 2 commits into from
Aug 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 72 additions & 2 deletions src/main/java/spoon/support/reflect/declaration/CtEnumImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,31 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import spoon.reflect.declaration.ModifierKind;

public class CtEnumImpl<T extends Enum<?>> extends CtClassImpl<T> implements CtEnum<T> {
private static final long serialVersionUID = 1L;

private List<CtEnumValue<?>> enumValues = CtElementImpl.<CtEnumValue<?>>emptyList();

private CtMethod<T[]> valuesMethod;

private CtMethod<T> valueOfMethod;

@Override
public void accept(CtVisitor visitor) {
visitor.visitCtEnum(this);
}

@Override
public Set<CtMethod<?>> getAllMethods() {
return getMethods();
Set<CtMethod<?>> allMethods = new HashSet<>(getMethods());
allMethods.add(valuesMethod());
allMethods.add(valueOfMethod());
return allMethods;
}

@Override
Expand All @@ -50,7 +59,7 @@ public boolean isSubtypeOf(CtTypeReference<?> type) {
return true;
}
}
return false;
return getSuperclass().isSubtypeOf(type);
}

@Override
Expand Down Expand Up @@ -111,4 +120,65 @@ public CtField<?> getField(String name) {
public CtEnum<T> clone() {
return (CtEnum<T>) super.clone();
}

@Override
public CtTypeReference<?> getSuperclass() {
return getFactory().Type().createReference(Enum.class);
}

private CtMethod valuesMethod() {
if (valuesMethod == null) {
valuesMethod = getFactory().Core().createMethod();
valuesMethod.setParent(this);
valuesMethod.addModifier(ModifierKind.PUBLIC);
valuesMethod.addModifier(ModifierKind.STATIC);
valuesMethod.setSimpleName("values");
valuesMethod.setImplicit(true);
valuesMethod.setType(factory.Type().createArrayReference(getReference()));
}
return valuesMethod;
}

private CtMethod valueOfMethod() {
if (valueOfMethod == null) {
valueOfMethod = getFactory().Core().createMethod();
valueOfMethod.setParent(this);
valueOfMethod.addModifier(ModifierKind.PUBLIC);
valueOfMethod.addModifier(ModifierKind.STATIC);
valueOfMethod.setSimpleName("valueOf");
valueOfMethod.setImplicit(true);
valueOfMethod.addThrownType(
getFactory().Type().createReference(IllegalArgumentException.class));
valueOfMethod.setType(getReference());
factory.Method().createParameter(valuesMethod, factory.Type().STRING, "name");
}
return valueOfMethod;
}

@Override
public <R> CtMethod<R> getMethod(String name, CtTypeReference<?>... parameterTypes) {
if ("values".equals(name) && parameterTypes.length == 0) {
return valuesMethod();
} else if ("valueOf".equals(name) && parameterTypes.length == 1 && parameterTypes[0].equals(factory.Type().STRING)) {
return valueOfMethod();
} else {
return super.getMethod(name, parameterTypes);
}
}

@Override
public <R> CtMethod<R> getMethod(CtTypeReference<R> returnType, String name, CtTypeReference<?>... parameterTypes) {
if ("values".equals(name)
&& parameterTypes.length == 0
&& returnType.equals(getReference())) {
return valuesMethod();
} else if ("valueOf".equals(name)
&& parameterTypes.length == 1
&& parameterTypes[0].equals(factory.Type().STRING)
&& returnType.equals(factory.Type().createArrayReference(getReference()))) {
return valueOfMethod();
} else {
return super.getMethod(returnType, name, parameterTypes);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void testScannerEnum() throws Exception {
final CtEnum<TextStyle> anEnum = new JavaReflectionTreeBuilder(createFactory()).scan(TextStyle.class);
assertNotNull(anEnum);
assertEquals("java.time.format.TextStyle", anEnum.getQualifiedName());
assertNull(anEnum.getSuperclass());
assertNotNull(anEnum.getSuperclass());
assertTrue(anEnum.getFields().size() > 0);
assertTrue(anEnum.getEnumValues().size() > 0);
assertTrue(anEnum.getMethods().size() > 0);
Expand Down
11 changes: 11 additions & 0 deletions src/test/java/spoon/test/reference/Enum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package spoon.test.reference;

public enum Enum {
A,
B,
C;

public static Enum getFirst(){
return valueOf("A");
}
}
18 changes: 18 additions & 0 deletions src/test/java/spoon/test/reference/ExecutableReferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,22 @@ public boolean matches(final CtExecutable<?> exec) {
}
});
}

@Test
public void testInvokeEnumMethod() {
final spoon.Launcher launcher = new spoon.Launcher();
launcher.addInputResource("./src/test/java/spoon/test/reference/Enum.java");
launcher.getEnvironment().setNoClasspath(true);
launcher.getEnvironment().setComplianceLevel(8);
launcher.buildModel();

CtInvocation invocation = launcher.getModel().getElements(new TypeFilter<CtInvocation>(CtInvocation.class) {
@Override
public boolean matches(CtInvocation element) {
return super.matches(element)
&& element.getExecutable().getSimpleName().equals("valueOf");
}
}).get(0);
assertNotNull(invocation.getExecutable().getExecutableDeclaration());
}
}
11 changes: 11 additions & 0 deletions src/test/java/spoon/test/reference/TypeReferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import spoon.reflect.declaration.CtEnum;
import static spoon.testing.utils.ModelUtils.buildClass;
import static spoon.testing.utils.ModelUtils.canBeBuilt;
import static spoon.testing.utils.ModelUtils.createFactory;
Expand Down Expand Up @@ -522,4 +523,14 @@ class B {
class Tacos<K extends A> {
}
}

@Test
public void testCorrectEnumParent() {
final Launcher launcher = new Launcher();
launcher.getEnvironment().setNoClasspath(true);
launcher.buildModel();
CtEnum e = launcher.getFactory().Enum().create("spoon.test.reference.EnumE");
CtTypeReference correctParent = launcher.getFactory().Type().createReference(java.lang.Enum.class);
assertEquals(correctParent, e.getReference().getSuperclass());
}
}