diff --git a/src/main/java/spoon/reflect/visitor/filter/FieldReferenceFunction.java b/src/main/java/spoon/reflect/visitor/filter/FieldReferenceFunction.java new file mode 100644 index 00000000000..91df5eab627 --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/filter/FieldReferenceFunction.java @@ -0,0 +1,49 @@ +/** + * 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 spoon.reflect.declaration.CtField; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.visitor.chain.CtConsumableFunction; +import spoon.reflect.visitor.chain.CtConsumer; + +/** + * This Query expects a {@link CtField} as input + * and returns all {@link CtFieldReference}s, which refers this input. + *
+ * Usage:
+ *
 {@code
+ * CtField param = ...;
+ * param
+ *   .map(new FieldReferenceFunction())
+ *   .forEach((CtFieldReference ref)->...process references...);
+ * }
+ * 
+ */ +public class FieldReferenceFunction implements CtConsumableFunction> { + + public FieldReferenceFunction() { + } + + @Override + public void apply(CtField field, CtConsumer outputConsumer) { + field + .map(new FieldScopeFunction()) + .filter(new DirectReferenceFilter>(field.getReference())) + .forEach(outputConsumer); + } +} diff --git a/src/main/java/spoon/reflect/visitor/filter/FieldScopeFunction.java b/src/main/java/spoon/reflect/visitor/filter/FieldScopeFunction.java new file mode 100644 index 00000000000..46f7a41382b --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/filter/FieldScopeFunction.java @@ -0,0 +1,87 @@ +/** + * 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 spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.visitor.chain.CtConsumableFunction; +import spoon.reflect.visitor.chain.CtConsumer; + +/** + * This Query expects a {@link CtField} as input + * and returns all CtElements, + * which are in visibility scope of that field. + * In other words, it returns all elements, + * which might be reference to that field. + *
+ * It can be used to search for variable declarations or + * variable references which might be in name conflict with input field. + *
+ * Usage:
+ *
 {@code
+ * CtField param = ...;
+ * param.map(new FieldScopeFunction()).forEach(...process result...);
+ * }
+ * 
+ */ +public class FieldScopeFunction implements CtConsumableFunction> { + + public FieldScopeFunction() { + } + + @Override + public void apply(CtField field, CtConsumer outputConsumer) { + if (field.hasModifier(ModifierKind.PRIVATE)) { + searchForPrivateField(field, outputConsumer); + } else if (field.hasModifier(ModifierKind.PUBLIC)) { + searchForPublicField(field, outputConsumer); + } else if (field.hasModifier(ModifierKind.PROTECTED)) { + searchForProtectedField(field, outputConsumer); + } else { + searchForPackageProtectedField(field, outputConsumer); + } + } + protected void searchForPrivateField(CtField field, CtConsumer outputConsumer) { + //private field can be referred from the scope of current top level type only + field.getTopLevelType() + .filterChildren(null) + .forEach(outputConsumer); + } + protected void searchForProtectedField(CtField field, CtConsumer outputConsumer) { + //protected field can be referred from the scope of current top level type only + field.getFactory().getModel().getRootPackage() + //search for all types which inherits from declaring type of this field + .filterChildren(new SubtypeFilter(field.getDeclaringType().getReference())) + //visit all elements in scope of these inherited types + .filterChildren(null) + .forEach(outputConsumer); + } + protected void searchForPublicField(CtField field, CtConsumer outputConsumer) { + //public field is visible everywhere + field.getFactory().getModel().getRootPackage() + //visit all children of root package + .filterChildren(null) + .forEach(outputConsumer); + } + protected void searchForPackageProtectedField(CtField field, CtConsumer outputConsumer) { + //package protected fields are visible in scope of the package of the top level type of the `field` + field.getTopLevelType().getPackage() + //visit all children of package, where top level type of the field is declared + .filterChildren(null) + .forEach(outputConsumer); + } +} diff --git a/src/main/java/spoon/reflect/visitor/filter/SubtypeFilter.java b/src/main/java/spoon/reflect/visitor/filter/SubtypeFilter.java new file mode 100644 index 00000000000..ecf8091bb48 --- /dev/null +++ b/src/main/java/spoon/reflect/visitor/filter/SubtypeFilter.java @@ -0,0 +1,57 @@ +/** + * 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 spoon.reflect.declaration.CtType; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.Filter; + +/** + * Matches all CtType elements, which are sub type of {@link #superType} + * Matches the input `superType` too. + * Call {@link #includingSelf(boolean)} with value false, if instance of {@link #superType} should no match this {@link Filter} + */ +public class SubtypeFilter extends AbstractFilter> { + + private CtTypeReference superType; + private String superTypeQualifiedName; + + public SubtypeFilter(CtTypeReference superType) { + this.superType = superType; + } + + /** + * @param includingSelf if false then element which is equal to to #superType is not matching + */ + public SubtypeFilter includingSelf(boolean includingSelf) { + if (includingSelf) { + superTypeQualifiedName = null; + } else { + superTypeQualifiedName = superType.getQualifiedName(); + } + return this; + } + + @Override + public boolean matches(CtType mayBeSubType) { + if (superTypeQualifiedName != null && superTypeQualifiedName.equals(mayBeSubType.getQualifiedName())) { + //we should not accept superType + return false; + } + return mayBeSubType.isSubtypeOf(superType); + } +}