1 /*
   2  * Copyright (c) 2015, 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 8080357
  27  * @summary Tests for EvaluationState.methods
  28  * @build KullaTesting TestingInputStream ExpectedDiagnostic
  29  * @run testng MethodsTest
  30  */
  31 
  32 import javax.tools.Diagnostic;
  33 
  34 import jdk.jshell.Snippet;
  35 import jdk.jshell.MethodSnippet;
  36 import jdk.jshell.Snippet.Status;
  37 import org.testng.annotations.Test;
  38 
  39 import static jdk.jshell.Snippet.Status.*;
  40 
  41 @Test
  42 public class MethodsTest extends KullaTesting {
  43 
  44     public void noMethods() {
  45         assertNumberOfActiveMethods(0);
  46     }
  47 
  48     public void testSignature1() {
  49         MethodSnippet m1 = methodKey(assertEval("void f() { g(); }", added(RECOVERABLE_DEFINED)));
  50         assertMethodDeclSnippet(m1, "f", "()void", RECOVERABLE_DEFINED, 1, 0);
  51         MethodSnippet m2 = methodKey(assertEval("void g() { }",
  52                 added(VALID),
  53                 ste(m1, RECOVERABLE_DEFINED, VALID, false, null)));
  54         assertMethodDeclSnippet(m2, "g", "()void", VALID, 0, 0);
  55     }
  56 
  57     public void testSignature2() {
  58         MethodSnippet m1 = (MethodSnippet) assertDeclareFail("void f() { return g(); }", "compiler.err.prob.found.req");
  59         assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2);
  60         MethodSnippet m2 = methodKey(assertEval("int f() { return g(); }",
  61                 ste(m1, REJECTED, RECOVERABLE_DEFINED, true, null)));
  62         assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2);
  63         assertMethodDeclSnippet(m2, "f", "()int", RECOVERABLE_DEFINED, 1, 0);
  64     }
  65 
  66     @Test(enabled = false) // TODO 8081690
  67     public void testSignature3() {
  68         MethodSnippet m1 = methodKey(assertEval("void f(Bar b) { }", added(RECOVERABLE_NOT_DEFINED)));
  69         assertMethodDeclSnippet(m1, "f", "(Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
  70         MethodSnippet m2 = methodKey(assertEval("void f(A.Bar b) { }", added(RECOVERABLE_NOT_DEFINED)));
  71         assertMethodDeclSnippet(m1, "f", "(Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
  72         assertMethodDeclSnippet(m2, "f", "(A.Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
  73         assertDrop(m1, ste(m1, RECOVERABLE_NOT_DEFINED, DROPPED, false, null));
  74         assertMethodDeclSnippet(m1, "f", "(Bar)void", DROPPED, 1, 0);
  75     }
  76     
  77     // 8080357
  78     public void testNonReplUnresolved() {
  79         // internal case
  80         assertEval("class CCC {}", added(VALID));
  81         assertEval("void f1() { CCC.xxxx(); }", added(RECOVERABLE_DEFINED));
  82         // external case, not recoverable
  83         assertDeclareFail("void f2() { System.xxxx(); }", "compiler.err.cant.resolve.location.args");
  84     }
  85 
  86     public void methods() {
  87         assertEval("int x() { return 10; }");
  88         assertEval("String y() { return null; }");
  89         assertEval("long z() { return 0; }");
  90         assertMethods(method("()int", "x"), method("()String", "y"), method("()long", "z"));
  91         assertActiveKeys();
  92     }
  93 
  94     public void methodOverload() {
  95         assertEval("int m() { return 1; }");
  96         assertEval("int m(int x) { return 2; }");
  97         assertEval("int m(String s) { return 3; }");
  98         assertEval("int m(int x, int y) { return 4; }");
  99         assertEval("int m(int x, String z) { return 5; }");
 100         assertEval("int m(int x, String z, long g) { return 6; }");
 101         assertMethods(
 102                 method("()int", "m"),
 103                 method("(int)int", "m"),
 104                 method("(String)int", "m"),
 105                 method("(int,int)int", "m"),
 106                 method("(int,String)int", "m"),
 107                 method("(int,String,long)int", "m")
 108         );
 109         assertEval("m();", "1");
 110         assertEval("m(3);", "2");
 111         assertEval("m(\"hi\");", "3");
 112         assertEval("m(7, 8);", "4");
 113         assertEval("m(7, \"eight\");", "5");
 114         assertEval("m(7, \"eight\", 9L);", "6");
 115         assertActiveKeys();
 116     }
 117 
 118     public void methodsRedeclaration1() {
 119         Snippet x = methodKey(assertEval("int x() { return 10; }"));
 120         Snippet y = methodKey(assertEval("String y() { return \"\"; }"));
 121         assertMethods(method("()int", "x"), method("()String", "y"));
 122         assertActiveKeys();
 123 
 124         assertEval("long x() { return 0; }",
 125                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
 126                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 127         assertMethods(method("()long", "x"), method("()String", "y"));
 128         assertActiveKeys();
 129 
 130         assertEval("String y() { return null; }",
 131                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 132                 ste(y, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 133         assertMethods(method("()long", "x"), method("()String", "y"));
 134         assertActiveKeys();
 135     }
 136 
 137     public void methodsRedeclaration2() {
 138         assertEval("int a() { return 1; }");
 139         assertMethods(method("()int", "a"));
 140         assertActiveKeys();
 141 
 142         Snippet b = methodKey(assertEval("Integer b() { return a(); }"));
 143         assertMethods(method("()int", "a"), method("()Integer", "b"));
 144         assertActiveKeys();
 145 
 146         Snippet c = methodKey(assertEval("double c() { return b(); }"));
 147         assertMethods(method("()int", "a"), method("()Integer", "b"), method("()double", "c"));
 148         assertActiveKeys();
 149 
 150         assertEval("double b() { return 3.14159; }",
 151                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
 152                 ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
 153                 ste(c, VALID, VALID, false, MAIN_SNIPPET));
 154         assertMethods(method("()int", "a"), method("()double", "b"), method("()double", "c"));
 155         assertEval("c();", "3.14159");
 156         assertActiveKeys();
 157     }
 158 
 159     public void methodsRedeclaration3() {
 160         Snippet x = methodKey(assertEval("int x(Object...a) { return 10; }"));
 161         assertMethods(method("(Object...)int", "x"));
 162         assertActiveKeys();
 163 
 164         assertEval("int x(Object[]a) { return 10; }",
 165                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
 166                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 167         assertMethods(method("(Object[])int", "x"));
 168         assertActiveKeys();
 169     }
 170 
 171 
 172     public void methodsRedeclaration4() {
 173         Snippet a = methodKey(assertEval("int foo(int a) { return a; }"));
 174         assertEval("int x = foo(10);");
 175         assertActiveKeys();
 176         assertMethods(method("(int)int", "foo"));
 177         assertEval("int foo(int a) { return a * a; }",
 178                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 179                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 180         assertActiveKeys();
 181     }
 182 
 183     public void methodsErrors() {
 184         assertDeclareFail("String f();",
 185                 new ExpectedDiagnostic("compiler.err.missing.meth.body.or.decl.abstract", 0, 11, 7, -1, -1, Diagnostic.Kind.ERROR));
 186         assertNumberOfActiveMethods(0);
 187         assertActiveKeys();
 188 
 189         assertDeclareFail("abstract String f();",
 190                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 8, 0, -1, -1, Diagnostic.Kind.ERROR));
 191         assertNumberOfActiveMethods(0);
 192         assertActiveKeys();
 193 
 194         assertDeclareFail("native String f();",
 195                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.ERROR));
 196         assertNumberOfActiveMethods(0);
 197         assertActiveKeys();
 198 
 199         assertDeclareFail("synchronized String f() {return null;}",
 200                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 12, 0, -1, -1, Diagnostic.Kind.ERROR));
 201         assertNumberOfActiveMethods(0);
 202         assertActiveKeys();
 203 
 204         assertDeclareFail("int f() {}", "compiler.err.missing.ret.stmt",
 205                 ste(MAIN_SNIPPET, REJECTED, REJECTED, false, null));
 206         assertNumberOfActiveMethods(0);
 207         assertActiveKeys();
 208 
 209         assertEval("String x() { return \"\"; };");
 210         assertMethods(method("()String", "x"));
 211         assertActiveKeys();
 212     }
 213 
 214     public void methodsWarn() {
 215         Snippet f = assertDeclareWarn1("public String f() {return null;}",
 216                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
 217                 added(VALID));
 218         assertNumberOfActiveMethods(1);
 219         assertActiveKeys();
 220 
 221         f = assertDeclareWarn1("protected String f() {return null;}",
 222                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING),
 223                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 224                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 225         assertNumberOfActiveMethods(1);
 226         assertActiveKeys();
 227 
 228         f = assertDeclareWarn1("private String f() {return null;}",
 229                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 7, 0, -1, -1, Diagnostic.Kind.WARNING),
 230                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 231                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 232         assertNumberOfActiveMethods(1);
 233         assertActiveKeys();
 234 
 235         f = assertDeclareWarn1("static String f() {return null;}",
 236                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
 237                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 238                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 239         assertNumberOfActiveMethods(1);
 240         assertActiveKeys();
 241 
 242         assertDeclareWarn1("final String f() {return null;}",
 243                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING),
 244                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
 245                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
 246         assertNumberOfActiveMethods(1);
 247         assertActiveKeys();
 248     }
 249 
 250     public void methodSignatureUnresolved() {
 251         MethodSnippet key = (MethodSnippet) methodKey(assertEval("und m() { return new und(); }", added(RECOVERABLE_NOT_DEFINED)));
 252         assertMethodDeclSnippet(key, "m", "()und", RECOVERABLE_NOT_DEFINED, 1, 0);
 253         assertUnresolvedDependencies1(key, Status.RECOVERABLE_NOT_DEFINED, "class und");
 254         assertEval("class und {}",
 255                 added(VALID),
 256                 ste(key, RECOVERABLE_NOT_DEFINED, VALID, true, null));
 257         assertMethodDeclSnippet(key, "m", "()und", Status.VALID, 0, 0);
 258         assertNumberOfActiveMethods(1);
 259         assertActiveKeys();
 260     }
 261 
 262     @Test(enabled = false) // TODO 8081689
 263     public void classMethodsAreNotVisible() {
 264         assertEval(
 265             "class A {" +
 266                 "int foo() {" +
 267                     "int x = 10;" +
 268                     "int y = 2 * x;" +
 269                     "return x * y;" +
 270                 "}" +
 271             "}");
 272         assertNumberOfActiveMethods(0);
 273         assertEval("int x = 10;", "10");
 274         assertEval("int foo() {" +
 275                         "int y = 2 * x;" +
 276                         "return x * y;" +
 277                         "}");
 278         assertMethods(method("()int", "foo"));
 279         assertEval("foo();", "200");
 280         assertActiveKeys();
 281     }
 282 
 283     public void lambdas() {
 284         assertEval("class Inner1 implements Runnable {" +
 285                 "public Runnable lambda1 = () -> {};" +
 286                 "public void function() {}" +
 287                 "public void run() {}" +
 288                 "}");
 289 
 290         assertEval("class Inner2 {" +
 291                 "private Runnable lambda1 = () -> {};" +
 292                 "private static void staticFunction() {}" +
 293                 "}");
 294 
 295         // the following method references and lambda functions
 296         // generate synthetic methods
 297         assertEval("Runnable run = () -> {};");
 298         assertEval("Inner1 inner = new Inner1();");
 299         assertEval("Runnable l1 = inner::function;");
 300         assertEval("Runnable l2 = Inner1::new;");
 301         assertEval("inner.lambda1 = inner::function;");
 302         assertEval("java.util.stream.IntStream.of(2).mapToObj(int[]::new);");
 303         assertNumberOfActiveMethods(0);
 304         assertActiveKeys();
 305     }
 306 }