Skip to content

Commit

Permalink
feature: AllTypeMembersFunction
Browse files Browse the repository at this point in the history
  • Loading branch information
pvojtechovsky committed Feb 23, 2017
1 parent 885dea1 commit b0d12b5
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Copyright (C) 2006-2017 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.reflect.visitor.filter;

import java.util.HashSet;
import java.util.Set;

import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypeMember;
import spoon.reflect.visitor.chain.CtConsumableFunction;
import spoon.reflect.visitor.chain.CtConsumer;
import spoon.reflect.visitor.chain.CtQuery;
import spoon.reflect.visitor.chain.CtQueryAware;

/**
* Expects {@link CtType} as input
* and produces all {@link CtTypeMember}s declared in input class
* or any super class or super interface
*/
public class AllTypeMembersFunction implements CtConsumableFunction<CtType<?>>, CtQueryAware {

private CtQuery query;
private final Class<?> memberClass;
private Set<String> distintSet;

/**
* returns all type members
*/
public AllTypeMembersFunction() {
this.memberClass = null;
}

/**
* returns all type members which are instance of `memberClass`.<br>
* Example:<br>
* <code>
* CtField allFields = ctType.map(new AllTypeMembersFunction(CtField.class)).list();
* </code>
*/
public AllTypeMembersFunction(Class<?> memberClass) {
this.memberClass = memberClass;
}

public AllTypeMembersFunction distinctSet(Set<String> distintSet) {
this.distintSet = distintSet;
return this;
}

@Override
public void apply(CtType<?> input, final CtConsumer<Object> outputConsumer) {
final CtQuery q = input.map(new SuperHierarchyFunction(distintSet == null ? new HashSet<String>() : distintSet).includingSelf(true));
q.forEach(new CtConsumer<CtType<?>>() {
@Override
public void accept(CtType<?> type) {
for (CtTypeMember typeMember : type.getTypeMembers()) {
if (memberClass == null || memberClass.isInstance(typeMember)) {
outputConsumer.accept(typeMember);
}
if (query.isTerminated()) {
q.setTerminated(true);
}
}
}
});
}

@Override
public void setQuery(CtQuery query) {
this.query = query;
}
}
89 changes: 21 additions & 68 deletions src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import spoon.reflect.code.CtBlock;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtAnnotationType;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtField;
Expand All @@ -43,9 +42,11 @@
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.EarlyTerminatingScanner;
import spoon.reflect.visitor.Query;
import spoon.reflect.visitor.chain.CtConsumer;
import spoon.reflect.visitor.filter.AllTypeMembersFunction;
import spoon.reflect.visitor.filter.NameFilter;
import spoon.reflect.visitor.filter.ReferenceTypeFilter;
import spoon.support.UnsettableProperty;
import spoon.support.SpoonClassNotFoundException;
import spoon.support.compiler.SnippetCompilationHelper;
import spoon.support.util.QualifiedNameBasedSortedSet;
import spoon.support.util.SignatureBasedSortedSet;
Expand All @@ -56,6 +57,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -185,25 +187,8 @@ public CtFieldReference<?> getDeclaredField(String name) {

@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;
CtField<?> field = map(new AllTypeMembersFunction(CtField.class)).select(new NameFilter<>(fieldName)).first();
return field == null ? null : field.getReference();
}


Expand Down Expand Up @@ -510,17 +495,13 @@ public boolean isGenerics() {

@Override
public List<CtFieldReference<?>> getAllFields() {
final List<CtFieldReference<?>> fields = getDeclaredFields();
if (this instanceof CtClass) {
CtTypeReference<?> st = ((CtClass<?>) this).getSuperclass();
if (st != null) {
fields.addAll(st.getAllFields());
}
Set<CtTypeReference<?>> superIFaces = ((CtClass<?>) this).getSuperInterfaces();
for (CtTypeReference<?> superIFace : superIFaces) {
fields.addAll(superIFace.getAllFields());
final List<CtFieldReference<?>> fields = new ArrayList<>();
map(new AllTypeMembersFunction(CtField.class)).forEach(new CtConsumer<CtField<?>>() {
@Override
public void accept(CtField<?> field) {
fields.add(field.getReference());
}
}
});
return fields;
}

Expand Down Expand Up @@ -884,46 +865,18 @@ public Collection<CtExecutableReference<?>> getAllExecutables() {
return l;
}

/**
* puts all methods of from in destination based on signatures only
*/
private void addAllBasedOnSignature(Set<CtMethod<?>> from, Set<CtMethod<?>> destination) {
List<String> signatures = new ArrayList<>();
for (CtMethod<?> m : destination) {
signatures.add(m.getSignature());
}

for (CtMethod<?> m : from) {
if (!signatures.contains(m.getSignature())) {
destination.add(m);
}
}
}

@Override
public Set<CtMethod<?>> getAllMethods() {
Set<CtMethod<?>> l = new SignatureBasedSortedSet<>(getMethods());
if ((getSuperclass() != null)) {
try {
CtType<?> t = getSuperclass().getTypeDeclaration();
addAllBasedOnSignature(t.getAllMethods(), l);
} catch (SpoonClassNotFoundException ignored) {
// should not be thrown in 'noClasspath' environment (#775)
}
} else if (this instanceof CtClass) {
// only CtCLasses extend object
addAllBasedOnSignature(getFactory().Type().get(Object.class).getMethods(), l);
}

for (CtTypeReference<?> ref : getSuperInterfaces()) {
try {
CtType<?> t = ref.getTypeDeclaration();
addAllBasedOnSignature(t.getAllMethods(), l);
} catch (SpoonClassNotFoundException ignored) {
// should not be thrown in 'noClasspath' environment (#775)
final Set<String> distinctSignatures = new HashSet<>();
final Set<CtMethod<?>> l = new SignatureBasedSortedSet<>();
map(new AllTypeMembersFunction(CtMethod.class)).forEach(new CtConsumer<CtMethod<?>>() {
@Override
public void accept(CtMethod<?> method) {
if (distinctSignatures.add(method.getSignature())) {
l.add(method);
}
}
}

});
return Collections.unmodifiableSet(l);
}

Expand Down

0 comments on commit b0d12b5

Please sign in to comment.