File tree Expand file tree Collapse file tree 4 files changed +109
-0
lines changed
test/library-tests/MemberRefExpr Expand file tree Collapse file tree 4 files changed +109
-0
lines changed Original file line number Diff line number Diff line change @@ -1227,6 +1227,28 @@ class MemberRefExpr extends FunctionalExpr, @memberref {
12271227 */
12281228 override Method asMethod ( ) { result = this .getAnonymousClass ( ) .getAMethod ( ) }
12291229
1230+ /**
1231+ * Gets the receiver type whose member this expression refers to. The result might not be
1232+ * the type which actually declares the member. For example, for the member reference `ArrayList::toString`,
1233+ * this predicate has the result `java.util.ArrayList`, the type explicitly referred to, while
1234+ * `getReferencedCallable` will have `java.util.AbstractCollection.toString` as result, which `ArrayList` inherits.
1235+ */
1236+ RefType getReceiverType ( ) {
1237+ exists ( Stmt stmt , Expr resultExpr |
1238+ stmt = asMethod ( ) .getBody ( ) .( SingletonBlock ) .getStmt ( ) and
1239+ (
1240+ resultExpr = stmt .( ReturnStmt ) .getResult ( )
1241+ or
1242+ // Note: Currently never an ExprStmt, but might change once https://github.com/github/codeql/issues/3605 is fixed
1243+ resultExpr = stmt .( ExprStmt ) .getExpr ( )
1244+ )
1245+ |
1246+ result = resultExpr .( MethodAccess ) .getReceiverType ( ) or
1247+ result = resultExpr .( ClassInstanceExpr ) .getConstructedType ( ) or
1248+ result = resultExpr .( ArrayCreationExpr ) .getType ( )
1249+ )
1250+ }
1251+
12301252 /**
12311253 * Gets the method or constructor referenced by this member reference expression.
12321254 */
Original file line number Diff line number Diff line change 1+ | Test.java:24:26:24:51 | ...::... | Inner<>.Inner<> | Test$Generic$Inner.class:0:0:0:0 | Inner<> |
2+ | Test.java:38:29:38:42 | ...::... | Object.toString | Test.java:1:7:1:10 | Test |
3+ | Test.java:39:29:39:42 | ...::... | Object.hashCode | Test.java:1:7:1:10 | Test |
4+ | Test.java:40:29:40:39 | ...::... | Object.clone | Test.java:1:7:1:10 | Test |
5+ | Test.java:41:40:41:64 | ...::... | Object.toString | Test$Generic.class:0:0:0:0 | Generic<String> |
6+ | Test.java:43:23:43:36 | ...::... | Object.toString | Test.java:1:7:1:10 | Test |
7+ | Test.java:44:23:44:36 | ...::... | Object.hashCode | Test.java:1:7:1:10 | Test |
8+ | Test.java:45:23:45:33 | ...::... | Object.clone | Test.java:1:7:1:10 | Test |
9+ | Test.java:48:22:48:35 | ...::... | Object.toString | Test.java:1:7:1:10 | Test |
10+ | Test.java:51:13:51:21 | ...::... | Test.Test | Test.java:1:7:1:10 | Test |
11+ | Test.java:52:13:52:32 | ...::... | Generic<String>.Generic<String> | Test$Generic.class:0:0:0:0 | Generic<String> |
12+ | Test.java:56:13:56:22 | ...::... | | file://:0:0:0:0 | int[] |
13+ | Test.java:57:13:57:26 | ...::... | | file://:0:0:0:0 | Generic<>[] |
14+ | Test.java:61:31:61:47 | ...::... | Test.doSomething | Test.java:1:7:1:10 | Test |
Original file line number Diff line number Diff line change 1+ import java
2+
3+ string getReferencedCallable ( MemberRefExpr e ) {
4+ if exists ( e .getReferencedCallable ( ) )
5+ then result = e .getReferencedCallable ( ) .getQualifiedName ( )
6+ else result = ""
7+ }
8+
9+ from MemberRefExpr e
10+ select e , getReferencedCallable ( e ) , e .getReceiverType ( )
Original file line number Diff line number Diff line change 1+ class Test {
2+ interface Function <T > {
3+ Object apply (T o ) throws Exception ;
4+ }
5+
6+ interface IntFunction {
7+ Object apply (int i );
8+ }
9+
10+ interface Supplier {
11+ Object get () throws Exception ;
12+ }
13+
14+ public Test () { }
15+
16+ static class Generic <T > {
17+ public Generic () { }
18+
19+ class Inner {
20+ public Inner () { }
21+ }
22+
23+ void test () {
24+ Supplier s = Generic <Number >.Inner ::new ;
25+ }
26+ }
27+
28+ void doSomething () { }
29+
30+ static class Sub extends Test {
31+ }
32+
33+ interface SubtypeConsumer {
34+ void consume (Sub s );
35+ }
36+
37+ void test () {
38+ Function <Test > f0 = Test ::toString ;
39+ Function <Test > f1 = Test ::hashCode ;
40+ Function <Test > f2 = Test ::clone ;
41+ Function <Generic <String >> f3 = Generic <String >::toString ;
42+
43+ Supplier s0 = this ::toString ;
44+ Supplier s1 = this ::hashCode ;
45+ Supplier s2 = this ::clone ;
46+
47+ // Discards result of method call
48+ Runnable r = this ::toString ;
49+
50+ Supplier [] classInstances = {
51+ Test ::new ,
52+ Generic <String >::new ,
53+ };
54+
55+ IntFunction [] arrays = {
56+ int []::new ,
57+ Generic []::new ,
58+ };
59+
60+ // SubtypeConsumer has `Sub` as parameter type, but receiver here is `Test` (supertype)
61+ SubtypeConsumer sub = Test ::doSomething ;
62+ }
63+ }
You can’t perform that action at this time.
0 commit comments