Skip to content

Commit

Permalink
feature LambdaFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
pvojtechovsky committed May 20, 2017
1 parent cdd2acb commit aef373e
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 2 deletions.
79 changes: 79 additions & 0 deletions src/main/java/spoon/reflect/visitor/filter/LambdaFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* 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.code.CtLambda;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypeInformation;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.Filter;

/**
* This filter matches all the {@link CtLambda} elements, which implements defined interface(s)
*/
public class LambdaFilter implements Filter<CtLambda<?>> {

private Set<String> qualifiedNamesOfInterfaces = new HashSet<>();

/**
* Use {@link #addImplementingInterface(CtTypeInformation)} to define set of interfaces whose lambdas it is search for
*/
public LambdaFilter() {
}

/**
* Matches all lambdas implementing `iface`
* Use {@link #addImplementingInterface(CtTypeInformation)} to define set of interfaces whose lambdas it is search for
*/
public LambdaFilter(CtInterface<?> iface) {
addImplementingInterface(iface);
}

/**
* Matches all lambdas implementing `iface`
* Use {@link #addImplementingInterface(CtTypeInformation)} to define set of interfaces whose lambdas it is search for
*/
public LambdaFilter(CtTypeReference<?> iface) {
addImplementingInterface(iface);
}

/**
* Allows to search for lambdas implemented by different interfaces.
* @param typeInfo interface whose lambda implementations it is searching for
*/
public LambdaFilter addImplementingInterface(CtTypeInformation typeInfo) {
if (typeInfo instanceof CtType) {
if (typeInfo instanceof CtInterface) {
qualifiedNamesOfInterfaces.add(typeInfo.getQualifiedName());
} //else ignore that request, because lambda can implement only interfaces
} else {
//do not check if it is interface or not. That check needs CtType in model and it might be not available in some modes
//it is OK to search for non interface types. It simply founds no lambda implementing that
qualifiedNamesOfInterfaces.add(typeInfo.getQualifiedName());
}
return this;
}

@Override
public boolean matches(CtLambda<?> lambda) {
return qualifiedNamesOfInterfaces.contains(lambda.getType().getQualifiedName());
}
}
25 changes: 23 additions & 2 deletions src/test/java/spoon/test/lambda/LambdaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtLambda;
import spoon.reflect.code.CtTypeAccess;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtType;
Expand All @@ -18,6 +19,7 @@
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.Filter;
import spoon.reflect.visitor.filter.AbstractFilter;
import spoon.reflect.visitor.filter.LambdaFilter;
import spoon.reflect.visitor.filter.NameFilter;
import spoon.reflect.visitor.filter.TypeFilter;
import spoon.test.lambda.testclasses.Bar;
Expand All @@ -30,9 +32,7 @@

import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -384,6 +384,27 @@ public void testGetOverriddenMethodWithFunction() throws Exception {
assertEquals(LambdaRxJava.NbpOperator.class.getName(), iface.getQualifiedName());
}

@Test
public void testLambdaFilter() throws Exception {
List<String> methodNames = foo.filterChildren(new LambdaFilter((CtInterface<?>) foo.getNestedType("CheckPerson"))).map((CtLambda l)->l.getParent(CtMethod.class).getSimpleName()).list();
assertHasStrings(methodNames);
methodNames = foo.filterChildren(new LambdaFilter((CtInterface<?>) foo.getNestedType("Check"))).map((CtLambda l)->l.getParent(CtMethod.class).getSimpleName()).list();
assertHasStrings(methodNames, "m", "m6");
methodNames = foo.filterChildren(new LambdaFilter((CtInterface<?>) foo.getNestedType("CheckPersons"))).map((CtLambda l)->l.getParent(CtMethod.class).getSimpleName()).list();
assertHasStrings(methodNames, "m3", "m5");
methodNames = foo.filterChildren(new LambdaFilter(factory.Interface().get(Predicate.class))).map((CtLambda l)->l.getParent(CtMethod.class).getSimpleName()).list();
assertHasStrings(methodNames, "m2", "m4", "m7", "m8");
}

private void assertHasStrings(List<String> methodNames, String... strs) {
for (String str : strs) {
assertTrue("List should contain "+str+" but it is missing.", methodNames.remove(str));
}
if(methodNames.size()>0) {
fail("List should't contain "+methodNames);
}
}

private void assertTypedBy(Class<?> expectedType, CtTypeReference<?> type) {
assertEquals("Lambda must be typed", expectedType, type.getActualClass());
}
Expand Down

0 comments on commit aef373e

Please sign in to comment.