| /******************************************************************************* |
| * Copyright (c) 2015, 2019 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Stephan Herrmann - Contribution for |
| * Bug 446691 - [1.8][null][compiler] NullPointerException in SingleNameReference.analyseCode |
| *******************************************************************************/ |
| package org.eclipse.jdt.core.tests.compiler.regression; |
| |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.EclipseHasABug; |
| import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.JavacHasABug; |
| |
| import junit.framework.Test; |
| @SuppressWarnings({ "rawtypes" }) |
| public class LambdaRegressionTest extends AbstractRegressionTest { |
| |
| static { |
| // TESTS_NAMES = new String[] { "test001"}; |
| // TESTS_NUMBERS = new int[] { 50 }; |
| // TESTS_RANGE = new int[] { 11, -1 }; |
| } |
| public LambdaRegressionTest(String name) { |
| super(name); |
| } |
| public static Test suite() { |
| return buildMinimalComplianceTestSuite(testClass(), F_1_8); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes |
| public void test001() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.util.HashMap;\n" + |
| "import java.util.Map;\n" + |
| "import java.util.function.Function;\n" + |
| "public class X {\n" + |
| " public static void main(String[] args) {\n" + |
| " new X().run();\n" + |
| " }\n" + |
| " public void run() {\n" + |
| " class Inner {\n" + |
| " public Inner() {\n" + |
| " System.out.println(\"miep\");\n" + |
| " }\n" + |
| " }\n" + |
| " Map<String, Inner> map = new HashMap<>();\n" + |
| " Function<String, Inner> function = (name) -> {\n" + |
| " Inner i = map.get(name);\n" + |
| " if (i == null) {\n" + |
| " i = new Inner();\n" + |
| " map.put(name, i);\n" + |
| " }\n" + |
| " return i;\n" + |
| "\n" + |
| " };\n" + |
| " function.apply(\"test\");\n" + |
| " }\n" + |
| "}\n", |
| }, |
| "miep" |
| ); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes |
| public void test002() { |
| this.runNegativeTest( |
| false, |
| EclipseHasABug.EclipseBug529197, |
| new String[] { |
| "X.java", |
| "import java.util.function.Consumer;\n" + |
| "@SuppressWarnings(\"all\")\n" + |
| "public class X {\n" + |
| " private final String text = \"Bug?\";\n" + |
| " public static void main(String[] args) {\n" + |
| " new X().doIt();\n" + |
| " }\n" + |
| " private void doIt() {\n" + |
| " new Sub();\n" + |
| " }\n" + |
| " private class Super<T> {\n" + |
| " public Super(Consumer<T> consumer) {\n" + |
| " }\n" + |
| " }\n" + |
| " private class Sub extends Super<String> {\n" + |
| " public Sub() {\n" + |
| " super(s -> System.out.println(text));\n" + |
| " // super(s -> System.out.println(\"miep\"));\n" + |
| " }\n" + |
| " }\n" + |
| "}\n", |
| }, |
| "----------\n" + |
| "1. ERROR in X.java (at line 17)\n" + |
| " super(s -> System.out.println(text));\n" + |
| " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + |
| "Cannot refer to \'this\' nor \'super\' while explicitly invoking a constructor\n" + |
| "----------\n" |
| ); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes |
| public void test003() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "import java.util.function.Consumer;\n" + |
| "@SuppressWarnings(\"all\")\n" + |
| "public class X {\n" + |
| " private final String text = \"Bug?\";\n" + |
| " public static void main(String[] args) {\n" + |
| " new X().doIt();\n" + |
| " }\n" + |
| " private void doIt() {\n" + |
| " new Sub();\n" + |
| " }\n" + |
| " private class Super<T> {\n" + |
| " public Super(Consumer<T> consumer) {\n" + |
| " }\n" + |
| " }\n" + |
| " private class Sub extends Super<String> {\n" + |
| " public Sub() {\n" + |
| " super(s -> System.out.println(\"miep\"));\n" + |
| " }\n" + |
| " }\n" + |
| "}\n", |
| }, |
| "" |
| ); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes |
| public void test004() { |
| this.runConformTest( |
| false, |
| JavacHasABug.JavacThrowsAnException, |
| new String[] { |
| "Y.java", |
| "import java.util.function.Supplier;\n" + |
| "class E {\n" + |
| " E(Supplier<Object> factory) { }\n" + |
| "}\n" + |
| "public class Y extends E {\n" + |
| " Y() {\n" + |
| " super( () -> {\n" + |
| " class Z extends E {\n" + |
| " Z() {\n" + |
| " super(() -> new Object());\n" + |
| " }\n" + |
| " }\n" + |
| " return null;\n" + |
| " });\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " new Y();\n" + |
| " }\n" + |
| "}" |
| }, |
| null); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=448724, [1.8] [compiler] Wrong resolution of overloaded method when irrelevant type parameter is present and lambda is used as parameter |
| public void test448724() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.util.concurrent.Callable;\n" + |
| "public class X {\n" + |
| " public void mismatchRunnableCallable() throws Exception {\n" + |
| " //Resolves to case1(Runnable) method invocation; lambda with block\n" + |
| " case1(() -> {\"abc\".length();});\n" + |
| " //Resolves to case1(Callable) method invocation, resulting in type mismatch; block removed - lambda with expression\n" + |
| " case1(() -> \"abc\".length());\n" + |
| " }\n" + |
| " public void noSuchMismatch() throws Exception {\n" + |
| " //no difference to case1 \n" + |
| " case2(() -> {\"abc\".length();});\n" + |
| " //the only difference to case 1 is the missing irrelevant <T> type parameter. Properly resolves to case2(Runnable) here\n" + |
| " case2(() -> \"abc\".length());\n" + |
| " }\n" + |
| " public void case1(final Runnable r) {\n" + |
| " System.out.println(\"case1: Runnable\");\n" + |
| " }\n" + |
| " public <T> void case1(Callable<Boolean> c) {\n" + |
| " System.out.println(\"case1: Callable\");\n" + |
| " }\n" + |
| " public void case2(final Runnable supplier) {\n" + |
| " System.out.println(\"case2: Runnable\");\n" + |
| " }\n" + |
| " public void case2(Callable<Boolean> conditionEvaluator) {\n" + |
| " System.out.println(\"case2: Callable\");\n" + |
| " }\n" + |
| " public static void main(String[] args) throws Exception {\n" + |
| " new X().mismatchRunnableCallable();\n" + |
| " new X().noSuchMismatch();\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "case1: Runnable\n" + |
| "case1: Runnable\n" + |
| "case2: Runnable\n" + |
| "case2: Runnable"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference |
| public void test447767() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static <T, U, V> T foo(T t, U u, V v) {\n" + |
| " System.out.println(\"Wrong!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" + |
| " System.out.println(\"Right!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t; \n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Right!"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference |
| public void test447767a() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static <T, U, V> T foo(T t, U u, I<T, U, V> i) {\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t; \n" + |
| " }\n" + |
| "}\n" |
| }, |
| "----------\n" + |
| "1. ERROR in X.java (at line 9)\n" + |
| " String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" + |
| " ^\n" + |
| "Type mismatch: cannot convert from Object to String\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference |
| public void test447767b() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static String goo(String s, String s2) {\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" + |
| " System.out.println(\"Right!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", X::goo));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t; \n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Right!"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference |
| public void test447767c() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static String goo(String s, String s2) {\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> T foo(T t, U u, V v) {\n" + |
| " System.out.println(\"Wrong!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" + |
| " System.out.println(\"Right!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", X::goo));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t; \n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Right!"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference |
| public void test447767d() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static String goo(String s, String s2) {\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> T foo(T t, U u, V v) {\n" + |
| " System.out.println(\"Wrong!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" + |
| " System.out.println(\"Right!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", X::goo));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t; \n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Right!"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=449410, [1.8][compiler] Eclipse java compiler does not detect a bad return type in lambda expression |
| public void test449410() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "import java.util.Collections;\n" + |
| "public class X {\n" + |
| " public static void main(String[] args) {\n" + |
| " Collections.emptyMap()\n" + |
| " .entrySet()\n" + |
| " .forEach(entry -> test() ? bad() : returnType());\n" + |
| " }\n" + |
| " private static boolean test() {\n" + |
| " return (System.currentTimeMillis() & 0x1) == 0;\n" + |
| " }\n" + |
| " private static void returnType() {\n" + |
| " }\n" + |
| " private static void bad() {\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "----------\n" + |
| "1. ERROR in X.java (at line 6)\n" + |
| " .forEach(entry -> test() ? bad() : returnType());\n" + |
| " ^^^^^^^\n" + |
| "The method forEach(Consumer<? super Map.Entry<Object,Object>>) in the type Iterable<Map.Entry<Object,Object>> is not applicable for the arguments ((<no type> entry) -> {})\n" + |
| "----------\n" + |
| "2. ERROR in X.java (at line 6)\n" + |
| " .forEach(entry -> test() ? bad() : returnType());\n" + |
| " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + |
| "Invalid expression as statement\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=449824, [1.8] Difference in behaviour with method references and lambdas |
| // Captures present behavior - may not be correct. |
| public void test449824() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "public class X {\n" + |
| " public static void main(String[] args) {\n" + |
| " Concrete<Target> fl = new Concrete<Target>();\n" + |
| " fl.call(each -> each.doSomething()); // fails\n" + |
| " fl.call((Target each) -> each.doSomething()); // fails\n" + |
| " fl.call(Target::doSomething); // succeeds in Eclipse 4.5M3 and 4.4.1\n" + |
| " // but fails in Java 8 1.8.0_11\n" + |
| " }\n" + |
| " public static class Target {\n" + |
| " public void doSomething() {\n" + |
| " }\n" + |
| " }\n" + |
| " public static class Concrete<T> implements Left<T>, Right<T> {\n" + |
| " public void call(RightHand<? super T> p) {\n" + |
| " }\n" + |
| " }\n" + |
| " public interface Left<T> {\n" + |
| " default void call(LeftHand<? super T> p) {\n" + |
| " }\n" + |
| " }\n" + |
| " public interface LeftHand<T> {\n" + |
| " public void left(T t);\n" + |
| " }\n" + |
| " public interface Right<T> {\n" + |
| " public void call(RightHand<? super T> p);\n" + |
| " }\n" + |
| " public interface RightHand<T> {\n" + |
| " public void right(T t);\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "----------\n" + |
| "1. ERROR in X.java (at line 4)\n" + |
| " fl.call(each -> each.doSomething()); // fails\n" + |
| " ^^^^\n" + |
| "The method call(X.RightHand<? super X.Target>) is ambiguous for the type X.Concrete<X.Target>\n" + |
| "----------\n" + |
| "2. ERROR in X.java (at line 6)\n" + |
| " fl.call(Target::doSomething); // succeeds in Eclipse 4.5M3 and 4.4.1\n" + |
| " ^^^^\n" + |
| "The method call(X.RightHand<? super X.Target>) is ambiguous for the type X.Concrete<X.Target>\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=448954, [1.8][compiler] Suspect error: "The method foo(String, String, X::goo) is undefined for the type X" |
| public void test448954() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "interface I<T, U, V> {\n" + |
| " T goo(U u, V v);\n" + |
| "}\n" + |
| "interface J {\n" + |
| " void foo();\n" + |
| "}\n" + |
| "public class X {\n" + |
| " static String goo(String s, String s2) {\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> T foo(T t, U u, J j) {\n" + |
| " System.out.println(\"Wrong!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" + |
| " System.out.println(\"Right!\");\n" + |
| " return null;\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " String s = goo(foo(\"String\", \"String\", X::goo));\n" + |
| " }\n" + |
| " static <T> T goo(T t) {\n" + |
| " return t;\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Right!"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=450380, [1.8][compiler] NPE in Scope.getExactConstructor(..) for bad constructor reference |
| public void test450380() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "import java.util.ArrayList;\n" + |
| "import java.util.function.IntFunction;\n" + |
| "public class X {\n" + |
| " IntFunction<ArrayList<String>> noo() {\n" + |
| " return System::new;\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "----------\n" + |
| "1. ERROR in X.java (at line 5)\n" + |
| " return System::new;\n" + |
| " ^^^^^^^^^^^\n" + |
| "The type System does not define System(int) that is applicable here\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=450604, [1.8] CCE at InferenceContext18.getParameter line 1377 |
| public void test450604() { |
| this.runNegativeTest( |
| new String[] { |
| "X.java", |
| "import java.io.IOException;\n" + |
| "import java.util.List;\n" + |
| "import java.util.function.Function;\n" + |
| "public class X<T, E extends Exception> {\n" + |
| " public static <T> List<T> of(T one) { return null; }\n" + |
| " public @SafeVarargs static <T> List<T> of(T... items) { return null; }\n" + |
| " public static void printDependencyLoops() throws IOException {\n" + |
| " Function<? super String, ? extends List<String>> mapping = X::of;\n" + |
| " }\n" + |
| "}\n" |
| }, |
| ""); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=450604, [1.8] CCE at InferenceContext18.getParameter line 1377 |
| public void test450604a() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.util.List;\n" + |
| "public class X {\n" + |
| " public static <T> List<T> of() { return null; }\n" + |
| " public static @SafeVarargs <T> List<T> of(T... values) { return null; }\n" + |
| " static void walkAll() {\n" + |
| " X.<String> of();\n" + |
| " }\n" + |
| "}\n" |
| }); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=451677, [1.8][compiler] missing type inference |
| public void _test451677() { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.util.ArrayList;\n" + |
| "import java.util.function.Function;\n" + |
| "public class X {\n" + |
| " public static void test() {\n" + |
| " operationOnCreated(create(123, size -> new ArrayList<Integer>(size)), l -> l.size()); // works with: (ArrayList<Integer> l) -> l.size()\n" + |
| " }\n" + |
| " public static <R, A> R create(A arg, Function<A, R> factory) {\n" + |
| " return factory.apply(arg);\n" + |
| " }\n" + |
| " public static <R, A> R operationOnCreated(A created, Function<A, R> function) {\n" + |
| " return function.apply(created);\n" + |
| " }\n" + |
| "}\n" |
| }); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=451840 |
| // [1.8] java.lang.BootstrapMethodError when running code with constructor reference |
| public void testBug451840() { |
| runNegativeTest(new String [] { |
| "X.java", |
| "public class X {\n" + |
| " public static void main(String[] args) {\n" + |
| " X test = new X();\n" + |
| " MySupplier<X> s = test::new; // incorrect\n" + |
| " }\n" + |
| " public interface MySupplier<T> {\n" + |
| " T create();\n" + |
| " }\n" + |
| "}"}, |
| "----------\n" + |
| "1. ERROR in X.java (at line 4)\n" + |
| " MySupplier<X> s = test::new; // incorrect\n" + |
| " ^^^^\n" + |
| "test cannot be resolved to a type\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=448556 |
| // [1.8][compiler] Invalid compiler error about effectively final variable outside the context of a lambda. |
| public void testBug4448556() { |
| this.runConformTest(new String [] { |
| "X.java", |
| "import java.io.Serializable;\n" + |
| "import java.util.Arrays;\n" + |
| "import java.util.List;\n" + |
| "public class X {\n" + |
| " private static final List<Integer> INTEGERS = Arrays.asList(1, 2, 3, 4);\n" + |
| " public static void main(String[] args) {\n" + |
| " for (int i = 0; i < INTEGERS.size(); i++) {\n" + |
| " MyPredicate<Integer> predicate = INTEGERS.get(i)::equals;\n" + |
| " }\n" + |
| " } \n" + |
| " public interface MyPredicate<T> extends Serializable {\n" + |
| " boolean accept(T each);\n" + |
| " }\n" + |
| "}" |
| }, |
| ""); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=448556 |
| // [1.8][compiler] Invalid compiler error about effectively final variable outside the context of a lambda. |
| public void testBug4448556a() { |
| this.runConformTest(new String [] { |
| "X.java", |
| "import java.io.Serializable;\n" + |
| "import java.util.Arrays;\n" + |
| "import java.util.List;\n" + |
| "public class X {\n" + |
| " int value = 0; \n" + |
| " private static final List<Integer> INTEGERS = Arrays.asList(1, 2, 3, 4);\n" + |
| " public Integer next() {\n" + |
| " return new Integer(++value);\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " X t = new X();\n" + |
| " MyPredicate<Integer> predicate = t.next()::equals;\n" + |
| " System.out.println(\"Value \" + t.value + \" accept \" + predicate.accept(t.value));\n" + |
| " }\n" + |
| " public interface MyPredicate<T> extends Serializable {\n" + |
| " boolean accept(T each);\n" + |
| " }\n" + |
| "}" |
| }, |
| "Value 1 accept true"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=453687 |
| // [1.8][compiler]Incorrect errors when compiling code with Method References |
| public void testBug453687() { |
| this.runConformTest(new String [] { |
| "X.java", |
| "import static java.util.stream.Collectors.groupingBy;\n" + |
| "import static java.util.stream.Collectors.mapping;\n" + |
| "import static java.util.stream.Collectors.toSet;\n" + |
| "import java.util.Locale;\n" + |
| "import java.util.Map;\n" + |
| "import java.util.Set;\n" + |
| "import java.util.stream.Stream;\n" + |
| "public class X {\n" + |
| " public static void main(String[] args) {\n" + |
| " Map<String, Set<String>> countryLanguagesMap = Stream.of(Locale.getAvailableLocales()).collect(\n" + |
| " groupingBy(Locale::getDisplayCountry, mapping(Locale::getDisplayLanguage, toSet())));\n" + |
| " }\n" + |
| "} " |
| }, |
| ""); |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=456481 - [1.8] VerifyError on constructor reference inside lambda |
| public void testBug456481() { |
| this.runConformTest(new String [] { |
| "Test.java", |
| "public class Test {\n" + |
| " interface Constructor {\n" + |
| " MyTest execute();\n" + |
| " }\n" + |
| " interface ArrayConstructor {\n" + |
| " MyTest[] execute(int no);\n" + |
| " }\n" + |
| " interface ParameterizedConstructor {\n" + |
| " MyParameterizedTest<String> execute();\n" + |
| " }\n" + |
| " class MyTest {\n" + |
| " MyTest() { System.out.println(\"Constructor executed\"); }\n" + |
| " }\n" + |
| " class MyParameterizedTest<T> {\n" + |
| " MyParameterizedTest() {\n" + |
| " System.out.println(\"Parameterized Constructor executed\");\n" + |
| " }\n" + |
| " }\n" + |
| " public Constructor getConstructor() {\n" + |
| " return getConstructor(() -> { return MyTest::new; });\n" + |
| " }\n" + |
| " public MyTest[] getArray(int no) {\n" + |
| " return new MyTest[no];\n" + |
| " }\n" + |
| " ArrayConstructor getArrayConstructor() {\n" + |
| " return getArrayConstructor(() -> {return MyTest[]::new;});\n" + |
| " }\n" + |
| " ParameterizedConstructor getParameterizedConstructor() {\n" + |
| " return getParameterizedConstructor(() -> {return MyParameterizedTest<String>::new;});\n" + |
| " }\n" + |
| " ArrayConstructor getArrayConstructor(ArrayWrapper w) {\n" + |
| " return w.unwrap();\n" + |
| " }\n" + |
| " public static void main(String argv[]) {\n" + |
| " Test t = new Test();\n" + |
| " MyTest mytest = t.getConstructor().execute();\n" + |
| " MyTest[] array = t.getArrayConstructor().execute(2);\n" + |
| " MyParameterizedTest<String> pt = t.getParameterizedConstructor().execute();\n" + |
| " }\n" + |
| " ParameterizedConstructor getParameterizedConstructor(PTWrapper ptw) {\n" + |
| " return ptw.unwrap();\n" + |
| " }\n" + |
| " Constructor getConstructor(Wrapper arg) {\n" + |
| " return arg.unwrap();\n" + |
| " }\n" + |
| " interface PTWrapper {\n" + |
| " ParameterizedConstructor unwrap();\n" + |
| " }\n" + |
| " interface ArrayWrapper {\n" + |
| " ArrayConstructor unwrap();\n" + |
| " }\n" + |
| " interface Wrapper {\n" + |
| " Constructor unwrap();\n" + |
| " }\n" + |
| "}" |
| }, |
| "Constructor executed\n" + |
| "Parameterized Constructor executed"); |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=457007, VerifyError |
| public void testBug457007() { |
| this.runConformTest(new String [] { |
| "Test.java", |
| "public class Test {\n" + |
| " void method() {\n" + |
| " class Bar {}\n" + |
| " java.util.function.Function<String, Bar> f = str -> new Bar();\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " System.out.println(\"done\");\n" + |
| " }\n" + |
| "}" |
| }, |
| "done"); |
| } |
| public void testBug446691_comment5() { |
| runConformTest(new String [] { |
| "Test.java", |
| "import java.util.*;\n" + |
| "\n" + |
| "public class Test {\n" + |
| " protected final Integer myInt;\n" + |
| "\n" + |
| " public Test() {\n" + |
| " myInt = Integer.valueOf(0);\n" + |
| " try {\n" + |
| " Optional.empty().orElseThrow(() -> new IllegalArgumentException(myInt.toString()));\n" + |
| " } catch (IllegalArgumentException e) {\n" + |
| " throw new RuntimeException();\n" + |
| " }\n" + |
| " return;\n" + |
| " }\n" + |
| "}\n" |
| }); |
| } |
| public void testBug446691_comment8() { |
| runConformTest(new String [] { |
| "Boom.java", |
| "public class Boom {\n" + |
| " private final String field;\n" + |
| " public Boom(String arg) {\n" + |
| " this.field = arg;\n" + |
| " try {\n" + |
| " java.util.function.Supplier<String> supplier = () -> field;\n" + |
| " } catch (Exception e) {\n" + |
| " \n" + |
| " }\n" + |
| " }\n" + |
| "}\n" |
| }); |
| } |
| public void testBug446691_comment14() { |
| runNegativeTest(new String [] { |
| "test/Main.java", |
| "package test;\n" + |
| "\n" + |
| "import java.util.logging.Logger;\n" + |
| "\n" + |
| "public class Main {\n" + |
| "\n" + |
| " private static final Logger LOG = Logger.getLogger(\"test\");\n" + |
| " private final static String value;\n" + |
| "\n" + |
| " static {\n" + |
| " try {\n" + |
| " LOG.info(() -> String.format(\"Value is: %s\", value));\n" + |
| " } catch (final Exception ex) {\n" + |
| " throw new ExceptionInInitializerError(ex);\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in test\\Main.java (at line 8)\n" + |
| " private final static String value;\n" + |
| " ^^^^^\n" + |
| "The blank final field value may not have been initialized\n" + |
| "----------\n" + |
| "2. ERROR in test\\Main.java (at line 12)\n" + |
| " LOG.info(() -> String.format(\"Value is: %s\", value));\n" + |
| " ^^^^^\n" + |
| "The blank final field value may not have been initialized\n" + |
| "----------\n"); |
| } |
| // error in lambda even if field is assigned later |
| public void testBug446691_comment14b() { |
| runNegativeTest(new String [] { |
| "test/Main.java", |
| "package test;\n" + |
| "\n" + |
| "import java.util.logging.Logger;\n" + |
| "\n" + |
| "public class Main {\n" + |
| "\n" + |
| " private static final Logger LOG = Logger.getLogger(\"test\");\n" + |
| " private final static String value;\n" + |
| "\n" + |
| " static {\n" + |
| " try {\n" + |
| " LOG.info(() -> String.format(\"Value is: %s\", value));\n" + |
| " } catch (final Exception ex) {\n" + |
| " throw new ExceptionInInitializerError(ex);\n" + |
| " }\n" + |
| " value = \"\";" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in test\\Main.java (at line 12)\n" + |
| " LOG.info(() -> String.format(\"Value is: %s\", value));\n" + |
| " ^^^^^\n" + |
| "The blank final field value may not have been initialized\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=463526 |
| // Parenthesis are incorrectly allowed in lambda when LambdaBody is an expression statement |
| public void testBug463526() { |
| runNegativeTest(new String [] { |
| "Test.java", |
| "public class Test {\n" + |
| " public static void main(String[] args) {\n" + |
| " Receiver r = new Receiver();\n" + |
| " r.accept((l) -> (doItOnTheClass(new Object())));\n" + |
| " }\n" + |
| " public static void doItOnTheClass(Object o) {\n" + |
| " System.out.println(\"done it\");\n" + |
| " }\n" + |
| " public static class Receiver {\n" + |
| " public void accept(Listener l) {\n" + |
| " l.doIt(new Object());\n" + |
| " }\n" + |
| " }\n" + |
| " public static interface Listener {\n" + |
| " public void doIt(Object o);\n" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in Test.java (at line 4)\n" + |
| " r.accept((l) -> (doItOnTheClass(new Object())));\n" + |
| " ^^^^^^\n" + |
| "The method accept(Test.Listener) in the type Test.Receiver is not applicable for the arguments ((<no type> l) -> {})\n" + |
| "----------\n" + |
| "2. ERROR in Test.java (at line 4)\n" + |
| " r.accept((l) -> (doItOnTheClass(new Object())));\n" + |
| " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + |
| "Invalid expression as statement\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=463526 |
| // Parenthesis are incorrectly allowed in lambda when LambdaBody is an expression statement |
| public void testBug463526b() { |
| runNegativeTest(new String [] { |
| "Test.java", |
| "import java.util.function.Consumer;\n" + |
| "public class Test {\n" + |
| " public static void main(String[] args) {\n" + |
| " Receiver r = new Receiver();\n" + |
| " r.process((o) -> (new Object()));\n" + |
| " }\n" + |
| " public static class Receiver {\n" + |
| " public void process(Consumer<Object> p) {\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in Test.java (at line 5)\n" + |
| " r.process((o) -> (new Object()));\n" + |
| " ^^^^^^^\n" + |
| "The method process(Consumer<Object>) in the type Test.Receiver is not applicable for the arguments ((<no type> o) -> {})\n" + |
| "----------\n" + |
| "2. ERROR in Test.java (at line 5)\n" + |
| " r.process((o) -> (new Object()));\n" + |
| " ^^^^^^^^^^^^^^\n" + |
| "Void methods cannot return a value\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=463526 |
| // Parenthesis are incorrectly allowed in lambda when LambdaBody is an expression statement |
| public void testBug463526c() { |
| runNegativeTest(new String [] { |
| "Test.java", |
| "import java.util.function.Consumer;\n" + |
| "public class Test {\n" + |
| " public static void main(String[] args) {\n" + |
| " Receiver r = new Receiver();\n" + |
| " r.assign((o) -> (o = new Object()));\n" + |
| " }\n" + |
| " public static class Receiver {\n" + |
| " public void assign(Consumer<Object> a) {\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in Test.java (at line 5)\n" + |
| " r.assign((o) -> (o = new Object()));\n" + |
| " ^^^^^^\n" + |
| "The method assign(Consumer<Object>) in the type Test.Receiver is not applicable for the arguments ((<no type> o) -> {})\n" + |
| "----------\n" + |
| "2. ERROR in Test.java (at line 5)\n" + |
| " r.assign((o) -> (o = new Object()));\n" + |
| " ^^^^^^^^^^^^^^^^^^\n" + |
| "Void methods cannot return a value\n" + |
| "----------\n"); |
| } |
| //https://bugs.eclipse.org/bugs/show_bug.cgi?id=464408 |
| public void testBug464408() { |
| runNegativeTest(new String[]{ |
| "test/X.java", |
| "import java.util.ArrayList;\n" + |
| "import java.util.List;\n" + |
| "public class X {\n" + |
| " void x() {\n" + |
| " List<List<String>> list = new ArrayList<>();\n" + |
| " list.stream().toArray(List<String>[]::new);\n" + |
| " }" + |
| "}" |
| }, "----------\n" + |
| "1. ERROR in test\\X.java (at line 6)\n" + |
| " list.stream().toArray(List<String>[]::new);\n" + |
| " ^^^^^^^^^^^^^^^^^^^\n" + |
| "Cannot create a generic array of List<String>\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=465900 |
| // Internal compiler error: java.lang.IllegalArgumentException: info cannot be null at org.eclipse.jdt.internal.compiler.codegen.StackMapFrame.addStackItem(StackMapFrame.java:81) |
| public void testBug465900() { |
| this.runConformTest(new String [] { |
| "X.java", |
| "import java.io.Serializable;\n" + |
| "import java.util.ArrayList;\n" + |
| "import java.util.List;\n" + |
| "import java.util.function.Supplier;\n" + |
| "public class X {\n" + |
| " private static final long serialVersionUID = 1L;\n" + |
| " protected void x() {\n" + |
| " String str = \"groep.koppeling.\" + (\"\".isEmpty() ? \"toevoegen\" : \"bewerken\");\n" + |
| " List<String> bean = new ArrayList<>();\n" + |
| " test(bean.get(0)::isEmpty);\n" + |
| " }\n" + |
| " private void test(SerializableSupplier<Boolean> test) {}\n" + |
| "}\n" + |
| "@FunctionalInterface\n" + |
| "interface SerializableSupplier<T> extends Supplier<T>, Serializable {}\n" |
| }, |
| ""); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=477888 |
| // [1.8][compiler] Compiler silently produces garbage but editor shows no errors |
| public void testBug477888() { |
| runNegativeTest(new String [] { |
| "Test.java", |
| "import java.io.IOException;\n" + |
| "import java.nio.file.Files;\n" + |
| "import java.nio.file.Paths;\n" + |
| "import java.util.function.Consumer;\n" + |
| "public class Test {\n" + |
| " public static void main(String[] args) throws IOException {\n" + |
| " Files.lines(Paths.get(args[0])).filter(x -> {return !x.startsWith(\".\");}).forEach(printMe());\n" + |
| " }\n" + |
| " private static Consumer<String> printMe() {\n" + |
| " return x -> x.isEmpty() ? System.out.println() : System.out.println(getIndex() + \" \" + x); // error must be reported here!\n" + |
| " }\n" + |
| " static int idx;\n" + |
| "\n" + |
| " private static int getIndex() {\n" + |
| " return ++idx;\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "----------\n" + |
| "1. ERROR in Test.java (at line 10)\n" + |
| " return x -> x.isEmpty() ? System.out.println() : System.out.println(getIndex() + \" \" + x); // error must be reported here!\n" + |
| " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + |
| "Invalid expression as statement\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=472648 |
| // [compiler][1.8] Lambda expression referencing method with generic type has incorrect compile errors |
| public void testBug472648() { |
| runNegativeTest( |
| false, |
| JavacHasABug.JavacBugFixed_901, |
| new String [] { |
| "Test.java", |
| "import java.util.ArrayList;\n" + |
| "import java.util.List;\n" + |
| "import java.util.function.Consumer;\n" + |
| "public class Test {\n" + |
| " public static void main(String argv[]) {\n" + |
| " new Test();\n" + |
| " }\n" + |
| " public Test() {\n" + |
| " List<Number> numList = new ArrayList<>();\n" + |
| " numList.add(1);\n" + |
| " numList.add(1.5);\n" + |
| " numList.add(2);\n" + |
| " numList.add(2.5);\n" + |
| " forEachValueOfType(numList, Integer.class, (Integer i) -> (System.out.println(Integer.toString(i))));\n" + |
| " }\n" + |
| " private <T> void forEachValueOfType(List<?> list, Class<T> type, Consumer<T> action) {\n" + |
| " \n" + |
| " for (Object o : list) {\n" + |
| " if (type.isAssignableFrom(o.getClass())) {\n" + |
| " @SuppressWarnings(\"unchecked\")\n" + |
| " T convertedObject = (T) o;\n" + |
| " action.accept(convertedObject);\n" + |
| " }\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "----------\n" + |
| "1. ERROR in Test.java (at line 14)\n" + |
| " forEachValueOfType(numList, Integer.class, (Integer i) -> (System.out.println(Integer.toString(i))));\n" + |
| " ^^^^^^^^^^^^^^^^^^\n" + |
| "The method forEachValueOfType(List<?>, Class<T>, Consumer<T>) in the type Test is not applicable for the arguments (List<Number>, Class<Integer>, (Integer i) -> {})\n" + |
| "----------\n" + |
| "2. ERROR in Test.java (at line 14)\n" + |
| " forEachValueOfType(numList, Integer.class, (Integer i) -> (System.out.println(Integer.toString(i))));\n" + |
| " ^^^^^^^\n" + |
| "Incompatible type specified for lambda expression's parameter i\n" + |
| "----------\n" + |
| "3. ERROR in Test.java (at line 14)\n" + |
| " forEachValueOfType(numList, Integer.class, (Integer i) -> (System.out.println(Integer.toString(i))));\n" + |
| " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + |
| "Invalid expression as statement\n" + |
| "----------\n"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=473432 |
| // Internal compiler error: java.lang.IllegalArgumentException: info cannot be null at org.eclipse.jdt.internal.compiler.codegen.StackMapFrame.addStackItem(StackMapFrame.java:81) |
| public void testBug473432() { |
| this.runConformTest(new String [] { |
| "Tester.java", |
| "import java.util.function.Function;\n" + |
| "public class Tester {\n" + |
| " private static class ValueWrapper<O> {\n" + |
| " private O val_;\n" + |
| " public ValueWrapper(O val) {\n" + |
| " val_ = val;\n" + |
| " }\n" + |
| " public <R> R mapOrElse(Function<O, R> func, R defaultValue) {\n" + |
| " if(val_ != null) {\n" + |
| " return func.apply(val_);\n" + |
| " }\n" + |
| " return defaultValue;\n" + |
| " }\n" + |
| " }\n" + |
| " private static void handleObject(Object object) {\n" + |
| " System.out.println(\"Handled: \" + object);\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " ValueWrapper<String> wrapper = new ValueWrapper<>(\"value\");\n" + |
| " boolean skipMethod = false;\n" + |
| " // works on both JDT 3.9.2 and 3.11.0\n" + |
| " Boolean result = skipMethod ? true : wrapper.mapOrElse(v -> false, null);\n" + |
| " System.out.println(result);\n" + |
| " wrapper = new ValueWrapper<>(null);\n" + |
| " // works on JDT 3.9.2\n" + |
| " handleObject(skipMethod ?\n" + |
| " true :\n" + |
| " wrapper.mapOrElse(v -> false, null));\n" + |
| " wrapper = new ValueWrapper<>(null);\n" + |
| " // works on neither version\n" + |
| " result = skipMethod ?\n" + |
| " true :\n" + |
| " wrapper.mapOrElse(v -> false, null);\n" + |
| " System.out.println(result);\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "false\n" + |
| "Handled: null\n" + |
| "null"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=511676 [1.8] Lambda with inner class defs causes java.lang.VerifyError: Bad type on operand stack |
| public void testBug511676() { |
| this.runConformTest(new String [] { |
| "A.java", |
| "import java.util.function.Function;\n" + |
| "public class A {\n" + |
| " interface C<T> { }\n" + |
| " interface O<T> {\n" + |
| " Object r(C<T> s);\n" + |
| " }\n" + |
| " static <T, R> O<R> m(O<T> source, Function<T, O<R>> mapper) {\n" + |
| " return o -> {\n" + |
| " class D {\n" + |
| " class E {\n" + |
| " }\n" + |
| " E e = new E();\n" + |
| " }\n" + |
| " D d = new D();\n" + |
| " return d.e;\n" + |
| " };\n" + |
| " }\n" + |
| " public static void main(String[] args) {\n" + |
| " m(null, null);\n" + |
| " System.out.println(\" Done\");\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Done"); |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=511676 [1.8] Lambda with inner class defs causes java.lang.VerifyError: Bad type on operand stack |
| public void testBug511676a() { |
| this.runConformTest(new String [] { |
| "A.java", |
| "public class A {\n" + |
| " interface C<T> { }\n" + |
| " interface O<T> {\n" + |
| " Object r(C<T> s);\n" + |
| " }\n" + |
| " static O<Object> def = o -> {\n" + |
| " class D {\n" + |
| " class E {\n" + |
| " }\n" + |
| " E e = new E();\n" + |
| " }\n" + |
| " D d = new D();\n" + |
| " return d.e;\n" + |
| " };\n" + |
| " public static void main(String[] args) {\n" + |
| " O<Object> o = A.def;\n" + |
| " System.out.println(\" Done\");\n" + |
| " }\n" + |
| "}\n" |
| }, |
| "Done"); |
| } |
| public void testBug543778() { |
| Runner runner = new Runner(); |
| runner.testFiles = |
| new String[] { |
| "Sandbox.java", |
| "import java.util.function.Supplier;\n" + |
| "\n" + |
| "public class Sandbox {\n" + |
| "\n" + |
| " <R extends Object> R get(Supplier<@NonNull R> impl) {\n" + |
| " return null;\n" + |
| " }\n" + |
| "\n" + |
| " Object getter() {\n" + |
| " return get(() -> new Object() {\n" + |
| "\n" + |
| " @Override\n" + |
| " public String toString() {\n" + |
| " return super.toString();\n" + |
| " }\n" + |
| "\n" + |
| " });\n" + |
| " }\n" + |
| "\n" + |
| "}\n", |
| "NonNull.java", |
| "import java.lang.annotation.ElementType;\n" + |
| "import java.lang.annotation.Retention;\n" + |
| "import java.lang.annotation.RetentionPolicy;\n" + |
| "import java.lang.annotation.Target;\n" + |
| "\n" + |
| "@Retention(RetentionPolicy.CLASS)\n" + |
| "@Target({ ElementType.TYPE_USE })\n" + |
| "public @interface NonNull {\n" + |
| " // marker annotation with no members\n" + |
| "}\n", |
| }; |
| runner.customOptions = getCompilerOptions(); |
| runner.customOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED); // bug happens due to type annotation handling |
| runner.runConformTest(); |
| } |
| public static Class testClass() { |
| return LambdaRegressionTest.class; |
| } |
| } |