Skip to content

Commit a9b9875

Browse files
authored
Miscellaneous matcher cleanup (#18)
* TypeMatcher is a FunctionalInterface * Provide strong-type form of 'not(...)' * Introduce AccessMatcher functional type * Add some common 'negative' access matchers * Add some common method matchers
1 parent 95dce6c commit a9b9875

File tree

6 files changed

+136
-44
lines changed

6 files changed

+136
-44
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2025-Present Datadog, Inc.
5+
*/
6+
7+
package datadog.instrument.classmatch;
8+
9+
import java.lang.reflect.Modifier;
10+
import java.util.function.IntPredicate;
11+
12+
/**
13+
* Predicate for matching access modifiers defined in <a
14+
* href="https://docs.oracle.com/javase/specs/jvms/se24/html/jvms-4.html">class-files</a>.
15+
*/
16+
@FunctionalInterface
17+
public interface AccessMatcher extends IntPredicate {
18+
19+
/** Matches public access. */
20+
AccessMatcher PUBLIC = Modifier::isPublic;
21+
22+
/** Matches private access. */
23+
AccessMatcher PRIVATE = Modifier::isPrivate;
24+
25+
/** Matches protected access. */
26+
AccessMatcher PROTECTED = Modifier::isProtected;
27+
28+
/** Matches package-private access. */
29+
AccessMatcher PACKAGE_PRIVATE =
30+
acc -> (acc & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)) == 0;
31+
32+
/** Matches static methods/fields. */
33+
AccessMatcher STATIC = Modifier::isStatic;
34+
35+
/** Matches non-static methods/fields. */
36+
AccessMatcher INSTANCE = acc -> (acc & Modifier.STATIC) == 0;
37+
38+
/** Matches final classes/methods/fields. */
39+
AccessMatcher FINAL = Modifier::isFinal;
40+
41+
/** Matches non-final classes/methods/fields. */
42+
AccessMatcher NON_FINAL = acc -> (acc & Modifier.FINAL) == 0;
43+
44+
/** Matches synchronized methods. */
45+
AccessMatcher SYNCHRONIZED = Modifier::isSynchronized;
46+
47+
/** Matches varargs methods. */
48+
AccessMatcher VARARGS = acc -> (acc & 0x0080) != 0;
49+
50+
/** Matches volatile fields. */
51+
AccessMatcher VOLATILE = Modifier::isVolatile;
52+
53+
/** Matches transient fields. */
54+
AccessMatcher TRANSIENT = Modifier::isTransient;
55+
56+
/** Matches interface classes. */
57+
AccessMatcher INTERFACE = Modifier::isInterface;
58+
59+
/** Matches non-interface classes. */
60+
AccessMatcher CLASS = acc -> (acc & Modifier.INTERFACE) == 0;
61+
62+
/** Matches abstract classes/methods. */
63+
AccessMatcher ABSTRACT = Modifier::isAbstract;
64+
65+
/** Matches non-abstract classes/methods. */
66+
AccessMatcher CONCRETE = acc -> (acc & Modifier.ABSTRACT) == 0;
67+
68+
/**
69+
* Conjunction of this matcher AND another.
70+
*
71+
* @param other the other matcher
72+
* @return conjunction of both matchers
73+
*/
74+
default AccessMatcher and(AccessMatcher other) {
75+
// simple approach as we don't expect many access-matcher unions
76+
return acc -> test(acc) && other.test(acc);
77+
}
78+
79+
/**
80+
* Disjunction of this matcher OR another.
81+
*
82+
* @param other the other matcher
83+
* @return disjunction of both matchers
84+
*/
85+
default AccessMatcher or(AccessMatcher other) {
86+
// simple approach as we don't expect many access-matcher unions
87+
return acc -> test(acc) || other.test(acc);
88+
}
89+
}

class-match/src/main/java/datadog/instrument/classmatch/ClassMatcher.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import static java.util.Arrays.asList;
1313

1414
import java.util.Collection;
15-
import java.util.function.IntPredicate;
1615
import java.util.function.Predicate;
1716

1817
/** Fluent-API for building {@link ClassOutline} predicates. */
@@ -36,7 +35,7 @@ static ClassMatcher declares(FieldMatcher fieldMatcher) {
3635
* @param fieldMatcher the field matcher
3736
* @return matcher of classes with a matching field
3837
*/
39-
static ClassMatcher declares(IntPredicate accessMatcher, FieldMatcher fieldMatcher) {
38+
static ClassMatcher declares(AccessMatcher accessMatcher, FieldMatcher fieldMatcher) {
4039
FieldMatcher combinedMatcher = fieldMatcher.access(accessMatcher);
4140
return c -> anyMatch(c.fields, combinedMatcher);
4241
}
@@ -58,7 +57,7 @@ static ClassMatcher declares(MethodMatcher methodMatcher) {
5857
* @param methodMatcher the method matcher
5958
* @return matcher of classes with a matching method
6059
*/
61-
static ClassMatcher declares(IntPredicate accessMatcher, MethodMatcher methodMatcher) {
60+
static ClassMatcher declares(AccessMatcher accessMatcher, MethodMatcher methodMatcher) {
6261
MethodMatcher combinedMatcher = methodMatcher.access(accessMatcher);
6362
return c -> anyMatch(c.methods, combinedMatcher);
6463
}

class-match/src/main/java/datadog/instrument/classmatch/FieldMatcher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import static datadog.instrument.classmatch.InternalMatchers.descriptor;
1010

11-
import java.util.function.IntPredicate;
1211
import java.util.function.Predicate;
1312

1413
/** Fluent-API for building {@link FieldOutline} predicates. */
@@ -41,7 +40,7 @@ static FieldMatcher field(Predicate<String> nameMatcher) {
4140
* @param accessMatcher the access matcher
4241
* @return matcher of fields with matching access
4342
*/
44-
default FieldMatcher access(IntPredicate accessMatcher) {
43+
default FieldMatcher access(AccessMatcher accessMatcher) {
4544
return f -> test(f) && accessMatcher.test(f.access);
4645
}
4746

class-match/src/main/java/datadog/instrument/classmatch/MethodMatcher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import static java.util.Arrays.asList;
1717

1818
import java.util.Collection;
19-
import java.util.function.IntPredicate;
2019
import java.util.function.Predicate;
2120

2221
/** Fluent-API for building {@link MethodOutline} predicates. */
@@ -76,7 +75,7 @@ static MethodMatcher staticInitializer() {
7675
* @param accessMatcher the access matcher
7776
* @return matcher of methods with matching access
7877
*/
79-
default MethodMatcher access(IntPredicate accessMatcher) {
78+
default MethodMatcher access(AccessMatcher accessMatcher) {
8079
return and(m -> accessMatcher.test(m.access));
8180
}
8281

class-match/src/main/java/datadog/instrument/classmatch/StandardMatchers.java

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,63 @@
88

99
import static java.util.Arrays.asList;
1010

11-
import java.lang.reflect.Modifier;
1211
import java.util.Collection;
1312
import java.util.HashSet;
14-
import java.util.function.IntPredicate;
1513
import java.util.function.Predicate;
1614

1715
/** Standard matchers, part of the public API. */
1816
public final class StandardMatchers {
1917

20-
/** Matches public access. */
21-
public static final IntPredicate PUBLIC = Modifier::isPublic;
22-
23-
/** Matches private access. */
24-
public static final IntPredicate PRIVATE = Modifier::isPrivate;
25-
26-
/** Matches protected access. */
27-
public static final IntPredicate PROTECTED = Modifier::isProtected;
28-
29-
/** Matches static access. */
30-
public static final IntPredicate STATIC = Modifier::isStatic;
31-
32-
/** Matches final classes/methods/fields. */
33-
public static final IntPredicate FINAL = Modifier::isFinal;
34-
35-
/** Matches synchronized methods. */
36-
public static final IntPredicate SYNCHRONIZED = Modifier::isSynchronized;
37-
38-
/** Matches volatile fields. */
39-
public static final IntPredicate VOLATILE = Modifier::isVolatile;
40-
41-
/** Matches transient fields. */
42-
public static final IntPredicate TRANSIENT = Modifier::isTransient;
18+
private StandardMatchers() {}
4319

44-
/** Matches native methods. */
45-
public static final IntPredicate NATIVE = Modifier::isNative;
20+
/**
21+
* Negates the given type matcher.
22+
*
23+
* @param matcher the matcher to negate
24+
* @return negation of the matcher
25+
*/
26+
public static TypeMatcher not(TypeMatcher matcher) {
27+
return cs -> !matcher.test(cs);
28+
}
4629

47-
/** Matches interface classes. */
48-
public static final IntPredicate INTERFACE = Modifier::isInterface;
30+
/**
31+
* Negates the given class matcher.
32+
*
33+
* @param matcher the matcher to negate
34+
* @return negation of the matcher
35+
*/
36+
public static ClassMatcher not(ClassMatcher matcher) {
37+
return c -> !matcher.test(c);
38+
}
4939

50-
/** Matches abstract classes. */
51-
public static final IntPredicate ABSTRACT = Modifier::isAbstract;
40+
/**
41+
* Negates the given field matcher.
42+
*
43+
* @param matcher the matcher to negate
44+
* @return negation of the matcher
45+
*/
46+
public static FieldMatcher not(FieldMatcher matcher) {
47+
return f -> !matcher.test(f);
48+
}
5249

53-
private StandardMatchers() {}
50+
/**
51+
* Negates the given method matcher.
52+
*
53+
* @param matcher the matcher to negate
54+
* @return negation of the matcher
55+
*/
56+
public static MethodMatcher not(MethodMatcher matcher) {
57+
return m -> !matcher.test(m);
58+
}
5459

5560
/**
56-
* Syntactic sugar around {@link IntPredicate#negate()}.
61+
* Negates the given access matcher.
5762
*
58-
* @param predicate the predicate to negate
59-
* @return negated predicate
63+
* @param matcher the matcher to negate
64+
* @return negation of the matcher
6065
*/
61-
public static IntPredicate not(IntPredicate predicate) {
62-
return predicate.negate();
66+
public static AccessMatcher not(AccessMatcher matcher) {
67+
return acc -> !matcher.test(acc);
6368
}
6469

6570
/**

class-match/src/main/java/datadog/instrument/classmatch/TypeMatcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.function.Predicate;
1414

1515
/** Fluent-API for building type hierarchy predicates. */
16+
@FunctionalInterface
1617
public interface TypeMatcher extends Predicate<CharSequence> {
1718

1819
/**

0 commit comments

Comments
 (0)