1 /*
2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 8231461
27  * @summary static/instance overload leads to 'unexpected static method found in unbound lookup' when resolving method reference
28  * @library /lib/combo /tools/lib /tools/javac/lib
29  * @modules
30  *      jdk.compiler/com.sun.tools.javac.api
31  *      jdk.compiler/com.sun.tools.javac.util
32  * @run testng BoundUnboundSearchTest
33  */
34 
35 import java.util.function.*;
36 
37 import javax.tools.Diagnostic;
38 
39 import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper;
40 import com.sun.tools.javac.util.Assert;
41 import com.sun.tools.javac.util.JCDiagnostic;
42 
43 import org.testng.annotations.Test;
44 import tools.javac.combo.CompilationTestCase;
45 
46 import static org.testng.Assert.assertEquals;
47 
48 @Test
49 public class BoundUnboundSearchTest extends CompilationTestCase {
50     static final String TEMPLATE =
51             """
52             import java.util.function.*;
53             class Test {
54                 #CANDIDATES
55                 void m() {
56                     Function<String, String> f = Test::foo;
57                 }
58             }
59             """;
60 
BoundUnboundSearchTest()61     public BoundUnboundSearchTest() {
62         setDefaultFilename("Test.java");
63         setCompileOptions(new String[]{"--debug=dumpMethodReferenceSearchResults"});
64     }
65 
getDiagConsumer(final int boundCandidate, final int unboundCandidate)66     private Consumer<Diagnostic<?>> getDiagConsumer(final int boundCandidate, final int unboundCandidate) {
67         return diagWrapper -> {
68             JCDiagnostic diagnostic = ((DiagnosticSourceUnwrapper)diagWrapper).d;
69             Object[] args = diagnostic.getArgs();
70             if (args[0].toString().equals("bound")) {
71                 Assert.check(args[2].equals(boundCandidate));
72             } else if (args[0].toString().equals("unbound")) {
73                 Assert.check(args[2].equals(unboundCandidate));
74             }
75         };
76     }
77 
test()78     public void test() {
79         assertOK(
80             getDiagConsumer(0, -1),
81                 TEMPLATE.replaceFirst("#CANDIDATES",
82                     """
83                     public String foo(Object o) { return "foo"; }           // candidate 0
84                     public static String foo(String o) { return "bar"; }    // candidate 1
85                     """
86             )
87         );
88 
89         assertOK(
90                 getDiagConsumer(0, -1),
91                 TEMPLATE.replaceFirst("#CANDIDATES",
92                     """
93                     public static String foo(Object o) { return "foo"; }    // candidate 0
94                     public static String foo(String o) { return "bar"; }    // candidate 0
95                     """
96                 )
97         );
98 
99         assertFail("compiler.err.prob.found.req",
100                 getDiagConsumer(0, -1),
101                 TEMPLATE.replaceFirst("#CANDIDATES",
102                     """
103                     public static String foo(Object o) { return "foo"; }    // candidate 0
104                     public String foo(String o) { return "bar"; }           // candidate 1
105                     """
106                 )
107         );
108 
109         assertFail("compiler.err.prob.found.req",
110                 getDiagConsumer(0, -1),
111                 TEMPLATE.replaceFirst("#CANDIDATES",
112                     """
113                     public String foo(Object o) { return "foo"; }           // candidate 0
114                     public String foo(String o) { return "bar"; }           // candidate 1
115                     """
116                 )
117         );
118 
119         assertFail("compiler.err.invalid.mref",
120                 getDiagConsumer(-1, -1),
121                 """
122                 import java.util.function.*;
123 
124                 public class Test {
125                     public String foo(Object o) { return "foo"; }
126                     public static String foo(String o) { return "bar"; }
127 
128                     public void test() {
129                         // method bar doesn't exist
130                         Function<String, String> f = Test::bar;
131                     }
132                 }
133                 """
134         );
135     }
136 }
137