ReplaceTest.java revision 3357:3e3553ee39d9
1/*
2 * Copyright (c) 2015, 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 8080069 8152925
26 * @summary Test of Snippet redefinition and replacement.
27 * @build KullaTesting TestingInputStream
28 * @run testng ReplaceTest
29 */
30
31import java.util.Collection;
32
33import java.util.List;
34import jdk.jshell.Snippet;
35import jdk.jshell.MethodSnippet;
36import jdk.jshell.PersistentSnippet;
37import jdk.jshell.TypeDeclSnippet;
38import jdk.jshell.VarSnippet;
39import jdk.jshell.DeclarationSnippet;
40import org.testng.annotations.Test;
41
42import jdk.jshell.SnippetEvent;
43import jdk.jshell.UnresolvedReferenceException;
44import static org.testng.Assert.assertEquals;
45import static jdk.jshell.Snippet.Status.*;
46import static jdk.jshell.Snippet.SubKind.*;
47import static org.testng.Assert.assertTrue;
48
49@Test
50public class ReplaceTest extends KullaTesting {
51
52    public void testRedefine() {
53        Snippet vx = varKey(assertEval("int x;"));
54        Snippet mu = methodKey(assertEval("int mu() { return x * 4; }"));
55        Snippet c = classKey(assertEval("class C { String v() { return \"#\" + mu(); } }"));
56        assertEval("C c0  = new C();");
57        assertEval("c0.v();", "\"#0\"");
58        assertEval("int x = 10;", "10",
59                ste(MAIN_SNIPPET, VALID, VALID, false, null),
60                ste(vx, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
61        assertEval("c0.v();", "\"#40\"");
62        assertEval("C c = new C();");
63        assertEval("c.v();", "\"#40\"");
64        assertEval("int mu() { return x * 3; }",
65                ste(MAIN_SNIPPET, VALID, VALID, false, null),
66                ste(mu, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
67        assertEval("c.v();", "\"#30\"");
68        assertEval("class C { String v() { return \"@\" + mu(); } }",
69                ste(MAIN_SNIPPET, VALID, VALID, false, null),
70                ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
71        assertEval("c0.v();", "\"@30\"");
72        assertEval("c = new C();");
73        assertEval("c.v();", "\"@30\"");
74        assertActiveKeys();
75    }
76
77    public void testReplaceClassToVar() {
78        Snippet oldA = classKey(assertEval("class A { public String toString() { return \"old\"; } }"));
79        Snippet v = varKey(assertEval("A a = new A();", "old"));
80        assertEval("a;", "old");
81        Snippet midA = classKey(assertEval("class A { public String toString() { return \"middle\"; } }",
82                ste(MAIN_SNIPPET, VALID, VALID, false, null),
83                ste(oldA, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
84        assertEval("a;", "middle");
85        assertEval("class A { int x; public String toString() { return \"new\"; } }",
86                ste(MAIN_SNIPPET, VALID, VALID, true, null),
87                ste(midA, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
88                ste(v, VALID, VALID, true, MAIN_SNIPPET));
89        assertEval("a;", "null");
90        assertActiveKeys();
91    }
92
93    public void testReplaceVarToMethod() {
94        Snippet x = varKey(assertEval("int x;"));
95        Snippet musn = methodKey(assertEval("double mu() { return x * 4; }"));
96        assertEval("x == 0;", "true");
97        assertEval("mu() == 0.0;", "true");
98        assertEval("double x = 2.5;",
99                ste(MAIN_SNIPPET, VALID, VALID, true, null),
100                ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
101        Collection<MethodSnippet> meths = getState().methods();
102        assertEquals(meths.size(), 1);
103        assertTrue(musn == meths.iterator().next(), "Identity must not change");
104        assertEval("x == 2.5;", "true");
105        assertEval("mu() == 10.0;", "true");  // Auto redefine
106        assertActiveKeys();
107    }
108
109    public void testReplaceMethodToMethod() {
110        Snippet a = methodKey(assertEval("double a() { return 2; }"));
111        Snippet b = methodKey(assertEval("double b() { return a() * 10; }"));
112        assertEval("double c() { return b() * 3; }");
113        assertEval("double d() { return c() + 1000; }");
114        assertEval("d();", "1060.0");
115        assertEval("int a() { return 5; }",
116                ste(MAIN_SNIPPET, VALID, VALID, true, null),
117                ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
118        assertEval("d();", "1150.0");
119        assertActiveKeys();
120    }
121
122    public void testReplaceClassToMethod() {
123        Snippet c = classKey(assertEval("class C { int f() { return 7; } }"));
124        Snippet m = methodKey(assertEval("int m() { return new C().f(); }"));
125        assertEval("m();", "7");
126        assertEval("class C { int x = 99; int f() { return x; } }",
127                ste(MAIN_SNIPPET, VALID, VALID, true, null),
128                ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
129        assertEval("m();", "99");
130        assertActiveKeys();
131    }
132
133    public void testReplaceVarToClass() {
134        Snippet x = varKey(assertEval("int x;"));
135        Snippet c = classKey(assertEval("class A { double a = 4 * x; }"));
136        assertEval("x == 0;", "true");
137        assertEval("new A().a == 0.0;", "true");
138        assertEval("double x = 2.5;",
139                ste(MAIN_SNIPPET, VALID, VALID, true, null),
140                ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
141        Collection<TypeDeclSnippet> classes = getState().types();
142        assertEquals(classes.size(), 1);
143        assertTrue(c == classes.iterator().next(), "Identity must not change");
144        assertEval("x == 2.5;", "true");
145        assertEval("new A().a == 10.0;", "true");
146        assertActiveKeys();
147    }
148
149    public void testReplaceMethodToClass() {
150        Snippet x = methodKey(assertEval("int x() { return 0; }"));
151        Snippet c = classKey(assertEval("class A { double a = 4 * x(); }"));
152        assertEval("x() == 0;", "true");
153        assertEval("new A().a == 0.0;", "true");
154        assertEval("double x() { return 2.5; }",
155                ste(MAIN_SNIPPET, VALID, VALID, true, null),
156                ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
157        assertEval("x();", "2.5");
158        Collection<TypeDeclSnippet> classes = getState().types();
159        assertEquals(classes.size(), 1);
160        assertTrue(c == classes.iterator().next(), "Identity must not change");
161        assertEval("x() == 2.5;", "true");
162        assertEval("new A().a == 10.0;", "true");
163        assertActiveKeys();
164    }
165
166    public void testReplaceClassToClass() {
167        TypeDeclSnippet a = classKey(assertEval("class A {}"));
168        assertTypeDeclSnippet(a, "A", VALID, CLASS_SUBKIND, 0, 0);
169        TypeDeclSnippet b = classKey(assertEval("class B extends A {}"));
170        TypeDeclSnippet c = classKey(assertEval("class C extends B {}"));
171        TypeDeclSnippet d = classKey(assertEval("class D extends C {}"));
172        assertEval("class A { int x; public String toString() { return \"NEW\"; } }",
173                ste(MAIN_SNIPPET, VALID, VALID, true, null),
174                ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
175                ste(b, VALID, VALID, true, MAIN_SNIPPET),
176                ste(c, VALID, VALID, true, b),
177                ste(d, VALID, VALID, true, c));
178        assertTypeDeclSnippet(b, "B", VALID, CLASS_SUBKIND, 0, 0);
179        assertTypeDeclSnippet(c, "C", VALID, CLASS_SUBKIND, 0, 0);
180        assertTypeDeclSnippet(d, "D", VALID, CLASS_SUBKIND, 0, 0);
181        assertEval("new D();", "NEW");
182        assertActiveKeys();
183    }
184
185    public void testOverwriteReplaceMethod() {
186        MethodSnippet k1 = methodKey(assertEval("String m(Integer i) { return i.toString(); }"));
187        MethodSnippet k2 = methodKey(assertEval("String m(java.lang.Integer i) { return \"java.lang.\" + i.toString(); }",
188                ste(MAIN_SNIPPET, VALID, VALID, true, null),
189                ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
190        assertMethodDeclSnippet(k1, "m", "(Integer)String", OVERWRITTEN, 0, 0);
191        assertEval("m(6);", "\"java.lang.6\"");
192        assertEval("String m(Integer i) { return i.toString(); }",
193                ste(MAIN_SNIPPET, VALID, VALID, true, null),
194                ste(k2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
195        assertMethodDeclSnippet(k2, "m", "(java.lang.Integer)String", OVERWRITTEN, 0, 0);
196        assertEval("m(6);", "\"6\"");
197        assertActiveKeys();
198    }
199
200    public void testOverwriteMethodForwardReferenceClass() {
201        Snippet k1 = methodKey(assertEval("int q(Boo b) { return b.x; }",
202                added(RECOVERABLE_NOT_DEFINED)));
203        assertUnresolvedDependencies1((MethodSnippet) k1, RECOVERABLE_NOT_DEFINED, "class Boo");
204        assertEval("class Boo { int x = 55; }",
205                added(VALID),
206                ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
207        assertMethodDeclSnippet((MethodSnippet) k1, "q", "(Boo)int", VALID, 0, 0);
208        assertEval("q(new Boo());", "55");
209        assertActiveKeys();
210    }
211
212    public void testOverwriteMethodForwardReferenceClassImport() {
213        MethodSnippet k1 = methodKey(assertEval("int ff(List lis) { return lis.size(); }",
214                added(RECOVERABLE_NOT_DEFINED)));
215        assertUnresolvedDependencies1(k1, RECOVERABLE_NOT_DEFINED, "class List");
216        assertEval("import java.util.*;",
217                added(VALID),
218                ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
219        assertMethodDeclSnippet(k1, "ff", "(List)int", VALID, 0, 0);
220        assertEval("ff(new ArrayList());", "0");
221        assertActiveKeys();
222    }
223
224    public void testForwardVarToMethod() {
225        DeclarationSnippet t = methodKey(assertEval("int t() { return x; }", added(RECOVERABLE_DEFINED)));
226        assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "variable x");
227        assertEvalUnresolvedException("t();", "t", 1, 0);
228        Snippet x = varKey(assertEval("int x = 33;", "33",
229                added(VALID),
230                ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
231        assertEval("t();", "33");
232        assertEval("double x = 0.88;",
233                "0.88", null,
234                DiagCheck.DIAG_OK,
235                DiagCheck.DIAG_ERROR,
236                ste(MAIN_SNIPPET, VALID, VALID, true, null),
237                ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
238                ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
239        assertEvalUnresolvedException("t();", "t", 0, 1);
240        assertActiveKeys();
241    }
242
243    public void testForwardMethodToMethod() {
244        Snippet t = methodKey(assertEval("int t() { return f(); }", added(RECOVERABLE_DEFINED)));
245        Snippet f = methodKey(assertEval("int f() { return g(); }",
246                added(RECOVERABLE_DEFINED),
247                ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
248        assertUnresolvedDependencies1((DeclarationSnippet) f, RECOVERABLE_DEFINED, "method g()");
249        assertEvalUnresolvedException("t();", "f", 1, 0);
250        Snippet g = methodKey(assertEval("int g() { return 55; }",
251                added(VALID),
252                ste(f, RECOVERABLE_DEFINED, VALID, false, null)));
253        assertEval("t();", "55");
254        assertEval("double g() { return 3.14159; }",
255                DiagCheck.DIAG_OK,
256                DiagCheck.DIAG_ERROR,
257                ste(MAIN_SNIPPET, VALID, VALID, true, null),
258                ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
259                ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
260        DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1);
261        assertTrue(exsn == f, "Identity must not change");
262        assertActiveKeys();
263    }
264
265    public void testForwardClassToMethod() {
266        DeclarationSnippet t = methodKey(assertEval("int t() { return new A().f(); }", added(RECOVERABLE_DEFINED)));
267        assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "class A");
268        assertEvalUnresolvedException("t();", "t", 1, 0);
269        Snippet a = classKey(assertEval(
270                "class A {\n" +
271                        "   int f() { return 10; }\n" +
272                "}",
273                added(VALID),
274                ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
275        assertEval("t();", "10");
276        assertEval(
277                "class A {\n" +
278                "   double f() { return 88.0; }\n" +
279                "}",
280                DiagCheck.DIAG_OK,
281                DiagCheck.DIAG_ERROR,
282                ste(MAIN_SNIPPET, VALID, VALID, true, null),
283                ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
284                ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
285        assertEvalUnresolvedException("t();", "t", 0, 1);
286        assertActiveKeys();
287    }
288
289    public void testForwardVarToClass() {
290        DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED)));
291        assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
292        Snippet g = varKey(assertEval("int g = 10;", "10",
293                added(VALID),
294                ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
295        assertEval("new A().f();", "10");
296        assertEval("double g = 10;", "10.0", null,
297                DiagCheck.DIAG_OK,
298                DiagCheck.DIAG_ERROR,
299                ste(MAIN_SNIPPET, VALID, VALID, true, null),
300                ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
301                ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
302        assertUnresolvedDependencies(a, 0);
303        assertActiveKeys();
304    }
305
306    public void testForwardVarToClassGeneric() {
307        DeclarationSnippet a = classKey(assertEval("class A<T> { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED)));
308        assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
309
310        List<SnippetEvent> events = assertEval("A<String> as = new A<>(\"hi\");", null,
311                UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null);
312        SnippetEvent ste = events.get(0);
313        Snippet assn = ste.snippet();
314        DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
315        assertEquals(unsn.name(), "A", "Wrong with unresolved");
316        assertEquals(getState().unresolvedDependencies(unsn).size(), 1, "Wrong size unresolved");
317        assertEquals(getState().diagnostics(unsn).size(), 0, "Expected no diagnostics");
318
319        Snippet g = varKey(assertEval("int g = 10;", "10",
320                added(VALID),
321                ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
322        assertEval("A<String> as = new A<>(\"low\");",
323                ste(MAIN_SNIPPET, VALID, VALID, false, null),
324                ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
325        assertEval("as.get();", "\"low\"");
326        assertUnresolvedDependencies(a, 0);
327        assertActiveKeys();
328    }
329
330   public void testForwardVarToClassExtendsImplements() {
331        DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID)));
332        DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID)));
333        DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID)));
334        DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED)));
335        DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID)));
336        assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g");
337        assertEvalUnresolvedException("new D();", "D", 1, 0);
338        assertEvalUnresolvedException("new E();", "D", 1, 0);
339        VarSnippet g = varKey(assertEval("int g = 10;", "10",
340                added(VALID),
341                ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
342        assertEval("E e = new E();");
343        assertDrop(g,
344                ste(g, VALID, DROPPED, true, null),
345                ste(dk, VALID, RECOVERABLE_DEFINED, false, g));
346        assertEvalUnresolvedException("new D();", "D", 1, 0);
347        assertEvalUnresolvedException("new E();", "D", 1, 0);
348        assertEval("e.ee();", "5");
349        assertEvalUnresolvedException("e.dd();", "D", 1, 0);
350        assertEval("e.cc();", "3");
351        assertEval("e.jj();", "2");
352        assertEval("e.ii();", "1");
353        assertActiveKeys();
354    }
355
356    public void testForwardVarToInterface() {
357        DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED)));
358        assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x");
359        DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID)));
360        assertEval("C c = new C();");
361        assertEval("c.z();", "2");
362        assertEvalUnresolvedException("c.f()", "I", 1, 0);
363        Snippet g = varKey(assertEval("int x = 55;", "55",
364                added(VALID),
365                ste(i, RECOVERABLE_DEFINED, VALID, false, null)));
366        assertEval("c.f();", "55");
367        assertUnresolvedDependencies(i, 0);
368        assertActiveKeys();
369    }
370
371    public void testForwardVarToEnum() {
372        DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_DEFINED)));
373        assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable fff");
374        Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5",
375                added(VALID),
376                ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
377        assertEval("E.Q.ff();", "4.5");
378        assertEval("double fff = 3.3;", "3.3", null,
379                DiagCheck.DIAG_OK,
380                DiagCheck.DIAG_ERROR,
381                ste(MAIN_SNIPPET, VALID, VALID, true, null),
382                ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
383                ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
384        assertUnresolvedDependencies(a, 0);
385        assertActiveKeys();
386    }
387
388    public void testForwardMethodToClass() {
389        DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED)));
390        assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()");
391        assertEval("A foo() { return null; }");
392        assertEvalUnresolvedException("new A();", "A", 1, 0);
393        Snippet g = methodKey(assertEval("int g() { return 10; }",
394                added(VALID),
395                ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
396        assertEval("new A().f();", "10");
397        assertEval("double g() { return 10; }",
398                DiagCheck.DIAG_OK,
399                DiagCheck.DIAG_ERROR,
400                ste(MAIN_SNIPPET, VALID, VALID, true, null),
401                ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
402                ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
403        assertUnresolvedDependencies(a, 0);
404        assertActiveKeys();
405    }
406
407    public void testForwardClassToClass1() {
408        Snippet a = classKey(assertEval("class A { B b = new B(); }", added(RECOVERABLE_NOT_DEFINED)));
409        assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location");
410
411        Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
412                added(VALID),
413                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
414        assertEval("new A().b;", "B");
415        assertEval("interface B { }",
416                DiagCheck.DIAG_OK,
417                DiagCheck.DIAG_ERROR,
418                ste(MAIN_SNIPPET, VALID, VALID, true, null),
419                ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
420                ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET));
421        assertEvalUnresolvedException("new A().b;", "A", 0, 1);
422        assertActiveKeys();
423    }
424
425    public void testForwardClassToClass2() {
426        Snippet a = classKey(assertEval("class A extends B { }", added(RECOVERABLE_NOT_DEFINED)));
427        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
428
429        Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
430                added(VALID),
431                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
432        assertEval("new A();", "B");
433        assertEval("interface B { }",
434                DiagCheck.DIAG_OK,
435                DiagCheck.DIAG_ERROR,
436                ste(MAIN_SNIPPET, VALID, VALID, true, null),
437                ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
438                ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
439        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
440        assertActiveKeys();
441    }
442
443    public void testForwardClassToClass3() {
444        Snippet a = classKey(assertEval("interface A extends B { static int f() { return 10; } }", added(RECOVERABLE_NOT_DEFINED)));
445        assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
446
447        Snippet b = classKey(assertEval("interface B { }",
448                added(VALID),
449                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
450        assertEval("A.f();", "10");
451        assertEval("class B { }",
452                DiagCheck.DIAG_OK,
453                DiagCheck.DIAG_ERROR,
454                ste(MAIN_SNIPPET, VALID, VALID, true, null),
455                ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
456                ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
457        assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
458        assertActiveKeys();
459    }
460
461    public void testImportDeclare() {
462        Snippet singleImport = importKey(assertEval("import java.util.List;", added(VALID)));
463        Snippet importOnDemand = importKey(assertEval("import java.util.*;", added(VALID)));
464        Snippet singleStaticImport = importKey(assertEval("import static java.lang.Math.abs;", added(VALID)));
465        Snippet staticImportOnDemand = importKey(assertEval("import static java.lang.Math.*;", added(VALID)));
466        assertEval("import java.util.List; //again",
467                ste(MAIN_SNIPPET, VALID, VALID, false, null),
468                ste(singleImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
469        assertEval("import java.util.*; //again",
470                ste(MAIN_SNIPPET, VALID, VALID, false, null),
471                ste(importOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
472        assertEval("import static java.lang.Math.abs; //again",
473                ste(MAIN_SNIPPET, VALID, VALID, false, null),
474                ste(singleStaticImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
475        assertEval("import static java.lang.Math.*; //again",
476                ste(MAIN_SNIPPET, VALID, VALID, false, null),
477                ste(staticImportOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
478        assertActiveKeys();
479    }
480
481    public void testForwardVariable() {
482        assertEval("int f() { return x; }", added(RECOVERABLE_DEFINED));
483        assertEvalUnresolvedException("f();", "f", 1, 0);
484        assertActiveKeys();
485    }
486
487    public void testLocalClassInUnresolved() {
488        Snippet f = methodKey(assertEval("void f() { class A {} g(); }", added(RECOVERABLE_DEFINED)));
489        assertEval("void g() {}",
490                added(VALID),
491                ste(f, RECOVERABLE_DEFINED, VALID, false, null));
492        assertEval("f();", "");
493    }
494
495    @Test(enabled = false) // TODO 8129420
496    public void testLocalClassEvolve() {
497        Snippet j = methodKey(assertEval("Object j() { return null; }", added(VALID)));
498        assertEval("Object j() { class B {}; return null; }",
499                ste(MAIN_SNIPPET, VALID, VALID, false, null));
500        assertEval("Object j() { class B {}; return new B(); }",
501                ste(MAIN_SNIPPET, VALID, VALID, false, null));
502        assertEval("j().getClass().getSimpleName();", "\"B\"");
503        assertEval("Object j() { class B { int p; public String toString() { return \"Yep\";} }; return new B(); }",
504                ste(MAIN_SNIPPET, VALID, VALID, false, null));
505        assertEval("j().getClass().getSimpleName();", "\"B\"");
506        assertEval("j();", "Yep");
507    }
508
509    public void testForwardSingleImportMethodToMethod() {
510        DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
511                added(RECOVERABLE_DEFINED)));
512        assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
513        assertEvalUnresolvedException("string();", "string", 1, 0);
514        assertEval("import static java.lang.String.format;",
515                added(VALID),
516                ste(string, RECOVERABLE_DEFINED, VALID, false, null));
517        assertEval("string();", "\"string\"");
518
519        assertEval("double format(String s) { return 0; }",
520                DiagCheck.DIAG_OK,
521                DiagCheck.DIAG_ERROR,
522                added(VALID),
523                ste(string, VALID, RECOVERABLE_DEFINED, false, null));
524        assertEvalUnresolvedException("string();", "string", 0, 1);
525        assertActiveKeys();
526    }
527
528    public void testForwardImportMethodOnDemandToMethod() {
529        DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
530                added(RECOVERABLE_DEFINED)));
531        assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
532        assertEvalUnresolvedException("string();", "string", 1, 0);
533        assertEval("import static java.lang.String.*;",
534                added(VALID),
535                ste(string, RECOVERABLE_DEFINED, VALID, false, null));
536        assertEval("string();", "\"string\"");
537
538        assertEval("double format(String s) { return 0; }",
539                DiagCheck.DIAG_OK,
540                DiagCheck.DIAG_ERROR,
541                added(VALID),
542                ste(string, VALID, RECOVERABLE_DEFINED, false, null));
543        assertEvalUnresolvedException("string();", "string", 0, 1);
544        assertActiveKeys();
545    }
546
547    public void testForwardSingleImportFieldToMethod() {
548        DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
549                added(RECOVERABLE_DEFINED)));
550        assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
551        assertEvalUnresolvedException("pi();", "pi", 1, 0);
552        assertEval("import static java.lang.Math.PI;",
553                added(VALID),
554                ste(pi, RECOVERABLE_DEFINED, VALID, false, null));
555        assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
556
557        assertEval("String PI;",
558                DiagCheck.DIAG_OK,
559                DiagCheck.DIAG_ERROR,
560                added(VALID),
561                ste(pi, VALID, RECOVERABLE_DEFINED, false, null));
562        assertEvalUnresolvedException("pi();", "pi", 0, 1);
563        assertActiveKeys();
564    }
565
566    public void testForwardImportFieldOnDemandToMethod() {
567        DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
568                added(RECOVERABLE_DEFINED)));
569        assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
570        assertEvalUnresolvedException("pi();", "pi", 1, 0);
571        assertEval("import static java.lang.Math.*;",
572                added(VALID),
573                ste(pi, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET));
574        assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
575
576        assertEval("String PI;",
577                DiagCheck.DIAG_OK,
578                DiagCheck.DIAG_ERROR,
579                added(VALID),
580                ste(pi, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
581        assertEvalUnresolvedException("pi();", "pi", 0, 1);
582        assertActiveKeys();
583    }
584
585    public void testForwardSingleImportMethodToClass1() {
586        PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
587                added(RECOVERABLE_DEFINED)));
588        assertEvalUnresolvedException("new A();", "A", 1, 0);
589        assertEval("import static java.lang.String.format;",
590                added(VALID),
591                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
592        assertEval("new A().s;", "\"10\"");
593        PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }",
594                DiagCheck.DIAG_OK,
595                DiagCheck.DIAG_ERROR,
596                added(VALID),
597                ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)));
598        assertEvalUnresolvedException("new A();", "A", 0, 1);
599        assertActiveKeys();
600        assertDrop(format,
601                ste(format, VALID, DROPPED, true, null),
602                ste(a, RECOVERABLE_DEFINED, VALID, false, format));
603    }
604
605    public void testForwardSingleImportMethodToClass2() {
606        PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
607                added(RECOVERABLE_DEFINED)));
608        assertEvalUnresolvedException("new A();", "A", 1, 0);
609        assertEval("import static java.lang.String.format;",
610                added(VALID),
611                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
612        assertEval("new A().s();", "\"10\"");
613        PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }",
614                DiagCheck.DIAG_OK,
615                DiagCheck.DIAG_ERROR,
616                added(VALID),
617                ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
618        assertEvalUnresolvedException("new A();", "A", 0, 1);
619        assertActiveKeys();
620        assertDrop(format,
621                ste(format, VALID, DROPPED, true, null),
622                ste(a, RECOVERABLE_DEFINED, VALID, false, format));
623    }
624
625    public void testForwardSingleImportClassToClass1() {
626        PersistentSnippet a = classKey(assertEval("class A { static List<Integer> list; }",
627                added(RECOVERABLE_NOT_DEFINED)));
628        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
629        assertEval("import java.util.List;",
630                added(VALID),
631                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
632        assertEval("import java.util.Arrays;", added(VALID));
633        assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
634
635        PersistentSnippet list = classKey(assertEval("class List {}",
636                DiagCheck.DIAG_OK,
637                DiagCheck.DIAG_ERROR,
638                added(VALID),
639                ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
640        assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
641        assertActiveKeys();
642        assertDrop(list,
643                ste(list, VALID, DROPPED, true, null),
644                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
645    }
646
647    public void testForwardSingleImportClassToClass2() {
648        PersistentSnippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
649                added(RECOVERABLE_NOT_DEFINED)));
650        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
651        assertEval("import java.util.ArrayList;",
652                added(VALID),
653                ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
654        Snippet vara = varKey(assertEval("A a = new A();", "[]"));
655
656        PersistentSnippet arraylist = classKey(assertEval("class ArrayList {}",
657                DiagCheck.DIAG_OK,
658                DiagCheck.DIAG_ERROR,
659                added(VALID),
660                ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
661                ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
662        assertDeclareFail("A a = new A();", "compiler.err.cant.resolve.location",
663                ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, REJECTED, false, null),
664                ste(vara, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET));
665        assertActiveKeys();
666        assertDrop(arraylist,
667                ste(arraylist, VALID, DROPPED, true, null),
668                ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist));
669    }
670
671    public void testForwardImportOnDemandMethodToClass1() {
672        PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
673                added(RECOVERABLE_DEFINED)));
674        assertEvalUnresolvedException("new A();", "A", 1, 0);
675        assertEval("import static java.lang.String.*;",
676                added(VALID),
677                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
678        assertEval("A x = new A();");
679        assertEval("x.s;", "\"10\"");
680        PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }",
681                DiagCheck.DIAG_OK,
682                DiagCheck.DIAG_ERROR,
683                added(VALID),
684                ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
685        assertEvalUnresolvedException("new A();", "A", 0, 1);
686        assertActiveKeys();
687        assertDrop(format,
688                ste(format, VALID, DROPPED, true, null),
689                ste(a, RECOVERABLE_DEFINED, VALID, false, format));
690        assertEval("x.s;", "\"10\"");
691    }
692
693    public void testForwardImportOnDemandMethodToClass2() {
694        PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
695                added(RECOVERABLE_DEFINED)));
696        assertEvalUnresolvedException("new A();", "A", 1, 0);
697        assertEval("import static java.lang.String.*;",
698                added(VALID),
699                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
700        assertEval("new A().s();", "\"10\"");
701        PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }",
702                DiagCheck.DIAG_OK,
703                DiagCheck.DIAG_ERROR,
704                added(VALID),
705                ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
706        assertEvalUnresolvedException("new A();", "A", 0, 1);
707        assertActiveKeys();
708        assertDrop(format,
709                ste(format, VALID, DROPPED, true, null),
710                ste(a, RECOVERABLE_DEFINED, VALID, false, format));
711    }
712
713    public void testForwardImportOnDemandClassToClass1() {
714        PersistentSnippet a = classKey(assertEval("class A { static List<Integer> list; }",
715                added(RECOVERABLE_NOT_DEFINED)));
716        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
717        assertEval("import java.util.*;",
718                added(VALID),
719                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
720        assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
721
722        PersistentSnippet list = classKey(assertEval("class List {}",
723                DiagCheck.DIAG_OK,
724                DiagCheck.DIAG_ERROR,
725                added(VALID),
726                ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
727        assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.cant.resolve.location");
728        assertActiveKeys();
729        assertDrop(list,
730                ste(list, VALID, DROPPED, true, null),
731                ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
732    }
733
734    public void testForwardImportOnDemandClassToClass2() {
735        PersistentSnippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
736                added(RECOVERABLE_NOT_DEFINED)));
737        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
738        assertEval("import java.util.*;",
739                added(VALID),
740                ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
741        Snippet vara = varKey(assertEval("A a = new A();", "[]"));
742
743        PersistentSnippet arraylist = classKey(assertEval("class ArrayList {}",
744                DiagCheck.DIAG_OK,
745                DiagCheck.DIAG_ERROR,
746                added(VALID),
747                ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
748                ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
749        assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
750        assertActiveKeys();
751        assertDrop(arraylist,
752                ste(arraylist, VALID, DROPPED, true, null),
753                ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist),
754                ste(vara, RECOVERABLE_NOT_DEFINED, VALID, true, clsA));
755    }
756
757    public void testForwardSingleImportFieldToClass1() {
758        PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
759                added(RECOVERABLE_DEFINED)));
760        assertEvalUnresolvedException("new A();", "A", 1, 0);
761        assertEval("import static java.lang.Math.PI;",
762                added(VALID),
763                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
764        assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
765
766        PersistentSnippet list = varKey(assertEval("String PI;",
767                DiagCheck.DIAG_OK,
768                DiagCheck.DIAG_ERROR,
769                added(VALID),
770                ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
771        assertEvalUnresolvedException("new A();", "A", 0, 1);
772        assertActiveKeys();
773        assertDrop(list,
774                ste(list, VALID, DROPPED, true, null),
775                ste(a, RECOVERABLE_DEFINED, VALID, false, list));
776    }
777
778    public void testForwardSingleImportFieldToClass2() {
779        PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }",
780                added(RECOVERABLE_DEFINED)));
781        assertEvalUnresolvedException("new A();", "A", 1, 0);
782        assertEval("import static java.lang.Math.PI;",
783                added(VALID),
784                ste(a, RECOVERABLE_DEFINED, VALID, true, null));
785        assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
786
787        PersistentSnippet list = varKey(assertEval("String PI;",
788                DiagCheck.DIAG_OK,
789                DiagCheck.DIAG_ERROR,
790                added(VALID),
791                ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
792        assertEvalUnresolvedException("new A();", "A", 0, 1);
793        assertActiveKeys();
794        assertDrop(list,
795                ste(list, VALID, DROPPED, true, null),
796                ste(a, RECOVERABLE_DEFINED, VALID, true, list));
797    }
798
799    public void testForwardImportOnDemandFieldToClass1() {
800        PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
801                added(RECOVERABLE_DEFINED)));
802        assertEvalUnresolvedException("new A();", "A", 1, 0);
803        assertEval("import static java.lang.Math.*;",
804                added(VALID),
805                ste(a, RECOVERABLE_DEFINED, VALID, false, null));
806        assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
807
808        PersistentSnippet list = varKey(assertEval("String PI;",
809                DiagCheck.DIAG_OK,
810                DiagCheck.DIAG_ERROR,
811                added(VALID),
812                ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
813        assertEvalUnresolvedException("new A();", "A", 0, 1);
814        assertActiveKeys();
815        assertDrop(list,
816                ste(list, VALID, DROPPED, true, null),
817                ste(a, RECOVERABLE_DEFINED, VALID, false, list));
818    }
819
820    public void testForwardImportOnDemandFieldToClass2() {
821        PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }",
822                added(RECOVERABLE_DEFINED)));
823        assertEvalUnresolvedException("new A();", "A", 1, 0);
824        assertEval("import static java.lang.Math.*;",
825                added(VALID),
826                ste(a, RECOVERABLE_DEFINED, VALID, true, null));
827        assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
828
829        PersistentSnippet list = varKey(assertEval("String PI;",
830                DiagCheck.DIAG_OK,
831                DiagCheck.DIAG_ERROR,
832                added(VALID),
833                ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
834        assertEvalUnresolvedException("new A();", "A", 0, 1);
835        assertActiveKeys();
836        assertDrop(list,
837                ste(list, VALID, DROPPED, true, null),
838                ste(a, RECOVERABLE_DEFINED, VALID, true, list));
839        assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
840    }
841
842    public void testReplaceCausesMethodReferenceError() {
843        Snippet l = classKey(assertEval("interface Logger { public void log(String message); }", added(VALID)));
844        Snippet v = varKey(assertEval("Logger l = System.out::println;", added(VALID)));
845        assertEval("interface Logger { public boolean accept(String message);  }",
846                DiagCheck.DIAG_OK,
847                DiagCheck.DIAG_ERROR,
848                ste(MAIN_SNIPPET, VALID, VALID, true, null),
849                ste(l, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
850                ste(v, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
851    }
852
853    public void testReplaceCausesClassCompilationError() {
854        Snippet l = classKey(assertEval("interface L { }", added(VALID)));
855        Snippet c = classKey(assertEval("class C implements L { }", added(VALID)));
856        assertEval("interface L { void m(); }",
857                DiagCheck.DIAG_OK,
858                DiagCheck.DIAG_ERROR,
859                ste(MAIN_SNIPPET, VALID, VALID, true, null),
860                ste(l, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
861                ste(c, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
862    }
863
864    public void testOverwriteNoUpdate() {
865        String xsi = "int x = 5;";
866        String xsd = "double x = 3.14159;";
867        VarSnippet xi = varKey(assertEval(xsi, added(VALID)));
868        String ms1 = "double m(Integer i) { return i + x; }";
869        String ms2 = "double m(java.lang.Integer i) { return i + x; }";
870        MethodSnippet k1 = methodKey(assertEval(ms1, added(VALID)));
871        VarSnippet xd = varKey(assertEval(xsd,
872                ste(MAIN_SNIPPET, VALID, VALID, true, null),
873                ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
874        MethodSnippet k2 = methodKey(assertEval(ms2,
875                ste(MAIN_SNIPPET, VALID, VALID, true, null), //TODO: technically, should be false
876                ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
877        VarSnippet xi2 = varKey(assertEval(xsi,
878                ste(MAIN_SNIPPET, VALID, VALID, true, null),
879                ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
880        varKey(assertEval(xsd,
881                ste(MAIN_SNIPPET, VALID, VALID, true, null),
882                ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
883    }
884}
885