diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java index 58b8c6ee66b..63dc8001abc 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java @@ -725,11 +725,6 @@ public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } - @Override - public void tagAsHavingIgnoredMandatoryErrors(int problemId) { - // Nothing to do for this context; - } - public void traverse( ASTVisitor visitor, ClassScope classScope) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index 66459d6e9b7..fc8f1c1666c 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -778,11 +778,6 @@ public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } -@Override -public void tagAsHavingIgnoredMandatoryErrors(int problemId) { - // Nothing to do for this context; -} - public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) { traverse(visitor, unitScope, true); } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index 52b1df80124..2064e545c94 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -56,7 +56,6 @@ import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; @@ -128,7 +127,6 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre public boolean hasOuterClassMemberReference = false; private int outerLocalVariablesSlotSize = 0; private boolean assistNode = false; - private boolean hasIgnoredMandatoryErrors = false; private ReferenceBinding classType; private Set thrownExceptions; private static final SyntheticArgumentBinding [] NO_SYNTHETIC_ARGUMENTS = new SyntheticArgumentBinding[0]; @@ -808,17 +806,6 @@ public MethodScope getScope() { return this.scope; } - private boolean enclosingScopesHaveErrors() { - Scope skope = this.enclosingScope; - while (skope != null) { - ReferenceContext context = skope.referenceContext(); - if (context != null && context.hasErrors()) - return true; - skope = skope.parent; - } - return false; - } - private void analyzeShape() { // Simple minded analysis for code assist & potential compatibility. class ShapeComputer extends ASTVisitor { @Override @@ -1022,8 +1009,7 @@ private LambdaExpression cachedResolvedCopy(TypeBinding targetType, boolean anyT if (!requireExceptionAnalysis) return copy; if (copy.thrownExceptions == null) - if (!copy.hasIgnoredMandatoryErrors && !enclosingScopesHaveErrors()) - copy.analyzeExceptions(); + copy.analyzeExceptions(); return copy; } finally { this.enclosingScope.problemReporter().switchErrorHandlingPolicy(oldPolicy); @@ -1231,42 +1217,6 @@ public void tagAsHavingErrors() { } } - @Override - public void tagAsHavingIgnoredMandatoryErrors(int problemId) { - switch (problemId) { - // 15.27.3 requires exception throw related errors to not influence congruence. Other errors should. Also don't abort shape analysis. - case IProblem.UnhandledExceptionOnAutoClose: - case IProblem.UnhandledExceptionInDefaultConstructor: - case IProblem.UnhandledException: - return; - /* The following structural problems can occur only because of target type imposition. Filter, so we can distinguish inherent errors - in explicit lambdas. This is to help decide whether to proceed with data/control flow analysis to discover shape. In case of inherent - errors, we will not call analyze code as it is not prepared to analyze broken programs. - */ - case IProblem.VoidMethodReturnsValue: - case IProblem.ShouldReturnValueHintMissingDefault: - case IProblem.ShouldReturnValue: - case IProblem.ReturnTypeMismatch: - case IProblem.IncompatibleLambdaParameterType: - case IProblem.lambdaParameterTypeMismatched: - case IProblem.lambdaSignatureMismatched: - case IProblem.LambdaDescriptorMentionsUnmentionable: - case IProblem.TargetTypeNotAFunctionalInterface: - case IProblem.illFormedParameterizationOfFunctionalInterface: - case IProblem.NoGenericLambda: - return; - default: - this.hasIgnoredMandatoryErrors = true; - MethodScope enclosingLambdaScope = this.scope == null ? null : this.scope.enclosingLambdaScope(); - while (enclosingLambdaScope != null) { - LambdaExpression enclosingLambda = (LambdaExpression) enclosingLambdaScope.referenceContext; - enclosingLambda.hasIgnoredMandatoryErrors = true; - enclosingLambdaScope = enclosingLambdaScope.enclosingLambdaScope(); - } - return; - } - } - public Set getThrownExceptions() { if (this.thrownExceptions == null) return Collections.emptySet(); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java index 7ca7079fb9a..5d6a595a902 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java @@ -455,11 +455,6 @@ public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } - @Override - public void tagAsHavingIgnoredMandatoryErrors(int problemId) { - // Nothing to do for this context; - } - public String getModuleVersion() { if (this.scope != null) { LookupEnvironment env = this.scope.environment().root; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java index 2d66b2af157..5385d4b7be7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java @@ -1646,11 +1646,6 @@ public void tagAsHavingErrors() { this.ignoreFurtherInvestigation = true; } -@Override -public void tagAsHavingIgnoredMandatoryErrors(int problemId) { - // Nothing to do for this context; -} - /** * Iteration for a package member type */ diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java index 6db2e276e46..c9daa78e12a 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java @@ -34,7 +34,4 @@ public interface ReferenceContext { boolean hasErrors(); void tagAsHavingErrors(); - - void tagAsHavingIgnoredMandatoryErrors(int problemId); - } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java index 9010a3fc1df..585f25358b3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java @@ -138,8 +138,6 @@ public void handle( return; // ignore non reportable warning } } - if (mandatory) - referenceContext.tagAsHavingIgnoredMandatoryErrors(problemId); return; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java index e4a6e783354..7d196feda37 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java @@ -7972,8 +7972,8 @@ public void testGH1060() { ); } -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161 -//LambdaConversionException due to invalid instantiated method type argument to LambdaMetafactory::metafactory +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161 +// LambdaConversionException due to invalid instantiated method type argument to LambdaMetafactory::metafactory public void testBug546161() { this.runConformTest( new String[] { @@ -7994,9 +7994,77 @@ public void testBug546161() { "" ); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=547231 +// Logging inside lambda fails with error +public void testBug547231() { + this.runConformTest( + new String[] { + "Problematic.java", + "import java.io.IOException;\n" + + "import java.nio.file.Path;\n" + + "import java.util.Collections;\n" + + "import java.util.Set;\n" + + "import java.util.function.Consumer;\n" + + "import java.util.logging.Level;\n" + + "import java.util.logging.Logger;\n" + + "\n" + + "public class Problematic {\n" + + "\n" + + " Logger LOGGER = Logger.getLogger(Problematic.class.getName());\n" + + "\n" + + " @FunctionalInterface\n" + + " private interface ThrowingConsumer {\n" + + " void accept(T t) throws E;\n" + + " }\n" + + "\n" + + " private class FileAsset {\n" + + " public FileAsset move(String path) throws IOException {\n" + + " System.out.println(path);\n" + + " return null;\n" + + " }\n" + + "\n" + + " public Path getPath() {\n" + + " return null;\n" + + " }\n" + + " }\n" + + "\n" + + " static void process(Consumer> code, ThrowingConsumer throwingConsumer)\n" + + " throws E {\n" + + " code.accept(t -> {\n" + + " try {\n" + + " throwingConsumer.accept(t);\n" + + " } catch (Exception e) {\n" + + " e.printStackTrace();\n" + + " }\n" + + " });\n" + + " }\n" + + "\n" + + " public void execute(String path) throws IOException {\n" + + " Set set = Collections.singleton(new FileAsset());\n" + + " process(set::forEach, (a) -> {\n" + + " process(set::forEach, (b) -> {\n" + + " process(set::forEach, (c) -> {\n" + + " c.move(path);\n" + + "\n" + + " // produces error: Unhandled exception type IOException\n" + + " LOGGER.log(Level.FINE, () -> \"Moved \" + c.getPath() + \" to \" + a);\n" + + "\n" + + " // no error\n" + + " LOGGER.log(Level.FINE, \"Moved \" + c.getPath() + \" to \" + a);\n" + + " });\n" + + " });\n" + + " });\n" + + " }\n" + + " public static void main(String [] args) {\n" + + " System.out.println(\"OK\");\n" + + " }\n" + + "}\n"}, + "OK" + ); +} -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161 -//LambdaConversionException due to invalid instantiated method type argument to LambdaMetafactory::metafactory +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161 +// LambdaConversionException due to invalid instantiated method type argument to LambdaMetafactory::metafactory public void testBug546161_2() { this.runConformTest( new String[] { @@ -8016,8 +8084,8 @@ public void testBug546161_2() { ); } -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=574269 -//java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=574269 +// java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object public void testBug574269() { this.runConformTest( new String[] { @@ -8087,8 +8155,8 @@ public void testBug574269() { ); } -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=574269 -//java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=574269 +// java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object public void testBug574269_2() { this.runConformTest( new String[] { @@ -8134,8 +8202,8 @@ public void testBug574269_2() { ); } -//https://bugs.eclipse.org/bugs/show_bug.cgi?id=570511 -//java.lang.BootstrapMethodError in Eclipse compiled code that doesn't happen with javac +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=570511 +// java.lang.BootstrapMethodError in Eclipse compiled code that doesn't happen with javac public void testBug570511() { this.runConformTest( new String[] { @@ -8390,6 +8458,82 @@ public void testBug576252() { "}\n"}, "class LambdaTest"); } + +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2065 +// Eclipse compiler incorrectly reports unhandled exceptions on lamba code +public void testIssue2065() { + + if (this.complianceLevel < ClassFileConstants.JDK10) + return; + + this.runConformTest( + new String[] { + "Foobar.java", + """ + import java.nio.file.*; + import java.util.*; + import java.util.function.Function; + import java.util.stream.Collectors; + + public class Foobar { + @FunctionalInterface + public interface FailableSupplier { + T get() throws E; + } + + public static T get(final FailableSupplier supplier) { + try { + return supplier.get(); + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + + @FunctionalInterface + public interface FailableFunction { + R apply(T input) throws E; + } + + public static R apply(final FailableFunction function, final T input) { + return get(() -> function.apply(input)); + } + + public static Function asFunction(final FailableFunction function) { + return input -> apply(function, input); + } + + public static Set> getFoobarClasses(final String packageName, final ClassLoader classLoader) { + return get(() -> { + final var resourcePath = packageName.replace('.', '/'); + var resource = classLoader.getResource(resourcePath).toURI(); + FileSystem fileSystem = null; + try { + if ("jar".equals(resource.getScheme())) { + fileSystem = FileSystems.newFileSystem(resource, Collections.emptyMap()); + } + final var localPath = Paths.get(resource); + return Files.list(localPath) + .map(file -> file.getFileName().toString()) + .filter(filename -> filename.endsWith(".class")) + .filter(filename -> !filename.contains("Foobar")) + .map(asFunction(fileName -> { + final var qualifiedClassName = packageName + '.' + fileName.substring(0, fileName.lastIndexOf(".class")).replace('/', '.'); + return (Class) Class.forName(qualifiedClassName, false, classLoader); + })) + .collect(Collectors.toUnmodifiableSet()); + } finally { + if (fileSystem != null) { + fileSystem.close(); + } + } + }); + } + } + """}, + ""); +} + + public static Class testClass() { return LambdaExpressionsTest.class; }