Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Stream counterparts to ReflectionSupport utility methods returning List #3084

Merged
merged 13 commits into from
Dec 16, 2022
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ repository on GitHub.

==== New Features and Improvements

* ❓

* allow methods returning a list to return a stream in the ReflectionSupport class
Ndione24 marked this conversation as resolved.
Show resolved Hide resolved

[[release-notes-5.10.0-M1-junit-jupiter]]
=== JUnit Jupiter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations;
import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated;
import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN;
import static org.junit.platform.commons.util.ReflectionUtils.findFields;
import static org.junit.platform.commons.util.ReflectionUtils.findFieldsAsStream;
import static org.junit.platform.commons.util.ReflectionUtils.getDeclaredConstructor;
import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue;

Expand Down Expand Up @@ -93,7 +93,7 @@ static void registerExtensionsFromFields(ExtensionRegistrar registrar, Class<?>

Predicate<Field> predicate = (instance == null ? ReflectionUtils::isStatic : ReflectionUtils::isNotStatic);

findFields(clazz, predicate, TOP_DOWN).stream()//
findFieldsAsStream(clazz, predicate, TOP_DOWN)//
.sorted(orderComparator)//
.forEach(field -> {
List<Class<? extends Extension>> extensionTypes = streamExtensionTypes(field).collect(toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static java.util.function.Predicate.isEqual;
import static java.util.stream.Collectors.toCollection;
import static org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.isTestOrTestFactoryOrTestTemplateMethod;
import static org.junit.platform.commons.support.ReflectionSupport.findNestedClasses;
import static org.junit.platform.commons.support.ReflectionSupport.findNestedClassesAsStream;
import static org.junit.platform.commons.util.FunctionUtils.where;
import static org.junit.platform.commons.util.ReflectionUtils.findMethods;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId;
Expand Down Expand Up @@ -135,7 +135,7 @@ private Resolution toResolution(Optional<? extends ClassBasedTestDescriptor> tes
return Resolution.match(Match.exact(it, () -> {
Stream<DiscoverySelector> methods = findMethods(testClass, isTestOrTestFactoryOrTestTemplateMethod).stream()
.map(method -> selectMethod(testClasses, method));
Stream<NestedClassSelector> nestedClasses = findNestedClasses(testClass, isNestedTestClass).stream()
Stream<NestedClassSelector> nestedClasses = findNestedClassesAsStream(testClass, isNestedTestClass)
.map(nestedClass -> DiscoverySelectors.selectNestedClass(testClasses, nestedClass));
return Stream.concat(methods, nestedClasses).collect(toCollection((Supplier<Set<DiscoverySelector>>) LinkedHashSet::new));
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.apiguardian.api.API;
import org.junit.platform.commons.JUnitException;
Expand Down Expand Up @@ -114,6 +115,29 @@ public static List<Class<?>> findAllClassesInClasspathRoot(URI root, Predicate<C
return ReflectionUtils.findAllClassesInClasspathRoot(root, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
* that match the specified {@code classFilter} and {@code classNameFilter}
* predicates.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning with the root of the classpath.
*
* @param root the URI for the classpath root in which to scan; never
* {@code null}
* @param classFilter the class type filter; never {@code null}
* @param classNameFilter the class name filter; never {@code null}
* @return a stream of all such classes found; never {@code null}
* but potentially empty
Ndione24 marked this conversation as resolved.
Show resolved Hide resolved
* @see #findAllClassesInPackage(String, Predicate, Predicate)
* @see #findAllClassesInModule(String, Predicate, Predicate)
*/
public static Stream<Class<?>> findAllClassesInClasspathRootAsStream(URI root, Predicate<Class<?>> classFilter,
Ndione24 marked this conversation as resolved.
Show resolved Hide resolved
Predicate<String> classNameFilter) {

return ReflectionUtils.findAllClassesInClasspathRootAsStream(root, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code basePackageName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -138,6 +162,30 @@ public static List<Class<?>> findAllClassesInPackage(String basePackageName, Pre
return ReflectionUtils.findAllClassesInPackage(basePackageName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code basePackageName}
* that match the specified {@code classFilter} and {@code classNameFilter}
* predicates.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning within the supplied base package.
*
* @param basePackageName the name of the base package in which to start
* scanning; must not be {@code null} and must be valid in terms of Java
* syntax
* @param classFilter the class type filter; never {@code null}
* @param classNameFilter the class name filter; never {@code null}
* @return a stream of all such classes found; never {@code null}
* but potentially empty
* @see #findAllClassesInClasspathRoot(URI, Predicate, Predicate)
* @see #findAllClassesInModule(String, Predicate, Predicate)
*/
public static Stream<Class<?>> findAllClassesInPackageAsStream(String basePackageName,
Predicate<Class<?>> classFilter, Predicate<String> classNameFilter) {

return ReflectionUtils.findAllClassesInPackageAsStream(basePackageName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code moduleName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -162,6 +210,30 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, Predicate
return ReflectionUtils.findAllClassesInModule(moduleName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code moduleName}
* that match the specified {@code classFilter} and {@code classNameFilter}
* predicates.
*
* <p>The module-path scanning algorithm searches recursively in all
* packages contained in the module.
*
* @param moduleName the name of the module to scan; never {@code null} or
* <em>empty</em>
* @param classFilter the class type filter; never {@code null}
* @param classNameFilter the class name filter; never {@code null}
* @return a stream of all such classes found; never {@code null}
* but potentially empty
* @since 1.1.1
Ndione24 marked this conversation as resolved.
Show resolved Hide resolved
* @see #findAllClassesInClasspathRoot(URI, Predicate, Predicate)
* @see #findAllClassesInPackage(String, Predicate, Predicate)
*/
public static Stream<Class<?>> findAllClassesInModuleAsStream(String moduleName, Predicate<Class<?>> classFilter,
Predicate<String> classNameFilter) {

return ReflectionUtils.findAllClassesInModuleAsStream(moduleName, classFilter, classNameFilter);
}

/**
* Create a new instance of the specified {@link Class} by invoking
* the constructor whose argument list matches the types of the supplied
Expand Down Expand Up @@ -225,6 +297,31 @@ public static List<Field> findFields(Class<?> clazz, Predicate<Field> predicate,
ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name()));
}

/**
* Find all {@linkplain Field fields} of the supplied class or interface
* that match the specified {@code predicate}.
*
* <p>Fields declared in the same class or interface will be ordered using
* an algorithm that is deterministic but intentionally nonobvious.
*
* <p>The results will not contain fields that are <em>hidden</em> or
* {@linkplain Field#isSynthetic() synthetic}.
*
* @param clazz the class or interface in which to find the fields; never {@code null}
* @param predicate the field filter; never {@code null}
* @param traversalMode the hierarchy traversal mode; never {@code null}
* @return a stream of all such fields found; never {@code null}
* but potentially empty
* @since 1.10
*/
@API(status = MAINTAINED, since = "1.10")
public static Stream<Field> findFieldsAsStream(Class<?> clazz, Predicate<Field> predicate,
HierarchyTraversalMode traversalMode) {
Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null");
return ReflectionUtils.findFieldsAsStream(clazz, predicate,
ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name()));
}

/**
* Try to read the value of a potentially inaccessible field.
*
Expand Down Expand Up @@ -307,6 +404,32 @@ public static List<Method> findMethods(Class<?> clazz, Predicate<Method> predica
ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name()));
}

/**
* Find all distinct {@linkplain Method methods} of the supplied class or
* interface that match the specified {@code predicate}.
*
* <p>The results will not contain instance methods that are <em>overridden</em>
* or {@code static} methods that are <em>hidden</em>.
*
* <p>If you're are looking for methods annotated with a certain annotation
* type, consider using
* {@link AnnotationSupport#findAnnotatedMethods(Class, Class, HierarchyTraversalMode)}.
*
* @param clazz the class or interface in which to find the methods; never {@code null}
* @param predicate the method filter; never {@code null}
* @param traversalMode the hierarchy traversal mode; never {@code null}
* @return a stream of all such methods found; never {@code null}
* but potentially empty
*/
public static Stream<Method> findMethodsAsStream(Class<?> clazz, Predicate<Method> predicate,
HierarchyTraversalMode traversalMode) {

Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null");

return ReflectionUtils.findMethodsAsStream(clazz, predicate,
ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name()));
}

/**
* Find all nested classes within the supplied class, or inherited by the
* supplied class, that conform to the supplied predicate.
Expand All @@ -333,4 +456,30 @@ public static List<Class<?>> findNestedClasses(Class<?> clazz, Predicate<Class<?
return ReflectionUtils.findNestedClasses(clazz, predicate);
}

/**
* Find all nested classes within the supplied class, or inherited by the
* supplied class, that conform to the supplied predicate.
*
* <p>This method does <strong>not</strong> search for nested classes
* recursively.
*
* <p>As of JUnit Platform 1.6, this method detects cycles in <em>inner</em>
* class hierarchies &mdash; from the supplied class up to the outermost
* enclosing class &mdash; and throws a {@link JUnitException} if such a cycle
* is detected. Cycles within inner class hierarchies <em>below</em> the
* supplied class are not detected by this method.
*
* @param clazz the class to be searched; never {@code null}
* @param predicate the predicate against which the list of nested classes is
* checked; never {@code null}
* @return a stream of all such classes found; never {@code null}
* but potentially empty
* @throws JUnitException if a cycle is detected within an inner class hierarchy
*/
public static Stream<Class<?>> findNestedClassesAsStream(Class<?> clazz, Predicate<Class<?>> predicate)
throws JUnitException {

return ReflectionUtils.findNestedClassesAsStream(clazz, predicate);
}

}
Loading