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

add CtTypeInformation.getDeclaredOrInheritedField(fieldName) #967

Merged
merged 1 commit into from
Nov 14, 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
14 changes: 14 additions & 0 deletions src/main/java/spoon/reflect/declaration/CtTypeInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ public interface CtTypeInformation {
*/
Collection<CtFieldReference<?>> getAllFields();

/**
* Gets a field from its name.
*
* @return null if does not exit
*/
CtFieldReference<?> getDeclaredField(String name);

/**
* Gets a field from this type or any super type or any implemented interface by field name.
*
* @return null if does not exit
*/
CtFieldReference<?> getDeclaredOrInheritedField(String fieldName);

/**
* Gets the executables declared by this type if applicable.
*/
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,36 @@ public CtField<?> getField(String name) {
return null;
}

@Override
public CtFieldReference<?> getDeclaredField(String name) {
CtField<?> field = getField(name);
return field != null ? getFactory().Field().createReference(field) : null;
}

@Override
public CtFieldReference<?> getDeclaredOrInheritedField(String fieldName) {
CtFieldReference<?> field = getDeclaredField(fieldName);
if (field != null) {
return field;
}
CtTypeReference<?> typeRef = getSuperclass();
if (typeRef != null) {
field = typeRef.getDeclaredOrInheritedField(fieldName);
if (field != null) {
return field;
}
}
Set<CtTypeReference<?>> ifaces = getSuperInterfaces();
for (CtTypeReference<?> iface : ifaces) {
field = iface.getDeclaredOrInheritedField(fieldName);
if (field != null) {
return field;
}
}
return field;
}


@Override
public List<CtField<?>> getFields() {
List<CtField<?>> fields = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,18 +370,26 @@ public Collection<CtFieldReference<?>> getDeclaredFields() {
* @return collection of field references
*/
private Collection<CtFieldReference<?>> getDeclaredFieldReferences() {
Collection<CtFieldReference<?>> references = new ArrayList<>();
for (Field f : getActualClass().getDeclaredFields()) {
references.add(getFactory().Field().createReference(f));
}
if (getActualClass().isAnnotation()) {
for (Method m : getActualClass().getDeclaredMethods()) {
CtTypeReference<?> retRef = getFactory().Type().createReference(m.getReturnType());
CtFieldReference<?> fr = getFactory().Field().createReference(this, retRef, m.getName());
references.add(fr);
Collection<CtFieldReference<?>> references = new ArrayList<>();
for (Field f : getDeclaredFields(getActualClass())) {
references.add(getFactory().Field().createReference(f));
}
if (getActualClass().isAnnotation()) {
for (Method m : getActualClass().getDeclaredMethods()) {
CtTypeReference<?> retRef = getFactory().Type().createReference(m.getReturnType());
CtFieldReference<?> fr = getFactory().Field().createReference(this, retRef, m.getName());
references.add(fr);
}
}
return references;
}

private Field[] getDeclaredFields(Class<?> cls) {
try {
return cls.getDeclaredFields();
} catch (Throwable e) {
throw new SpoonClassNotFoundException("cannot load fields of class: " + getQualifiedName(), e);
}
return references;
}

private Collection<CtFieldReference<?>> handleParentNotFound(SpoonClassNotFoundException cnfe) {
Expand All @@ -396,6 +404,58 @@ private Collection<CtFieldReference<?>> handleParentNotFound(SpoonClassNotFoundE
}
}

@Override
public CtFieldReference<?> getDeclaredField(String name) {
if (name == null) {
return null;
}
CtType<?> t = getDeclaration();
if (t == null) {
try {
Collection<CtFieldReference<?>> fields = getDeclaredFieldReferences();
for (CtFieldReference<?> field : fields) {
if (name.equals(field.getSimpleName())) {
return field;
}
}
} catch (SpoonClassNotFoundException cnfe) {
handleParentNotFound(cnfe);
return null;
}
return null;
} else {
return t.getDeclaredField(name);
}
}

public CtFieldReference<?> getDeclaredOrInheritedField(String fieldName) {
CtType<?> t = getDeclaration();
if (t == null) {
CtFieldReference<?> field = getDeclaredField(fieldName);
if (field != null) {
return field;
}
CtTypeReference<?> typeRef = getSuperclass();
if (typeRef != null) {
field = typeRef.getDeclaredOrInheritedField(fieldName);
if (field != null) {
return field;
}
}
Set<CtTypeReference<?>> ifaces = getSuperInterfaces();
for (CtTypeReference<?> iface : ifaces) {
field = iface.getDeclaredOrInheritedField(fieldName);
if (field != null) {
return field;
}
}
return field;
} else {
return t.getDeclaredOrInheritedField(fieldName);
}
}


@Override
public Collection<CtExecutableReference<?>> getDeclaredExecutables() {
CtType<T> t = getDeclaration();
Expand Down
12 changes: 12 additions & 0 deletions src/test/java/spoon/test/model/ClassWithSuperAndIFace.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package spoon.test.model;

public class ClassWithSuperAndIFace extends Foo implements InterfaceWrithFields
{
String classField;

public ClassWithSuperAndIFace()
{
// TODO Auto-generated constructor stub
}

}
20 changes: 20 additions & 0 deletions src/test/java/spoon/test/model/ClassWithSuperOutOfModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package spoon.test.model;

import java.io.ByteArrayInputStream;

public class ClassWithSuperOutOfModel extends ByteArrayInputStream
{

public ClassWithSuperOutOfModel(byte[] p_buf)
{
super(p_buf);
// TODO Auto-generated constructor stub
}

public ClassWithSuperOutOfModel(byte[] p_buf, int p_offset, int p_length)
{
super(p_buf, p_offset, p_length);
// TODO Auto-generated constructor stub
}

}
7 changes: 7 additions & 0 deletions src/test/java/spoon/test/model/InterfaceWrithFields.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package spoon.test.model;

public interface InterfaceWrithFields
{
String IFACE_FIELD_1 = "f1";
long IFACE_FIELD_2 = 49;
}
36 changes: 36 additions & 0 deletions src/test/java/spoon/test/model/TypeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.TypeFactory;
import spoon.reflect.reference.CtExecutableReference;
import spoon.reflect.reference.CtFieldReference;
import spoon.reflect.reference.CtTypeReference;

import java.util.Collection;
Expand Down Expand Up @@ -62,4 +63,39 @@ public void testGetUsedTypesForTypeInRootPackage() throws Exception {
CtClass<?> cl = createFactory().Code().createCodeSnippetStatement("class X { X x; }").compile();
assertEquals(0, cl.getUsedTypes(false).size());
}

@Test
public void testGetDeclaredOrIheritedFieldOnType() throws Exception {
CtType<?> type = build("spoon.test.model", "ClassWithSuperAndIFace");

assertEquals("classField", type.getDeclaredOrInheritedField("classField").getSimpleName());
assertEquals("i", type.getDeclaredOrInheritedField("i").getSimpleName());
assertNull(type.getDeclaredOrInheritedField("fooMethod"));
assertEquals("j", type.getDeclaredOrInheritedField("j").getSimpleName());
assertEquals("IFACE_FIELD_1", type.getDeclaredOrInheritedField("IFACE_FIELD_1").getSimpleName());
assertEquals("IFACE_FIELD_2", type.getDeclaredOrInheritedField("IFACE_FIELD_2").getSimpleName());
assertNull(type.getDeclaredOrInheritedField("notExists"));
}

@Test
public void testGetDeclaredOrIheritedFieldOnTypeRef() throws Exception {
CtTypeReference<?> type = build("spoon.test.model", "ClassWithSuperAndIFace").getReference();

assertEquals("classField", type.getDeclaredOrInheritedField("classField").getSimpleName());
assertEquals("i", type.getDeclaredOrInheritedField("i").getSimpleName());
assertNull(type.getDeclaredOrInheritedField("fooMethod"));
assertEquals("j", type.getDeclaredOrInheritedField("j").getSimpleName());
assertEquals("IFACE_FIELD_1", type.getDeclaredOrInheritedField("IFACE_FIELD_1").getSimpleName());
assertEquals("IFACE_FIELD_2", type.getDeclaredOrInheritedField("IFACE_FIELD_2").getSimpleName());
assertNull(type.getDeclaredOrInheritedField("notExists"));
}
@Test

public void testGetDeclaredOrIheritedFieldByReflection() throws Exception {
CtTypeReference<?> type = build("spoon.test.model", "ClassWithSuperOutOfModel").getReference();

assertEquals("buf", type.getDeclaredOrInheritedField("buf").getSimpleName());
assertEquals("count", type.getDeclaredOrInheritedField("count").getSimpleName());

}
}