1 /*
2  * Copyright (c) 2016, 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 8173232
26  * @summary Test of forward referencing of snippets (related to import).
27  * @build KullaTesting TestingInputStream
28  * @run testng ForwardReferenceImportTest
29  */
30 
31 import jdk.jshell.Snippet;
32 import jdk.jshell.DeclarationSnippet;
33 import org.testng.annotations.Test;
34 
35 import static jdk.jshell.Snippet.Status.*;
36 
37 @Test
38 public class ForwardReferenceImportTest extends KullaTesting {
39 
testImportDeclare()40     public void testImportDeclare() {
41         Snippet singleImport = importKey(assertEval("import java.util.List;", added(VALID)));
42         Snippet importOnDemand = importKey(assertEval("import java.util.*;", added(VALID)));
43         Snippet singleStaticImport = importKey(assertEval("import static java.lang.Math.abs;", added(VALID)));
44         Snippet staticImportOnDemand = importKey(assertEval("import static java.lang.Math.*;", added(VALID)));
45         assertEval("import java.util.List; //again",
46                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
47                 ste(singleImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
48         assertEval("import java.util.*; //again",
49                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
50                 ste(importOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
51         assertEval("import static java.lang.Math.abs; //again",
52                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
53                 ste(singleStaticImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
54         assertEval("import static java.lang.Math.*; //again",
55                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
56                 ste(staticImportOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
57         assertActiveKeys();
58     }
59 
testForwardSingleImportMethodToMethod()60     public void testForwardSingleImportMethodToMethod() {
61         DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
62                 added(RECOVERABLE_DEFINED)));
63         assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
64         assertEvalUnresolvedException("string();", "string", 1, 0);
65         assertEval("import static java.lang.String.format;",
66                 added(VALID),
67                 ste(string, RECOVERABLE_DEFINED, VALID, false, null));
68         assertEval("string();", "\"string\"");
69 
70         assertEval("double format(String s) { return 0; }",
71                 DiagCheck.DIAG_OK,
72                 DiagCheck.DIAG_ERROR,
73                 added(VALID),
74                 ste(string, VALID, RECOVERABLE_DEFINED, false, null));
75         assertEvalUnresolvedException("string();", "string", 0, 1);
76         assertActiveKeys();
77     }
78 
testForwardImportMethodOnDemandToMethod()79     public void testForwardImportMethodOnDemandToMethod() {
80         DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
81                 added(RECOVERABLE_DEFINED)));
82         assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
83         assertEvalUnresolvedException("string();", "string", 1, 0);
84         assertEval("import static java.lang.String.*;",
85                 added(VALID),
86                 ste(string, RECOVERABLE_DEFINED, VALID, false, null));
87         assertEval("string();", "\"string\"");
88 
89         assertEval("double format(String s) { return 0; }",
90                 DiagCheck.DIAG_OK,
91                 DiagCheck.DIAG_ERROR,
92                 added(VALID),
93                 ste(string, VALID, RECOVERABLE_DEFINED, false, null));
94         assertEvalUnresolvedException("string();", "string", 0, 1);
95         assertActiveKeys();
96     }
97 
testForwardSingleImportFieldToMethod()98     public void testForwardSingleImportFieldToMethod() {
99         DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
100                 added(RECOVERABLE_DEFINED)));
101         assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
102         assertEvalUnresolvedException("pi();", "pi", 1, 0);
103         assertEval("import static java.lang.Math.PI;",
104                 added(VALID),
105                 ste(pi, RECOVERABLE_DEFINED, VALID, false, null));
106         assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
107 
108         assertEval("String PI;",
109                 DiagCheck.DIAG_OK,
110                 DiagCheck.DIAG_ERROR,
111                 added(VALID),
112                 ste(pi, VALID, RECOVERABLE_DEFINED, false, null));
113         assertEvalUnresolvedException("pi();", "pi", 0, 1);
114         assertActiveKeys();
115     }
116 
testForwardImportFieldOnDemandToMethod()117     public void testForwardImportFieldOnDemandToMethod() {
118         DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
119                 added(RECOVERABLE_DEFINED)));
120         assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
121         assertEvalUnresolvedException("pi();", "pi", 1, 0);
122         assertEval("import static java.lang.Math.*;",
123                 added(VALID),
124                 ste(pi, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET));
125         assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
126 
127         assertEval("String PI;",
128                 DiagCheck.DIAG_OK,
129                 DiagCheck.DIAG_ERROR,
130                 added(VALID),
131                 ste(pi, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
132         assertEvalUnresolvedException("pi();", "pi", 0, 1);
133         assertActiveKeys();
134     }
135 
testForwardSingleImportMethodToClass1()136     public void testForwardSingleImportMethodToClass1() {
137         Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
138                 added(RECOVERABLE_DEFINED)));
139         assertEvalUnresolvedException("new A();", "A", 1, 0);
140         assertEval("import static java.lang.String.format;",
141                 added(VALID),
142                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
143         assertEval("new A().s;", "\"10\"");
144         Snippet format = methodKey(assertEval("void format(String s, int d) { }",
145                 DiagCheck.DIAG_OK,
146                 DiagCheck.DIAG_ERROR,
147                 added(VALID),
148                 ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)));
149         assertEvalUnresolvedException("new A();", "A", 0, 1);
150         assertActiveKeys();
151         assertDrop(format,
152                 ste(format, VALID, DROPPED, true, null),
153                 ste(a, RECOVERABLE_DEFINED, VALID, false, format));
154     }
155 
testForwardSingleImportMethodToClass2()156     public void testForwardSingleImportMethodToClass2() {
157         Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
158                 added(RECOVERABLE_DEFINED)));
159         assertEvalUnresolvedException("new A();", "A", 1, 0);
160         assertEval("import static java.lang.String.format;",
161                 added(VALID),
162                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
163         assertEval("new A().s();", "\"10\"");
164         Snippet format = methodKey(assertEval("void format(String s, int d) { }",
165                 DiagCheck.DIAG_OK,
166                 DiagCheck.DIAG_ERROR,
167                 added(VALID),
168                 ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
169         assertEvalUnresolvedException("new A();", "A", 0, 1);
170         assertActiveKeys();
171         assertDrop(format,
172                 ste(format, VALID, DROPPED, true, null),
173                 ste(a, RECOVERABLE_DEFINED, VALID, false, format));
174     }
175 
testForwardSingleImportClassToClass1()176     public void testForwardSingleImportClassToClass1() {
177         Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
178                 added(RECOVERABLE_NOT_DEFINED)));
179         assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
180         assertEval("import java.util.List;",
181                 added(VALID),
182                 ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
183         assertEval("import java.util.Arrays;", added(VALID));
184         assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
185 
186         Snippet list = classKey(assertEval("class List {}",
187                 DiagCheck.DIAG_OK,
188                 DiagCheck.DIAG_ERROR,
189                 added(VALID),
190                 ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
191         assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.single.import");
192         assertActiveKeys();
193         assertDrop(list,
194                 ste(list, VALID, DROPPED, true, null),
195                 ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
196     }
197 
testForwardSingleImportClassToClass2()198     public void testForwardSingleImportClassToClass2() {
199         Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
200                 added(RECOVERABLE_NOT_DEFINED)));
201         assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
202         assertEval("import java.util.ArrayList;",
203                 added(VALID),
204                 ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
205         Snippet vara = varKey(assertEval("A a = new A();", "[]"));
206 
207         Snippet arraylist = classKey(assertEval("class ArrayList {}",
208                 DiagCheck.DIAG_OK,
209                 DiagCheck.DIAG_ERROR,
210                 added(VALID),
211                 ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
212                 ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
213         assertDeclareFail("A a = new A();", "compiler.err.cant.resolve.location",
214                 ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, REJECTED, false, null),
215                 ste(vara, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET));
216         assertActiveKeys();
217         assertDrop(arraylist,
218                 ste(arraylist, VALID, DROPPED, true, null),
219                 ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist));
220     }
221 
testForwardImportOnDemandMethodToClass1()222     public void testForwardImportOnDemandMethodToClass1() {
223         Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
224                 added(RECOVERABLE_DEFINED)));
225         assertEvalUnresolvedException("new A();", "A", 1, 0);
226         assertEval("import static java.lang.String.*;",
227                 added(VALID),
228                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
229         assertEval("A x = new A();");
230         assertEval("x.s;", "\"10\"");
231         Snippet format = methodKey(assertEval("void format(String s, int d) { }",
232                 DiagCheck.DIAG_OK,
233                 DiagCheck.DIAG_ERROR,
234                 added(VALID),
235                 ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
236         assertEvalUnresolvedException("new A();", "A", 0, 1);
237         assertActiveKeys();
238         assertDrop(format,
239                 ste(format, VALID, DROPPED, true, null),
240                 ste(a, RECOVERABLE_DEFINED, VALID, false, format));
241         assertEval("x.s;", "\"10\"");
242     }
243 
testForwardImportOnDemandMethodToClass2()244     public void testForwardImportOnDemandMethodToClass2() {
245         Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
246                 added(RECOVERABLE_DEFINED)));
247         assertEvalUnresolvedException("new A();", "A", 1, 0);
248         assertEval("import static java.lang.String.*;",
249                 added(VALID),
250                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
251         assertEval("new A().s();", "\"10\"");
252         Snippet format = methodKey(assertEval("void format(String s, int d) { }",
253                 DiagCheck.DIAG_OK,
254                 DiagCheck.DIAG_ERROR,
255                 added(VALID),
256                 ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
257         assertEvalUnresolvedException("new A();", "A", 0, 1);
258         assertActiveKeys();
259         assertDrop(format,
260                 ste(format, VALID, DROPPED, true, null),
261                 ste(a, RECOVERABLE_DEFINED, VALID, false, format));
262     }
263 
testForwardImportOnDemandClassToClass1()264     public void testForwardImportOnDemandClassToClass1() {
265         Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
266                 added(RECOVERABLE_NOT_DEFINED)));
267         assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
268         assertEval("import java.util.*;",
269                 added(VALID),
270                 ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
271         assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
272 
273         Snippet list = classKey(assertEval("class List {}",
274                 DiagCheck.DIAG_OK,
275                 DiagCheck.DIAG_ERROR,
276                 added(VALID),
277                 ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
278         assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.cant.resolve.location");
279         assertActiveKeys();
280         assertDrop(list,
281                 ste(list, VALID, DROPPED, true, null),
282                 ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
283     }
284 
testForwardImportOnDemandClassToClass2()285     public void testForwardImportOnDemandClassToClass2() {
286         Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
287                 added(RECOVERABLE_NOT_DEFINED)));
288         assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
289         assertEval("import java.util.*;",
290                 added(VALID),
291                 ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
292         Snippet vara = varKey(assertEval("A a = new A();", "[]"));
293 
294         Snippet arraylist = classKey(assertEval("class ArrayList {}",
295                 DiagCheck.DIAG_OK,
296                 DiagCheck.DIAG_ERROR,
297                 added(VALID),
298                 ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
299                 ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
300         assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
301         assertActiveKeys();
302         assertDrop(arraylist,
303                 ste(arraylist, VALID, DROPPED, true, null),
304                 ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist),
305                 ste(vara, RECOVERABLE_NOT_DEFINED, VALID, true, clsA));
306     }
307 
testForwardSingleImportFieldToClass1()308     public void testForwardSingleImportFieldToClass1() {
309         Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
310                 added(RECOVERABLE_DEFINED)));
311         assertEvalUnresolvedException("new A();", "A", 1, 0);
312         assertEval("import static java.lang.Math.PI;",
313                 added(VALID),
314                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
315         assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
316 
317         Snippet list = varKey(assertEval("String PI;",
318                 DiagCheck.DIAG_OK,
319                 DiagCheck.DIAG_ERROR,
320                 added(VALID),
321                 ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
322         assertEvalUnresolvedException("new A();", "A", 0, 1);
323         assertActiveKeys();
324         assertDrop(list,
325                 ste(list, VALID, DROPPED, true, null),
326                 ste(a, RECOVERABLE_DEFINED, VALID, false, list));
327     }
328 
testForwardSingleImportFieldToClass2()329     public void testForwardSingleImportFieldToClass2() {
330         Snippet a = classKey(assertEval("class A { static double pi = PI; }",
331                 added(RECOVERABLE_DEFINED)));
332         assertEvalUnresolvedException("new A();", "A", 1, 0);
333         assertEval("import static java.lang.Math.PI;",
334                 added(VALID),
335                 ste(a, RECOVERABLE_DEFINED, VALID, true, null));
336         assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
337 
338         Snippet list = varKey(assertEval("String PI;",
339                 DiagCheck.DIAG_OK,
340                 DiagCheck.DIAG_ERROR,
341                 added(VALID),
342                 ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
343         assertEvalUnresolvedException("new A();", "A", 0, 1);
344         assertActiveKeys();
345         assertDrop(list,
346                 ste(list, VALID, DROPPED, true, null),
347                 ste(a, RECOVERABLE_DEFINED, VALID, true, list));
348     }
349 
testForwardImportOnDemandFieldToClass1()350     public void testForwardImportOnDemandFieldToClass1() {
351         Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
352                 added(RECOVERABLE_DEFINED)));
353         assertEvalUnresolvedException("new A();", "A", 1, 0);
354         assertEval("import static java.lang.Math.*;",
355                 added(VALID),
356                 ste(a, RECOVERABLE_DEFINED, VALID, false, null));
357         assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
358 
359         Snippet list = varKey(assertEval("String PI;",
360                 DiagCheck.DIAG_OK,
361                 DiagCheck.DIAG_ERROR,
362                 added(VALID),
363                 ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
364         assertEvalUnresolvedException("new A();", "A", 0, 1);
365         assertActiveKeys();
366         assertDrop(list,
367                 ste(list, VALID, DROPPED, true, null),
368                 ste(a, RECOVERABLE_DEFINED, VALID, false, list));
369     }
370 
testForwardImportOnDemandFieldToClass2()371     public void testForwardImportOnDemandFieldToClass2() {
372         Snippet a = classKey(assertEval("class A { static double pi = PI; }",
373                 added(RECOVERABLE_DEFINED)));
374         assertEvalUnresolvedException("new A();", "A", 1, 0);
375         assertEval("import static java.lang.Math.*;",
376                 added(VALID),
377                 ste(a, RECOVERABLE_DEFINED, VALID, true, null));
378         assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
379 
380         Snippet list = varKey(assertEval("String PI;",
381                 DiagCheck.DIAG_OK,
382                 DiagCheck.DIAG_ERROR,
383                 added(VALID),
384                 ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
385         assertEvalUnresolvedException("new A();", "A", 0, 1);
386         assertActiveKeys();
387         assertDrop(list,
388                 ste(list, VALID, DROPPED, true, null),
389                 ste(a, RECOVERABLE_DEFINED, VALID, true, list));
390         assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
391     }
392 }
393