Skip to content

Commit b7e8f9a

Browse files
authored
ref-0.10.1 - fix exception, docs, ci matrix, dependabot
* 0.10.1 - fix exception in JavassistHelper.getParametersAnnotations, docs * ci: Setup GitHub actions for basic PR CI (#333) * Make the path format to be platform-compatible (#299) * enable Dependabot v2 (#319) * Enable automatic module name (#308)
1 parent ee52a9d commit b7e8f9a

16 files changed

+158
-55
lines changed

.github/dependabot.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "maven"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/maven-ci.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# This workflow will build a Java project with Maven
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3+
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [ master ]
9+
pull_request:
10+
branches: [ master ]
11+
12+
jobs:
13+
build:
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
java: [ '8', '9', '11', '13', '15', '17']
18+
os: [ ubuntu-latest ]
19+
name: Java ${{ matrix.Java }} on ${{ matrix.os }}
20+
runs-on: ${{ matrix.os }}
21+
22+
steps:
23+
- uses: actions/checkout@v2
24+
25+
- name: Setup Java
26+
uses: actions/setup-java@v2
27+
with:
28+
distribution: 'adopt'
29+
java-version: ${{ matrix.java }}
30+
31+
- name: Show version
32+
run: mvn -version
33+
34+
- name: Cache Maven packages
35+
uses: actions/cache@v1
36+
with:
37+
path: ~/.m2/repository
38+
key: ${{ runner.os }}-m2
39+
restore-keys: ${{ runner.os }}-m2
40+
41+
- name: Test with Maven
42+
run: mvn -B clean package ${{ matrix.jdk }}

README.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
*Released `org.reflections:reflections:0.10`*
1+
*Released `org.reflections:reflections:0.10.1`*
22

33
*Reflections library has ~4 million downloads per month from Maven Central, and is being used by thousands of [projects](https://github.com/ronmamo/reflections/network/dependents) and [libraries](https://mvnrepository.com/artifact/org.reflections/reflections/usages).
44
Thank you for your continuous support! And apologize for the issues. We're looking for community collaborators to assist in reviewing pull requests and issues, please reach out.*
55

6-
# Java runtime metadata analysis, in the spirit of [Scannotations](http://bill.burkecentral.com/2008/01/14/scanning-java-annotations-at-runtime/)
6+
# Java runtime metadata analysis
77

88
[![Build Status](https://travis-ci.org/ronmamo/reflections.svg?branch=master)](https://travis-ci.org/ronmamo/reflections)
99

@@ -16,18 +16,20 @@ Using Reflections you can query for example:
1616
* Resources found in classpath
1717
And more...
1818

19+
*Reflections was written in the spirit of [Scannotations](http://bill.burkecentral.com/2008/01/14/scanning-java-annotations-at-runtime/) library*
20+
1921
## Usage
2022
Add Reflections dependency to your project:
2123
```xml
2224
# Maven
2325
<dependency>
2426
<groupId>org.reflections</groupId>
2527
<artifactId>reflections</artifactId>
26-
<version>0.10</version>
28+
<version>0.10.1</version>
2729
</dependency>
2830

2931
# Gradle
30-
implementation 'org.reflections:reflections:0.10'
32+
implementation 'org.reflections:reflections:0.10.1'
3133
```
3234

3335
Create Reflections instance and use the query functions:
@@ -41,7 +43,7 @@ Set<Class<?>> annotated =
4143
reflections.get(TypesAnnotated.with(SomeAnnotation.class).asClass());
4244
```
4345

44-
*Note that there are some breaking changes with Reflections 0.10, along with performance improvements and more functional API. Migration is encouraged and should be easy though.*
46+
*Note that there are some breaking changes with Reflections 0.10+, along with performance improvements and more functional API. Migration is encouraged and should be easy though.*
4547

4648
### Scan
4749
Creating Reflections instance requires providing scanning configuration:
@@ -263,7 +265,9 @@ Although less common, it can be useful for accessing types and members in a stro
263265
Can be used for finding usages between packages, layers, modules, types etc.
264266

265267
### Contribute
266-
Pull requests are welcomed!!
268+
Pull requests are welcomed!!
269+
Here are some issues labeled with [please contribute :heart:](https://github.com/ronmamo/reflections/issues?q=is%3Aissue+is%3Aopen+label%3A%22please+contribute+%E2%9D%A4%EF%B8%8F%22+label%3A%22good+first+issue%22)
270+
*We're looking for community collaborators to assist in reviewing pull requests and issues, please reach out.*
267271

268272
Dual licenced with Apache 2 and [WTFPL](http://www.wtfpl.net/), just do what the fuck you want to.
269273

pom.xml

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>org.reflections</groupId>
66
<artifactId>reflections</artifactId>
7-
<version>0.11-SNAPSHOT</version>
7+
<version>0.10.1-SNAPSHOT</version>
88
<packaging>jar</packaging>
99

1010
<name>Reflections</name>
@@ -232,6 +232,9 @@
232232
<configuration>
233233
<archive>
234234
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
235+
<manifestEntries>
236+
<Automatic-Module-Name>org.reflections</Automatic-Module-Name>
237+
</manifestEntries>
235238
</archive>
236239
</configuration>
237240
</plugin>

src/main/java/org/reflections/ReflectionUtils.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
import static java.util.stream.Collectors.toList;
2424

2525
/**
26-
* utils for querying java reflection meta types {@link #SuperTypes}, {@link #Annotations}, {@link #AnnotationTypes}, {@link #Methods}, {@link #Constructors}, {@link #Fields}.
27-
* <pre>{@code Set<Class<?>> supertypes = get(SuperTypes.of(type))
26+
* utils for querying java reflection meta types
27+
* <p>see {@link #SuperTypes}, {@link #Annotations}, {@link #AnnotationTypes}, {@link #Methods}, {@link #Constructors} and {@link #Fields}.
28+
* <pre>{@code
29+
* Set<Class<?>> supertypes = get(SuperTypes.of(type))
2830
* Set<Annotation> annotations = get(Annotations.of(type))
2931
* }</pre>
30-
* <p>generally, apply {@link #get(QueryFunction)} on {@link QueryFunction} created by {@link UtilQueryBuilder}, and optionally use the functional methods in QueryFunction
32+
* <p>generally, apply {@link #get(QueryFunction)} on {@link QueryFunction} created by {@link UtilQueryBuilder}, and optionally use the functional methods in QueryFunction.
3133
* <pre>{@code get(Methods.of(type)
3234
* .filter(withPublic().and(withPrefix("get")).and(withParameterCount(0)))
3335
* .as(Method.class)

src/main/java/org/reflections/Reflections.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
* </ul>
6565
*
6666
* <p>Create Reflections instance, preferably using {@link ConfigurationBuilder}:
67-
* <pre>{@code Reflections reflections = new Reflections(
67+
* <pre>{@code
68+
* Reflections reflections = new Reflections(
6869
* new ConfigurationBuilder()
6970
* .forPackage("com.my.project"));
7071
*
@@ -87,7 +88,8 @@
8788
* <p>Classloader can optionally be used for resolving runtime classes from names.
8889
*
8990
* <p></p>Query using {@link Reflections#get(QueryFunction)}, such as:
90-
* <pre>{@code Set<Class<?>> modules = reflections.get(SubTypes.of(Module.class).asClass());
91+
* <pre>{@code
92+
* Set<Class<?>> modules = reflections.get(SubTypes.of(Module.class).asClass());
9193
* Set<Class<?>> singletons = reflections.get(TypesAnnotated.with(Singleton.class).asClass());
9294
* Set<String> properties = reflections.get(Resources.with(".*\\.properties"));
9395
* Set<Method> requests = reflections.get(MethodsAnnotated.with(RequestMapping.class).as(Method.class));

src/main/java/org/reflections/scanners/Scanners.java

+3
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@
2727
* <li>{@link #SubTypes}</li>
2828
* <li>{@link #TypesAnnotated}</li>
2929
* <li>{@link #MethodsAnnotated}</li>
30+
* <li>{@link #ConstructorsAnnotated}</li>
3031
* <li>{@link #FieldsAnnotated}</li>
3132
* <li>{@link #Resources}</li>
3233
* <li>{@link #MethodsParameter}</li>
34+
* <li>{@link #ConstructorsParameter}</li>
3335
* <li>{@link #MethodsSignature}</li>
36+
* <li>{@link #ConstructorsSignature}</li>
3437
* <li>{@link #MethodsReturn}</li>
3538
* </ul>
3639
* <i>note that scanners must be configured in {@link org.reflections.Configuration} in order to be queried</i>

src/main/java/org/reflections/util/JavassistHelper.java

+29-19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import javassist.bytecode.annotation.Annotation;
1212

1313
import java.util.ArrayList;
14-
import java.util.Arrays;
1514
import java.util.Collections;
1615
import java.util.List;
1716
import java.util.function.Function;
@@ -22,12 +21,6 @@ public class JavassistHelper {
2221
/** setting this static to false will result in returning only {@link java.lang.annotation.RetentionPolicy#RUNTIME} visible annotation */
2322
public static boolean includeInvisibleTag = true;
2423

25-
public static List<String> getAnnotations(Function<String, AttributeInfo> function) {
26-
List<String> list = getAnnotations((AnnotationsAttribute) function.apply(AnnotationsAttribute.visibleTag));
27-
if (includeInvisibleTag) list.addAll(getAnnotations((AnnotationsAttribute) function.apply(AnnotationsAttribute.invisibleTag)));
28-
return list;
29-
}
30-
3124
public static String fieldName(ClassFile classFile, FieldInfo object) {
3225
return String.format("%s.%s", classFile.getName(), object.getName());
3326
}
@@ -70,22 +63,39 @@ public static String getReturnType(MethodInfo method) {
7063
return Descriptor.toString(descriptor);
7164
}
7265

73-
public static List<List<String>> getParametersAnnotations(MethodInfo method) {
74-
List<List<String>> list = getAnnotations((ParameterAnnotationsAttribute) method.getAttribute(ParameterAnnotationsAttribute.visibleTag));
75-
if (includeInvisibleTag) list.addAll(getAnnotations((ParameterAnnotationsAttribute) method.getAttribute(ParameterAnnotationsAttribute.invisibleTag)));
76-
return list;
77-
}
66+
public static List<String> getAnnotations(Function<String, AttributeInfo> function) {
67+
Function<String, List<String>> names = function
68+
.andThen(attribute -> attribute != null ? ((AnnotationsAttribute) attribute).getAnnotations() : null)
69+
.andThen(JavassistHelper::annotationNames);
7870

79-
private static List<List<String>> getAnnotations(ParameterAnnotationsAttribute attribute) {
80-
return mapList(attribute, ParameterAnnotationsAttribute::getAnnotations, aa -> mapList(aa, a -> a, Annotation::getTypeName));
71+
List<String> result = new ArrayList<>(names.apply(AnnotationsAttribute.visibleTag));
72+
if (includeInvisibleTag) result.addAll(names.apply(AnnotationsAttribute.invisibleTag));
73+
return result;
8174
}
8275

83-
private static List<String> getAnnotations(AnnotationsAttribute attribute) {
84-
return mapList(attribute, AnnotationsAttribute::getAnnotations, Annotation::getTypeName);
76+
public static List<List<String>> getParametersAnnotations(MethodInfo method) {
77+
Function<String, List<List<String>>> names = ((Function<String, AttributeInfo>) method::getAttribute)
78+
.andThen(attribute -> attribute != null ? ((ParameterAnnotationsAttribute) attribute).getAnnotations() : null)
79+
.andThen((Annotation[][] aa) -> aa != null ? Stream.of(aa).map(JavassistHelper::annotationNames).collect(Collectors.toList()) : Collections.emptyList());
80+
81+
List<List<String>> visibleAnnotations = names.apply(ParameterAnnotationsAttribute.visibleTag);
82+
if (!includeInvisibleTag) return new ArrayList<>(visibleAnnotations);
83+
84+
List<List<String>> invisibleAnnotations = names.apply(ParameterAnnotationsAttribute.invisibleTag);
85+
if (invisibleAnnotations.isEmpty()) return new ArrayList<>(visibleAnnotations);
86+
87+
// horror
88+
List<List<String>> result = new ArrayList<>();
89+
for (int i = 0; i < Math.max(visibleAnnotations.size(), invisibleAnnotations.size()); i++) {
90+
List<String> concat = new ArrayList<>();
91+
if (i < visibleAnnotations.size()) concat.addAll(visibleAnnotations.get(i));
92+
if (i < invisibleAnnotations.size()) concat.addAll(invisibleAnnotations.get(i));
93+
result.add(concat);
94+
}
95+
return result;
8596
}
8697

87-
// todo inline & simplify
88-
private static <T, A, R> List<R> mapList(T t, Function<T, A[]> f1, Function<A, R> f2) {
89-
return t != null ? Arrays.stream(f1.apply(t)).map(f2).collect(Collectors.toList()) : Collections.emptyList();
98+
private static List<String> annotationNames(Annotation[] annotations) {
99+
return annotations != null ? Stream.of(annotations).map(Annotation::getTypeName).collect(Collectors.toList()) : Collections.emptyList();
90100
}
91101
}

src/main/java/org/reflections/util/ReflectionUtilsPredicates.java

+15
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public static <T extends Member> Predicate<T> withPrefix(final String prefix) {
3434
return input -> input != null && input.getName().startsWith(prefix);
3535
}
3636

37+
/**
38+
* where annotated element name startsWith given {@code prefix}
39+
*/
40+
public static <T> Predicate<T> withNamePrefix(final String prefix) {
41+
return input -> toName(input).startsWith(prefix);
42+
}
43+
3744
/**
3845
* where member's {@code toString} matches given {@code regex}
3946
* <pre> get(Methods.of(someClass).filter(withPattern("public void .*"))) </pre>
@@ -200,6 +207,14 @@ public static boolean isAssignable(Class[] childClasses, Class[] parentClasses)
200207
}
201208

202209
//
210+
private static String toName(Object input) {
211+
return input == null ? "" :
212+
input.getClass().equals(Class.class) ? ((Class<?>) input).getName() :
213+
input instanceof Member ? ((Member) input).getName() :
214+
input instanceof Annotation ? ((Annotation) input).annotationType().getName() :
215+
input.toString();
216+
}
217+
203218
private static Class[] parameterTypes(Member member) {
204219
return member != null ?
205220
member.getClass() == Method.class ? ((Method) member).getParameterTypes() :

src/test/java/org/reflections/MyTestModelStore.java

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ interface methods {
3636
interface value {}
3737
}
3838
}
39+
interface TestModel$AM2 {
40+
}
3941
interface TestModel$C1 {
4042
interface annotations {
4143
interface org_reflections_TestModel$AC1 {}

src/test/java/org/reflections/ReflectionUtilsQueryTest.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,9 @@ public void testMembers() throws NoSuchMethodException, NoSuchFieldException {
124124
@Test
125125
public void nestedQuery() {
126126
Set<Class<? extends Annotation>> annotations =
127-
get(Annotations.of(
127+
get(AnnotationTypes.of(
128128
Methods.of(C4.class))
129-
.map(Annotation::annotationType)
130-
.filter(a -> !a.getName().startsWith("java."))
131-
.as());
129+
.filter(withNamePrefix("org.reflections")));
132130

133131
assertThat(annotations,
134132
equalTo(AM1.class));
@@ -198,6 +196,7 @@ public void annotationToMap() {
198196
Set<Map<String, Object>> valueMaps =
199197
get(Annotations.of(
200198
Methods.of(CombinedTestModel.Impl.class))
199+
.filter(withNamePrefix("org.reflections"))
201200
.map(ReflectionUtils::toMap));
202201

203202
// todo proper assert

src/test/java/org/reflections/ReflectionUtilsTest.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import org.reflections.scanners.Scanners;
77

88
import java.lang.annotation.Annotation;
9+
import java.lang.annotation.Documented;
10+
import java.lang.annotation.Inherited;
11+
import java.lang.annotation.Retention;
12+
import java.lang.annotation.Target;
913
import java.lang.reflect.Field;
1014
import java.lang.reflect.Member;
1115
import java.lang.reflect.Method;
@@ -14,13 +18,15 @@
1418
import java.util.Collection;
1519
import java.util.Collections;
1620
import java.util.HashSet;
21+
import java.util.List;
1722
import java.util.Set;
1823
import java.util.stream.Collectors;
1924

2025
import static org.hamcrest.MatcherAssert.assertThat;
2126
import static org.junit.jupiter.api.Assertions.*;
2227
import static org.reflections.ReflectionUtils.*;
2328
import static org.reflections.ReflectionsTest.are;
29+
import static org.reflections.ReflectionsTest.equalTo;
2430

2531
@SuppressWarnings("unchecked")
2632
public class ReflectionUtilsTest {
@@ -48,17 +54,11 @@ public void getAllTest() {
4854

4955
assertThat(getAllConstructors(TestModel.C4.class, withParametersCount(0)), names(TestModel.C4.class.getName()));
5056

51-
assertEquals(toStringSorted(getAllAnnotations(TestModel.C3.class)),
52-
"[@java.lang.annotation.Documented(), " +
53-
"@java.lang.annotation.Inherited(), " +
54-
"@java.lang.annotation.Retention(value=RUNTIME), " +
55-
"@java.lang.annotation.Target(value=ANNOTATION_TYPE), " +
56-
"@org.reflections.TestModel$AC1(), " +
57-
"@org.reflections.TestModel$AC1n(), " +
58-
"@org.reflections.TestModel$AC2(value=ac2), " +
59-
"@org.reflections.TestModel$AI1(), " +
60-
"@org.reflections.TestModel$AI2(), " +
61-
"@org.reflections.TestModel$MAI1()]");
57+
Set<Annotation> allAnnotations = getAllAnnotations(TestModel.C3.class);
58+
assertThat(allAnnotations.stream().map(Annotation::annotationType).collect(Collectors.toSet()),
59+
equalTo(Documented.class, Inherited.class, Retention.class, Target.class,
60+
TestModel.MAI1.class, TestModel.AI1.class, TestModel.AI2.class,
61+
TestModel.AC1.class, TestModel.AC1n.class, TestModel.AC2.class));
6262

6363
Method m4 = getMethods(TestModel.C4.class, withName("m4")).iterator().next();
6464
assertEquals(m4.getName(), "m4");

0 commit comments

Comments
 (0)