From 5def51be0294554ca5a8945b08c2d786c25ec2e1 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 | 82 +++++++++++++++++++ .../reflect/declaration/CtTypeImpl.java | 18 ++-- 2 files changed, 90 insertions(+), 10 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..38b64653c7d --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/filter/AllTypeMembersFunction.java @@ -0,0 +1,82 @@ +/** + * 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 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; + + /** + * 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; + } + + @Override + public void apply(CtType input, CtConsumer outputConsumer) { + final CtQuery q = input.map(new SuperHierarchyFunction(new HashSet()).includingSelf(true)); + q.forEach(new CtConsumer>() { + @Override + public void accept(CtType type) { + for (CtTypeMember typeMember : type.getTypeMembers()) { + sendToOutput(typeMember, outputConsumer); + if (query.isTerminated()) { + q.setTerminated(true); + } + } + } + }); + } + + protected void sendToOutput(CtTypeMember typeMember, CtConsumer outputConsumer) { + if (memberClass == null || memberClass.isInstance(typeMember)) { + outputConsumer.accept(typeMember); + } + } + + @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..2c02f0e2ddb 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtTypeImpl.java @@ -43,6 +43,8 @@ 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.ReferenceTypeFilter; import spoon.support.UnsettableProperty; import spoon.support.SpoonClassNotFoundException; @@ -510,17 +512,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; }