From 6d6e2a2ee3bd874367535b8308e93faa172cbc6a Mon Sep 17 00:00:00 2001 From: Pavel Vojtechovsky Date: Sun, 8 Jan 2017 13:34:47 +0100 Subject: [PATCH] add query factory and use it --- .../java/spoon/reflect/factory/Factory.java | 3 ++ .../spoon/reflect/factory/FactoryImpl.java | 13 +++++ .../spoon/reflect/factory/QueryFactory.java | 51 +++++++++++++++++++ .../reflect/declaration/CtElementImpl.java | 7 ++- .../java/spoon/test/filters/FilterTest.java | 17 +++++-- 5 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 src/main/java/spoon/reflect/factory/QueryFactory.java diff --git a/src/main/java/spoon/reflect/factory/Factory.java b/src/main/java/spoon/reflect/factory/Factory.java index 06305f93ecd..cff191c1612 100644 --- a/src/main/java/spoon/reflect/factory/Factory.java +++ b/src/main/java/spoon/reflect/factory/Factory.java @@ -150,6 +150,9 @@ public interface Factory { ConstructorFactory Constructor(); // used 3 times + QueryFactory Query(); + + /** * @see CodeFactory#createAnnotation(CtTypeReference) */ diff --git a/src/main/java/spoon/reflect/factory/FactoryImpl.java b/src/main/java/spoon/reflect/factory/FactoryImpl.java index 6952ef4f7ab..4e961e55f7a 100644 --- a/src/main/java/spoon/reflect/factory/FactoryImpl.java +++ b/src/main/java/spoon/reflect/factory/FactoryImpl.java @@ -335,6 +335,19 @@ public TypeFactory Type() { return type; } + private transient QueryFactory query; + + /** + * The query sub-factory. + */ + @Override + public QueryFactory Query() { + if (query == null) { + query = new QueryFactory(this); + } + return query; + } + /** * A constructor that takes the parent factory */ diff --git a/src/main/java/spoon/reflect/factory/QueryFactory.java b/src/main/java/spoon/reflect/factory/QueryFactory.java new file mode 100644 index 00000000000..e84b533d67f --- /dev/null +++ b/src/main/java/spoon/reflect/factory/QueryFactory.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2006-2016 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.factory; + +import spoon.reflect.visitor.chain.CtQuery; +import spoon.reflect.visitor.chain.CtQueryImpl; + +/** + * A factory to create some queries on the Spoon metamodel. + */ +public class QueryFactory extends SubFactory { + + /** + * Creates the evaluation factory. + */ + public QueryFactory(Factory factory) { + super(factory); + } + + /** + * Creates a unbound query. Use {@link CtQuery#setInput(Object...)} + * before {@link CtQuery#forEach(spoon.reflect.visitor.chain.CtConsumer)} + * or {@link CtQuery#list()} is called + */ + public CtQuery createQuery() { + return new CtQueryImpl(); + } + + /** + * Creates a bound query. Use directly + * {@link CtQuery#forEach(spoon.reflect.visitor.chain.CtConsumer)} + * or {@link CtQuery#list()} to evaluate the query + */ + public CtQuery createQuery(Object input) { + return new CtQueryImpl(input); + } +} diff --git a/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java b/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java index 9509e097136..b67f9b72b91 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtElementImpl.java @@ -31,7 +31,6 @@ import spoon.reflect.visitor.Filter; import spoon.reflect.visitor.ModelConsistencyChecker; import spoon.reflect.visitor.Query; -import spoon.reflect.visitor.chain.CtQueryImpl; import spoon.reflect.visitor.chain.CtFunction; import spoon.reflect.visitor.chain.CtConsumableFunction; import spoon.reflect.visitor.chain.CtQuery; @@ -261,17 +260,17 @@ public List getElements(Filter filter) { @Override public CtQuery map(CtConsumableFunction queryStep) { - return new CtQueryImpl(this).map(queryStep); + return factory.Query().createQuery(this).map(queryStep); } @Override public CtQuery map(CtFunction function) { - return new CtQueryImpl(this).map(function); + return factory.Query().createQuery(this).map(function); } @Override public

CtQuery filterChildren(Filter

predicate) { - return new CtQueryImpl(this).filterChildren(predicate); + return factory.Query().createQuery(this).filterChildren(predicate); } public List getReferences(Filter filter) { diff --git a/src/test/java/spoon/test/filters/FilterTest.java b/src/test/java/spoon/test/filters/FilterTest.java index 0f5fef1b844..f7f7c16a646 100644 --- a/src/test/java/spoon/test/filters/FilterTest.java +++ b/src/test/java/spoon/test/filters/FilterTest.java @@ -629,7 +629,7 @@ public void testElementMapConsumableFunction() throws Exception { @Test public void testElementMapFunctionArray() throws Exception { final Launcher launcher = new Launcher(); - CtQueryImpl q = new CtQueryImpl().map((String s)->new String[]{"a", null, s}); + CtQuery q = launcher.getFactory().Query().createQuery().map((String s)->new String[]{"a", null, s}); List list = q.setInput(null).list(); assertEquals(0, list.size()); @@ -641,7 +641,7 @@ public void testElementMapFunctionArray() throws Exception { @Test public void testElementMapFunctionNull() throws Exception { final Launcher launcher = new Launcher(); - CtQueryImpl q = new CtQueryImpl().map((String s)->null); + CtQuery q = launcher.getFactory().Query().createQuery().map((String s)->null); List list = q.setInput(null).list(); assertEquals(0, list.size()); @@ -701,7 +701,7 @@ class Context { CtClass cls = launcher.getFactory().Class().get(Tacos.class); CtClass cls2 = launcher.getFactory().Class().get(Tostada.class); - CtQueryImpl q = new CtQueryImpl().map((CtClass c, CtConsumer out)->out.accept(c.getSimpleName())); + CtQueryImpl q = (CtQueryImpl)launcher.getFactory().Query().createQuery().map((CtClass c, CtConsumer out)->out.accept(c.getSimpleName())); q.evaluate(cls, (String name)->{ context.count++; assertEquals(cls.getSimpleName(), name); @@ -730,8 +730,15 @@ class Context { Context context = new Context(); CtClass cls = launcher.getFactory().Class().get(Tacos.class); - CtQueryImpl allChildPublicClasses = new CtQueryImpl().filterChildren((CtClass clazz)->clazz.hasModifier(ModifierKind.PUBLIC)); - launcher.getFactory().Package().getRootPackage().map((in,out)->allChildPublicClasses.evaluate(in,out)).forEach((CtElement clazz)->{ + CtQuery allChildPublicClasses = (CtQueryImpl)launcher.getFactory().Query().createQuery().filterChildren((CtClass clazz)->clazz.hasModifier(ModifierKind.PUBLIC)); + launcher.getFactory().Package().getRootPackage().map((in,out)->allChildPublicClasses.setInput(in).forEach(out)).forEach((CtElement clazz)->{ + context.count++; + assertTrue(clazz instanceof CtClass); + assertTrue(((CtClass)clazz).hasModifier(ModifierKind.PUBLIC)); + }); + assertTrue(context.count>0); + context.count=0; + launcher.getFactory().Package().getRootPackage().map((in,out)->((CtQueryImpl)allChildPublicClasses).evaluate(in,out)).forEach((CtElement clazz)->{ context.count++; assertTrue(clazz instanceof CtClass); assertTrue(((CtClass)clazz).hasModifier(ModifierKind.PUBLIC));