From 638658d4bdf460febd0d583797ba71affec04770 Mon Sep 17 00:00:00 2001 From: Pavel Vojtechovsky Date: Wed, 22 Feb 2017 21:37:18 +0100 Subject: [PATCH] feature: AllTypeMembersFunction --- .../filter/AllTypeMembersFunction.java | 85 ++++++++++++++++++ .../reflect/declaration/CtTypeImpl.java | 89 +++++-------------- 2 files changed, 106 insertions(+), 68 deletions(-) create mode 100644 src/main/java/spoon/reflect/visitor/filter/AllTypeMembersFunction.java diff --git a/src/main/java/spoon/reflect/visitor/filter/AllTypeMembersFunction.java b/src/main/java/spoon/reflect/visitor/filter/AllTypeMembersFunction.java new file mode 100644 index 00000000000..6ad1cc7469d --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/filter/AllTypeMembersFunction.java @@ -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>, CtQueryAware { + + private CtQuery query; + private final Class memberClass; + private Set distintSet; + + /** + * returns all type members + */ + public AllTypeMembersFunction() { + this.memberClass = null; + } + + /** + * returns all type members which are instance of `memberClass`.
+ * Example:
+ * + * CtField allFields = ctType.map(new AllTypeMembersFunction(CtField.class)).list(); + * + */ + public AllTypeMembersFunction(Class memberClass) { + this.memberClass = memberClass; + } + + public AllTypeMembersFunction distinctSet(Set distintSet) { + this.distintSet = distintSet; + return this; + } + + @Override + public void apply(CtType input, final CtConsumer outputConsumer) { + final CtQuery q = input.map(new SuperHierarchyFunction(distintSet == null ? new HashSet() : distintSet).includingSelf(true)); + q.forEach(new CtConsumer>() { + @Override + public void accept(CtType type) { + for (CtTypeMember typeMember : type.getTypeMembers()) { + if (memberClass == null || memberClass.isInstance(typeMember)) { + outputConsumer.accept(typeMember); + } + if (query.isTerminated()) { + q.terminate(); + } + } + } + }); + } + + @Override + public void setQuery(CtQuery query) { + this.query = query; + } +} diff --git a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java index 8debde709fd..14588555ae3 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java @@ -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; @@ -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; @@ -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; @@ -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> 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(); } @@ -510,17 +495,13 @@ public boolean isGenerics() { @Override public List> getAllFields() { - final List> fields = getDeclaredFields(); - if (this instanceof CtClass) { - CtTypeReference st = ((CtClass) this).getSuperclass(); - if (st != null) { - fields.addAll(st.getAllFields()); - } - Set> superIFaces = ((CtClass) this).getSuperInterfaces(); - for (CtTypeReference superIFace : superIFaces) { - fields.addAll(superIFace.getAllFields()); + final List> fields = new ArrayList<>(); + map(new AllTypeMembersFunction(CtField.class)).forEach(new CtConsumer>() { + @Override + public void accept(CtField field) { + fields.add(field.getReference()); } - } + }); return fields; } @@ -884,46 +865,18 @@ public Collection> getAllExecutables() { return l; } - /** - * puts all methods of from in destination based on signatures only - */ - private void addAllBasedOnSignature(Set> from, Set> destination) { - List 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> getAllMethods() { - Set> 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 distinctSignatures = new HashSet<>(); + final Set> l = new SignatureBasedSortedSet<>(); + map(new AllTypeMembersFunction(CtMethod.class)).forEach(new CtConsumer>() { + @Override + public void accept(CtMethod method) { + if (distinctSignatures.add(method.getSignature())) { + l.add(method); + } } - } - + }); return Collections.unmodifiableSet(l); }