Releng: update jdt.core to I20160317-0200 for 4.6 M6
diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
index f13a31b2..91d907f 100644
--- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.12.100.qualifier
+Bundle-Version: 3.12.200.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests.compiler,
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index 1bfc96a..34d0158 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
- <version>3.12.100-SNAPSHOT</version>
+ <version>3.12.200-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
index e14509c..7ffbefb 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2014 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2278,4 +2278,46 @@
expectedReplacedSource,
"diet ast");
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=473008
+public void test473008() {
+ String string =
+ "interface FooFunctional {\n" +
+ " void function();\n" +
+ "}\n" +
+ "public class Foo {\n" +
+ " public void bar() {\n" +
+ " private FooFunctional lambda = this::bar;\n" +
+ " new StringBuffer(" +
+ " }\n" +
+ "}\n";
+ String completeBehind = "StringBuffer(";
+ int cursorLocation = string.indexOf(completeBehind) + completeBehind.length() - 1;
+
+ String expectedCompletionNodeToString = "<CompleteOnAllocationExpression:new StringBuffer()>";
+ String expectedParentNodeToString = "<NONE>";
+ String completionIdentifier = "";
+ String expectedReplacedSource = "";
+ String expectedUnitDisplayString =
+ "interface FooFunctional {\n" +
+ " void function();\n" +
+ "}\n" +
+ "public class Foo {\n" +
+ " public Foo() {\n" +
+ " }\n" +
+ " public void bar() {\n" +
+ " private FooFunctional lambda;\n" +
+ " <CompleteOnAllocationExpression:new StringBuffer()>;\n" +
+ " }\n" +
+ "}\n";
+
+ checkMethodParse(
+ string.toCharArray(),
+ cursorLocation,
+ expectedCompletionNodeToString,
+ expectedParentNodeToString,
+ expectedUnitDisplayString,
+ completionIdentifier,
+ expectedReplacedSource,
+ "diet ast");
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
index e0abec8..6ea595b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -49,7 +49,7 @@
" }\n" +
" public class SubInnerBar extends InnerBar {\n" +
" SubInnerBar() {\n" +
- " super(<SelectOnMessageSend:fred()>);\n" +
+ " Bar.super(<SelectOnMessageSend:fred()>);\n" +
" }\n" +
" }\n" +
" static Bar x;\n" +
@@ -98,7 +98,7 @@
" }\n" +
" public class SubInnerBar extends InnerBar {\n" +
" SubInnerBar() {\n" +
- " this(<SelectOnMessageSend:fred()>);\n" +
+ " Bar.this(<SelectOnMessageSend:fred()>);\n" +
" }\n" +
" }\n" +
" static Bar x;\n" +
@@ -147,7 +147,7 @@
" }\n" +
" public class SubInnerBar extends InnerBar {\n" +
" SubInnerBar(Bar x) {\n" +
- " super(<SelectOnMessageSend:fred()>);\n" +
+ " primary().super(<SelectOnMessageSend:fred()>);\n" +
" }\n" +
" }\n" +
" static Bar x;\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
index 9166a00..852c395 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -176,4 +176,77 @@
expectedReplacedSource,
testName);
}
-}
\ No newline at end of file
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693
+public void test476693() throws JavaModelException {
+ String string =
+ "import static java.util.stream.Collectors.toList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.Spliterator;\n" +
+ "import java.util.stream.Stream;\n" +
+ "interface Seq<T> extends Stream<T>, Iterable<T> {\n" +
+ " @Override\n" +
+ " default Spliterator<T> spliterator() {\n" +
+ " return Iterable.super.spliterator();\n" +
+ " }\n" +
+ "}\n" +
+ "interface Tuple2<T1, T2> {}\n" +
+ "interface Tuple3<T1, T2, T3> {}\n" +
+ "\n" +
+ "public class Test<T1, T2, T3> {\n" +
+ " <T1, T2> Seq<Tuple2<T1, T2>> m(Stream<T1> arg1, Stream<T2> arg2) {\n" +
+ " System.out.println(\"m1\"); return null;\n" +
+ " }\n" +
+ " <T1, T2> Seq<Tuple2<T1, T2>> m(Seq<T1> arg1, Seq<T2> arg2){\n" +
+ " System.out.println(\"m3\"); return null;\n" +
+ " }\n" +
+ " <T1, T2, T3> void m(Seq<T1> c1, Seq<T2> c2, Seq<T3> c3) {\n" +
+ " // Click F3 on the m() call. This will jump to m1, erroneously\n" +
+ " List<Tuple2<T1, T2>> l = m(c1, c2).collect(toList());\n" +
+ " System.out.println(\"Hello\"); // This shouldn't appear in the selection parse tree\n" +
+ " }\n" +
+ "}";
+
+ String expectedCompletionNodeToString = "<SelectOnMessageSend:m(c1, c2)>";
+
+ String completionIdentifier = "m";
+ String expectedUnitDisplayString =
+ "import static java.util.stream.Collectors.toList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.Spliterator;\n" +
+ "import java.util.stream.Stream;\n" +
+ "interface Seq<T> extends Stream<T>, Iterable<T> {\n" +
+ " default @Override Spliterator<T> spliterator() {\n" +
+ " }\n" +
+ "}\n" +
+ "interface Tuple2<T1, T2> {\n" +
+ "}\n" +
+ "interface Tuple3<T1, T2, T3> {\n" +
+ "}\n" +
+ "public class Test<T1, T2, T3> {\n" +
+ " public Test() {\n" +
+ " }\n" +
+ " <T1, T2>Seq<Tuple2<T1, T2>> m(Stream<T1> arg1, Stream<T2> arg2) {\n" +
+ " }\n" +
+ " <T1, T2>Seq<Tuple2<T1, T2>> m(Seq<T1> arg1, Seq<T2> arg2) {\n" +
+ " }\n" +
+ " <T1, T2, T3>void m(Seq<T1> c1, Seq<T2> c2, Seq<T3> c3) {\n" +
+ " List<Tuple2<T1, T2>> l = <SelectOnMessageSend:m(c1, c2)>.collect(toList());\n" +
+ " }\n" +
+ "}\n";
+ String expectedReplacedSource = "m(c1, c2)";
+ String testName = "<select>";
+
+ int selectionStart = string.indexOf("m(c1, c2)");
+ int selectionEnd = selectionStart;
+
+ this.checkMethodParse(
+ string.toCharArray(),
+ selectionStart,
+ selectionEnd,
+ expectedCompletionNodeToString,
+ expectedUnitDisplayString,
+ completionIdentifier,
+ expectedReplacedSource,
+ testName);
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
index f2eea51..d2e1072 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2014 GK Software AG and others.
+ * Copyright (c) 2010, 2016 GK Software AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.osgi.framework.Bundle;
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -97,6 +98,10 @@
// enable null annotations:
defaultOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+
+ defaultOptions.put(CompilerOptions.OPTION_PessimisticNullAnalysisForFreeTypeVariables, JavaCore.ERROR);
+ defaultOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.WARNING);
+
// leave other new options at these defaults:
// defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, JavaCore.ERROR);
// defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, JavaCore.ERROR);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
index be896d9..357958e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
@@ -2098,6 +2098,52 @@
"Hello World!");
}
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=486908
+public void testBug486908_A(){
+ if (this.complianceLevel >= ClassFileConstants.JDK1_7) {
+ this.runConformTest(new String[] {
+ "Random.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "public class Random {\n" +
+ " private final List<Object> values;\n" +
+ " public Random() {\n" +
+ " values = new ArrayList<>();\n" +
+ " }\n" +
+ " public Random(Object arg) {\n" +
+ " if(arg instanceof Random) {\n" +
+ " values = ((Random)(arg)).values; //Compile error here.\n" +
+ " } else {\n" +
+ " throw new IllegalArgumentException(\"arg is not instance of Random\");\n" +
+ " }\n" +
+ " }\n" +
+ " public static void foo() {\n" +
+ " return;\n" +
+ " }\n" +
+ " public static void main(String[] args){\n" +
+ " foo();\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+}
+public void testBug486908_B() {
+ this.runConformTest(new String[] {
+ "Sample.java",
+ "public class Sample {\n" +
+ " public final String value;\n" +
+ " public Sample() {\n" +
+ " this.value = new Sample().value;\n" +
+ " }\n" +
+ " public static void foo() {\n" +
+ " return;\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " foo();\n" +
+ " }\n" +
+ "}\n"
+ });
+}
public static Class testClass() {
return AssignmentTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 4524048..3c5e188 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2077,6 +2077,7 @@
" <option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped\" value=\"warning\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict\" value=\"error\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecViolation\" value=\"error\"/>\n" +
@@ -2084,6 +2085,7 @@
" <option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 773ddb6..19da8f2 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -841,6 +841,8 @@
expectedProblemAttributes.put("NonNullMessageSendComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NonNullSpecdFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("NonNullTypeVariableFromLegacyMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("NonNullMethodTypeVariableFromLegacyMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("NonStaticContextForEnumMemberType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -941,6 +943,7 @@
expectedProblemAttributes.put("ReferenceExpressionReturnNullRedef", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("ReferenceExpressionReturnNullRedefUnchecked", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("RequiredNonNullButProvidedFreeTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RequiredNonNullButProvidedSpecdNullable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1009,6 +1012,7 @@
expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
+ expectedProblemAttributes.put("UncheckedAccessOfValueOfFreeTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("UndefinedAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -1032,6 +1036,8 @@
expectedProblemAttributes.put("UnhandledWarningToken", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
expectedProblemAttributes.put("UninitializedBlankFinalField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("UninitializedFreeTypeVariableField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("UninitializedFreeTypeVariableFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("UninitializedLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("UninitializedLocalVariableHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("UninitializedNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1752,6 +1758,8 @@
expectedProblemAttributes.put("NonNullSpecdFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NonNullMessageSendComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("NonNullTypeVariableFromLegacyMethod", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_TYPEVAR_FROM_LEGACY_INVOCATION));
+ expectedProblemAttributes.put("NonNullMethodTypeVariableFromLegacyMethod", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_TYPEVAR_FROM_LEGACY_INVOCATION));
expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
expectedProblemAttributes.put("NonStaticContextForEnumMemberType", SKIP);
@@ -1768,7 +1776,7 @@
expectedProblemAttributes.put("NullableFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
expectedProblemAttributes.put("NullAnnotationUnsupportedLocation", SKIP);
expectedProblemAttributes.put("NullAnnotationUnsupportedLocationAtType", SKIP);
- expectedProblemAttributes.put("NullityMismatchAgainstFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
+ expectedProblemAttributes.put("NullityMismatchAgainstFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
expectedProblemAttributes.put("NullityMismatchingTypeAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("NullityMismatchingTypeAnnotationSuperHint", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("NullityMismatchTypeArgument", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
@@ -1778,7 +1786,7 @@
expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
- expectedProblemAttributes.put("NullNotCompatibleToFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
+ expectedProblemAttributes.put("NullNotCompatibleToFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
expectedProblemAttributes.put("NullSourceString", SKIP);
expectedProblemAttributes.put("NullUnboxing", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
expectedProblemAttributes.put("NumericValueOutOfRange", SKIP);
@@ -1858,6 +1866,7 @@
expectedProblemAttributes.put("RepeatableAnnotationTypeTargetMismatch", SKIP);
expectedProblemAttributes.put("RepeatableAnnotationWithRepeatingContainerAnnotation", SKIP);
expectedProblemAttributes.put("RepeatedAnnotationWithContainerAnnotation", SKIP);
+ expectedProblemAttributes.put("RequiredNonNullButProvidedFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_ANNOTATION_INFERENCE_CONFLICT));
expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION));
@@ -1920,6 +1929,7 @@
expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION));
expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(JavaCore.COMPILER_PB_TYPE_PARAMETER_HIDING));
expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(JavaCore.COMPILER_PB_AUTOBOXING));
+ expectedProblemAttributes.put("UncheckedAccessOfValueOfFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
expectedProblemAttributes.put("UndefinedAnnotationMember", SKIP);
@@ -1943,6 +1953,8 @@
expectedProblemAttributes.put("UnhandledWarningToken", new ProblemAttributes(JavaCore.COMPILER_PB_UNHANDLED_WARNING_TOKEN));
expectedProblemAttributes.put("UninitializedBlankFinalField", SKIP);
expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", SKIP);
+ expectedProblemAttributes.put("UninitializedFreeTypeVariableField", SKIP);
+ expectedProblemAttributes.put("UninitializedFreeTypeVariableFieldHintMissingDefault", SKIP);
expectedProblemAttributes.put("UninitializedLocalVariable", SKIP);
expectedProblemAttributes.put("UninitializedLocalVariableHintMissingDefault", SKIP);
expectedProblemAttributes.put("UninitializedNonNullField", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
index c0763a3..6cc0ae1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
@@ -65,7 +65,7 @@
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
public void test002() {
- this.runNegativeTest(
+ this.runConformTest(
new String[] {
"X.java",
"interface I {\n" +
@@ -79,13 +79,7 @@
"public class X {\n" +
" Object p = (I & J) () -> {};\n" +
"}\n" ,
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " Object p = (I & J) () -> {};\n" +
- " ^^^^^\n" +
- "The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" +
- "----------\n");
+ });
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
public void test003() {
@@ -257,7 +251,7 @@
"3. ERROR in X.java (at line 10)\n" +
" Object p = (@Marker java.lang. @Readonly String & I & J) () -> {};\n" +
" ^^^^^\n" +
- "The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" +
+ "The target type of this expression must be a functional interface\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index acc8216..ce08ab4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -50222,7 +50222,9 @@
"1. ERROR in X.java (at line 9)\n" +
" Integer j = ffi.bar(ffi, new Foo());\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Foo<Integer> to Integer\n" +
+ (this.complianceLevel < ClassFileConstants.JDK1_8
+ ? "Type mismatch: cannot convert from Foo<Integer> to Integer\n"
+ : "Type mismatch: cannot convert from Foo to Integer\n") +
"----------\n" +
"2. WARNING in X.java (at line 9)\n" +
" Integer j = ffi.bar(ffi, new Foo());\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
index c5df191..805dd10 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation.
+ * Copyright (c) 2011, 2016 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -3034,6 +3034,38 @@
"----------\n");
}
}
+public void testBug488649_JDK6791481_ex1() {
+ int count = 1;
+ runNegativeTest(
+ new String[] {
+ "Test.java",
+ "class Test<X> {\n" +
+ " X m(Class<X> c) {return null;}\n" +
+ " X x = m((Class)String.class);\n" +
+ "}\n"
+ },
+ "----------\n" +
+ (this.complianceLevel >= ClassFileConstants.JDK1_8
+ ?
+ (count++)+". ERROR in Test.java (at line 3)\n" +
+ " X x = m((Class)String.class);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Type mismatch: cannot convert from Object to X\n" + // <- want to see this error, but at 1.7- we keep javac compatibility
+ "----------\n"
+ :
+ ""
+ )+
+ (count++)+". WARNING in Test.java (at line 3)\n" +
+ " X x = m((Class)String.class);\n" +
+ " ^^^^^^^^^^^^^^^^^^^\n" +
+ "Type safety: The expression of type Class needs unchecked conversion to conform to Class<X>\n" +
+ "----------\n" +
+ (count++)+". WARNING in Test.java (at line 3)\n" +
+ " X x = m((Class)String.class);\n" +
+ " ^^^^^\n" +
+ "Class is a raw type. References to generic type Class<T> should be parameterized\n" +
+ "----------\n");
+}
public static Class testClass() {
return GenericsRegressionTest_1_7.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index c62cebf..4167aa3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -5829,4 +5829,242 @@
"}\n"
});
}
+public void testBug483228a() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface UnaryOp<T> { T apply(T arg); }\n" +
+ "interface IntegerToNumber { Number apply(Integer arg); }\n" +
+ "\n" +
+ "public class X {\n" +
+ "\n" +
+ " <T> void m(UnaryOp<T> f) {}\n" +
+ " void m(IntegerToNumber f) {}\n" +
+ "\n" +
+ " void test() {\n" +
+ " m((Integer i) -> i);\n" +
+ " } \n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " m((Integer i) -> i);\n" +
+ " ^\n" +
+ "The method m(UnaryOp<Integer>) is ambiguous for the type X\n" +
+ "----------\n");
+}
+public void testBug449824a() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " interface FI1<T> {\n" +
+ " public T get(X x, T n);\n" +
+ " }\n" +
+ " interface FI2 {\n" +
+ " public Integer get(X x, Integer t);\n" +
+ " }\n" +
+ " void m(FI1<Number> fi) { }\n" +
+ " void m(FI2 fi) { }\n" +
+ " Integer id(Number n) {\n" +
+ " return null;\n" +
+ " }\n" +
+ " void test() {\n" +
+ " m(X::id);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 14)\n" +
+ " m(X::id);\n" +
+ " ^\n" +
+ "The method m(X.FI1<Number>) is ambiguous for the type X\n" +
+ "----------\n");
+}
+public void testBug449824b() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " interface FI1<T> {\n" +
+ " public T get(T... n);\n" +
+ " }\n" +
+ " interface FI2 {\n" +
+ " public Integer get(Integer... t);\n" +
+ " }\n" +
+ " void m(FI1<Number> fi) { }\n" +
+ " void m(FI2 fi) { }\n" +
+ " Integer id(Number[] n) {\n" +
+ " return null;\n" +
+ " }\n" +
+ " void test() {\n" +
+ " m(this::id);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 3)\n" +
+ " public T get(T... n);\n" +
+ " ^\n" +
+ "Type safety: Potential heap pollution via varargs parameter n\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " m(this::id);\n" +
+ " ^\n" +
+ "The method m(X.FI1<Number>) is ambiguous for the type X\n" +
+ "----------\n");
+}
+public void testBug487746_comment2() {
+ runConformTest(
+ new String[] {
+ "Example.java",
+ "\n" +
+ "import java.time.Instant;\n" +
+ "import java.util.Comparator;\n" +
+ "import java.util.stream.Collectors;\n" +
+ "\n" +
+ "public class Example {\n" +
+ " public void test1() {\n" +
+ " // Returns Collector<Something,?,Something> - CORRECT\n" +
+ " Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list -> list.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" +
+ " );\n" +
+ " }\n" +
+ " \n" +
+ " public void test2() {\n" +
+ " Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" +
+ " // Returns Collector<Something,?,Object> - INCORRECT!\n" +
+ " Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" +
+ " )\n" +
+ " )));\n" +
+ " }\n" +
+ " private interface Something {\n" +
+ " public int getSize();\n" +
+ " public Instant getTime();\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+public void _testBug487746_comment9() { // FIXME: still reports an unexpected error
+ runConformTest(
+ new String[] {
+ "Example.java",
+ "\n" +
+ "import java.time.Instant;\n" +
+ "import java.util.Comparator;\n" +
+ "import java.util.List;\n" +
+ "import java.util.stream.Collectors;\n" +
+ "\n" +
+ "public class Example {\n" +
+ " public void doesntCompile(List<Something> things) {\n" +
+ " things.stream()\n" +
+ " .filter(thing -> thing.getSize() > 100)\n" +
+ " .collect(Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" +
+ " Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" +
+ " )\n" +
+ " ))))\n" +
+ " .forEach((size, thing) -> {\n" +
+ " System.out.println(thing.getSize()); // Compile error because Eclipse thinks 'thing' is Object\n" +
+ " });\n" +
+ " }\n" +
+ " private interface Something {\n" +
+ " public int getSize();\n" +
+ " public Instant getTime();\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+public void testBug480075() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.stream.*;\n" +
+ "public class X {\n" +
+ " void test() {\n" +
+ " IntStream.of(42).mapToObj(i -> i > 42 ? \"gt\" : i < 42 ? \"lt\" : \"42\").findFirst();\n" +
+ "\n" +
+ " Stream.generate(Object::new).map(o -> o != null ? o : o == null ? o : o).findAny();\n" +
+ "\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+public void testBug488649() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "class A<T> {}\n" +
+ "public class X {\n" +
+ " static <U> U get(A<U> a) { return null; }\n" +
+ " void test(A a) {\n" +
+ " get(a).missing();\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " void test(A a) {\n" +
+ " ^\n" +
+ "A is a raw type. References to generic type A<T> should be parameterized\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 5)\n" +
+ " get(a).missing();\n" +
+ " ^^^^^^\n" +
+ "Type safety: Unchecked invocation get(A) of the generic method get(A<U>) of type X\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 5)\n" +
+ " get(a).missing();\n" +
+ " ^\n" +
+ "Type safety: The expression of type A needs unchecked conversion to conform to A<Object>\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 5)\n" +
+ " get(a).missing();\n" +
+ " ^^^^^^^\n" +
+ "The method missing() is undefined for the type Object\n" +
+ "----------\n");
+}
+public void testBug488672() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "\n" +
+ "public class X {\n" +
+ " void foo(Manager manager) {\n" +
+ " HashSet<String> activeBindings = new HashSet<>(manager.getActiveBindingsDisregardingContextFlat());\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class Manager {\n" +
+ " Collection getActiveBindingsDisregardingContextFlat() {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+public void testBug488795() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "interface Parameter {}\n" +
+ "interface Parameters<S extends Parameters<S, T>, T extends Parameter> extends Iterable<T> {\n" +
+ " S get();\n" +
+ "}\n" +
+ "public class X {\n" +
+ " void test(Parameters<?,?> parameters) {\n" +
+ " for(Parameter p : parameters.get())\n" +
+ " System.out.println(p);\n" +
+ " }\n" +
+ "}\n"
+ });
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
index f525875..ade8bf4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
index af65cdd..ec7fd34 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2014 Jesper Steen Moller, IBM and others.
+ * Copyright (c) 2013, 2016 Jesper Steen Moller, IBM and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -3212,7 +3212,7 @@
"}\n" +
"interface J {\n" +
" public void foo();\n" +
- " public void bar();\n" +
+ " public default void bar() {}\n" +
"}\n" +
"interface K {\n" +
" public void foo();\n" +
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 b426473..fc03010 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
@@ -24,6 +24,7 @@
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.IMethodInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.util.BootstrapMethodsAttribute;
import junit.framework.Test;
@@ -4969,14 +4970,14 @@
" SerializableFunction<List<String>, List<String>> f = X::foo;\n" +
" Method[] methods = X.class.getDeclaredMethods();\n" +
" for (Method m : methods) {\n" +
- " if (m.getName().contains(\"lambda\")) {\n" +
+ " if (m.getName().contains(\"foo\")) {\n" +
" System.out.println(\"- \" + m.getGenericReturnType() + \" \" + m.getName() + \"(\" + Arrays.asList(m.getGenericParameterTypes()) + \")\");\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n"
},
- "- java.util.List<java.lang.String> lambda$0([java.util.List<java.lang.String>])");
+ "- java.util.List<java.lang.String> foo([java.util.List<java.lang.String>])");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447119, [1.8][compiler] method references lost generic type information (4.4 -> 4.4.1 regression)
public void test447119d() {
@@ -5017,9 +5018,9 @@
" }\n" +
"}\n"
},
- "Lambda binds to: X.lambda$0\n" +
+ "Lambda binds to: X.noop\n" +
"Methods (with generics):\n" +
- "[- java.util.List<java.lang.String> lambda$0(java.util.List<java.lang.String>), - java.util.List<java.lang.String> noop(java.util.List<java.lang.String>)]",
+ "[- java.util.List<java.lang.String> noop(java.util.List<java.lang.String>)]",
null,
true,
new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
@@ -5882,6 +5883,168 @@
},
"10");
}
+public void testBug487586() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "\n" +
+ "interface Calculator {\n" +
+ " public int calculate(int a, int b);\n" +
+ "}\n" +
+ "\n" +
+ "interface Sumator {\n" +
+ " public int test();\n" +
+ "\n" +
+ " public int test3(int a, int b);\n" +
+ "}\n" +
+ "\n" +
+ "// intersection of both types\n" +
+ "interface Both extends Sumator, Calculator {\n" +
+ "\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " Calculator test = (Calculator & Sumator) (a, b) -> a + b;\n" +
+ " System.out.println(test.calculate(2, 3));\n" +
+ "\n" +
+ " Sumator sumator = (Calculator & Sumator) (a, b) -> a + b; // does compile, but throws an Exception\n" +
+ " sumator.test();\n" +
+ "\n" +
+ " Both both = (Both) (a, b) -> a + b; // does not compile\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 18)\n" +
+ " Calculator test = (Calculator & Sumator) (a, b) -> a + b;\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The target type of this expression must be a functional interface\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 21)\n" +
+ " Sumator sumator = (Calculator & Sumator) (a, b) -> a + b; // does compile, but throws an Exception\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The target type of this expression must be a functional interface\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 24)\n" +
+ " Both both = (Both) (a, b) -> a + b; // does not compile\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The target type of this expression must be a functional interface\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=452587 Java 8: Method references to the same method do not share BootstrapMethod
+public void testBug452587() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ " public class Test {\n" +
+ " public static void main(String[] args) {\n" +
+ " Runnable m = Test::m;\n" +
+ " Runnable n = Test::m;\n" +
+ " Runnable o = Test::m;\n" +
+ " Runnable p = Test::m;\n" +
+ " Runnable q = Test::m;\n" +
+ " }\n" +
+ " public static void m() {}\n" +
+ " }\n"
+ });
+ IClassFileReader classFileReader = ToolFactory.createDefaultClassFileReader(OUTPUT_DIR + File.separator + "Test.class", IClassFileReader.ALL);
+ BootstrapMethodsAttribute bootstrapMethodsAttribute = null;
+ IClassFileAttribute[] attrs = classFileReader.getAttributes();
+ for (int i=0,max=attrs.length;i<max;i++) {
+ if (new String(attrs[i].getAttributeName()).equals("BootstrapMethods")) {
+ bootstrapMethodsAttribute = (BootstrapMethodsAttribute)attrs[i];
+ break;
+ }
+ }
+ assertNotNull("BootstrapMethods attribute not found", bootstrapMethodsAttribute);
+ int bmaLength = bootstrapMethodsAttribute.getBootstrapMethodsLength();
+ assertEquals("Incorrect number of bootstrap methods found", 1, bmaLength);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=485529 [1.8][compiler] Verify error with constructor reference to nested class constructor
+public void testBug485529() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "interface I {\n" +
+ " X makeX(int x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " class Y extends X {\n" +
+ " class Z extends X {\n" +
+ " private Z(int z) {\n" +
+ " }\n" +
+ " private Z() {}\n" +
+ " }\n" +
+ " private Y(int y) {\n" +
+ " }\n" +
+ " Y() {\n" +
+ " }\n" +
+ " }\n" +
+ " I i = Y :: new;\n" +
+ " private X(int x) {\n" +
+ " }\n" +
+ " \n" +
+ " X() {\n" +
+ " }\n" +
+ " public static void main(String[] args) {\n" +
+ " new X();\n" +
+ " \n" +
+ " }\n" +
+ "}"
+ },
+ "");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479284 [1.8][inference] fail to resolve matching types for lambda and method reference + NPE at build
+public void testBug479284() {
+ runNegativeTest(
+ new String[] {
+ "BadInferenceMars451.java",
+ "package bug.report;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.Arrays;\n" +
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "import java.util.function.BinaryOperator;\n" +
+ "import java.util.function.Function;\n" +
+ "import java.util.stream.Collectors;\n" +
+ "/**\n" +
+ " * Problem is valid on Version: Mars.1 Release (4.5.1) Build id: 20150924-1200\n" +
+ " */\n" +
+ "public class BadInferenceMars451 {\n" +
+ " public static Map<Object, List<X>> BadInferenceMars451Casus1() {\n" +
+ " List<X> stuff = new ArrayList<>();\n" +
+ " return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451::sum));\n" +
+ " }\n" +
+ " public static Map<Object, List<X>> BadInferenceMars451Casus1Fixed1() {\n" +
+ " List<X> stuff = new ArrayList<>();\n" +
+ " return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), (BinaryOperator<List<X>>) BadInferenceMars451::sum));\n" +
+ " }\n" +
+ " public static Map<Object, List<X>> BadInferenceMars451Casus1Fixed2() {\n" +
+ " List<X> stuff = new ArrayList<>();\n" +
+ " return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.<X> asList(t), BadInferenceMars451::sum));\n" +
+ " }\n" +
+ " /* \n" +
+ " * Uncomment this to see eclipse crash at build\n" +
+ " * this doesnt work but it should not crash the ide\n" +
+ " */ \n" +
+ " public static Map<Object, List<X>> BadInferenceMars451Casus1Crash() {\n" +
+ " List<X> stuff = new ArrayList<>();\n" +
+ " return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451<X>::sum));\n" +
+ " }\n" +
+ " public static <T> List<T> sum(List<T> l1, List<T> l2) {\n" +
+ " return null;\n" +
+ " }\n" +
+ " public static class X {\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in BadInferenceMars451.java (at line 31)\n" +
+ " return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451<X>::sum));\n" +
+ " ^^^^^^^^^^^^^^^^^^^\n" +
+ "The type BadInferenceMars451 is not generic; it cannot be parameterized with arguments <BadInferenceMars451.X>\n" +
+ "----------\n");
+}
public static Class testClass() {
return LambdaExpressionsTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
index 0078f71..369f46d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 IBM Corporation and others.
+ * Copyright (c) 2015, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -409,6 +409,11 @@
" 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"
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
index 85c739b..10131d7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
@@ -7311,9 +7311,7 @@
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=420598, [1.8][compiler] Incorrect error about intersection cast type not being a functional interface.
public void testIntersectionCast() {
- this.runNegativeTest(
- true /* skipJavac */,
- JavacTestOptions.EclipseHasABug.EclipseBug424410,
+ this.runConformTest(
new String[] {
"X.java",
"import java.io.Serializable;\n" +
@@ -7328,23 +7326,18 @@
"interface L {\n" +
" void foo();\n" +
"}\n" +
+ "interface All extends J, I, K, L {}\n" +
"public class X {\n" +
" public static void main(String[] args) {\n" +
" I i = (I & Serializable) () -> {};\n" +
" i = (I & J & K) () -> {};\n" +
" i = (J & I & K) () -> {}; \n" +
" i = (J & I & K & L) () -> {}; \n" +
+ " i = (All) () -> {};\n" +
" }\n" +
- "}\n" +
- ""
+ "}\n"
},
- "----------\n" +
- "1. ERROR in X.java (at line 18)\n" +
- " i = (J & I & K & L) () -> {}; \n" +
- " ^^^^^\n" +
- "The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" +
- "----------\n"
- );
+ "");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=421711, [1.8][compiler] '_' as identifier for a lambda parameter should be rejected.
public void testUnderScoreParameter() {
@@ -9051,11 +9044,16 @@
" ^^^^^^^^\n" +
"The method removeIf(Predicate<? super Process>) in the type Collection<Process> is not applicable for the arguments ((int x) -> {})\n" +
"----------\n" +
- "2. ERROR in X.java (at line 3)\n" +
- " list.removeIf((int x) -> \"\");\n" +
- " ^^^^^^^^^^^^^\n" +
- "The target type of this expression is not a well formed parameterized type due to bound(s) mismatch\n" +
- "----------\n");
+ "2. ERROR in X.java (at line 3)\n" +
+ " list.removeIf((int x) -> \"\");\n" +
+ " ^^^\n" +
+ "Lambda expression\'s parameter x is expected to be of type Process\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 3)\n" +
+ " list.removeIf((int x) -> \"\");\n" +
+ " ^^\n" +
+ "Type mismatch: cannot convert from String to boolean\n" +
+ "----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=424154, [1.8][compiler] PolyTypeBinding must not render the full lambda body in error messages
//Variations where return types or arguments mismatch or both.
@@ -9863,6 +9861,168 @@
"The blank final field s may not have been initialized\n" +
"----------\n");
}
+public void testBug487390() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface ConsumeN {\n" +
+ " void consume(String.. strings); // syntax error here\n" +
+ "}\n" +
+ "public class X {\n" +
+ "\n" +
+ " void consu(ConsumeN c) { }\n" +
+ " void test() {\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 2)\n" +
+ " void consume(String.. strings); // syntax error here\n" +
+ " ^\n" +
+ "Syntax error on token \".\", Identifier expected\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " ^^^^^\n" +
+ "The method consu(ConsumeN) in the type X is not applicable for the arguments ((String... s) -> {})\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 8)\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Lambda expression\'s signature does not match the signature of the functional interface method consume()\n" +
+ "----------\n");
+}
+public void testBug487390b() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface ConsumeN {\n" +
+ " void consume();\n" +
+ "}\n" +
+ "public class X {\n" +
+ "\n" +
+ " void consu(ConsumeN c) { }\n" +
+ " void test() {\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " ^^^^^\n" +
+ "The method consu(ConsumeN) in the type X is not applicable for the arguments ((String... s) -> {})\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " consu((String... s) -> System.out.print(s.length));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Lambda expression\'s signature does not match the signature of the functional interface method consume()\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=458332, [1.8][compiler] only 409 method references/lambda expressions per class possible
+public void testBug458332() {
+ runNegativeTest(
+ new String[] {
+ "Test.java",
+ "import java.io.Serializable;\n" +
+ "import java.util.function.Consumer;\n" +
+ "public class Test {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(Data.part1().length);\n" +
+ " System.out.println(Data.part2().length);\n" +
+ " }\n" +
+ " @FunctionalInterface\n" +
+ " private static interface MethodRef extends Consumer<String[]>, Serializable {}\n" +
+ " private static class Data {\n" +
+ " static MethodRef[] part1() {\n" +
+ " return new MethodRef[] {\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " };\n" +
+ " }\n" +
+ " static MethodRef[] part2() {\n" +
+ " return new MethodRef[] {\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" +
+ " };\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in Test.java (at line 10)\n" +
+ " private static class Data {\n" +
+ " ^^^^\n" +
+ "The code of method $deserializeLambda$(SerializedLambda) is exceeding the 65535 bytes limit\n" +
+ "----------\n");
+}
public static Class testClass() {
return NegativeLambdaExpressionsTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
index e7d516a..434ea2c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
import java.util.Map;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
@@ -297,4 +298,213 @@
// compiler results
null /* do not check error string */);
}
+ public void testImportUnresolved() {
+ Map<String,String> options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
+ runNegativeTest(
+ true, // flush dir
+ new String[] {
+ "X.java",
+ "import com.bogus.Missing;\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " new X().test();\n" +
+ " }\n" +
+ " void test() {\n" +
+ " System.out.println(\"OK\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ null, // libs
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " import com.bogus.Missing;\n" +
+ " ^^^^^^^^^\n" +
+ "The import com.bogus cannot be resolved\n" +
+ "----------\n",
+ "OK",
+ "",
+ JavacTestOptions.SKIP);
+ }
+ public void testImportUnresolved_fatal() {
+ Map<String,String> options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_PB_FATAL_OPTIONAL_ERROR, JavaCore.ENABLED);
+ runNegativeTest(
+ true, // flush dir
+ new String[] {
+ "p/Z.java",
+ "package p;\n" +
+ "public class Z {\n" +
+ " public static void main(String[] args) throws Exception {\n" +
+ " try {\n" +
+ " Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+ " } catch (java.lang.Error e) {\n" +
+ " System.err.println(e.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "X.java",
+ "import com.bogus.Missing;\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " new X().test();\n" +
+ " }\n" +
+ " void test() {\n" +
+ " System.out.println(\"OK\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ null, // libs
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " import com.bogus.Missing;\n" +
+ " ^^^^^^^^^\n" +
+ "The import com.bogus cannot be resolved\n" +
+ "----------\n",
+ "",
+ "Unresolved compilation problem: \n" +
+ " The import com.bogus cannot be resolved",
+ JavacTestOptions.SKIP);
+ }
+ public void testPackageConflict() {
+ runNegativeTest(
+ true, // flush dir
+ new String[] {
+ "p/z.java",
+ "package p;\n" +
+ "public class z {\n" +
+ " public static void main(String[] args) throws Exception {\n" +
+ " try {\n" +
+ " Class.forName(\"p.z.X\").newInstance();\n" +
+ " } catch (ClassNotFoundException e) {\n" +
+ " System.out.println(e.getClass().getName());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "p/z/X.java",
+ "package p.z;\n" +
+ "public class X {\n" +
+ " public X() {\n" +
+ " System.out.println(\"OK\");\n" +
+ " }\n" +
+ "}\n",
+ },
+ null, // libs
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in p\\z\\X.java (at line 1)\n" +
+ " package p.z;\n" +
+ " ^^^\n" +
+ "The package p.z collides with a type\n" +
+ "----------\n",
+ "java.lang.ClassNotFoundException", // cannot generate code in presence of the above error
+ "",
+ JavacTestOptions.SKIP);
+ }
+ public void testImportVariousProblems() {
+ runNegativeTest(
+ true, // flush dir
+ new String[] {
+ "p/Z.java",
+ "package p;\n" +
+ "public class Z {\n" +
+ " public static void main(String[] args) throws Exception {\n" +
+ " try {\n" +
+ " Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+ " } catch (ClassNotFoundException e) {\n" +
+ " System.out.println(e.getClass().getName());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "p1/Y.java",
+ "package p1;\n" +
+ "public class Y {}\n",
+ "p2/Y.java",
+ "package p2;\n" +
+ "public class Y {}\n",
+ "X.java",
+ "import java.util;\n" +
+ "import p.Z;\n" +
+ "import p1.Y;\n" +
+ "import p2.Y;\n" +
+ "public class X {\n" +
+ " public X() {\n" +
+ " System.out.println(\"OK\");\n" +
+ " }\n" +
+ "}\n" +
+ "class Z {}\n"
+ },
+ null, // libs
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " import java.util;\n" +
+ " ^^^^^^^^^\n" +
+ "Only a type can be imported. java.util resolves to a package\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 2)\n" +
+ " import p.Z;\n" +
+ " ^^^\n" +
+ "The import p.Z conflicts with a type defined in the same file\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 4)\n" +
+ " import p2.Y;\n" +
+ " ^^^^\n" +
+ "The import p2.Y collides with another import statement\n" +
+ "----------\n",
+ "OK",
+ "",
+ JavacTestOptions.SKIP);
+ }
+ public void testImportStaticProblems() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses static imports
+ runNegativeTest(
+ true, // flush dir
+ new String[] {
+ "p/Z.java",
+ "package p;\n" +
+ "public class Z {\n" +
+ " public static void main(String[] args) throws Exception {\n" +
+ " try {\n" +
+ " Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+ " } catch (ClassNotFoundException e) {\n" +
+ " System.out.println(e.getClass().getName());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "p1/Y.java",
+ "package p1;\n" +
+ "public class Y {\n" +
+ " static int f;\n" +
+ "}\n",
+ "X.java",
+ "import static p1.Y;\n" +
+ "import static p1.Y.f;\n" +
+ "public class X {\n" +
+ " public X() {\n" +
+ " System.out.println(\"OK\");\n" +
+ " }\n" +
+ "}\n" +
+ "class Z {}\n"
+ },
+ null, // libs
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " import static p1.Y;\n" +
+ " ^^^^\n" +
+ "The static import p1.Y must be a field or member type\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 2)\n" +
+ " import static p1.Y.f;\n" +
+ " ^^^^^^\n" +
+ "The field Y.p1.Y.f is not visible\n" +
+ "----------\n",
+ "OK",
+ "",
+ JavacTestOptions.SKIP);
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index 792f9e2..64b32ce 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -8115,7 +8115,11 @@
"Null type safety: The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" +
"----------\n"
:
- ""));
+ "3. WARNING in EclipseBug.java (at line 10)\n" +
+ " return commandType.newInstance();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull Class<T extends @NonNull String>\'. Type \'Class<T>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n"));
}
public void testBug459967_Enum_valueOf() {
runConformTestWithLibs(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java
new file mode 100644
index 0000000..68677dd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java
@@ -0,0 +1,313 @@
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+
+import junit.framework.Test;
+
+public class NullChecksTests extends AbstractNullAnnotationTest {
+
+ public NullChecksTests(String name) {
+ super(name);
+ }
+
+ // Static initializer to specify tests subset using TESTS_* static variables
+ // All specified tests which do not belong to the class are skipped...
+ static {
+// TESTS_NAMES = new String[] { "testAssertNonNull1" };
+// TESTS_NUMBERS = new int[] { 561 };
+// TESTS_RANGE = new int[] { 1, 2049 };
+ }
+
+ public static Test suite() {
+ return buildMinimalComplianceTestSuite(testClass(), F_1_8);
+ }
+
+ public static Class<NullChecksTests> testClass() {
+ return NullChecksTests.class;
+ }
+
+ public void testAssertNonNull1() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " static @NonNull String hide(String some) {\n" +
+ " return some;\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " @NonNull String myHiddenNull = hide(null);\n" +
+ " try {\n" +
+ " assertNonNull(\"foo\", myHiddenNull);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(npe.getMessage());\n" +
+ " }\n" +
+ " try {\n" +
+ " assertNonNullWithMessage(\"Shouldn't!\", \"foo\", myHiddenNull);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(npe.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "Value in position 1 must not be null\n" +
+ "Shouldn\'t!");
+ }
+
+ public void testAssertNonNullElements() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "import java.util.*;\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " static @NonNull String hide(String some) {\n" +
+ " return some;\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " @NonNull List<String> myList = new ArrayList<>();\n" +
+ " myList.add(\"foo\");\n" +
+ " myList.add(null);\n" +
+ " try {\n" +
+ " assertNonNullElements(myList);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(npe.getMessage());\n" +
+ " }\n" +
+ " @NonNull List<@NonNull String> myList2 = new ArrayList<>();\n" +
+ " myList2.add(\"foo\");\n" +
+ " myList2.add(hide(null));\n" +
+ " try {\n" +
+ " assertNonNullElements(myList2, \"Shouldn't!\");\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(npe.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "Value in position 1 must not be null\n" +
+ "Shouldn\'t!");
+ }
+
+ public void testRequireNonNull() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " static @NonNull String hide(String some) {\n" +
+ " return some;\n" +
+ " }\n" +
+ " static void test(@Nullable String str, @Nullable X x) {\n" +
+ " @NonNull String nnStr;\n" +
+ " @NonNull X nnX;\n" +
+ " try {\n" +
+ " nnStr = requireNonNull(str);\n" +
+ " nnX = requireNonNull(null, \"Shouldn\'t!\");\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(npe.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(\"foo\", null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "Shouldn\'t!");
+ }
+
+ public void testRequireNonEmptyString() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " static @NonNull String hide(String some) {\n" +
+ " return some;\n" +
+ " }\n" +
+ " static void test(@Nullable String str1, @Nullable String str2) {\n" +
+ " @NonNull String nnStr;\n" +
+ " try {\n" +
+ " nnStr = requireNonEmpty(str1);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(\"npe:\"+npe.getMessage());\n" +
+ " }\n" +
+ " try {\n" +
+ " nnStr = requireNonEmpty(str2, \"Shouldn't!\");\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(\"npe\"+npe.getMessage());\n" +
+ " } catch (IllegalArgumentException iae) {\n" +
+ " System.out.println(iae.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(null, \"\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "npe:null\n" +
+ "Shouldn\'t!");
+ }
+
+ public void testRequireNonEmptyCollection() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " static void test(@Nullable Collection<String> strs, @Nullable Collection<String> strs1, Collection<String> strs2) {\n" +
+ " @NonNull Collection<String> nnStrs;\n" +
+ " try {\n" +
+ " nnStrs = requireNonEmpty(strs);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(\"NPE:\"+npe.getMessage());\n" +
+ " }\n" +
+ " try {\n" +
+ " nnStrs = requireNonEmpty(strs1);\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(\"npe:\"+npe.getMessage());\n" +
+ " }\n" +
+ " try {\n" +
+ " nnStrs = requireNonEmpty(strs2, \"Shouldn't!\");\n" +
+ " } catch (NullPointerException npe) {\n" +
+ " System.out.println(\"npe\"+npe.getMessage());\n" +
+ " } catch (IllegalArgumentException iae) {\n" +
+ " System.out.println(iae.getMessage());\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(Collections.singletonList(\"good\"), null, Collections.emptyList());\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "npe:null\n" +
+ "Shouldn\'t!");
+ }
+
+ public void testIsNull() {
+ Map<String, String> compilerOptions = getCompilerOptions();
+ compilerOptions.put(JavaCore.COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " @SuppressWarnings(\"null\")\n" +
+ " static <T> @NonNull T hide(T some) {\n" +
+ " return some;\n" +
+ " }\n" +
+ " static void test(@NonNull X x1, @NonNull X x2, @NonNull X x3) {\n" +
+ " if (isNull(x1))\n" +
+ " System.out.println(\"IS NULL\");\n" +
+ " if (isAnyNull(x2, x1))\n" +
+ " System.out.println(\"IS ANY NULL 1\");\n" +
+ " if (isAnyNull(x2, x3))\n" +
+ " System.out.println(\"IS ANY NULL 2\");\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(hide(null), new X(), new X());\n" +
+ " }\n" +
+ "}\n"
+ },
+ compilerOptions,
+ "",
+ "IS NULL\n" +
+ "IS ANY NULL 1");
+ }
+
+ public void testAsNullable() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " static void test(Optional<X> xopt) {\n" +
+ " if (xopt != null) {\n" +
+ " X x = asNullable(xopt);\n" +
+ " if (x == null)\n" +
+ " System.out.println(\"NULL\");\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(Optional.ofNullable(null));\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "NULL");
+ }
+
+ public void testNonNullElse() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.function.*;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " static void test(String str, String noStr, @NonNull Supplier<@NonNull String> prov) {\n" +
+ " System.out.println(nonNullElse(str, \"ELSE1\"));\n" +
+ " System.out.println(nonNullElse(noStr, \"ELSE2\"));\n" +
+ " System.out.println(nonNullElseGet(str, () -> \"ELSE3\"));\n" +
+ " System.out.println(nonNullElseGet(noStr, prov));\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(\"good\", null, () -> \"ELSE4\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "good\n" +
+ "ELSE2\n" +
+ "good\n" +
+ "ELSE4");
+ }
+
+ public void _testIfNonNull() { // FIXME: see https://bugs.eclipse.org/489609 - [1.8][null] null annotation on wildcard is dropped during inference
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import static org.eclipse.jdt.annotation.Checks.*;\n" +
+ "public class X {\n" +
+ " static void test(@Nullable String str) {\n" +
+ " ifNonNull(str, s -> print(s));\n" +
+ " }\n" +
+ " static void print(@NonNull String s) {\n" +
+ " System.out.print(s);\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " test(\"good\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "",
+ "good");
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index 10401b2..14d4d19 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -10251,11 +10251,16 @@
" }\n" +
" }\n" +
"}\n"},
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " if (a == null) {\n" +
- " ^\n" +
- "Redundant null check: The variable a can only be null at this location\n" +
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " a = null;\n" +
+ " ^\n" +
+ "Redundant assignment: The variable a can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 7)\n" +
+ " if (a == null) {\n" +
+ " ^\n" +
+ "Redundant null check: The variable a can only be null at this location\n" +
"----------\n",
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
}
@@ -10281,18 +10286,23 @@
" }\n" +
" }\n" +
"}\n"},
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " if (a == null) {\n" +
- " ^\n" +
- "Redundant null check: The variable a can only be null at this location\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 13)\n" +
- " if (a == null) {\n" +
- " ^\n" +
- "Null comparison always yields false: The variable a cannot be null at this location\n" +
- "----------\n" +
- "3. WARNING in X.java (at line 13)\n" +
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " a = null;\n" +
+ " ^\n" +
+ "Redundant assignment: The variable a can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 7)\n" +
+ " if (a == null) {\n" +
+ " ^\n" +
+ "Redundant null check: The variable a can only be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 13)\n" +
+ " if (a == null) {\n" +
+ " ^\n" +
+ "Null comparison always yields false: The variable a cannot be null at this location\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 13)\n" +
" if (a == null) {\n" +
" System.out.println();\n" +
" }\n" +
@@ -13335,7 +13345,10 @@
}
// variation with nested loops.
public void testBug321926l() {
- this.runConformTest(
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.WARNING);
+
+ this.runTest(
new String[] {
"X.java",
"import java.io.IOException;\n" +
@@ -13374,7 +13387,22 @@
" }\n" +
" }\n" +
"}"},
- "Compiler good Compiler good");
+ false,
+ "----------\n" +
+ "1. WARNING in X.java (at line 8)\n" +
+ " someVariable = null;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Redundant assignment: The variable someVariable can only be null at this location\n" +
+ "----------\n",
+ "Compiler good Compiler good",
+ "",
+ true, // force execution
+ null, // classlibs
+ true, // flush output,
+ null, // vm args
+ options,
+ null,
+ null);
}
public void testBug321926m() {
this.runConformTest(
@@ -17681,4 +17709,269 @@
"Potential null pointer access: The variable s may be null at this location\n" +
"----------\n");
}
+public void testBug486912KnownNullInLoop() {
+ runNegativeTest(
+ new String[] {
+ "test/KnownNullInLoop.java",
+ "package test;\n" +
+ "\n" +
+ "public class KnownNullInLoop {\n" +
+ " public void testDoWhile() {\n" +
+ " Object o1 = null;\n" +
+ " do {\n" +
+ " o1.hashCode(); // ERROR1: known null, but no problem reported.\n" +
+ " } while (false);\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhileWithBreak() {\n" +
+ " Object o1 = null;\n" +
+ " while (true) {\n" +
+ " o1.hashCode(); // ERROR2: known null, but no problem reported.\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ "----------\n" +
+ "1. ERROR in test\\KnownNullInLoop.java (at line 7)\n" +
+ " o1.hashCode(); // ERROR1: known null, but no problem reported.\n" +
+ " ^^\n" +
+ "Null pointer access: The variable o1 can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in test\\KnownNullInLoop.java (at line 14)\n" +
+ " o1.hashCode(); // ERROR2: known null, but no problem reported.\n" +
+ " ^^\n" +
+ "Null pointer access: The variable o1 can only be null at this location\n" +
+ "----------\n"
+ );
+}
+public void testBug486912PotNullInLoop_orig() {
+ runNegativeTest(
+ new String[] {
+ "test/PotNullInLoop.java",
+ "package test;\n" +
+ "\n" +
+ "public class PotNullInLoop {\n" +
+ " boolean b;\n" +
+ "\n" +
+ " public void testDoWhile1() {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o2;\n" + // actually: def nn
+ " Object potNull = b ? o1 : o1;\n" + // actually: def n
+ " Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+ " do {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+ " ponNullOrNonNull.hashCode(); // ERROR 2: pot null, but nothing reported\n" +
+ " } while (false);\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhileWithBreak() {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o2;\n" +
+ " Object potNull = b ? o1 : o1;\n" +
+ " Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+ " while (b) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+ " ponNullOrNonNull.hashCode(); // ERROR 4: pot null, but nothing reported\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhile() {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o2;\n" +
+ " Object potNull = b ? o1 : o1;\n" +
+ " Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+ " while (b) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testFor() {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o2;\n" +
+ " Object potNull = b ? o1 : o1;\n" +
+ " Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testForEach() {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o2;\n" +
+ " Object potNull = b ? o1 : o1;\n" +
+ " Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ "}\n" +
+ "",
+ },
+ "----------\n" +
+ "1. ERROR in test\\PotNullInLoop.java (at line 14)\n" +
+ " potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable potNull can only be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in test\\PotNullInLoop.java (at line 15)\n" +
+ " ponNullOrNonNull.hashCode(); // ERROR 2: pot null, but nothing reported\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in test\\PotNullInLoop.java (at line 27)\n" +
+ " potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable potNull can only be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in test\\PotNullInLoop.java (at line 28)\n" +
+ " ponNullOrNonNull.hashCode(); // ERROR 4: pot null, but nothing reported\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in test\\PotNullInLoop.java (at line 41)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable potNull can only be null at this location\n" +
+ "----------\n" +
+ "6. ERROR in test\\PotNullInLoop.java (at line 42)\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" +
+ "----------\n" +
+ "7. ERROR in test\\PotNullInLoop.java (at line 54)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable potNull can only be null at this location\n" +
+ "----------\n" +
+ "8. ERROR in test\\PotNullInLoop.java (at line 55)\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" +
+ "----------\n" +
+ "9. ERROR in test\\PotNullInLoop.java (at line 67)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Null pointer access: The variable potNull can only be null at this location\n" +
+ "----------\n" +
+ "10. ERROR in test\\PotNullInLoop.java (at line 68)\n" +
+ " ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" +
+ "----------\n"
+ );
+}
+// variant of testBug486912PotNullInLoop_orig spiced up with potentiality from an 'unknown' o0:
+public void testBug486912PotNullInLoop() {
+ runNegativeTest(
+ new String[] {
+ "test/PotNullInLoop.java",
+ "package test;\n" +
+ "\n" +
+ "public class PotNullInLoop {\n" +
+ " boolean b;\n" +
+ "\n" +
+ " public void testDoWhile1(Object o0) {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o0;\n" +
+ " Object potNull = b ? o1 : o0;\n" +
+ " do {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+ " } while (false);\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhileWithBreak(Object o0) {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o0;\n" +
+ " Object potNull = b ? o1 : o0;\n" +
+ " while (b) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhile(Object o0) {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o0;\n" +
+ " Object potNull = b ? o1 : o0;\n" +
+ " while (b) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testFor(Object o0) {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o0;\n" +
+ " Object potNull = b ? o1 : o0;\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testForEach(Object o0) {\n" +
+ " Object o1 = null;\n" +
+ " Object o2 = new Object();\n" +
+ " Object potNonNull = b ? o2 : o0;\n" +
+ " Object potNull = b ? o1 : o0;\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " potNonNull.hashCode(); // OK\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ "}\n" +
+ "",
+ },
+ "----------\n" +
+ "1. ERROR in test\\PotNullInLoop.java (at line 13)\n" +
+ " potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The variable potNull may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in test\\PotNullInLoop.java (at line 24)\n" +
+ " potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The variable potNull may be null at this location\n" +
+ "----------\n" +
+ "3. ERROR in test\\PotNullInLoop.java (at line 36)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The variable potNull may be null at this location\n" +
+ "----------\n" +
+ "4. ERROR in test\\PotNullInLoop.java (at line 47)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The variable potNull may be null at this location\n" +
+ "----------\n" +
+ "5. ERROR in test\\PotNullInLoop.java (at line 58)\n" +
+ " potNull.hashCode(); // OK: pot null, is reported\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: The variable potNull may be null at this location\n" +
+ "----------\n"
+ );
+}
}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index f92be0a..5c75171 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -177,9 +177,16 @@
"@Target({METHOD,PARAMETER,LOCAL_VARIABLE,TYPE_USE})\n" +
"public @interface Dummy {\n" +
"}\n",
+ "p/List.java",
+ "package p;\n" +
+ "public interface List<T> {\n" +
+ " T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+ " void add(T e);\n" +
+ " void add(int i, T e);\n" +
+ "}\n",
"X.java",
"import org.eclipse.jdt.annotation.*;\n" +
- "import java.util.List;\n" +
+ "import p.List;\n" +
"public class X {\n" +
" void foo(@Nullable List<@NonNull Object> l) {\n" +
" System.out.print(l.get(0).toString()); // problem: l may be null\n" +
@@ -189,7 +196,7 @@
" System.out.print(l.get(0).toString()); // problem: l may be null\n" +
" l.add(0, null); // problem: cannot insert 'null' into this list\n" +
" }\n" +
- " void bar2(@Dummy java.util.@Nullable List<java.lang.@NonNull Object> l2) {\n" +
+ " void bar2(@Dummy p.@Nullable List<java.lang.@NonNull Object> l2) {\n" +
" System.out.print(l2.get(0).toString()); // problem: l2 may be null\n" +
" l2.add(0, null); // problem: cannot insert 'null' into this list\n" +
" }\n" +
@@ -198,7 +205,7 @@
"1. ERROR in X.java (at line 5)\n" +
" System.out.print(l.get(0).toString()); // problem: l may be null\n" +
" ^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"2. ERROR in X.java (at line 6)\n" +
" l.add(null); // problem: cannot insert \'null\' into this list\n" +
@@ -208,7 +215,7 @@
"3. ERROR in X.java (at line 9)\n" +
" System.out.print(l.get(0).toString()); // problem: l may be null\n" +
" ^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"4. ERROR in X.java (at line 10)\n" +
" l.add(0, null); // problem: cannot insert \'null\' into this list\n" +
@@ -218,7 +225,7 @@
"5. ERROR in X.java (at line 13)\n" +
" System.out.print(l2.get(0).toString()); // problem: l2 may be null\n" +
" ^^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"6. ERROR in X.java (at line 14)\n" +
" l2.add(0, null); // problem: cannot insert \'null\' into this list\n" +
@@ -240,18 +247,21 @@
" public X foo(Y l) {\n" +
" return anX;\n" +
" }\n" +
+ " public I(X x) {\n" +
+ " anX = x;\n" +
+ " }\n" +
" }\n" +
" void bar(A<@Nullable Object>.I<@NonNull Object> i) {\n" + // legal instantiation
" @NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" +
" }\n" +
"}\n"},
"----------\n" +
- "1. ERROR in A.java (at line 10)\n" +
+ "1. ERROR in A.java (at line 13)\n" +
" @NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" +
" ^^^^^^^^^^^\n" +
"Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable Object'\n" +
"----------\n" +
- "2. ERROR in A.java (at line 10)\n" +
+ "2. ERROR in A.java (at line 13)\n" +
" @NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" +
" ^^^^\n" +
"Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
@@ -353,7 +363,7 @@
"1. ERROR in B.java (at line 4)\n" +
" ai.foo(null); // problems: ai can be null, arg must not be null\n" +
" ^^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"2. ERROR in B.java (at line 4)\n" +
" ai.foo(null); // problems: ai can be null, arg must not be null\n" +
@@ -417,6 +427,7 @@
"Wrapper.java",
"public class Wrapper<T> {\n" +
" T content;" +
+ " public Wrapper(T t) { content = t; }\n" +
" public T content() { return content; }\n" +
"}\n",
"A.java",
@@ -451,6 +462,7 @@
"Wrapper.java",
"public class Wrapper<T> {\n" +
" T content;" +
+ " public Wrapper(T t) { content = t; }\n" +
" public T content() { return content; }\n" +
"}\n",
"A.java",
@@ -522,7 +534,7 @@
"4. ERROR in A.java (at line 15)\n" +
" string = maybeStringArray[0]; // problems: indexing nullable array & unchecked conversion\n" +
" ^^^^^^^^^^^^^^^^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"5. WARNING in A.java (at line 15)\n" +
" string = maybeStringArray[0]; // problems: indexing nullable array & unchecked conversion\n" +
@@ -532,7 +544,7 @@
"6. ERROR in A.java (at line 17)\n" +
" maybeStringArray[0] = null; // problem: indexing nullable array\n" +
" ^^^^^^^^^^^^^^^^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n");
}
@@ -1048,7 +1060,7 @@
"1. ERROR in Y1.java (at line 4)\n" +
" System.out.println(p.X1.f1.length);\n" +
" ^^\n" +
- "Potential null pointer access: this expression has a '@Nullable' type\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
"----------\n" +
"2. ERROR in Y1.java (at line 5)\n" +
" System.out.println(X1.f2[0].length);\n" +
@@ -1308,9 +1320,16 @@
customOptions.put(JavaCore.COMPILER_PB_MISSING_SERIAL_VERSION, JavaCore.IGNORE);
runConformTestWithLibs(
new String[] {
+ "p/List.java",
+ "package p;\n" +
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public interface List<T> {\n" +
+ " T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+ "}\n",
"p/X1.java",
"package p;\n" +
- "import java.util.*;\n" +
+ "import java.util.Map;\n" +
+ "import p.List;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"import static java.lang.annotation.ElementType.*;\n" +
"import java.lang.annotation.*;\n" +
@@ -2438,6 +2457,8 @@
// poly-null method
public void testNullTypeInference1() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
runNegativeTestWithLibs(
new String[] {
"X.java",
@@ -2459,7 +2480,7 @@
" }\n" +
"}\n"
},
- getCompilerOptions(),
+ compilerOptions,
"----------\n" +
"1. ERROR in X.java (at line 9)\n" +
" return polyNullMethod(strings).get(0);\n" +
@@ -3078,6 +3099,11 @@
" ls.add(null);\n" +
" ^^^^\n" +
"Null type mismatch: required \'@NonNull ? extends @NonNull String\' but the provided value is null\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 10)\n" +
+ " @NonNull String s = ls.get(0);\n" +
+ " ^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull capture#of ? extends @NonNull String>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
"----------\n");
}
@@ -3400,12 +3426,17 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in X.java (at line 10)\n" +
+ "1. WARNING in X.java (at line 6)\n" +
+ " return l.get(0);\n" +
+ " ^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<@NonNull T>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 10)\n" +
" s.foo(new ArrayList<String>()); // (1)\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Null type safety (type annotations): The expression of type \'ArrayList<String>\' needs unchecked conversion to conform to \'@NonNull List<@NonNull String>\', corresponding supertype is 'List<String>'\n" +
"----------\n" +
- "2. ERROR in X.java (at line 11)\n" +
+ "3. ERROR in X.java (at line 11)\n" +
" s.foo(null); // (2)\n" +
" ^^^^\n" +
"Null type mismatch: required \'@NonNull List<@NonNull String>\' but the provided value is null\n" +
@@ -3736,15 +3767,15 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in X.java (at line 4)\n" +
+ "1. ERROR in X.java (at line 4)\n" +
" consume(t); // error, t can be null\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
- "2. WARNING in X.java (at line 5)\n" +
+ "2. ERROR in X.java (at line 5)\n" +
" consumeObject(t); // error, t can be null\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull Object\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
"3. ERROR in X.java (at line 8)\n" +
" consume(t); // error, both sides explicit, mismatch\n" +
@@ -3794,15 +3825,15 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in X.java (at line 4)\n" +
+ "1. ERROR in X.java (at line 4)\n" +
" consume(t); // error, t can be null\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T extends Number\' needs unchecked conversion to conform to \'@NonNull T extends Number\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
- "2. WARNING in X.java (at line 5)\n" +
+ "2. ERROR in X.java (at line 5)\n" +
" consumeObject(t); // error, t can be null\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T extends Number\' needs unchecked conversion to conform to \'@NonNull Object\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
"3. ERROR in X.java (at line 8)\n" +
" consume(t); // error, both sides explicit, mismatch\n" +
@@ -4404,27 +4435,32 @@
" ^^^^\n" +
"Null type mismatch: required \'? extends @NonNull A\' but the provided value is null\n" +
"----------\n" +
- "2. ERROR in C.java (at line 15)\n" +
+ "2. WARNING in C.java (at line 14)\n" +
+ " return la1.get(0); // OK\n" +
+ " ^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<capture#of ? extends @NonNull A>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "3. ERROR in C.java (at line 15)\n" +
" la1 = lb2; // ERR2\n" +
" ^^^\n" +
"Null type mismatch (type annotations): required \'List<? extends @NonNull A>\' but this expression has type \'List<@Nullable B>\'\n" +
"----------\n" +
- "3. ERROR in C.java (at line 17)\n" +
+ "4. ERROR in C.java (at line 17)\n" +
" la2.add(null); // ERR3\n" +
" ^^^^\n" +
"Null type mismatch: required \'? extends @Nullable A\' but the provided value is null\n" +
"----------\n" +
- "4. ERROR in C.java (at line 19)\n" +
+ "5. ERROR in C.java (at line 19)\n" +
" return la2.get(0); // ERR4\n" +
" ^^^^^^^^^^\n" +
"Null type mismatch (type annotations): required \'@NonNull A\' but this expression has type \'capture#of ? extends @Nullable A\'\n" +
"----------\n" +
- "5. ERROR in C.java (at line 25)\n" +
+ "6. ERROR in C.java (at line 25)\n" +
" <T extends @Nullable A> T mExtends1(List<T> t) { return null; /*ERR5*/ }\n" +
" ^^^^\n" +
"Null type mismatch: required \'T extends @Nullable A\' but the provided value is null\n" +
"----------\n" +
- "6. ERROR in C.java (at line 26)\n" +
+ "7. ERROR in C.java (at line 26)\n" +
" <T extends @NonNull A> T mExtends2(List<T> t) { return null; /*ERR6*/ }\n" +
" ^^^^\n" +
"Null type mismatch: required \'T extends @NonNull A\' but the provided value is null\n" +
@@ -4734,12 +4770,12 @@
"1. ERROR in X.java (at line 6)\n" +
" in.add(null); // NOK, cannot assume nullable\n" +
" ^^^^\n" +
- "Null type mismatch (type annotations): \'null\' is not compatible to the free type variable '? extends Number'\n" +
+ "Null type mismatch (type annotations): \'null\' is not compatible to the free type variable \'? extends Number\'\n" +
"----------\n" +
- "2. WARNING in X.java (at line 7)\n" +
+ "2. ERROR in X.java (at line 7)\n" +
" needNN(in.get(0)); // NOK, cannot assume nonnull\n" +
" ^^^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'capture#of ? extends Number\' needs unchecked conversion to conform to \'@NonNull Number\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'capture#2-of ? extends java.lang.Number\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
"3. ERROR in X.java (at line 8)\n" +
" return new ArrayList<@Nullable T>(); // NOK, cannot assume nullable for T in List<T>\n" +
@@ -4947,17 +4983,22 @@
},
getCompilerOptions(),
"----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
+ "1. WARNING in X.java (at line 8)\n" +
+ " @NonNull Number n = l.get(0); // OK\n" +
+ " ^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<capture#of ? extends @NonNull Number>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
" return null; // ERR\n" +
" ^^^^\n" +
"Null type mismatch: required \'T extends @NonNull Number\' but the provided value is null\n" +
"----------\n" +
- "2. WARNING in X.java (at line 13)\n" +
+ "3. WARNING in X.java (at line 13)\n" +
" @NonNull Number nnn = inner.process(Integer.valueOf(3), new ArrayList<@Nullable Integer>()); // WARN on 1. arg; ERR on 2. arg\n" +
" ^^^^^^^^^^^^^^^^^^\n" +
"Null type safety (type annotations): The expression of type \'Integer\' needs unchecked conversion to conform to \'@NonNull Integer\'\n" +
"----------\n" +
- "3. ERROR in X.java (at line 13)\n" +
+ "4. ERROR in X.java (at line 13)\n" +
" @NonNull Number nnn = inner.process(Integer.valueOf(3), new ArrayList<@Nullable Integer>()); // WARN on 1. arg; ERR on 2. arg\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Null type mismatch (type annotations): required \'List<? extends @NonNull Number>\' but this expression has type \'ArrayList<@Nullable Integer>\', corresponding supertype is \'List<@Nullable Integer>\'\n" +
@@ -5971,6 +6012,8 @@
}
// top-level annotation is overridden at use-site, details remain - parameterized type
public void testTypeVariable19() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
runNegativeTestWithLibs(
new String[] {
"X.java",
@@ -5999,7 +6042,7 @@
" }\n" +
"}\n"
},
- getCompilerOptions(),
+ compilerOptions,
"----------\n" +
"1. ERROR in X.java (at line 15)\n" +
" case 0 : return i1.get0().get(0).toUpperCase(); // problem at detail\n" +
@@ -6491,10 +6534,10 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in X.java (at line 5)\n" +
+ "1. ERROR in X.java (at line 5)\n" +
" @NonNull T localT = t; // err#1\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
"2. ERROR in X.java (at line 6)\n" +
" return null; // err must mention free type variable, not @NonNull\n" +
@@ -6521,10 +6564,10 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in X.java (at line 8)\n" +
+ "1. ERROR in X.java (at line 8)\n" +
" @NonNull T localT = t; // err#1\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n" +
"2. ERROR in X.java (at line 9)\n" +
" return null; // err must mention free type variable, not @NonNull\n" +
@@ -6667,7 +6710,17 @@
},
getCompilerOptions(),
"----------\n" +
- "1. ERROR in Foo.java (at line 20)\n" +
+ "1. WARNING in Foo.java (at line 17)\n" +
+ " return requireNonNull(foos).get(0);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<capture#of ? extends @NonNull Foo>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "2. WARNING in Foo.java (at line 20)\n" +
+ " return requireNonNull(foos.get(0)).get(0);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull Foo>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "3. ERROR in Foo.java (at line 20)\n" +
" return requireNonNull(foos.get(0)).get(0);\n" +
" ^^^^\n" +
"Potential null pointer access: this expression has a \'@Nullable\' type\n" +
@@ -6732,7 +6785,7 @@
},
options,
"");
- runConformTestWithLibs(
+ runNegativeTestWithLibs(
new String[] {
"UnequalBinaryNode.java",
"public class UnequalBinaryNode<L extends ExtendedNode, R extends ExtendedNode>\n" +
@@ -6748,7 +6801,17 @@
"}\n"
},
options,
- "");
+ "----------\n" +
+ "1. ERROR in UnequalBinaryNode.java (at line 8)\n" +
+ " left.setParent(this);\n" +
+ " ^^^^\n" +
+ "Potential null pointer access: this expression has type \'L\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in UnequalBinaryNode.java (at line 9)\n" +
+ " right.setParent(this); // error on this line without fix\n" +
+ " ^^^^^\n" +
+ "Potential null pointer access: this expression has type \'R\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n");
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=434582,
//[1.8][compiler][null] @Nullable annotation in type parameter causes NullPointerException in JDT core
@@ -7709,6 +7772,7 @@
public void testBug448709() {
Map compilerOptions = getCompilerOptions();
compilerOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION, JavaCore.WARNING); // ensure program is runnable
+ compilerOptions.put(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES, JavaCore.WARNING); // ensure program is runnable
runConformTestWithLibs(
new String[] {
"Test.java",
@@ -7761,22 +7825,27 @@
},
compilerOptions,
"----------\n" +
- "1. WARNING in Test.java (at line 39)\n" +
+ "1. WARNING in Test.java (at line 21)\n" +
+ " final U result = mapper.apply(source);\n" +
+ " ^^^^^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. WARNING in Test.java (at line 39)\n" +
" map(optNullableString, testMethodRef);\n" +
" ^^^^^^^^^^^^^\n" +
"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" +
"----------\n" +
- "2. WARNING in Test.java (at line 41)\n" +
+ "3. WARNING in Test.java (at line 41)\n" +
" map(optNullableString, Test::testMethod); // Error: Null type mismatch at parameter 1: required \'@NonNull String\' but provided \'@Nullable String\' via method descriptor Function<String,Integer>.apply(String)\n" +
" ^^^^^^^^^^^^^^^^\n" +
"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" +
"----------\n" +
- "3. WARNING in Test.java (at line 43)\n" +
+ "4. WARNING in Test.java (at line 43)\n" +
" map(optNullableString, (s) -> Test.testMethod(s));\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" +
"----------\n" +
- "4. WARNING in Test.java (at line 43)\n" +
+ "5. WARNING in Test.java (at line 43)\n" +
" map(optNullableString, (s) -> Test.testMethod(s));\n" +
" ^\n" +
"Null type mismatch (type annotations): required \'@NonNull String\' but this expression has type \'@Nullable String\'\n" +
@@ -7785,6 +7854,28 @@
"1->2\n" +
"1->2");
}
+public void testBug448709b() {
+ runConformTestWithLibs(
+ new String[] {
+ "Test.java",
+ "import java.util.*;\n" +
+ "import java.util.function.*;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "\n" +
+ "public class Test {\n" +
+ "\n" +
+ " public static final <T,U> void map(final @NonNull Optional<T> optional, final Function<@NonNull ? super T,? extends U> mapper) {\n" +
+ " final T source = optional.get();\n" +
+ " if (source != null) {\n" +
+ " final U result = mapper.apply(source);\n" +
+ " System.out.println(source+\"->\"+result);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+}
public void testBug459967_Array_constructor() {
runConformTestWithLibs(
new String[] {
@@ -7994,6 +8085,11 @@
" @NonNull GenericType gt = cwru.method().get(0);\n" +
" ^^^^^^^^^^^\n" +
"GenericType is a raw type. References to generic type GenericType<T> should be parameterized\n" +
+ "----------\n" +
+ "2. WARNING in projB\\ClassThatImports.java (at line 7)\n" +
+ " @NonNull GenericType gt = cwru.method().get(0);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<@NonNull GenericType>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
"----------\n");
}
@@ -8270,6 +8366,8 @@
getCompilerOptions(), "");
}
public void testBug456584() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES, JavaCore.WARNING);
runConformTestWithLibs(
new String[] {
"Test.java",
@@ -8286,12 +8384,17 @@
"\n" +
"}\n"
},
- getCompilerOptions(),
+ compilerOptions,
"----------\n" +
"1. WARNING in Test.java (at line 9)\n" +
" return Objects.requireNonNull(function.apply(input));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on substitution \'T=@NonNull capture#of ? extends R\'. Declaring type \'Objects\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n" +
+ "2. WARNING in Test.java (at line 9)\n" +
+ " return Objects.requireNonNull(function.apply(input));\n" +
" ^^^^^^^^^^^^^^^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'capture#of ? extends R\' needs unchecked conversion to conform to \'@NonNull capture#of ? extends R\'\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'capture#2-of ? extends R\', a free type variable that may represent a \'@Nullable\' type\n" +
"----------\n");
}
public void testBug447661() {
@@ -8894,13 +8997,20 @@
},
getCompilerOptions(),
"----------\n" +
- "1. ERROR in X.java (at line 12)\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " return list.get(0);\n" +
+ " ^^^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
" public class X extends Super<@NonNull String, List<@Nullable String>> {\n" +
" ^^^^\n" +
"Null constraint mismatch: The type \'List<@Nullable String>\' is not a valid substitute for the type parameter \'T extends List<S>\'\n" +
"----------\n");
}
public void testBug477719() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
runConformTestWithLibs(
new String[] {
"X.java",
@@ -8915,7 +9025,7 @@
" }\n" +
"}\n"
},
- getCompilerOptions(),
+ compilerOptions,
"");
}
public void testBug482247() {
@@ -8951,6 +9061,23 @@
"Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" +
"----------\n");
}
+public void testBug482247_comment5() {
+ runConformTestWithLibs(
+ new String[] {
+ "Snippet.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Snippet {\n" +
+ " @NonNull String[] s1 = new String[0]; // No warning\n" +
+ " public void handleIncidentBeforeCreate() {\n" +
+ " @NonNull String[] s = new String[0]; // Warning\n" +
+ " String [] @NonNull[] s2 = new String[0][];\n" +
+ " String [] @NonNull[] @Nullable[] s3 = new String[0][][];\n" +
+ " }\n" +
+ "}"
+ },
+ getCompilerOptions(),
+ "");
+}
public void testBug483146() {
runConformTestWithLibs(
new String[] {
@@ -9078,12 +9205,17 @@
},
getCompilerOptions(),
"----------\n" +
- "1. ERROR in X.java (at line 14)\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " return list.get(0);\n" +
+ " ^^^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
" <T extends List<@Nullable String>> @NonNull String pick(T list) {\n" +
" ^\n" +
"Cannot redefine null constraints of type variable \'T extends List<@NonNull String>\' declared in \'Super<String>.pick(T)\'\n" +
"----------\n" +
- "2. ERROR in X.java (at line 15)\n" +
+ "3. ERROR in X.java (at line 15)\n" +
" return super.pick(list);\n" +
" ^^^^^^^^^^^^^^^^\n" +
"Null constraint mismatch: The type \'T extends List<@Nullable String>\' is not a valid substitute for the type parameter \'T extends List<@NonNull String>\'\n" +
@@ -9512,9 +9644,14 @@
customOptions.put(JavaCore.COMPILER_PB_MISSING_SERIAL_VERSION, JavaCore.IGNORE);
runNegativeTestWithLibs(
new String[] {
+ "p/List.java",
+ "package p;\n" +
+ "public interface List<T> {\n" +
+ " T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+ "}\n",
"p/X1.java",
"package p;\n" +
- "import java.util.*;\n" +
+ "import java.util.Map;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"import static java.lang.annotation.ElementType.*;\n" +
"import java.lang.annotation.*;\n" +
@@ -9587,17 +9724,22 @@
" ^\n" +
"Null type mismatch (type annotations): required \'@NonNull Object\' but this expression has type \'T1 extends @Nullable Number\'\n" +
"----------\n" +
- "3. ERROR in x\\C.java (at line 13)\n" +
+ "3. ERROR in x\\C.java (at line 10)\n" +
+ " return t.toString(); // legal???\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'T1\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "4. ERROR in x\\C.java (at line 13)\n" +
" consume(null); // illegal - OK\n" +
" ^^^^\n" +
"Null type mismatch: required \'T1 extends @Nullable Number\' but the provided value is null\n" +
"----------\n" +
- "4. ERROR in x\\C.java (at line 14)\n" +
+ "5. ERROR in x\\C.java (at line 14)\n" +
" @NonNull Object t = provide(); // error, should warn?\n" +
" ^^^^^^^^^\n" +
"Null type mismatch (type annotations): required \'@NonNull Object\' but this expression has type \'T1 extends @Nullable Number\'\n" +
"----------\n" +
- "5. ERROR in x\\C.java (at line 18)\n" +
+ "6. ERROR in x\\C.java (at line 18)\n" +
" return null; // error, should warn?\n" +
" ^^^^\n" +
"Null type mismatch: required \'T1 extends @Nullable Number\' but the provided value is null\n" +
@@ -9957,20 +10099,20 @@
},
getCompilerOptions(),
"----------\n" +
- "1. WARNING in test\\TestInterdepInvokeNN.java (at line 48)\n" +
+ "1. ERROR in test\\TestInterdepInvokeNN.java (at line 48)\n" +
" return f2(e); // error 1 expected\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'E21 extends T21\' needs unchecked conversion to conform to \'@NonNull E21 extends T21\'\n" +
+ "Null type safety: required '@NonNull' but this expression has type 'E21', a free type variable that may represent a '@Nullable' type\n" +
"----------\n" +
- "2. WARNING in test\\TestInterdepInvokeNN.java (at line 66)\n" +
+ "2. ERROR in test\\TestInterdepInvokeNN.java (at line 66)\n" +
" return f3(e); // error 2 expected\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'E31 extends T31\' needs unchecked conversion to conform to \'@NonNull E31 extends T31\'\n" +
+ "Null type safety: required '@NonNull' but this expression has type 'E31', a free type variable that may represent a '@Nullable' type\n" +
"----------\n" +
- "3. WARNING in test\\TestInterdepInvokeNN.java (at line 84)\n" +
+ "3. ERROR in test\\TestInterdepInvokeNN.java (at line 84)\n" +
" return f4(e); // error 3 expected\n" +
" ^\n" +
- "Null type safety (type annotations): The expression of type \'E41 extends T41\' needs unchecked conversion to conform to \'@NonNull E41 extends T41\'\n" +
+ "Null type safety: required '@NonNull' but this expression has type 'E41', a free type variable that may represent a '@Nullable' type\n" +
"----------\n"
);
}
@@ -10346,4 +10488,891 @@
"----------\n"
);
}
+public void testBug485030() {
+ runConformTestWithLibs(new String[] {
+ "SomeAnnotation.java",
+ "import static java.lang.annotation.ElementType.TYPE_USE;\n" +
+ "import java.lang.annotation.Target;\n" +
+
+ "@Target({ TYPE_USE })\n" +
+ "@interface SomeAnnotation {\n" +
+ "}\n",
+
+ "TestContradictoryOnGenericArray.java",
+ "import java.io.Serializable;\n" +
+
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+
+ "@NonNullByDefault\n" +
+ "public class TestContradictoryOnGenericArray {\n" +
+ " public <@SomeAnnotation Q extends Serializable> void f() {\n" +
+ " final @Nullable Q[] array = null;\n" +
+ " }\n" +
+ "}\n"
+ }, getCompilerOptions(), "");
+}
+public void testBug485302() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "WildCardNullable.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "public class WildCardNullable {\n" +
+ " static class A<T> {\n" +
+ " @Nullable\n" +
+ " T returnNull() {\n" +
+ " return null;\n" +
+ " }\n" +
+ "\n" +
+ " void acceptNonNullT(@NonNull T t) {\n" +
+ " }\n" +
+ "\n" +
+ " void acceptNonNullObject(@NonNull Object x) {\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " static @NonNull Number g(A<? extends @NonNull Number> a) {\n" +
+ " return a.returnNull(); // error 1 expected\n" +
+ " }\n" +
+ "\n" +
+ " public static final <T> void map(final A<@NonNull ? super T> a, T t) {\n" +
+ " a.acceptNonNullT(t); // warning 2 expected\n" +
+ " a.acceptNonNullObject(t); // warning 3 expected\n" +
+ " }\n" +
+ "}\n" +
+ ""
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in WildCardNullable.java (at line 21)\n" +
+ " return a.returnNull(); // error 1 expected\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "Null type mismatch (type annotations): required \'@NonNull Number\' but this expression has type \'@Nullable capture#of ? extends Number\'\n" +
+ "----------\n" +
+ "2. ERROR in WildCardNullable.java (at line 25)\n" +
+ " a.acceptNonNullT(t); // warning 2 expected\n" +
+ " ^\n" +
+ "Null type safety: required '@NonNull' but this expression has type 'T', a free type variable that may represent a '@Nullable' type\n" +
+ "----------\n" +
+ "3. ERROR in WildCardNullable.java (at line 26)\n" +
+ " a.acceptNonNullObject(t); // warning 3 expected\n" +
+ " ^\n" +
+ "Null type safety: required '@NonNull' but this expression has type 'T', a free type variable that may represent a '@Nullable' type\n" +
+ "----------\n"
+ );
+}
+
+public void testBug485027() {
+ runConformTestWithLibs(new String[] {
+ "SomeAnnotation.java",
+ "import static java.lang.annotation.ElementType.TYPE_USE;\n" +
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "import java.lang.annotation.Target;\n" +
+
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@Target({ TYPE_USE })\n" +
+ "@interface SomeAnnotation {\n" +
+ "}\n",
+
+ "Base.java",
+ "import java.io.Serializable;\n" +
+
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+
+ "@NonNullByDefault\n" +
+ "public class Base {\n" +
+ " public <@SomeAnnotation Q extends Serializable> void setValuesArray(Q @Nullable [] value) {\n" +
+ " }\n" +
+ "}\n"
+ }, getCompilerOptions(), "");
+
+ runConformTestWithLibs(new String[] {
+ "Derived.java",
+ "import java.io.Serializable;\n" +
+
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+
+ "@NonNullByDefault\n" +
+ "public class Derived extends Base {\n" +
+ " @Override\n" +
+ " public final <@SomeAnnotation Q1 extends Serializable> void setValuesArray(Q1 @Nullable [] value) {\n" +
+ " }\n" +
+ "}"
+ }, getCompilerOptions(), "");
+}
+public void testBug485565() {
+ runConformTestWithLibs(
+ new String[] {
+ "test2/ClassWithRegistry.java",
+ "package test2;\n" +
+ "\n" +
+ "import java.rmi.registry.Registry;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "public class ClassWithRegistry {\n" +
+ " @Nullable\n" +
+ " public Registry registry;\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ ""
+ );
+ runConformTestWithLibs(
+ new String[] {
+ "test1/ClassWithLambda.java",
+ "package test1;\n" +
+ "\n" +
+ "import test2.ClassWithRegistry;\n" +
+ "\n" +
+ "// must be compiled before ZClassWithBug\n" +
+ "public class ClassWithLambda {\n" +
+ " interface Lambda {\n" +
+ " void f();\n" +
+ " }\n" +
+ "\n" +
+ " public static void invoke(Lambda lambda) {\n" +
+ " lambda.f();\n" +
+ " }\n" +
+ "\n" +
+ " public void f() {\n" +
+ " new ClassWithRegistry(); // must be accessed as class file\n" +
+ " invoke(() -> java.rmi.registry.Registry.class.hashCode());\n" +
+ " }\n" +
+ "}\n",
+ "test1/ZClassWithBug.java",
+ "package test1;\n" +
+ "\n" +
+ "import java.rmi.registry.Registry;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public abstract class ZClassWithBug {\n" +
+ "\n" +
+ " @Nullable\n" +
+ " public Registry rmiregistry;\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ ""
+ );
+}
+public void testBug485814() {
+ runConformTestWithLibs(
+ new String[] {
+ "test/ExplainedResult.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class ExplainedResult<V2> extends Result<V2> {\n" +
+ "\n" +
+ " public ExplainedResult(int score, V2 extractedValue2) {\n" +
+ " super(score, extractedValue2);\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public <OtherV2> ExplainedResult<OtherV2> withValue(OtherV2 otherValue2) {\n" +
+ " return new ExplainedResult<OtherV2>(this.score, otherValue2);\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ "test/Result.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class Result<V1> {\n" +
+ "\n" +
+ " public final int score;\n" +
+ "\n" +
+ " public final V1 extractedValue;\n" +
+ "\n" +
+ " public Result(int score, V1 extractedValue1) {\n" +
+ " this.score = score;\n" +
+ " this.extractedValue = extractedValue1;\n" +
+ " }\n" +
+ "\n" +
+ " public <OtherV1> Result<OtherV1> withValue(OtherV1 otherValue1) {\n" +
+ " return new Result<OtherV1>(score, otherValue1);\n" +
+ " }\n" +
+ "}\n" +
+ ""
+ },
+ getCompilerOptions(),
+ ""
+ );
+}
+public void testBug485581() {
+ runConformTestWithLibs(
+ new String[] {
+ "test/MatchResult.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class MatchResult<V> implements Comparable<MatchResult<?>> {\n" +
+ " public final int score;\n" +
+ " public final V value;\n" +
+ "\n" +
+ " public MatchResult(int score, V value) {\n" +
+ " this.score = score;\n" +
+ " this.value = value;\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public int compareTo(MatchResult<?> o) {\n" +
+ " return score - o.score;\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ ""
+ );
+ runConformTestWithLibs(
+ new String[] {
+ "test/FVEHandler.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class FVEHandler {\n" +
+ " public static void process(MatchResult<?> matchResult) {\n" +
+ " if (matchResult.value != null) {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ ""
+ );
+}
+public void testBug485374() {
+ runConformTestWithLibs(
+ new String[] {
+ "test/I.java",
+ "package test;\n" +
+ "public interface I<W> {\n" +
+ " public class Nested {\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ "test/D.java",
+ "package test;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class D implements I<I.@NonNull Nested> {\n" +
+ "}\n" +
+ ""
+ },
+ getCompilerOptions(),
+ ""
+ );
+ runNegativeTestWithLibs(
+ new String[] {
+ "test2/Import.java",
+ "package test2;\n" +
+ "import test.D;\n" +
+ "class Import {}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in test2\\Import.java (at line 2)\n" +
+ " import test.D;\n" +
+ " ^^^^^^\n" +
+ "The import test.D is never used\n" +
+ "----------\n"
+ );
+}
+
+public void testBug466556a() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/C.java",
+ "package test;\n" +
+ "class C<T extends Number> {\n" +
+ " int consume(T t) {\n" +
+ " return t.intValue(); // NOT OK since T could be nullable\n" +
+ " }\n" +
+ " T provide() {\n" +
+ " return null; // NOT OK since T could require nonnull\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\C.java (at line 4)\n" +
+ " return t.intValue(); // NOT OK since T could be nullable\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in test\\C.java (at line 7)\n" +
+ " return null; // NOT OK since T could require nonnull\n" +
+ " ^^^^\n" +
+ "Null type mismatch (type annotations): \'null\' is not compatible to the free type variable \'T\'\n" +
+ "----------\n"
+ );
+}
+public void testBug466556nonfree() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/C.java",
+ "package test;\n" +
+ "class C<T extends @org.eclipse.jdt.annotation.NonNull Number> {\n" +
+ " int consume(T t) {\n" +
+ " return t.intValue(); // OK since T has upper bound with @NonNull\n" +
+ " }\n" +
+ " T provide() {\n" +
+ " return null; // NOT OK since T could require nonnull\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\C.java (at line 7)\n" +
+ " return null; // NOT OK since T could require nonnull\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'T extends @NonNull Number\' but the provided value is null\n" +
+ "----------\n"
+ );
+}
+public void testBug466556b() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/C.java",
+ "package test;\n" +
+ "\n" +
+ "import java.util.function.Supplier;\n" +
+ "\n" +
+ "class C<T> {\n" +
+ " int consume(T t) {\n" +
+ " return t.hashCode();\n" +
+ " }\n" +
+ " void consume2(Supplier<T> s) {\n" +
+ " s.get().hashCode();\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\C.java (at line 7)\n" +
+ " return t.hashCode();\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in test\\C.java (at line 10)\n" +
+ " s.get().hashCode();\n" +
+ " ^^^^^^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n"
+ );
+}
+public void testBug466556c() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/C.java",
+ "package test;\n" +
+ "\n" +
+ "import java.util.function.Supplier;\n" +
+ "\n" +
+ "class C<T extends Number> {\n" +
+ " int consume(T t) {\n" +
+ " Number n = t;\n" +
+ " return n.intValue();\n" +
+ " }\n" +
+ "\n" +
+ " int consume2(Supplier<T> s) {\n" +
+ " Number n = s.get();\n" +
+ " return n.intValue();\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\C.java (at line 8)\n" +
+ " return n.intValue();\n" +
+ " ^\n" +
+ "Potential null pointer access: The variable n may be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in test\\C.java (at line 13)\n" +
+ " return n.intValue();\n" +
+ " ^\n" +
+ "Potential null pointer access: The variable n may be null at this location\n" +
+ "----------\n"
+ );
+}
+public void testBug466556field() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/D.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "class E<T> {\n" +
+ " T t;\n" +
+ "}\n" +
+ "\n" +
+ "class D<T> {\n" +
+ " enum X {\n" +
+ " x\n" +
+ " };\n" +
+ "\n" +
+ " T t1;\n" +
+ " T t2;\n" +
+ " T t3;\n" +
+ " @Nullable\n" +
+ " T t4;\n" +
+ " @NonNull\n" +
+ " T t5;\n" +
+ " @NonNull\n" +
+ " T t6;\n" +
+ " @NonNull\n" +
+ " T t7;\n" +
+ "\n" +
+ " D(@NonNull T t) {\n" +
+ " t2 = t;\n" +
+ " switch (X.x) {\n" +
+ " case x:\n" +
+ " t1 = t;\n" +
+ " t5 = t;\n" +
+ " }\n" +
+ " t6 = t;\n" +
+ " }\n" +
+ "\n" +
+ " void f() {\n" +
+ " t1.hashCode();\n" +
+ " t2.hashCode();\n" +
+ " t3.hashCode();\n" +
+ " t4.hashCode();\n" +
+ " t5.hashCode();\n" +
+ " t6.hashCode();\n" +
+ " t7.hashCode();\n" +
+ " T t = t1;\n" +
+ " t.hashCode();\n" +
+ " }\n" +
+ " void g() {\n" +
+ " if(t1 != null)\n" +
+ " t1.hashCode();\n // problem report expected because syntactic null analysis for fields is off\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\D.java (at line 7)\n" +
+ " T t;\n" +
+ " ^\n" +
+ "The field t may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type\n" +
+ "----------\n" +
+ "2. ERROR in test\\D.java (at line 27)\n" +
+ " D(@NonNull T t) {\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The field t1 may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" +
+ "----------\n" +
+ "3. ERROR in test\\D.java (at line 27)\n" +
+ " D(@NonNull T t) {\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The field t3 may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" +
+ "----------\n" +
+ "4. ERROR in test\\D.java (at line 27)\n" +
+ " D(@NonNull T t) {\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The @NonNull field t5 may not have been initialized. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" +
+ "----------\n" +
+ "5. ERROR in test\\D.java (at line 27)\n" +
+ " D(@NonNull T t) {\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The @NonNull field t7 may not have been initialized. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" +
+ "----------\n" +
+ "6. ERROR in test\\D.java (at line 38)\n" +
+ " t1.hashCode();\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "7. ERROR in test\\D.java (at line 39)\n" +
+ " t2.hashCode();\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "8. ERROR in test\\D.java (at line 40)\n" +
+ " t3.hashCode();\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "9. ERROR in test\\D.java (at line 41)\n" +
+ " t4.hashCode();\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has a \'@Nullable\' type\n" +
+ "----------\n" +
+ "10. ERROR in test\\D.java (at line 46)\n" +
+ " t.hashCode();\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "11. ERROR in test\\D.java (at line 50)\n" +
+ " t1.hashCode();\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n"
+ );
+}
+public void testBug466556withRaw() {
+ runConformTestWithLibs(
+ new String[] {
+ "test/TestWithRaw.java",
+ "package test;\n" +
+ "\n" +
+ "public class TestWithRaw {\n" +
+ " @SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n" +
+ " public static void uncheckedEnumValueOf(final Class<?> valueClass, final String value) {\n" +
+ " Class valueClass2 = valueClass;\n" +
+ " Enum.valueOf(valueClass2, value).name();\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ ""
+ );
+}
+public void testBug466556withPGMB() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/TestWithParameterizedGenericMethodBinding.java",
+ "package test;\n" +
+ "\n" +
+ "public class TestWithParameterizedGenericMethodBinding {\n" +
+ " static <T, E extends T> T f1(E e) {\n" +
+ " return e;\n" +
+ " }\n" +
+ "\n" +
+ " static <T11, E11 extends T11> void g11(E11 e) {\n" +
+ " f1(e).hashCode();\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\TestWithParameterizedGenericMethodBinding.java (at line 9)\n" +
+ " f1(e).hashCode();\n" +
+ " ^^^^^\n" +
+ "Potential null pointer access: this expression has type \'E11\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n"
+ );
+}
+public void testBug466556captures() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/TestCapture.java",
+ "package test;\n" +
+ "\n" +
+ "class I {\n" +
+ " int i;\n" +
+ "\n" +
+ " String s() {\n" +
+ " return \"\";\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class KE<E extends I> {\n" +
+ " public final E e;\n" +
+ "\n" +
+ " public E getE() {\n" +
+ " return e;\n" +
+ " }\n" +
+ "\n" +
+ " public KE(E element) {\n" +
+ " this.e = element;\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class TestFreeTypeVariable<E2 extends I> {\n" +
+ " public void test(KE<E2> ke) {\n" +
+ " int i1 = ke.e.i; // error 1\n" +
+ " ke.e.s().substring(i1); // error 2\n" +
+ " int i2 = ke.getE().i; // error 3\n" +
+ " ke.getE().s().substring(i2); // error 4\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "public class TestCapture {\n" +
+ " public void test(KE<? extends I> ke) {\n" +
+ " int i1 = ke.e.i; // error 5\n" +
+ " ke.e.s().substring(i1); // error 6\n" +
+ " int i2 = ke.getE().i; // error 7\n" +
+ " ke.getE().s().substring(i2); // error 8\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\TestCapture.java (at line 25)\n" +
+ " int i1 = ke.e.i; // error 1\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in test\\TestCapture.java (at line 26)\n" +
+ " ke.e.s().substring(i1); // error 2\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "3. ERROR in test\\TestCapture.java (at line 27)\n" +
+ " int i2 = ke.getE().i; // error 3\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "4. ERROR in test\\TestCapture.java (at line 28)\n" +
+ " ke.getE().s().substring(i2); // error 4\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "5. ERROR in test\\TestCapture.java (at line 34)\n" +
+ " int i1 = ke.e.i; // error 5\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'capture#1-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "6. ERROR in test\\TestCapture.java (at line 35)\n" +
+ " ke.e.s().substring(i1); // error 6\n" +
+ " ^\n" +
+ "Potential null pointer access: this expression has type \'capture#2-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "7. ERROR in test\\TestCapture.java (at line 36)\n" +
+ " int i2 = ke.getE().i; // error 7\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: this expression has type \'capture#3-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "8. ERROR in test\\TestCapture.java (at line 37)\n" +
+ " ke.getE().s().substring(i2); // error 8\n" +
+ " ^^^^^^^^^\n" +
+ "Potential null pointer access: this expression has type \'capture#4-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n"
+ );
+}
+public void testBug466556Loops() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/TestLoop.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class TestLoop<T> {\n" +
+ " boolean b;\n" +
+ "\n" +
+ " public static void nn(@NonNull Object value) {\n" +
+ " assert value != null;\n" +
+ " }\n" +
+ "\n" +
+ " public void testDoWhile(T t1) {\n" +
+ " nn(t1); // 1: unchecked warning\n" +
+ " do {\n" +
+ " nn(t1); // 2: unchecked warning\n" +
+ " t1.hashCode(); // 3: Potential null pointer access...free type variable\n" +
+ " } while (b);\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhileWithBreak(T t1) {\n" +
+ " while (true) {\n" +
+ " nn(t1); // 4: unchecked warning\n" +
+ " t1.hashCode(); // 5: Potential null pointer access...free type variable\n" +
+ " if (b)\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testWhile(T t1) {\n" +
+ " while (TestLoop.class.hashCode() == 4711) {\n" +
+ " nn(t1); // 6: unchecked warning\n" +
+ " t1.hashCode(); // 7: Potential null pointer access...free type variable\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testFor(T t1) {\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " nn(t1); // 8: unchecked warning\n" +
+ " t1.hashCode(); // 9: Potential null pointer access...free type variable\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public void testForEach(T t1) {\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " nn(t1); // 10: unchecked warning\n" +
+ " t1.hashCode(); // 11: Potential null pointer access: The variable t1 may be null at this location\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\TestLoop.java (at line 13)\n" +
+ " nn(t1); // 1: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "2. ERROR in test\\TestLoop.java (at line 15)\n" +
+ " nn(t1); // 2: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "3. ERROR in test\\TestLoop.java (at line 16)\n" +
+ " t1.hashCode(); // 3: Potential null pointer access...free type variable\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "4. ERROR in test\\TestLoop.java (at line 22)\n" +
+ " nn(t1); // 4: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "5. ERROR in test\\TestLoop.java (at line 23)\n" +
+ " t1.hashCode(); // 5: Potential null pointer access...free type variable\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "6. ERROR in test\\TestLoop.java (at line 31)\n" +
+ " nn(t1); // 6: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "7. ERROR in test\\TestLoop.java (at line 32)\n" +
+ " t1.hashCode(); // 7: Potential null pointer access...free type variable\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "8. ERROR in test\\TestLoop.java (at line 38)\n" +
+ " nn(t1); // 8: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "9. ERROR in test\\TestLoop.java (at line 39)\n" +
+ " t1.hashCode(); // 9: Potential null pointer access...free type variable\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "10. ERROR in test\\TestLoop.java (at line 45)\n" +
+ " nn(t1); // 10: unchecked warning\n" +
+ " ^^\n" +
+ "Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n" +
+ "11. ERROR in test\\TestLoop.java (at line 46)\n" +
+ " t1.hashCode(); // 11: Potential null pointer access: The variable t1 may be null at this location\n" +
+ " ^^\n" +
+ "Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" +
+ "----------\n"
+ );
+}
+public void testBug461268() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+ compilerOptions.put(CompilerOptions.OPTION_PessimisticNullAnalysisForFreeTypeVariables, JavaCore.IGNORE);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " void test(List<@NonNull String> list) {\n" +
+ " @NonNull String s = list.get(0);\n" +
+ " }\n" +
+ "}\n"
+ },
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " @NonNull String s = list.get(0);\n" +
+ " ^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull String>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n");
+}
+public void testBug461268invoke() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.Map;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " void test(Map<Object, @NonNull String> map) {\n" +
+ " map.get(this).length();\n" +
+ " }\n" +
+ "}\n"
+ },
+ compilerOptions,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " map.get(this).length();\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'Map<Object,@NonNull String>\'. Type \'Map<K,V>\' doesn\'t seem to be designed with null type annotations in mind\n" +
+ "----------\n");
+}
+public void testBug461268nnbd() {
+ Map compilerOptions = getCompilerOptions();
+ compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+ runConformTestWithLibs(
+ new String[] {
+ "test2/Container.java",
+ "package test2;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class Container<T> {\n" +
+ " public static <T> T getFrom(Container<T> container) {\n" +
+ " return container.get();\n" +
+ " }\n" +
+ "\n" +
+ " private final T t;\n" +
+ "\n" +
+ " public Container(T t) {\n" +
+ " this.t = t;\n" +
+ " }\n" +
+ "\n" +
+ " private T get() {\n" + // we really mean 'T' unannotated, believe it due to @NonNullByDefault
+ " return this.t;\n" +
+ " }\n" +
+ "}\n",
+ },
+ getCompilerOptions(),
+ ""
+ );
+ runConformTestWithLibs(
+ new String[] {
+ "test/Test.java",
+ "package test;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+ "\n" +
+ "import test2.Container;\n" +
+ "\n" +
+ "@NonNullByDefault\n" +
+ "public class Test {\n" +
+ " String f(Container<String> c) {\n" +
+ " return Container.getFrom(c);\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ ""
+ );
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
index e9111e8..86a4714 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 GoPivotal, Inc. All Rights Reserved.
+ * Copyright (c) 2014, 2016 GoPivotal, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
* Olivier Tardieu tardieu@us.ibm.com - Contributions for
* Bug 442416 - $deserializeLambda$ missing cases for nested lambdas
* Bug 442418 - $deserializeLambda$ off-by-one error when deserializing the captured arguments of a lambda that also capture this
+ * IBM Corporation - Additional tests
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -1532,7 +1533,254 @@
null,true,
new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
}
-
+
+ public void testbug479119() {
+ this.runConformTest(
+ new String[]{
+ "Testbed.java",
+ "import java.io.ObjectStreamClass;\n" +
+ "import java.io.Serializable;\n" +
+ "import java.lang.invoke.SerializedLambda;\n" +
+ "import java.lang.reflect.Method;\n" +
+ "import java.util.function.IntFunction;\n" +
+ "import java.util.stream.Stream;\n" +
+ "public class Testbed {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" +
+ " }\n" +
+ " private static void foo() { }\n" +
+ " static interface MethodRef extends Runnable, Serializable { }\n" +
+ " private static Method getMethod(MethodRef methodRef) {\n" +
+ " try {\n" +
+ " final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" +
+ " invokeWriteReplaceMethod.setAccessible(true);\n" +
+ " final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" +
+ " ObjectStreamClass.lookupAny(methodRef.getClass()),\n" +
+ " methodRef\n" +
+ " );\n" +
+ " System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" +
+ " final Method[] methods = Stream.of(Class.forName(l.getImplClass()).getDeclaredMethods()).\n" +
+ " filter(m -> m.getName().equals(l.getImplMethodName())).\n" +
+ " toArray(Method[]::new);\n" +
+ " if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" +
+ " return methods[0];\n" +
+ " } catch(Exception e) {\n" +
+ " throw new RuntimeException(e);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Looking for Testbed.foo\n" +
+ "Looking for Testbed.foo\n" +
+ "true",
+ null,true,
+ new String[]{"-Ddummy"});
+
+ String bootstrapEntries = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "Testbed.class");
+ String expectedOutput =
+ "0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
+ " Method arguments:\n"+
+ " ()V\n"+
+ " invokestatic Testbed.foo:()V\n"+
+ " ()V\n"+
+ " 1\n"+
+ "1: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
+ " Method arguments:\n"+
+ " (Ljava/lang/Object;)Z\n"+
+ " invokestatic Testbed.lambda$0:(Ljava/lang/invoke/SerializedLambda;Ljava/lang/reflect/Method;)Z\n"+
+ " (Ljava/lang/reflect/Method;)Z\n"+
+ "2: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
+ " Method arguments:\n"+
+ " (I)Ljava/lang/Object;\n"+
+ " invokestatic Testbed.lambda$1:(I)[Ljava/lang/reflect/Method;\n"+
+ " (I)[Ljava/lang/reflect/Method;\n";
+
+ checkExpected(expectedOutput, bootstrapEntries);
+ }
+
+ public void testbug479119a() {
+ this.runConformTest(
+ new String[]{
+ "Testbed.java",
+ "import java.io.ObjectStreamClass;\n" +
+ "import java.io.Serializable;\n" +
+ "import java.lang.invoke.SerializedLambda;\n" +
+ "import java.lang.reflect.Constructor;\n" +
+ "import java.lang.reflect.Executable;\n" +
+ "import java.lang.reflect.Method;\n" +
+ "import java.util.function.IntFunction;\n" +
+ "import java.util.stream.Stream;\n" +
+ "public class Testbed {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" +
+ " System.out.println(getMethod(new Foo()::method).equals(getMethod(new Bar()::method)));\n" +
+ " System.out.println(getMethod(MethodRefImpl::new).equals(getMethod(MethodRefImpl::new)));\n" +
+ " }\n" +
+ " static class MethodRefImpl implements MethodRef {\n" +
+ " @Override\n" +
+ " public void run() {}\n" +
+ " }\n" +
+ " public static class Base {\n" +
+ " public void method () {}\n" +
+ " }\n" +
+ " public static class Foo extends Base {}\n" +
+ " public static class Bar extends Base {}\n" +
+ " private static void foo() { }\n" +
+ " static interface MethodRef extends Runnable, Serializable { }\n" +
+ " private static Executable getMethod(MethodRef methodRef) {\n" +
+ " try {\n" +
+ " final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" +
+ " invokeWriteReplaceMethod.setAccessible(true);\n" +
+ " final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" +
+ " ObjectStreamClass.lookupAny(methodRef.getClass()),\n" +
+ " methodRef\n" +
+ " );\n" +
+ " System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" +
+ " boolean isConstructor = l.getImplMethodName().indexOf(\"<init>\") >= 0;\n" +
+ " final Executable[] methods = Stream.of(isConstructor ? Class.forName(l.getImplClass()).getDeclaredConstructors() : Class.forName(l.getImplClass()).getDeclaredMethods()).\n" +
+ " filter(m -> m.getName().equals(isConstructor ? l.getImplClass() : l.getImplMethodName())).\n" +
+ " toArray(isConstructor ? Constructor[]::new : Method[]::new);\n" +
+ " if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" +
+ " return methods[0];\n" +
+ " } catch(Exception e) {\n" +
+ " throw new RuntimeException(e);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Looking for Testbed.foo\n" +
+ "Looking for Testbed.foo\n" +
+ "true\n" +
+ "Looking for Testbed$Base.method\n" +
+ "Looking for Testbed$Base.method\n" +
+ "true\n" +
+ "Looking for Testbed$MethodRefImpl.<init>\n" +
+ "Looking for Testbed$MethodRefImpl.<init>\n" +
+ "true",
+ null,true,
+ new String[]{"-Ddummy"});
+ }
+
+ // Serializable reference expressions that share the same name
+ public void testbug479119b() {
+ this.runConformTest(
+ new String[]{
+ "X.java",
+ "import java.io.ByteArrayInputStream;\n" +
+ "import java.io.ByteArrayOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "import java.io.ObjectInputStream;\n" +
+ "import java.io.ObjectOutputStream;\n" +
+ "import java.io.Serializable;\n" +
+ "public class X {\n" +
+ " public static interface Consumer<T> extends Serializable {\n" +
+ " void accept(T t);\n" +
+ " }\n" +
+ " public static class Foo {\n" +
+ " public void method () {\n" +
+ " System.out.println(\"Foo\");\n" +
+ " }\n" +
+ " }\n" +
+ " public static class Bar {\n" +
+ " public void method () {\n" +
+ " System.out.println(\"Bar\");\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main (String[] args) throws IOException, ClassNotFoundException {\n" +
+ " Consumer<Foo> foo = Foo::method;\n" +
+ " Consumer<Bar> bar = Bar::method;\n" +
+ " Consumer<Foo> baz = (b) -> {b.method();};\n" +
+ " ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" +
+ " try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" +
+ " oo.writeObject(bar);\n" +
+ " }\n" +
+ " try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" +
+ " Consumer<Bar> x = (Consumer)oi.readObject();\n" +
+ " x.accept(new Bar());\n" +
+ " }\n" +
+ " debug.reset();\n" +
+ " try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" +
+ " oo.writeObject(foo);\n" +
+ " }\n" +
+ " try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" +
+ " Consumer<Foo> x = (Consumer)oi.readObject();\n" +
+ " x.accept(new Foo());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Bar\n" +
+ "Foo",
+ null,true,
+ new String[]{"-Ddummy"});
+ }
+ public void testbug479119_comment20() {
+ this.runConformTest(
+ new String[]{
+ "Testbed.java",
+ "import java.io.ByteArrayInputStream;\n" +
+ "import java.io.ByteArrayOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "import java.io.ObjectInputStream;\n" +
+ "import java.io.ObjectOutputStream;\n" +
+ "import java.io.Serializable;\n" +
+ "interface FI extends Serializable{\n" +
+ " void run(Testbed args);\n" +
+ "}\n" +
+ "interface IF extends Serializable{\n" +
+ " void run();\n" +
+ "}\n" +
+ "public class Testbed implements Serializable{\n" +
+ " String f;\n" +
+ " Testbed(String str) {\n" +
+ " f = str;\n" +
+ " }\n" +
+ " void test() throws IOException, ClassNotFoundException {\n" +
+ " accept(Testbed::foo);\n" +
+ " accept(this::foo); \n" +
+ " }\n" +
+ " void foo() {\n" +
+ " System.out.println(this.f);\n" +
+ " }\n" +
+ " void accept(FI fi) {\n" +
+ " fi.run(this);\n" +
+ " }\n" +
+ " void accept(IF i) {\n" +
+ " i.run();\n" +
+ " }\n" +
+ " public static void main(String[] args) throws ClassNotFoundException, IOException {\n" +
+ " Testbed t = new Testbed(\"IF\");\n" +
+ " Testbed t2 = new Testbed(\"FI\");\n" +
+ " IF i = t::foo;\n" +
+ " FI f = Testbed::foo;\n" +
+ " ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" +
+ " try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" +
+ " {\n" +
+ " oo.writeObject(i);\n" +
+ " }\n" +
+ " try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" +
+ " {\n" +
+ " IF x = (IF)oi.readObject();\n" +
+ " t.accept(x);\n" +
+ " }\n" +
+ " debug=new ByteArrayOutputStream();\n" +
+ " try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" +
+ " {\n" +
+ " oo.writeObject(f);\n" +
+ " }\n" +
+ " try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" +
+ " {\n" +
+ " FI x = (FI)oi.readObject();\n" +
+ " t2.accept(x);\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ },
+ "IF\n" +
+ "FI",
+ null,true,
+ new String[]{"-Ddummy"});
+ }
// ---
private void checkExpected(String expected, String actual) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
index e10053f..012cffa 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
@@ -3226,5 +3226,36 @@
"}"
});
}
-}
-
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=442580
+ // Explicit static import after two wildcard imports is ambiguous (works in javac)
+ public void testBug442580() {
+ this.runConformTest(new String [] {
+ "a/A.java",
+ "package a;\n" +
+ "\n" +
+ "public class A {\n" +
+ " public static void foo() {\n" +
+ " System.out.println(\"A.foo\");\n" +
+ " }\n" +
+ "}",
+ "b/B.java",
+ "package b;\n" +
+ "\n" +
+ "public class B {\n" +
+ " public static void foo() {\n" +
+ " System.out.println(\"B.foo\");\n" +
+ " }\n" +
+ "}",
+ "Test.java",
+ "import static a.A.*;\n" +
+ "import static b.B.*;\n" +
+ "import static b.B.foo;\n" +
+ "\n" +
+ "public class Test {\n" +
+ " public static void main(String[] args) {\n" +
+ " foo();\n" +
+ " }\n" +
+ "}"
+ });
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
index c463de4..a48eb46 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.10.100.qualifier
+Bundle-Version: 3.10.200.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 66b2fb2..144082d 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core.tests.model</artifactId>
- <version>3.10.100-SNAPSHOT</version>
+ <version>3.10.200-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
index 03e0a71..f9f412f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -5183,52 +5183,6 @@
IMethodBinding binding = lambdaExpression.resolveMethodBinding();
assertTrue("Should be a varargs", binding.isVarargs());
}
-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=463942
-public void testBug463942_001() throws JavaModelException {
- String contents =
- "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
- "@interface Marker {\n" +
- " String value() default \"\";\n" +
- "}\n" +
- "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
- "@interface Marker2 {\n" +
- " String value() default \"22\";\n" +
- "}\n" +
- "public class X {\n" +
- " public String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") [] str = null;\n" +
- "}";
-
- this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
- ASTNode node = buildAST(contents, this.workingCopy);
- assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
- CompilationUnit compilationUnit = (CompilationUnit) node;
- assertProblemsSize(compilationUnit, 0);
-
- /* public String @Marker("i0") @Marker2 [] [] @Marker("i1") [] str = null; */
- node = getASTNode(compilationUnit, 2, 0);
- assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
- FieldDeclaration field = (FieldDeclaration) node;
- List fragments = field.fragments();
- assertEquals("Incorrect no of fragments", 1, fragments.size());
- VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
- IVariableBinding variable = fragment.resolveBinding();
- assertNotNull("Should not be null", variable);
- ITypeBinding typeBinding = variable.getType();
- assertNotNull("Should not be null", typeBinding);
- IAnnotationBinding[][] dimAnnotations = typeBinding.getTypeAnnotationsOnDimensions();
-
- assertEquals("Incorrect type annotations", 3, dimAnnotations.length);
- IAnnotationBinding[] annotations = dimAnnotations[0];
- assertTrue("Incorrect number of annotations", annotations.length == 2);
- assertEquals("Incorrect type annotations", "@Marker(value = i0)", annotations[0].toString());
- assertEquals("Incorrect type annotations", "@Marker2()", annotations[1].toString());
- annotations = dimAnnotations[1];
- assertTrue("Incorrect number of annotations", annotations.length == 0);
- annotations = dimAnnotations[2];
- assertTrue("Incorrect number of annotations", annotations.length == 1);
- assertEquals("Incorrect type annotations", "@Marker(value = i1)", annotations[0].toString());
-
-}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399792
public void testBug470794_001() throws JavaModelException {
@@ -5245,7 +5199,7 @@
"}\n" +
"interface J {\n" +
" public void foo();\n" +
- " public void bar();\n" +
+ " public default void bar() {}\n" +
"}\n" +
"interface K {\n" +
" public void foo();\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
index 0e046f7..20affbf 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
@@ -2569,4 +2569,87 @@
deleteFile("/Converter18/src/X.java");
}
}
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=487716
+ public void testBug487716() throws Exception {
+ try {
+ String contents =
+ "import java.lang.annotation.ElementType; \n" +
+ "import java.lang.annotation.Target; \n" +
+ "@Target({ElementType.TYPE_USE, ElementType.CONSTRUCTOR})\n" +
+ "@interface A {} \n" +
+ "class X {\n" +
+ " @A X() {}\n" +
+ " X _x_ = new X();\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy, false);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+
+ List types = compilationUnit.types();
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+
+ // On the Allocation expression type - new X()
+ FieldDeclaration field = typeDecl.getFields()[0];
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ITypeBinding type = fragment.getInitializer().resolveTypeBinding();
+ IAnnotationBinding[] annots = type.getTypeAnnotations();
+ assertEquals("Incorrect no of annotations", 1, annots.length);
+
+ // On constructor declaration - X()
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ assertTrue("Should be a constructor", method.isConstructor());
+ IMethodBinding methodBinding = method.resolveBinding();
+ annots = methodBinding.getAnnotations();
+ assertEquals("Incorrect no of annotations", 1, annots.length);
+ } finally {
+ deleteFile("/Converter18/src/X.java");
+ }
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=487716
+ public void testBug487716a() throws Exception {
+ try {
+ String contents =
+ "package p;\n" +
+ "import java.lang.annotation.ElementType; \n" +
+ "import java.lang.annotation.Target; \n" +
+ "@Target({ElementType.TYPE_USE})\n" +
+ "@interface A {} \n" +
+ "class X {\n" +
+ " @A X() {}\n" +
+ " class Y {\n" +
+ " @A Y() {}\n" +
+ " Y _y_ = new X().new Y();\n" +
+ " }\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/p/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy, false);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+
+ List types = compilationUnit.types();
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+
+ assertEquals(1, typeDecl.getTypes().length);
+ typeDecl = typeDecl.getTypes()[0];
+
+ // On the Qualified Allocation expression type - new X().new Y()
+ FieldDeclaration field = typeDecl.getFields()[0];
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ITypeBinding type = fragment.getInitializer().resolveTypeBinding();
+ IAnnotationBinding[] annots = type.getTypeAnnotations();
+ assertEquals("Incorrect no of annotations", 1, annots.length);
+
+ // On constructor declaration - Y()
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ assertTrue("Should be a constructor", method.isConstructor());
+ IMethodBinding methodBinding = method.resolveBinding();
+ annots = methodBinding.getAnnotations();
+ assertEquals("Incorrect no of annotations", 0, annots.length);
+ } finally {
+ deleteFile("/Converter18/src/X.java");
+ }
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 7873823..fd7718e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -12342,4 +12342,15 @@
"}";
formatSource(source);
}
+/**
+ * https://bugs.eclipse.org/487375 - [formatter] block comment in front of method signature effects too much indentation
+ */
+public void testBug487375() {
+ String source =
+ "public class Test {\r\n" +
+ " /* public */ void foo() {\r\n" +
+ " }\r\n" +
+ "}";
+ formatSource(source);
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index d7ecc6e..2c7499a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -8038,6 +8038,7 @@
public void test558() {
Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
+ options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -8078,6 +8079,7 @@
*/
public void test559() {
Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
+ options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -8382,6 +8384,7 @@
public void test575() {
Map options = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
+ options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -10879,6 +10882,7 @@
*/
public void test728() {
this.formatterPrefs = null;
+ this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT);
this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD);
this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD);
this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE);
@@ -13302,4 +13306,561 @@
"}"
);
}
+/**
+ * https://bugs.eclipse.org/487375 - [formatter] block comment in front of method signature effects too much indentation
+ */
+public void testBug486719() {
+ this.formatterPrefs.page_width = 80;
+ String source =
+ "public class Example {\n" +
+ " int foo(Object a, Object b, Object c) {\n" +
+ " if (a == b) return 1;if (a == c) return 2; //$IDENTITY-COMPARISON$\n" +
+ " boolean aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = a == b && a == c; //$IDENTITY-COMPARISON$\n" +
+ " return 3;\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628a() {
+ setComplianceLevel(CompilerOptions.VERSION_1_5);
+ this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = false;
+ String source =
+ "public enum SomeEnum {\n" +
+ " @XmlEnumValue(\"val1\") VAL_1(\"val1\"), @XmlEnumValue(\"val2\") VAL_2(\"val2\");\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628b() {
+ setComplianceLevel(CompilerOptions.VERSION_1_5);
+ this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = true;
+ String source =
+ "public enum SomeEnum {\n" +
+ " @XmlEnumValue(\"val1\")\n" +
+ " VAL_1(\"val1\"), @XmlEnumValue(\"val2\")\n" +
+ " VAL_2(\"val2\");\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628c() {
+ setComplianceLevel(CompilerOptions.VERSION_1_5);
+ this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = true;
+ this.formatterPrefs.alignment_for_enum_constants = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "public enum SomeEnum {\n" +
+ " @XmlEnumValue(\"val1\")\n" +
+ " VAL_1(\"val1\"),\n" +
+ " @XmlEnumValue(\"val2\")\n" +
+ " VAL_2(\"val2\");\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628d() {
+ setComplianceLevel(CompilerOptions.VERSION_1_5);
+ this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = false;
+ this.formatterPrefs.alignment_for_enum_constants = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "public enum SomeEnum {\n" +
+ " @XmlEnumValue(\"val1\") VAL_1(\"val1\"),\n" +
+ " @XmlEnumValue(\"val2\") VAL_2(\"val2\");\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264a() {
+ this.formatterPrefs.page_width = 50;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (int counter = 0; counter < argument; counter++) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264b() {
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_COMPACT_SPLIT;
+ this.formatterPrefs.page_width = 50;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (int counter = 0; counter < argument; counter++) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (int counter = 0; counter < argument;\n" +
+ " counter++) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264c() {
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (int counter = 0; counter < argument; counter++) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (\n" +
+ " int counter = 0;\n" +
+ " counter < argument;\n" +
+ " counter++) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264d() {
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (int counter = 0; ; ) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (\n" +
+ " int counter = 0;;) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264e() {
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (;;argument--, argument--) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (;;\n" +
+ " argument--, argument--) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264f() {
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " int foo(int argument) {\n" +
+ " for (;;) {\n" +
+ " doSomething(counter);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/465910 - [formatter] add a 'wrap before operator' option for conditional expressions
+ */
+public void testBug465910() {
+ this.formatterPrefs.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " Result foo(boolean argument) {\n" +
+ " return argument ? doOneThing() : doOtherThing();\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " Result foo(boolean argument) {\n" +
+ " return argument\n" +
+ " ? doOneThing()\n" +
+ " : doOtherThing();\n" +
+ " }\n" +
+ "}"
+ );
+ this.formatterPrefs.wrap_before_conditional_operator = false;
+ formatSource(source,
+ "class Example {\n" +
+ " Result foo(boolean argument) {\n" +
+ " return argument ?\n" +
+ " doOneThing() :\n" +
+ " doOtherThing();\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/325631 - [formatter] Code formatter Expressions > Assignments lacks "Wrap before operator" option
+ */
+public void testBug325631() {
+ this.formatterPrefs.alignment_for_assignment = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String source =
+ "class Example {\n" +
+ " String value = \"\";\n" +
+ " void foo(boolean argument) {\n" +
+ " if (\"test\".equals(value = artument))\n" +
+ " doSomething();\n" +
+ " }\n" +
+ "}";
+ formatSource(source,
+ "class Example {\n" +
+ " String value =\n" +
+ " \"\";\n" +
+ "\n" +
+ " void foo(boolean argument) {\n" +
+ " if (\"test\".equals(value =\n" +
+ " artument))\n" +
+ " doSomething();\n" +
+ " }\n" +
+ "}");
+ this.formatterPrefs.wrap_before_assignment_operator = true;
+ formatSource(source,
+ "class Example {\n" +
+ " String value\n" +
+ " = \"\";\n" +
+ "\n" +
+ " void foo(boolean argument) {\n" +
+ " if (\"test\".equals(value\n" +
+ " = artument))\n" +
+ " doSomething();\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540a() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out01.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540b() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out02.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540c() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out03.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540d() throws JavaModelException {
+ this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out04.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540e() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out05.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540f() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out06.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540g() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out07.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540h() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ this.formatterPrefs.parenthesis_positions_in_lambda_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out08.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540i() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out09.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540j() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_try_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.PRESERVE_POSITIONS;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out10.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540k() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_catch_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.PRESERVE_POSITIONS;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out11.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540l() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out12.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540m() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_NEXT_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out13.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540n() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_switch_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out14.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540p() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_catch_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_lambda_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_switch_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ this.formatterPrefs.parenthesis_positions_in_try_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out15.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540q() throws JavaModelException {
+ this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String source =
+ "public class Test {\n" +
+ " void foo() {\n" +
+ " for (\n" +
+ " String s : Arrays.asList(\"aa\")\n" +
+ " ) {\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540r() throws JavaModelException {
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+ String source =
+ "public class Test extends Exception {\n" +
+ " Test instance = new Test(\n" +
+ " 1\n" +
+ " );\n" +
+ "\n" +
+ " Test(int a) {\n" +
+ " this(\n" +
+ " a, 0\n" +
+ " );\n" +
+ " }\n" +
+ "\n" +
+ " Test(int a, int b) {\n" +
+ " super(\n" +
+ " a + \"=\" + b\n" +
+ " );\n" +
+ " }\n" +
+ "\n" +
+ " public void printStackTrace() {\n" +
+ " super.printStackTrace(\n" +
+ " );\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540s() throws JavaModelException {
+ this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+ String source =
+ "public class Test extends Exception {\n" +
+ " void foo() {\n" +
+ " new StringBuilder().append(\"aaaaaaaaa\" + \"bbbbbbbbbbbbbbb\" + \"cccccccccccccc\" + \"dddddddddd\")\n" +
+ " .append(\"aaaaaaa\" + \"bbbbbbbbbbbbb\" + \"cccccccccccccc\" + \"ddddddddd\");\n" +
+ " }\n" +
+ "}";
+ formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959a() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out1.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959b() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.alignment_for_parameterized_type_references = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out2.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959c() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.alignment_for_type_arguments = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out3.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959d() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.alignment_for_type_parameters = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out4.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959e() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ int policy = Alignment.M_NEXT_SHIFTED_SPLIT + Alignment.M_FORCE;
+ this.formatterPrefs.alignment_for_parameterized_type_references = policy;
+ this.formatterPrefs.alignment_for_type_arguments = policy;
+ this.formatterPrefs.alignment_for_type_parameters = policy;
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out5.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959f() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE;
+ int policy = Alignment.M_NEXT_PER_LINE_SPLIT + Alignment.M_INDENT_ON_COLUMN + Alignment.M_FORCE;
+ this.formatterPrefs.alignment_for_parameterized_type_references = policy;
+ this.formatterPrefs.alignment_for_type_arguments = policy;
+ this.formatterPrefs.alignment_for_type_parameters = policy;
+ String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+ formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out6.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959g() throws JavaModelException {
+ setComplianceLevel(CompilerOptions.VERSION_1_8);
+ this.formatterPrefs.alignment_for_type_parameters = Alignment.M_COMPACT_SPLIT;
+ String source =
+ "public interface IteratedDescribeLinkList<\n" +
+ " T extends IteratedDescribeLinkList<T, E, A, B, C, D, F, G, H, I, X, Y, Z, J, K>, E extends IteratedDescribeLink,\n" +
+ " A extends Iterated, B extends Iterated, C extends IteratedList<C, A, F, H, Y, J>,\n" +
+ " D extends IteratedList<D, B, G, I, Z, K>, F extends MasteredList<F, H, C, A, J, Y>,\n" +
+ " G extends MasteredList<G, I, D, B, K, Z>, H extends Mastered, I extends Mastered, X extends T, Y extends C,\n" +
+ " Z extends D, J extends F, K extends G> extends ObjectToObjectLinkList<T, E, A, B, C, D, X, Y, Z> {\n" +
+ "}";
+ formatSource(source);
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
index fcd1e49..2be5e05 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -4970,16 +4970,13 @@
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
this.wc.codeComplete(cursorLocation, requestor, this.wcOwner);
- int start = str.lastIndexOf(completeBehind);
- int end = start + completeBehind.length();
-
assertResults(
"expectedTypesSignatures=null\n"+
"expectedTypesKeys=null",
requestor.getContext());
assertResults(
- "testCompletionEmptyToken2[PACKAGE_REF]{testCompletionEmptyToken2, testCompletionEmptyToken2, null, null, null, ["+start+", "+end+"], " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_NAME + R_NON_RESTRICTED) + "}",
+ "",
requestor.getResults());
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
index ccdb387..1131cb7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,7 +22,7 @@
import org.eclipse.jdt.core.eval.IEvaluationContext;
import org.eclipse.jdt.internal.codeassist.RelevanceConstants;
-@SuppressWarnings({"rawtypes", "unchecked"})
+//@SuppressWarnings({"rawtypes", "unchecked"})
public class CompletionTests18 extends AbstractJavaModelCompletionTests {
static {
@@ -1543,7 +1543,7 @@
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length() + 1;
IJavaProject javaProject = getJavaProject("Completion");
- Map options = javaProject.getOptions(true);
+ Map<String, String> options = javaProject.getOptions(true);
options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
options.put(JavaCore.COMPILER_INHERIT_NULL_ANNOTATIONS, JavaCore.ENABLED);
javaProject.setOptions(options);
@@ -2662,4 +2662,83 @@
RelevanceConstants.R_INTERESTING + RelevanceConstants.R_NON_RESTRICTED +
RelevanceConstants.R_CASE) + "}", requestor.getResults());
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=473008
+public void test473008a() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Foo.java",
+ "interface FooFunctional {\n" +
+ " void function();\n" +
+ "}\n" +
+ "public class Foo {\n" +
+ " private FooFunctional lambda = this::bar;\n" +
+ " public void bar() {\n" +
+ " new StringBuffer" +
+ " }\n" +
+ "}\n");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+ requestor.allowAllRequiredProposals();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "new StringBuffer";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+ assertResults(
+ "StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [147, 159], " + relevance + "}\n" +
+ "StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [147, 159], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+ , requestor.getResults());
+}
+public void test473008b() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Foo.java",
+ "interface FooFunctional {\n" +
+ " void function();\n" +
+ "}\n" +
+ "public class Foo {\n" +
+ " public void bar() {\n" +
+ " private FooFunctional lambda = this::bar;\n" +
+ " new StringBuffer" +
+ " }\n" +
+ "}\n");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+ requestor.allowAllRequiredProposals();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "new StringBuffer";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+ assertResults(
+ "StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [149, 161], " + relevance + "}\n" +
+ "StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [149, 161], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+ , requestor.getResults());
+}
+public void test473008c() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Foo.java",
+ "interface FooFunctional {\n" +
+ " void function();\n" +
+ "}\n" +
+ "public class Foo {\n" +
+ " public void bar() {\n" +
+ " private FooFunctional lambda = () -> bar();\n" +
+ " new StringBuffer" +
+ " }\n" +
+ "}\n");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+ requestor.allowAllRequiredProposals();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "new StringBuffer";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+ assertResults(
+ "StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [151, 163], " + relevance + "}\n" +
+ "StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [151, 163], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+ , requestor.getResults());
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
index 52a03b0..827681c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -6445,4 +6445,48 @@
(RelevanceConstants.R_DEFAULT + RelevanceConstants.R_RESOLVED + RelevanceConstants.R_INTERESTING + RelevanceConstants.R_NON_RESTRICTED
+ RelevanceConstants.R_CASE + RelevanceConstants.R_UNQUALIFIED) + "}", requestor.getResults());
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479656
+public void test479656() throws Exception {
+ try {
+ IFile f = getFile("/Completion/bug479656.jar");
+ IJavaProject p = this.createJavaProject(
+ "P",
+ new String[]{"src"},
+ new String[]{"JCL_LIB"},
+ "bin", "1.5");
+ this.createFile("/P/bug479656.jar", f.getContents());
+ this.addLibraryEntry(p, "/P/bug479656.jar", true);
+ this.createFolder("/P/src/com/google/gwt/event/shared");
+ this.createFile(
+ "/P/src/com/google/gwt/event/shared/GwtEvent.java",
+ "package com.google.gwt.event.shared;\n" +
+ "public abstract class GwtEvent<H> {\n" +
+ " public static class Type<H> {}\n" +
+ "}\n");
+ this.createFolder("/P/src/test");
+ this.createFile(
+ "/P/src/test/Test.java",
+ "package test;\n" +
+ "public class Test {\n" +
+ " String value = \"\";\n" +
+ " com.gtouch5.shared.data.store.event.StoreEvent<String> event = null;\n" +
+ " public Test() {\n" +
+ " value.toS\n" +
+ " }\n" +
+ "}\n");
+ refresh(p);
+ waitUntilIndexesReady();
+ ICompilationUnit cu = getCompilationUnit("P", "src", "test", "Test.java");
+ String source = cu.getSource();
+ String completeBehind = "value.toS";
+ int cursorLocation = source.lastIndexOf(completeBehind) + completeBehind.length();
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, false, true, true);
+ cu.codeComplete(cursorLocation, requestor);
+ assertResults(
+ "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 35}",
+ requestor.getResults());
+ } finally {
+ deleteProject("P");
+ }
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 19c8363..defb870 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 GK Software AG, and others.
+ * Copyright (c) 2014, 2016 GK Software AG, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -56,6 +56,7 @@
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ExternalAnnotationUtil;
import org.eclipse.jdt.core.util.ExternalAnnotationUtil.MergeStrategy;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.core.ClasspathAttribute;
import org.osgi.framework.Bundle;
@@ -249,6 +250,22 @@
addClasspathEntry(this.project, entry);
}
+ protected void addProjectDependencyWithExternalAnnotations(
+ IJavaProject javaProject,
+ String referencedProjectName,
+ String externalAnnotationPath,
+ Map options) throws CoreException, IOException
+ {
+ IClasspathAttribute[] extraAttributes = new IClasspathAttribute[] { new ClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, externalAnnotationPath) };
+ IClasspathEntry entry = JavaCore.newProjectEntry(
+ new Path(referencedProjectName),
+ null/*access rules*/,
+ false/*combine access rules*/,
+ extraAttributes,
+ false/*exported*/);
+ addClasspathEntry(this.project, entry);
+ }
+
protected void createFileInProject(String projectRelativeFolder, String fileName, String content) throws CoreException {
String folderPath = this.project.getProject().getName()+'/'+projectRelativeFolder;
createFolder(folderPath);
@@ -292,6 +309,43 @@
assertEquals("Number of problems", messages.length, nMatch);
}
+ protected void assertProblems(IProblem[] problems, String[] messages, int[] lines, int[] severities) throws CoreException {
+ int nMatch = 0;
+ for (int i = 0; i < problems.length; i++) {
+ for (int j = 0; j < messages.length; j++) {
+ if (messages[j] == null) continue;
+ if (problems[i].toString().equals(messages[j])
+ && problems[i].getSourceLineNumber() == lines[j]) {
+ switch(severities[j] & ProblemSeverities.CoreSeverityMASK ) {
+ case ProblemSeverities.Error:
+ if (!problems[i].isError()) continue;
+ break;
+ case ProblemSeverities.Warning:
+ if (!problems[i].isWarning()) continue;
+ break;
+ case ProblemSeverities.Info:
+ if (!problems[i].isInfo()) continue;
+ break;
+ default:
+ throw new IllegalArgumentException("Bad severity expected: "+severities[j]);
+ }
+ messages[j] = null;
+ problems[i] = null;
+ nMatch++;
+ break;
+ }
+ }
+ }
+ for (int i = 0; i < problems.length; i++) {
+ if (problems[i] != null)
+ fail("Unexpected problem "+problems[i]+" at "+problems[i].getSourceLineNumber());
+ }
+ for (int i = 0; i < messages.length; i++) {
+ if (messages[i] != null)
+ System.err.println("Unmatched problem "+messages[i]);
+ }
+ assertEquals("Number of problems", messages.length, nMatch);
+ }
protected boolean hasJRE18() {
return ((AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_8) != 0);
}
@@ -466,10 +520,11 @@
CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
IProblem[] problems = reconciled.getProblems();
assertProblems(problems, new String[] {
+ "Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Iterator<@NonNull capture#of ?>'. Type 'Iterator<E>' doesn't seem to be designed with null type annotations in mind",
"Pb(953) Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable capture#of ?'",
"Pb(953) Null type mismatch (type annotations): required '@NonNull CharSequence' but this expression has type '@Nullable capture#of ? extends CharSequence'",
"Pb(953) Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable capture#of ? super CharSequence'"
- }, new int[] { 13, 16, 19 });
+ }, new int[] { 10, 13, 16, 19 });
}
public void testLibsWithArrays() throws Exception {
@@ -1419,4 +1474,215 @@
Platform.removeLogListener(listener);
}
}
+
+ /** Lib exists as workspace project. Perform full build. */
+ public void testProjectDependencyFullBuild() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ setupJavaProject("Test1");
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ assertNoMarkers(markers);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile1() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test1");
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertNoProblems(problems);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Type-Annotations in zip file. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile2() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test3b");
+ Util.createSourceZip(
+ new String[] {
+ "libs/MyFunction.eea",
+ "class libs/MyFunction\n" +
+ " <T:R:>\n" +
+ "\n" +
+ "compose\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+T0T;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ "\n",
+ "libs/Arrays.eea",
+ "class libs/Arrays\n" +
+ "\n" +
+ "array\n" +
+ " [Ljava/lang/String;\n" +
+ " [1L0java/lang/String;\n" +
+ "\n" +
+ "getArray\n" +
+ " ()[[Ljava/lang/String;\n" +
+ " ()[0[1L0java/lang/String;\n"
+ },
+ this.project.getProject().getLocation().toString()+"/annots.zip");
+ this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Reconcile2.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertNoProblems(problems);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Invocations conflict with type parameter constraints. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile3() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test3b");
+ Util.createSourceZip(
+ new String[] {
+ "libs/MyFunction.eea",
+ "class libs/MyFunction\n" +
+ " <T:R:>\n" +
+ " <T:1R:>\n" +
+ "\n" +
+ "compose\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ " <1V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ "\n",
+ },
+ this.project.getProject().getLocation().toString()+"/annots.zip");
+ this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Reconcile3.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ assertProblems(reconciled.getProblems(), new String[] {
+ "Pb(964) Null constraint mismatch: The type '@Nullable B' is not a valid substitute for the type parameter '@NonNull R'",
+ "Pb(964) Null constraint mismatch: The type '@Nullable String' is not a valid substitute for the type parameter '@NonNull V'",
+ }, new int[] { 12, 17 });
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ public void testFreeTypeVariableReturn() throws Exception {
+ myCreateJavaProject("TestLibs");
+ addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+ "/UnannotatedLib/libs/Lib1.java",
+ "package libs;\n" +
+ "\n" +
+ "public interface Lib1<T> {\n" +
+ " T get();\n" +
+ "}\n"
+ }, null);
+ IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+ ICompilationUnit unit = fragment.createCompilationUnit("Test1.java",
+ "package tests;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "\n" +
+ "import libs.Lib1;\n" +
+ "\n" +
+ "public class Test1 {\n" +
+ " @NonNull String test0(Lib1<@Nullable String> lib) {\n" +
+ " return lib.get();\n" +
+ " }\n" +
+ " @NonNull String test1(Lib1<@NonNull String> lib) {\n" +
+ " return lib.get();\n" +
+ " }\n" +
+ "}\n",
+ true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ assertProblems(reconciled.getProblems(), new String[] {
+ "Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
+ "Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
+ }, new int[] { 8, 11 });
+ // just mark that Lib1 now has null annotations:
+ createFileInProject("annots/libs", "Lib1.eea",
+ "class libs/Lib1\n" +
+ " <T:Ljava/lang/Object;>\n" +
+ " <T:Ljava/lang/Object;>\n" +
+ "\n");
+ reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ assertProblems(reconciled.getProblems(), new String[] {
+ "Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
+ }, new int[] { 8 });
+ }
+
+ public void testFreeTypeVariableReturnSeverities() throws Exception {
+ myCreateJavaProject("TestLibs");
+ addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+ "/UnannotatedLib/libs/Lib1.java",
+ "package libs;\n" +
+ "\n" +
+ "public interface Lib1<T> {\n" +
+ " T get();\n" +
+ "}\n"
+ }, null);
+ this.currentProject = this.project;
+ addLibrary("lib2.jar", null, new String[] {
+ "/UnanntatedLib2/libs/Lib2.java",
+ "package libs;\n" +
+ "\n" +
+ "public interface Lib2<T> {\n" +
+ " T get();\n" +
+ "}\n"
+ }, "1.8");
+ IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+ fragment.createCompilationUnit("Lib3.java",
+ "package tests;\n" +
+ "public interface Lib3<T> {\n" +
+ " T get();\n" +
+ "}\n",
+ true, new NullProgressMonitor());
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
+ ICompilationUnit unit = fragment.createCompilationUnit("Test1.java",
+ "package tests;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "\n" +
+ "import libs.Lib1;\n" +
+ "import libs.Lib2;\n" +
+ "import tests.Lib3;\n" +
+ "\n" +
+ "public class Test1 {\n" +
+ " @NonNull String test1(Lib1<@NonNull String> lib) {\n" +
+ " return lib.get();\n" + // legacy, prepared for .eea but still not annotated (=> Warning)
+ " }\n" +
+ " @NonNull String test2(Lib2<@NonNull String> lib) {\n" +
+ " return lib.get();\n" + // legacy, not prepared for .eea (=> Info)
+ " }\n" +
+ " @NonNull String test3(Lib3<@NonNull String> lib) {\n" +
+ " return lib.get();\n" + // not legacy, is from the same project
+ " }\n" +
+ "}\n",
+ true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ assertProblems(reconciled.getProblems(), new String[] {
+ "Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
+ "Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib2<@NonNull String>'. Type 'Lib2<T>' doesn't seem to be designed with null type annotations in mind",
+ }, new int[] { 10, 13 }, new int[] { ProblemSeverities.Warning, ProblemSeverities.Info } );
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
index 71ac9d7..af6ab69 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,8 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;
-import java.util.ArrayList;
-import java.util.List;
+import java.io.IOException;
import junit.framework.Test;
@@ -35,6 +34,7 @@
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeReferenceMatch;
import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.LambdaMethod;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.eclipse.jdt.internal.core.search.matching.AndPattern;
import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
@@ -42,7 +42,6 @@
/**
* Non-regression tests for bugs fixed in Java Search engine.
*/
-@SuppressWarnings({"rawtypes", "unchecked"})
public class JavaSearchBugs8Tests extends AbstractJavaSearchTests {
static {
@@ -58,10 +57,8 @@
return buildModelTestSuite(JavaSearchBugs8Tests.class, BYTECODE_DECLARATION_ORDER);
}
class TestCollector extends JavaSearchResultCollector {
- public List matches = new ArrayList();
public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException {
super.acceptSearchMatch(searchMatch);
- this.matches.add(searchMatch);
}
}
class ReferenceCollector extends JavaSearchResultCollector {
@@ -4707,6 +4704,38 @@
deleteProject("P");
}
}
+// not solely a search issue but easily reproducible using search
+public void test473343_0001() throws CoreException, IOException {
+ try {
+ IJavaProject project = createJavaProject("P", new String[] {"a-b"}, new String[] {"JCL18_LIB"}, "bin", "1.8", true);
+ String source = "interface Consumer<T> {\n" +
+ " void accept(T t);\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " Consumer<? super Y> action = (i_) -> X.foo(i_);\n" +
+ " private static void foo(Y tb) {\n" +
+ " }\n" +
+ "}\n";
+ createFile("/P/a-b/X.java", source);
+ createFile("/P/a-b/Y.java", "public class Y{}");
+ waitForAutoBuild();
+
+ ICompilationUnit unit = getCompilationUnit("/P/a-b/X.java");
+ String foo = "foo";
+ IJavaElement[] elements = unit.codeSelect(source.indexOf(foo), foo.length());
+ SearchPattern pattern = SearchPattern.createPattern(elements[0], REFERENCES, ERASURE_RULE);
+ search(pattern, SearchEngine.createJavaSearchScope(new IJavaElement[] { project }, IJavaSearchScope.SOURCES), this.resultCollector);
+ LambdaMethod method = (LambdaMethod) this.resultCollector.match.getElement();
+ try {
+ SearchPattern.createPattern(method, REFERENCES, ERASURE_RULE);
+ } catch (IllegalArgumentException e) {
+ assertFalse("Test Failed", true);
+ }
+ } finally {
+ deleteProject("P");
+ }
+}
// Add new tests in JavaSearchBugs8Tests
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
index ccc0168..4c8dfd0 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
index 14efe24..631d1b9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,6 +14,7 @@
import junit.framework.Test;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.BindingKey;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
@@ -21,6 +22,7 @@
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.internal.core.LambdaExpression;
import org.eclipse.jdt.internal.core.LambdaMethod;
@@ -2187,7 +2189,7 @@
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
- "comparing(java.util.function.Function<? super T,? extends U>) {key=Ljava/util/Comparator<>;.comparing<T:Ljava/lang/Object;U::Ljava/lang/Comparable<-TU;>;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator<TT;>;%<Ljava/lang/Object;^{259#0};>} [in Comparator [in Comparator.class [in java.util [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
+ "comparing(java.util.function.Function<? super T,? extends U>) {key=Ljava/util/Comparator<>;.comparing<T:Ljava/lang/Object;U::Ljava/lang/Comparable<-TU;>;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator<TT;>;%<LX~Person;Ljava/lang/String;>} [in Comparator [in Comparator.class [in java.util [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
elements, true
);
}
@@ -2813,4 +2815,88 @@
"fooY() [in Y [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]",
elements);
}
+// nested poly invocation:
+public void testBug487791() throws JavaModelException {
+ this.wc = getWorkingCopy(
+ "Resolve/src/Example.java",
+ "import java.util.Comparator;\n" +
+ "import java.util.stream.Collectors;\n" +
+ "\n" +
+ "interface Something {\n" +
+ " public int getSize();\n" +
+ " public Instant getTime();\n" +
+ "}\n" +
+ "interface Instant extends Comparable<Instant> {\n" +
+ "}\n" +
+ "public class Example {\n" +
+ " public void test2() {\n" +
+ " java.util.stream.Collector<Something,?,java.util.Map<Integer,Something>> c = \n" +
+ " Collectors.collectingAndThen(\n" +
+ " Collectors.<Something>toList(),\n" +
+ " list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" +
+ " // Returns Collector<Something,?,Object> - INCORRECT!\n" +
+ " Collectors.collectingAndThen(\n" + // <-- select here
+ " Collectors.<Something>toList(),\n" +
+ " list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" +
+ " )\n" +
+ " )));\n" +
+ " }\n" +
+ "}\n");
+ this.wc.becomeWorkingCopy(null);
+
+ String str = this.wc.getSource();
+ String selection = "collectingAndThen";
+ int start = str.lastIndexOf(selection);
+ int length = selection.length();
+
+ IJavaElement[] elements = this.wc.codeSelect(start, length);
+ assertElementsEqual(
+ "Unexpected elements",
+ "collectingAndThen(java.util.stream.Collector<T,A,R>, java.util.function.Function<R,RR>) [in Collectors [in Collectors.class [in java.util.stream [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
+ elements
+ );
+ String signature = new BindingKey(((IMethod) elements[0]).getKey()).toSignature();
+ String[] typeArguments = Signature.getTypeArguments(signature);
+ assertEquals("number of type arguments", 3, typeArguments.length);
+ assertEquals("4th type argument", "LSomething;", typeArguments[2]);
+ String returnType = Signature.getReturnType(signature);
+ assertEquals("return type", "Ljava.util.stream.Collector<LSomething;!*LSomething;>;", returnType);
+}
+// ReferenceExpression:
+public void testBug487791b() throws JavaModelException {
+ this.wc = getWorkingCopy(
+ "Resolve/src/Example.java",
+ "import java.util.function.Function;\n" +
+ "\n" +
+ "public class Example {\n" +
+ " static <T> T id(T t) { return t; }\n" +
+ " static <T,X> T f1 (X x) { return null; }\n" +
+ " \n" +
+ " String test() {\n" +
+ " return f3(y -> y.f2(Example::f1, id(y)));\n" + // <- select f1 here
+ " }\n" +
+ " <U,V> V f2(Function<U, V> f, U u) {return f.apply(null);}\n" +
+ " <R> R f3(Function<Example,R> f) { return null; }\n" +
+ "}\n");
+ this.wc.becomeWorkingCopy(null);
+
+ String str = this.wc.getSource();
+ String selection = "f1";
+ int start = str.lastIndexOf(selection);
+ int length = selection.length();
+
+ IJavaElement[] elements = this.wc.codeSelect(start, length);
+ assertElementsEqual(
+ "Unexpected elements",
+ "f1(X) [in Example [in [Working copy] Example.java [in <default> [in src [in Resolve]]]]]",
+ elements
+ );
+ BindingKey bindingKey = new BindingKey(((IMethod) elements[0]).getKey());
+ String signature = bindingKey.toSignature();
+ assertEquals("signature", "<T:Ljava.lang.Object;X:Ljava.lang.Object;>(LExample;)Ljava.lang.String;", signature);
+ String[] typeArguments = bindingKey.getTypeArguments();
+ assertEquals("number of type arguments", 2, typeArguments.length);
+ assertEquals("1st type argument", "Ljava.lang.String;", typeArguments[0]);
+ assertEquals("2nd type argument", "LExample;", typeArguments[1]);
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
new file mode 100644
index 0000000..f8a6de7
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="var" path="JCL18_LIB"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
new file mode 100644
index 0000000..b68234a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Lib</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
new file mode 100644
index 0000000..29b7e15
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
@@ -0,0 +1,6 @@
+package libs;
+
+public class Arrays {
+ public String[][] getArray() { return null; }
+ public static final String[] array = new String[1] { null }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
new file mode 100644
index 0000000..6f7bff6
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
@@ -0,0 +1,10 @@
+package libs;
+
+public interface MyFunction<T,R> {
+
+ R apply(T t);
+
+ default <V> MyFunction<V, R> compose(MyFunction<? super V, ? extends T> before) {
+ return (V v) -> apply(before.apply(v));
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
new file mode 100644
index 0000000..ad51f8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
@@ -0,0 +1,6 @@
+package libs;
+public interface MyMap<K,V> {
+ V get(Object key);
+ V put(K key, V val);
+ V remove(Object key);
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
new file mode 100644
index 0000000..1574d24
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.core.tests.model.TEST_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
new file mode 100644
index 0000000..ea7fde1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Test3</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
new file mode 100644
index 0000000..385d7cb
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
@@ -0,0 +1,24 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile2 {
+ C test(MyFunction<A,@Nullable B> f1, MyFunction<B,C> f2, A a) {
+ return f2.compose(f1).apply(a); // actually incompatible, but we tweak compose to pretend it's compatible
+ }
+
+ void test2(Arrays lib) {
+ @Nullable String[]@NonNull[] arr = lib.getArray();
+ if (arr == null)
+ throw new NullPointerException(); // not dead code
+ @Nullable String @NonNull[] arr2 = Arrays.array;
+ Arrays.array[1] = null;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
new file mode 100644
index 0000000..7a777c0
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
@@ -0,0 +1,19 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile3 {
+ void test1(MyFunction<A,@Nullable B> f1) {
+ // nothing
+ }
+
+ void test2(MyFunction<A,@NonNull B> f2a, MyFunction<@Nullable String,@NonNull A> f2b) {
+ f2a.<@Nullable String>compose(f2b);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java
new file mode 100644
index 0000000..a5a247f
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java
@@ -0,0 +1,43 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ @Deprecated()
+ void method2(
+ String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "ccccccccccccccccccc");
+ break;
+ }
+ }
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5, String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)
+ ) {
+ argument1.method2(argument5);
+ }
+ }
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {};
+}
+
+enum SomeEnum {
+ VALUE1(),
+ VALUE2("example")
+}
+
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java
new file mode 100644
index 0000000..7f66138
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java
@@ -0,0 +1,45 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java
new file mode 100644
index 0000000..2e6566c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java
@@ -0,0 +1,49 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(
+ String argument
+ ) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(
+ Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6
+ ) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java
new file mode 100644
index 0000000..f42580b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java
@@ -0,0 +1,47 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(
+ Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6
+ ) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java
new file mode 100644
index 0000000..9b157b2
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java
@@ -0,0 +1,50 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1(
+ ) {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(
+ String argument
+ ) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(
+ Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6
+ ) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java
new file mode 100644
index 0000000..ac9baa7
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java
@@ -0,0 +1,53 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(
+ this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc"
+ );
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(
+ argument4
+ )) {
+ argument1.method2(
+ argument5
+ );
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(
+ ""
+ ));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java
new file mode 100644
index 0000000..a517035
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java
@@ -0,0 +1,50 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(
+ this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc"
+ );
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(
+ ), VALUE2(
+ "example"
+ )
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java
new file mode 100644
index 0000000..4ee529a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java
@@ -0,0 +1,53 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (
+ counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0
+ ) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (
+ argument1.toString().contains(argument4)
+ ) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (
+ example.toString()//
+ .contains("")
+ );
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2(
+ "example"
+ )
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java
new file mode 100644
index 0000000..bfeb310
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java
@@ -0,0 +1,49 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (
+ Example example, String text
+ ) -> {
+ do {
+ example.method1();
+ } while (
+ example.toString()//
+ .contains("")
+ );
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java
new file mode 100644
index 0000000..1a26b45
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java
@@ -0,0 +1,57 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(
+ this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc"
+ );
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (
+ argument1.toString().contains(
+ argument4
+ )
+ ) {
+ argument1.method2(
+ argument5
+ );
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (
+ example.toString()//
+ .contains(
+ ""
+ )
+ );
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java
new file mode 100644
index 0000000..ddc6a5e
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java
@@ -0,0 +1,48 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (
+ AutoCloseable resource = null
+ ) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(
+ String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java
new file mode 100644
index 0000000..09ea887
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java
@@ -0,0 +1,48 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (
+ Exception e
+ ) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)
+ ) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java
new file mode 100644
index 0000000..d1c3ab2
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java
@@ -0,0 +1,47 @@
+public class Example {
+ @SomeAnnotation(
+ key1 = "value1", key2 = "value2"
+ )
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java
new file mode 100644
index 0000000..15c9d73
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java
@@ -0,0 +1,49 @@
+public class Example {
+ @SomeAnnotation(key1 = "value1", key2 = "value2")
+ void method1() {
+ for (
+ int counter = 0;
+ counter < 100;
+ counter++
+ ) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated()
+ void method2(String argument) {
+ switch (argument) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java
new file mode 100644
index 0000000..edb3b61
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java
@@ -0,0 +1,50 @@
+public class Example {
+ @SomeAnnotation(
+ key1 = "value1", key2 = "value2"
+ )
+ void method1() {
+ for (int counter = 0; counter < 100; counter++) {
+ if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+ try (AutoCloseable resource = null) {
+ // read resource
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Deprecated(
+ )
+ void method2(String argument) {
+ switch (
+ argument
+ ) {
+ case "1":
+ this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc");
+ break;
+ }
+ }
+
+ void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6) {
+ method1();
+ while (argument1.toString().contains(argument4)) {
+ argument1.method2(argument5);
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+ do {
+ example.method1();
+ } while (example.toString()//
+ .contains(""));
+ };
+ Runnable r = () -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java
new file mode 100644
index 0000000..1a69c2c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java
@@ -0,0 +1,86 @@
+public class Example {
+ @SomeAnnotation(
+ key1 = "value1", key2 = "value2"
+ )
+ void method1(
+ ) {
+ for (
+ int counter = 0; counter < 100; counter++
+ ) {
+ if (
+ counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0
+ ) {
+ try (
+ AutoCloseable resource = null
+ ) {
+ // read resource
+ } catch (
+ Exception e
+ ) {
+ e.printStackTrace(
+ );
+ }
+ }
+ }
+ }
+
+ @Deprecated(
+ )
+ void method2(
+ String argument
+ ) {
+ switch (
+ argument
+ ) {
+ case "1":
+ this.method3(
+ this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccc"
+ );
+ break;
+ }
+ }
+
+ void method3(
+ Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+ String argument6
+ ) {
+ method1(
+ );
+ while (
+ argument1.toString(
+ ).contains(
+ argument4
+ )
+ ) {
+ argument1.method2(
+ argument5
+ );
+ }
+ }
+
+ java.util.function.BiConsumer<Example, String> lambda = (
+ Example example, String text
+ ) -> {
+ do {
+ example.method1(
+ );
+ } while (
+ example.toString(
+ )//
+ .contains(
+ ""
+ )
+ );
+ };
+ Runnable r = (
+ ) -> {
+ };
+}
+
+enum SomeEnum {
+ VALUE1(
+ ), VALUE2(
+ "example"
+ )
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java
new file mode 100644
index 0000000..1159d8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java
@@ -0,0 +1,55 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+ T t;
+ S s;
+ A<T, S> a;
+
+ Object field = a.<T, S>getMap(t, s);
+
+ public A() {
+ <T, S>this(null, null);
+ }
+
+ public <M, N> A(M param1, N param2) {
+
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<B, List<String>> {
+
+ public <M, N> B(M param1, N param2) {
+ <M, N>super(param1, param2);
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ B b = new <M, N>B(key, value);
+ AMethod method = b::<String, String>getMap;
+ AMethod method2 = super::<String, String>getMap;
+ AMethod method3 = AMap<M>::<String, String>new;
+ AMethod method4 = AMap<M>::<String, String>createAMap;
+ return super.<M, N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+ public <M, N> AMap(String param1, String param2) {
+
+ }
+
+ public static <M, N> AMap<M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java
new file mode 100644
index 0000000..1159d8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java
@@ -0,0 +1,55 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+ T t;
+ S s;
+ A<T, S> a;
+
+ Object field = a.<T, S>getMap(t, s);
+
+ public A() {
+ <T, S>this(null, null);
+ }
+
+ public <M, N> A(M param1, N param2) {
+
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<B, List<String>> {
+
+ public <M, N> B(M param1, N param2) {
+ <M, N>super(param1, param2);
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ B b = new <M, N>B(key, value);
+ AMethod method = b::<String, String>getMap;
+ AMethod method2 = super::<String, String>getMap;
+ AMethod method3 = AMap<M>::<String, String>new;
+ AMethod method4 = AMap<M>::<String, String>createAMap;
+ return super.<M, N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+ public <M, N> AMap(String param1, String param2) {
+
+ }
+
+ public static <M, N> AMap<M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java
new file mode 100644
index 0000000..3b94dfd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java
@@ -0,0 +1,74 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<
+ T,
+ S>, S extends List<
+ ?>> {
+
+ T t;
+ S s;
+ A<
+ T,
+ S> a;
+
+ Object field = a.<T, S>getMap(t, s);
+
+ public A() {
+ <T, S>this(null, null);
+ }
+
+ public <M, N> A(M param1, N param2) {
+
+ }
+
+ public <M, N> Map<
+ M,
+ N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<
+ B,
+ List<
+ String>> {
+
+ public <M, N> B(M param1, N param2) {
+ <M, N>super(param1, param2);
+ }
+
+ public <M, N> Map<
+ M,
+ N> getMap(M key, N value) {
+ B b = new <M, N>B(key, value);
+ AMethod method = b::<String, String>getMap;
+ AMethod method2 = super::<String, String>getMap;
+ AMethod method3 = AMap<
+ M>::<String, String>new;
+ AMethod method4 = AMap<
+ M>::<String, String>createAMap;
+ return super.<M, N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<
+ String,
+ String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<
+ String,
+ String> {
+ public <M, N> AMap(String param1, String param2) {
+
+ }
+
+ public static <M, N> AMap<
+ M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java
new file mode 100644
index 0000000..f2fab44
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java
@@ -0,0 +1,73 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+ T t;
+ S s;
+ A<T, S> a;
+
+ Object field = a.<
+ T,
+ S>getMap(t, s);
+
+ public A() {
+ <
+ T,
+ S>this(null, null);
+ }
+
+ public <M, N> A(M param1, N param2) {
+
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<B, List<String>> {
+
+ public <M, N> B(M param1, N param2) {
+ <
+ M,
+ N>super(param1, param2);
+ }
+
+ public <M, N> Map<M, N> getMap(M key, N value) {
+ B b = new <
+ M,
+ N>B(key, value);
+ AMethod method = b::<
+ String,
+ String>getMap;
+ AMethod method2 = super::<
+ String,
+ String>getMap;
+ AMethod method3 = AMap<M>::<
+ String,
+ String>new;
+ AMethod method4 = AMap<M>::<
+ String,
+ String>createAMap;
+ return super.<
+ M,
+ N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+ public <M, N> AMap(String param1, String param2) {
+
+ }
+
+ public static <M, N> AMap<M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java
new file mode 100644
index 0000000..8913334
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java
@@ -0,0 +1,70 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<
+ T extends A<T, S>,
+ S extends List<?>> {
+
+ T t;
+ S s;
+ A<T, S> a;
+
+ Object field = a.<T, S>getMap(t, s);
+
+ public A() {
+ <T, S>this(null, null);
+ }
+
+ public <
+ M,
+ N> A(M param1, N param2) {
+
+ }
+
+ public <
+ M,
+ N> Map<M, N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<B, List<String>> {
+
+ public <
+ M,
+ N> B(M param1, N param2) {
+ <M, N>super(param1, param2);
+ }
+
+ public <
+ M,
+ N> Map<M, N> getMap(M key, N value) {
+ B b = new <M, N>B(key, value);
+ AMethod method = b::<String, String>getMap;
+ AMethod method2 = super::<String, String>getMap;
+ AMethod method3 = AMap<M>::<String, String>new;
+ AMethod method4 = AMap<M>::<String, String>createAMap;
+ return super.<M, N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<String, String> getMap(String key, String value);
+}
+
+class AMap<
+ T> extends HashMap<String, String> {
+ public <
+ M,
+ N> AMap(String param1, String param2) {
+
+ }
+
+ public static <
+ M,
+ N> AMap<M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java
new file mode 100644
index 0000000..f1ac68c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java
@@ -0,0 +1,107 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<
+ T extends A<
+ T,
+ S>,
+ S extends List<
+ ?>> {
+
+ T t;
+ S s;
+ A<
+ T,
+ S> a;
+
+ Object field = a.<
+ T,
+ S>getMap(t, s);
+
+ public A() {
+ <
+ T,
+ S>this(null, null);
+ }
+
+ public <
+ M,
+ N> A(M param1, N param2) {
+
+ }
+
+ public <
+ M,
+ N> Map<
+ M,
+ N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<
+ B,
+ List<
+ String>> {
+
+ public <
+ M,
+ N> B(M param1, N param2) {
+ <
+ M,
+ N>super(param1, param2);
+ }
+
+ public <
+ M,
+ N> Map<
+ M,
+ N> getMap(M key, N value) {
+ B b = new <
+ M,
+ N>B(key, value);
+ AMethod method = b::<
+ String,
+ String>getMap;
+ AMethod method2 = super::<
+ String,
+ String>getMap;
+ AMethod method3 = AMap<
+ M>::<
+ String,
+ String>new;
+ AMethod method4 = AMap<
+ M>::<
+ String,
+ String>createAMap;
+ return super.<
+ M,
+ N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<
+ String,
+ String> getMap(String key, String value);
+}
+
+class AMap<
+ T> extends HashMap<
+ String,
+ String> {
+ public <
+ M,
+ N> AMap(String param1, String param2) {
+
+ }
+
+ public static <
+ M,
+ N> AMap<
+ M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java
new file mode 100644
index 0000000..49a28e1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java
@@ -0,0 +1,78 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T,
+ S>,
+ S extends List<?>> {
+
+ T t;
+ S s;
+ A<T,
+ S> a;
+
+ Object field = a.<T,
+ S>getMap(t, s);
+
+ public A() {
+ <T,
+ S>this(null, null);
+ }
+
+ public <M,
+ N> A(M param1, N param2) {
+
+ }
+
+ public <M,
+ N> Map<M,
+ N> getMap(M key, N value) {
+ return null;
+ }
+
+}
+
+class B extends A<B,
+ List<String>> {
+
+ public <M,
+ N> B(M param1, N param2) {
+ <M,
+ N>super(param1, param2);
+ }
+
+ public <M,
+ N> Map<M,
+ N> getMap(M key, N value) {
+ B b = new <M,
+ N>B(key, value);
+ AMethod method = b::<String,
+ String>getMap;
+ AMethod method2 = super::<String,
+ String>getMap;
+ AMethod method3 = AMap<M>::<String,
+ String>new;
+ AMethod method4 = AMap<M>::<String,
+ String>createAMap;
+ return super.<M,
+ N>getMap(key, value);
+ }
+}
+
+interface AMethod {
+ Map<String,
+ String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String,
+ String> {
+ public <M,
+ N> AMap(String param1, String param2) {
+
+ }
+
+ public static <M,
+ N> AMap<M> createAMap(String param1, String param2) {
+ return new AMap<>(param1, param2);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index 5b67493..69540cf 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -177,7 +177,7 @@
public boolean hasAnnotationFileFor(String qualifiedTypeName) {
int pos = qualifiedTypeName.lastIndexOf('/');
if (pos != -1 && (pos + 1 < qualifiedTypeName.length())) {
- String fileName = qualifiedTypeName.substring(pos + 1) + '.' + ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION;
+ String fileName = qualifiedTypeName.substring(pos + 1) + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
return doesFileExist(fileName, qualifiedTypeName.substring(0, pos));
}
return false;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index 8d56c0a..77ad903 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -127,7 +127,7 @@
}
@Override
public boolean hasAnnotationFileFor(String qualifiedTypeName) {
- return this.zipFile.getEntry(qualifiedTypeName+'.'+ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION) != null;
+ return this.zipFile.getEntry(qualifiedTypeName+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX) != null;
}
public char[][][] findTypeNames(String qualifiedPackageName) {
if (!isPackage(qualifiedPackageName))
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index da461e4..eda23ea 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -11011,7 +11011,7 @@
private void findPackages(CompletionOnPackageReference packageStatement) {
- this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.');
+ this.completionToken = CharOperation.concatWithAll(packageStatement.tokens, '.');
if (this.completionToken.length == 0)
return;
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 544a2ba..d3a15e0 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -4467,9 +4467,9 @@
super.consumeInvocationExpression();
triggerRecoveryUponLambdaClosure(this.expressionStack[this.expressionPtr], false);
}
-protected void consumeIdentifierOrNew(boolean newForm) {
+protected void consumeReferenceExpression(ReferenceExpression referenceExpression) {
this.inReferenceExpression = false;
- super.consumeIdentifierOrNew(newForm);
+ super.consumeReferenceExpression(referenceExpression);
}
protected void consumeOnlySynchronized() {
super.consumeOnlySynchronized();
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
index b0f1690..a19d3ca 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
@@ -15,6 +15,8 @@
import java.util.Map;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -25,8 +27,11 @@
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.SourceType;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
@@ -90,8 +95,36 @@
* secondary types defined in the same compilation unit).
*/
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
- CompilationResult result =
- new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=479656
+ // In case of the requested type not being a member type (i.e. not being a top level type)
+ // we need to find the top level ones and use them for resolution
+ CompilationResult result = null;
+ SourceTypeElementInfo sourceType;
+ if (sourceTypes[0].getEnclosingType() != null) {
+ try {
+ if (sourceTypes[0] instanceof SourceType) {
+ sourceType = (SourceTypeElementInfo) ((SourceType) sourceTypes[0]).getElementInfo();
+ } else {
+ sourceType = (SourceTypeElementInfo) sourceTypes[0];
+ }
+ IType[] types = sourceType.getHandle().getCompilationUnit().getTypes();
+ sourceTypes = new ISourceType[types.length];
+ sourceTypes[0] = sourceType;
+ int length = types.length;
+ for (int i = 0; i < length; i++) {
+ ISourceType otherType =
+ (ISourceType) ((JavaElement) types[i]).getElementInfo();
+ sourceTypes[i] = otherType;
+ }
+ ISourceType otherType =
+ (ISourceType) ((JavaElement) types[0]).getElementInfo();
+ result = new CompilationResult(otherType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ } catch (JavaModelException e) {
+ // Unlikely to reach here as the elements have already been opened in NameLookup.
+ }
+ } else {
+ result = new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ }
CompilationUnitDeclaration unit =
SourceTypeConverter.buildCompilationUnit(
sourceTypes,//sourceTypes[0] is always toplevel here
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
index c585070..b467c95 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -95,7 +95,9 @@
public TypeBinding resolveType(BlockScope scope) {
- super.resolveType(scope);
+ TypeBinding type = super.resolveType(scope);
+ if (type != null && type.isPolyType())
+ return type; // wait for more inference/resolution
// tolerate some error cases
if(this.binding == null ||
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index 79f6922..7c87b9f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -64,8 +64,9 @@
protected static final int K_BETWEEN_CASE_AND_COLON = SELECTION_PARSER + 1; // whether we are inside a block
protected static final int K_INSIDE_RETURN_STATEMENT = SELECTION_PARSER + 2; // whether we are between the keyword 'return' and the end of a return statement
protected static final int K_CAST_STATEMENT = SELECTION_PARSER + 3; // whether we are between ')' and the end of a cast statement
-
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693
+ private boolean selectionNodeFound;
public ASTNode assistNodeParent; // the parent node of assist node
/* public fields */
@@ -821,6 +822,21 @@
this.lastIgnoredToken = -1;
}
}
+ if (this.selectionNodeFound) {
+ this.restartRecovery = true;
+ }
+}
+protected void consumeAssignment() {
+ super.consumeAssignment();
+ if (this.selectionNodeFound) {
+ this.restartRecovery = true;
+ }
+}
+protected void consumeBlockStatement() {
+ super.consumeBlockStatement();
+ if (this.selectionNodeFound) {
+ this.restartRecovery = true;
+ }
}
protected void consumeMarkerAnnotation(boolean isTypeAnnotation) {
int index;
@@ -1525,7 +1541,9 @@
}
this.assistNode = messageSend;
if (!this.diet){
- this.restartRecovery = true; // force to restart in recovery mode
+ // Don't restart recovery, not yet, until variable decl statement has been consumed.
+ // This is to ensure chained method invocations are taken into account for resolution.
+ this.selectionNodeFound = true;
this.lastIgnoredToken = -1;
}
@@ -1554,7 +1572,9 @@
}
this.assistNode = messageSend;
if (!this.diet){
- this.restartRecovery = true; // force to restart in recovery mode
+ // Don't restart recovery, not yet, until variable decl statement has been consumed.
+ // This is to ensure chained method invocations are taken into account for resolution.
+ this.selectionNodeFound = true;
this.lastIgnoredToken = -1;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 89c602e..486320b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1660,7 +1660,8 @@
int IllegalArrayTypeInIntersectionCast = TypeRelated + 893;
/** @since 3.10 */
int DuplicateBoundInIntersectionCast = TypeRelated + 894;
- /** @since 3.10 */
+ /** @deprecated This problem is no longer reported; number Of functional interface is not an issue, number of abstract methods is.
+ * @since 3.10 */
int MultipleFunctionalInterfaces = TypeRelated + 895;
/** @since 3.10 */
int StaticInterfaceMethodNotBelow18 = Internal + Syntax + 896;
@@ -1820,6 +1821,18 @@
int IllegalReturnNullityRedefinitionFreeTypeVariable = MethodRelated + 974;
/** @since 3.12 */
int IllegalRedefinitionOfTypeVariable = 975;
+ /** @since 3.12 */
+ int UncheckedAccessOfValueOfFreeTypeVariable = 976;
+ /** @since 3.12 */
+ int UninitializedFreeTypeVariableField = 977;
+ /** @since 3.12 */
+ int UninitializedFreeTypeVariableFieldHintMissingDefault = 978;
+ /** @since 3.12 */
+ int RequiredNonNullButProvidedFreeTypeVariable = TypeRelated + 979;
+ /** @since 3.12 */
+ int NonNullTypeVariableFromLegacyMethod = TypeRelated + 980;
+ /** @since 3.12 */
+ int NonNullMethodTypeVariableFromLegacyMethod = TypeRelated + 981;
// Java 8 work
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index d184e0a..874c7bb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -62,6 +62,7 @@
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -77,10 +78,10 @@
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
-import org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker;
+import org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream;
import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -100,6 +101,8 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
+import org.eclipse.jdt.internal.compiler.problem.AbortType;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
import org.eclipse.jdt.internal.compiler.util.Messages;
@@ -1038,13 +1041,36 @@
case SyntheticMethodBinding.DeserializeLambda:
deserializeLambdaMethod = syntheticMethod; // delay processing
break;
+ case SyntheticMethodBinding.SerializableMethodReference:
+ // Nothing to be done
+ break;
}
}
emittedSyntheticsCount = currentSyntheticsCount;
}
}
if (deserializeLambdaMethod != null) {
- addSyntheticDeserializeLambda(deserializeLambdaMethod,this.referenceBinding.syntheticMethods());
+ int problemResetPC = 0;
+ this.codeStream.wideMode = false;
+ boolean restart = false;
+ do {
+ try {
+ problemResetPC = this.contentsOffset;
+ addSyntheticDeserializeLambda(deserializeLambdaMethod,this.referenceBinding.syntheticMethods());
+ restart = false;
+ } catch (AbortMethod e) {
+ // Restart code generation if possible ...
+ if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+ // a branch target required a goto_w, restart code generation in wide mode.
+ this.contentsOffset = problemResetPC;
+ this.methodCount--;
+ this.codeStream.resetInWideMode(); // request wide mode
+ restart = true;
+ } else {
+ throw new AbortType(this.referenceBinding.scope.referenceContext.compilationResult, e.problem);
+ }
+ }
+ } while (restart);
}
}
@@ -3038,12 +3064,9 @@
FunctionalExpression functional = (FunctionalExpression) functionalExpressionList.get(i);
MethodBinding [] bridges = functional.getRequiredBridges();
TypeBinding[] markerInterfaces = null;
- if (functional instanceof LambdaExpression &&
- (((markerInterfaces=((LambdaExpression)functional).getMarkerInterfaces()) != null) ||
- ((LambdaExpression)functional).isSerializable) ||
- bridges != null) {
-
- LambdaExpression lambdaEx = (LambdaExpression)functional;
+ if ((functional instanceof LambdaExpression
+ && (((markerInterfaces = ((LambdaExpression) functional).getMarkerInterfaces()) != null))
+ || bridges != null) || functional.isSerializable) {
// may need even more space
int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry
if (markerInterfaces != null) {
@@ -3085,7 +3108,7 @@
this.contents[localContentsOffset++] = (byte) methodTypeIndex;
int bitflags = 0;
- if (lambdaEx.isSerializable) {
+ if (functional.isSerializable) {
bitflags |= ClassFileConstants.FLAG_SERIALIZABLE;
}
if (markerInterfaces!=null) {
@@ -3576,6 +3599,11 @@
generateCodeAttributeHeader();
this.codeStream.init(this);
this.codeStream.generateSyntheticBodyForDeserializeLambda(methodBinding, syntheticMethodBindings);
+ int code_length = this.codeStream.position;
+ if (code_length > 65535) {
+ this.referenceBinding.scope.problemReporter().bytecodeExceeds64KLimit(
+ methodBinding, this.referenceBinding.sourceStart(), this.referenceBinding.sourceEnd());
+ }
completeCodeAttributeForSyntheticMethod(
methodBinding,
codeAttributeOffset,
@@ -5360,10 +5388,17 @@
if (this.bootstrapMethods == null) {
this.bootstrapMethods = new ArrayList();
}
+ if (expression instanceof ReferenceExpression) {
+ for (int i = 0; i < this.bootstrapMethods.size(); i++) {
+ FunctionalExpression fexp = (FunctionalExpression) this.bootstrapMethods.get(i);
+ if (fexp.binding == expression.binding
+ && TypeBinding.equalsEquals(fexp.expectedType(), expression.expectedType()))
+ return expression.bootstrapMethodNumber = i;
+ }
+ }
this.bootstrapMethods.add(expression);
// Record which bootstrap method was assigned to the expression
- expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1;
- return this.bootstrapMethods.size() - 1;
+ return expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1;
}
public void reset(SourceTypeBinding typeBinding) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index aacac0a..80e2e1b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -358,7 +358,8 @@
:giro */
public boolean checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
// SH}
- boolean is1_7 = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7;
+ long sourceLevel = scope.compilerOptions().sourceLevel;
+ boolean is1_7 = sourceLevel >= ClassFileConstants.JDK1_7;
TypeBinding[] params = method.parameters;
int paramLength = params.length;
boolean isRawMemberInvocation = !method.isStatic()
@@ -451,11 +452,13 @@
}
} else if (rawOriginalGenericMethod != null
|| uncheckedBoundCheck
- || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0
- && method instanceof ParameterizedGenericMethodBinding
- /*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/)) {
- scope.problemReporter().unsafeRawGenericMethodInvocation((ASTNode)invocationSite, method, argumentTypes);
- return true;
+ || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0)) {
+ if (method instanceof ParameterizedGenericMethodBinding) {
+ scope.problemReporter().unsafeRawGenericMethodInvocation((ASTNode)invocationSite, method, argumentTypes);
+ return true;
+ }
+ if (sourceLevel >= ClassFileConstants.JDK1_8)
+ return true; // signal to erase return type and exceptions, while keeping javac compatibility at 1.7-
}
return false;
}
@@ -1014,7 +1017,8 @@
recipientTargetMask = TagBits.AnnotationForField;
break;
case Binding.METHOD:
- recipientTargetMask = TagBits.AnnotationForMethod;
+ MethodBinding method = (MethodBinding) recipient;
+ recipientTargetMask = method.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod;
break;
default:
return;
@@ -1094,6 +1098,8 @@
method.tagBits &= ~(se8nullBits);
}
}
+ } else {
+ method.setTypeAnnotations(se8Annotations);
}
break;
}
@@ -1122,22 +1128,24 @@
TypeReference unionRef = typeRef.isUnionType() ? ((UnionTypeReference) typeRef).typeReferences[0] : null;
// for arrays: @T X[] SE7 associates @T to the type, but in SE8 it affects the leaf component type
- long prevNullBits = existingType.leafComponentType().tagBits & TagBits.AnnotationNullMASK;
+ TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
+ if (se8nullBits != 0 && oldLeafType.isBaseType()) {
+ scope.problemReporter().illegalAnnotationForBaseType(typeRef, new Annotation[] { se8NullAnnotation }, se8nullBits);
+ return existingType;
+ }
+
+ long prevNullBits = oldLeafType.tagBits & TagBits.AnnotationNullMASK;
if ((prevNullBits | se8nullBits) == TagBits.AnnotationNullMASK) { // contradiction after merge?
- if (!(existingType instanceof TypeVariableBinding)) { // let type-use annotations override annotations on the type parameter declaration
+ if (!(oldLeafType instanceof TypeVariableBinding)) { // let type-use annotations override annotations on the type parameter declaration
if (prevNullBits != TagBits.AnnotationNullMASK && se8nullBits != TagBits.AnnotationNullMASK) { // conflict caused by the merge?
scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation);
}
se8Annotations = Binding.NO_ANNOTATIONS;
se8nullBits = 0;
}
- existingType = existingType.withoutToplevelNullAnnotation();
+ oldLeafType = oldLeafType.withoutToplevelNullAnnotation();
}
- TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
- if (se8nullBits != 0 && oldLeafType.isBaseType()) {
- scope.problemReporter().illegalAnnotationForBaseType(typeRef, new Annotation[] { se8NullAnnotation }, se8nullBits);
- return existingType;
- }
+
AnnotationBinding [][] goodies = new AnnotationBinding[typeRef.getAnnotatableLevels()][];
goodies[0] = se8Annotations; // @T X.Y.Z local; ==> @T should annotate X
TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 28b5382..e3ed770 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -365,6 +365,9 @@
flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
else if (tagBits == TagBits.AnnotationNullable)
flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
+ else if (methodBinding.parameters[i].isFreeTypeVariable()) {
+ flowInfo.markNullStatus(methodArguments[i].binding, FlowInfo.FREE_TYPEVARIABLE);
+ }
} else {
if (methodBinding.parameterNonNullness != null) {
// leverage null-info from parameter annotations:
@@ -829,7 +832,7 @@
if (!(this.isGenerated || this.isCopied))
// SH}
resolveJavadoc();
- resolveAnnotations(this.scope, this.annotations, this.binding);
+ resolveAnnotations(this.scope, this.annotations, this.binding, this.isConstructor());
long sourceLevel = this.scope.compilerOptions().sourceLevel;
if (sourceLevel < ClassFileConstants.JDK1_8) // otherwise already checked via Argument.createBinding
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 315d40b..4f3b5a2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -629,6 +629,10 @@
}
}
}
+ if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 &&
+ this.binding.getTypeAnnotations() != Binding.NO_ANNOTATIONS) {
+ this.resolvedType = scope.environment().createAnnotatedType(this.resolvedType, this.binding.getTypeAnnotations());
+ }
//{ObjectTeams: may need to wrap the resolved type
this.resolvedType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.resolvedType, scope, this);
DependentTypeBinding dependentTypeBinding = this.resolvedType.asPlainDependentType();
@@ -966,6 +970,8 @@
if (value != null)
((InferenceContext18) value).cleanUp();
this.inferenceContexts = null;
+ this.outerInferenceContext = null;
+ this.solutionsPerTargetType = null;
}
//-- interface InvocationSite: --
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index a922eff..6aaaa5c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -48,8 +48,6 @@
public Annotation [][] annotationsOnDimensions; // jsr308 style annotations.
public ArrayInitializer initializer;
- private TypeBinding expectedType;
-
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
for (int i = 0, max = this.dimensions.length; i < max; i++) {
Expression dim;
@@ -186,21 +184,6 @@
{
scope.problemReporter().contradictoryNullAnnotations(this.type.annotations[this.type.annotations.length-1]);
}
- LookupEnvironment environment = scope.environment();
- if (environment.usesNullTypeAnnotations()
- && this.annotationsOnDimensions == null // don't annotate if explicit annotations are given on dimensions ...
- && ((referenceType.tagBits & TagBits.AnnotationNullMASK) == 0) // ... or leaf type
- && this.expectedType != null) // need this to determine our action
- {
- Expression lastDim = this.dimensions[this.dimensions.length-1];
- if (lastDim instanceof IntLiteral && ((IntLiteral) lastDim).value == 0) {
- long tagBit = this.expectedType.leafComponentType().tagBits & TagBits.AnnotationNullMASK;
- // let new X[0] be seen as "@NonNull X[]", or "@Nullable X[]" just as expected
- AnnotationBinding[] nullAnnotations = environment.nullAnnotationsFromTagBits(tagBit);
- if (nullAnnotations != null)
- referenceType = environment.createAnnotatedType(referenceType, nullAnnotations);
- }
- }
//{ObjectTeams:
referenceType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(referenceType, scope, this);
// SH}
@@ -231,10 +214,6 @@
return this.resolvedType;
}
- @Override
- public void setExpectedType(TypeBinding expectedType) {
- this.expectedType = expectedType;
- }
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index c520d9a..65a74bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -479,7 +479,7 @@
return this.resolvedType = null;
}
if (isPolyExpression()) {
- if (this.expectedType == null) {
+ if (this.expectedType == null || !this.expectedType.isProperType(true)) {
return new PolyTypeBinding(this);
}
return this.resolvedType = computeConversions(scope, this.expectedType) ? this.expectedType : null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index fa576fb..a1c18a6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -339,7 +339,7 @@
((this.bits & ASTNode.IsDefaultConstructor) != 0)
? (ASTNode) this.scope.referenceType().declarationOf(field.original())
: this);
- } else if (field.isNonNull()) {
+ } else if (field.isNonNull() || field.type.isFreeTypeVariable()) {
FieldDeclaration fieldDecl = this.scope.referenceType().declarationOf(field.original());
if (!isValueProvidedUsingAnnotation(fieldDecl))
this.scope.problemReporter().uninitializedNonNullField(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index cc61fc0..de60c7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -117,6 +117,13 @@
condLoopContext.complainOnDeferredNullChecks(currentScope,
actionInfo.addPotentialNullInfoFrom(
condInfo.initsWhenTrue().unconditionalInits()));
+ } else {
+ loopingContext.complainOnDeferredNullChecks(currentScope,
+ flowInfo.unconditionalCopy().addPotentialNullInfoFrom(
+ condInfo.initsWhenTrue().unconditionalInits()), false);
+ condLoopContext.complainOnDeferredNullChecks(currentScope,
+ actionInfo.addPotentialNullInfoFrom(
+ condInfo.initsWhenTrue().unconditionalInits()), false);
}
if (loopingContext.hasEscapingExceptions()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926
FlowInfo loopbackFlowInfo = flowInfo.copy();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index e5b0f4d..72bca9a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -194,7 +194,7 @@
public int implicitConversion;
public TypeBinding resolvedType;
- static Expression [] NO_EXPRESSIONS = new Expression[0];
+ public static Expression [] NO_EXPRESSIONS = new Expression[0];
public static final boolean isConstantValueRepresentable(Constant constant, int constantTypeID, int targetTypeID) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 680c44b..94110e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -166,7 +166,7 @@
// assigning a final field outside an initializer or constructor or wrong reference
currentScope.problemReporter().cannotAssignToFinalField(this.binding, this);
}
- } else if (this.binding.isNonNull()) {
+ } else if (this.binding.isNonNull() || this.binding.type.isTypeVariable()) {
// in a context where it can be assigned?
if ( !isCompound
&& this.receiver.isThis()
@@ -195,7 +195,7 @@
}
if (currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7) {
FieldBinding fieldBinding = this.binding;
- if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
+ if (this.receiver.isThis() && fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index 4de04c5..6c18cc8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -456,7 +456,7 @@
boolean isTargetJsr14 = this.scope.compilerOptions().targetJDK == ClassFileConstants.JDK1_4;
if (collectionType.isCapture()) {
TypeBinding upperBound = ((CaptureBinding)collectionType).firstBound;
- if (upperBound.isArrayType())
+ if (upperBound != null && upperBound.isArrayType())
collectionType = upperBound; // partially anticipating the fix for https://bugs.openjdk.java.net/browse/JDK-8013843
}
if (collectionType.isArrayType()) { // for(E e : E[])
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
index 9a37592..8dd97dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
@@ -47,6 +47,7 @@
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
public abstract class FunctionalExpression extends Expression {
@@ -63,6 +64,7 @@
public boolean shouldCaptureInstance = false; // Whether the expression needs access to instance data of enclosing type
protected static IErrorHandlingPolicy silentErrorHandlingPolicy = DefaultErrorHandlingPolicies.ignoreAllProblems();
private boolean hasReportedSamProblem = false;
+ public boolean isSerializable;
public FunctionalExpression(CompilationResult compilationResult) {
this.compilationResult = compilationResult;
@@ -131,7 +133,7 @@
// we simulate an *invocation* of this functional expression,
// where the expected type of the expression is the return type of the sam:
MethodBinding sam = this.expectedType.getSingleAbstractMethod(this.enclosingScope, true);
- if (sam != null) {
+ if (sam != null && sam.problemId() != ProblemReasons.NoSuchSingleAbstractMethod) {
if (sam.isConstructor())
return sam.declaringClass;
else
@@ -185,6 +187,17 @@
this.descriptor = sam;
if (skipKosherCheck || kosherDescriptor(blockScope, sam, true)) {
+ if (this.expectedType instanceof IntersectionTypeBinding18) {
+ ReferenceBinding[] intersectingTypes = ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
+ for (int t = 0, max = intersectingTypes.length; t < max; t++) {
+ if (intersectingTypes[t].findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
+ this.isSerializable = true;
+ break;
+ }
+ }
+ } else if (this.expectedType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
+ this.isSerializable = true;
+ }
if (blockScope.environment().globalOptions.isAnnotationBasedNullAnalysisEnabled)
NullAnnotationMatching.checkForContradictions(sam, this, blockScope);
return this.resolvedType = this.expectedType;
@@ -205,10 +218,6 @@
blockScope.problemReporter().illFormedParameterizationOfFunctionalInterface(this);
this.hasReportedSamProblem = true;
break;
- case ProblemReasons.IntersectionHasMultipleFunctionalInterfaces:
- blockScope.problemReporter().multipleFunctionalInterfaces(this);
- this.hasReportedSamProblem = true;
- break;
}
return null;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
index 2f30eea..89b10ee 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
@@ -42,6 +42,7 @@
*/
InferenceContext18 getInferenceContext(ParameterizedMethodBinding method);
+ /** Discard any state from type inference when compilation is done. */
void cleanUpInferenceContexts();
/** Record result against target type */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index c1eb9be..2477ddb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -65,7 +65,6 @@
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
@@ -111,7 +110,6 @@
boolean voidCompatible = true;
boolean valueCompatible = false;
boolean returnsValue;
- public boolean isSerializable;
private boolean requiresGenericSignature;
boolean returnsVoid;
public LambdaExpression original = this;
@@ -381,7 +379,7 @@
this.binding.setParameterAnnotations(parameterAnnotations);
}
- if (!argumentsTypeElided && this.binding.isVarargs()) {
+ if (!argumentsTypeElided && !argumentsHaveErrors && this.binding.isVarargs()) {
if (!this.binding.parameters[this.binding.parameters.length - 1].isReifiable()) {
this.scope.problemReporter().possibleHeapPollutionFromVararg(this.arguments[this.arguments.length - 1]);
}
@@ -435,18 +433,6 @@
if (!this.returnsVoid && !this.returnsValue)
this.valueCompatible = this.body.doesNotCompleteNormally();
}
- if (this.expectedType instanceof IntersectionTypeBinding18) {
- ReferenceBinding[] intersectingTypes = ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
- for (int t = 0, max = intersectingTypes.length; t < max; t++) {
- if (intersectingTypes[t].findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
- this.isSerializable = true;
- break;
- }
- }
- } else if (this.expectedType != null &&
- this.expectedType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
- this.isSerializable = true;
- }
if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
this.scope.problemReporter().missingTypeInLambda(this, this.binding);
}
@@ -466,9 +452,11 @@
if (withWildCards != null) {
if (!argumentTypesElided) {
InferenceContext18 freshInferenceContext = new InferenceContext18(blockScope);
- ReferenceBinding inferredType = freshInferenceContext.inferFunctionalInterfaceParameterization(this, blockScope, withWildCards);
- freshInferenceContext.cleanUp();
- return inferredType;
+ try {
+ return freshInferenceContext.inferFunctionalInterfaceParameterization(this, blockScope, withWildCards);
+ } finally {
+ freshInferenceContext.cleanUp();
+ }
} else {
return findGroundTargetTypeForElidedLambda(blockScope, withWildCards);
}
@@ -825,6 +813,9 @@
// copy here is potentially compatible with the target type and has its shape fully computed: i.e value/void compatibility is determined and result expressions have been gathered.
targetType = findGroundTargetType(this.enclosingScope, targetType, argumentsTypeElided());
MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope, true);
+ if (sam == null || sam.problemId() == ProblemReasons.NoSuchSingleAbstractMethod) {
+ return false;
+ }
if (sam.returnType.id == TypeIds.T_void) {
if (!copy.voidCompatible)
return false;
@@ -876,10 +867,7 @@
copy = this.copiesPerTargetType.values().iterator().next();
}
}
- final CompilerOptions compilerOptions = this.enclosingScope.compilerOptions();
- boolean analyzeNPE = compilerOptions.isAnnotationBasedNullAnalysisEnabled;
IErrorHandlingPolicy oldPolicy = this.enclosingScope.problemReporter().switchErrorHandlingPolicy(silentErrorHandlingPolicy);
- compilerOptions.isAnnotationBasedNullAnalysisEnabled = false;
try {
if (copy == null) {
copy = copy();
@@ -904,7 +892,6 @@
copy.analyzeExceptions();
return copy;
} finally {
- compilerOptions.isAnnotationBasedNullAnalysisEnabled = analyzeNPE;
this.enclosingScope.problemReporter().switchErrorHandlingPolicy(oldPolicy);
}
}
@@ -959,33 +946,34 @@
LambdaExpression copy = cachedResolvedCopy(s, true /* any resolved copy is good */, false, null); // we expect a cached copy - otherwise control won't reach here.
Expression [] returnExpressions = copy.resultExpressions;
int returnExpressionsLength = returnExpressions == null ? 0 : returnExpressions.length;
-
- int i;
- // r1 is a primitive type, r2 is a reference type, and each result expression is a standalone expression (15.2) of a primitive type
- if (r1.isBaseType() && !r2.isBaseType()) {
- for (i = 0; i < returnExpressionsLength; i++) {
- if (returnExpressions[i].isPolyExpression() || !returnExpressions[i].resolvedType.isBaseType())
- break;
+ if (returnExpressionsLength > 0) {
+ int i;
+ // r1 is a primitive type, r2 is a reference type, and each result expression is a standalone expression (15.2) of a primitive type
+ if (r1.isBaseType() && !r2.isBaseType()) {
+ for (i = 0; i < returnExpressionsLength; i++) {
+ if (returnExpressions[i].isPolyExpression() || !returnExpressions[i].resolvedType.isBaseType())
+ break;
+ }
+ if (i == returnExpressionsLength)
+ return true;
}
- if (i == returnExpressionsLength)
- return true;
- }
- if (!r1.isBaseType() && r2.isBaseType()) {
- for (i = 0; i < returnExpressionsLength; i++) {
- if (returnExpressions[i].resolvedType.isBaseType())
- break;
+ if (!r1.isBaseType() && r2.isBaseType()) {
+ for (i = 0; i < returnExpressionsLength; i++) {
+ if (returnExpressions[i].resolvedType.isBaseType())
+ break;
+ }
+ if (i == returnExpressionsLength)
+ return true;
}
- if (i == returnExpressionsLength)
- return true;
- }
- if (r1.isFunctionalInterface(this.enclosingScope) && r2.isFunctionalInterface(this.enclosingScope)) {
- for (i = 0; i < returnExpressionsLength; i++) {
- Expression resultExpression = returnExpressions[i];
- if (!resultExpression.sIsMoreSpecific(r1, r2, skope))
- break;
- }
- if (i == returnExpressionsLength)
- return true;
+ if (r1.isFunctionalInterface(this.enclosingScope) && r2.isFunctionalInterface(this.enclosingScope)) {
+ for (i = 0; i < returnExpressionsLength; i++) {
+ Expression resultExpression = returnExpressions[i];
+ if (!resultExpression.sIsMoreSpecific(r1, r2, skope))
+ break;
+ }
+ if (i == returnExpressionsLength)
+ return true;
+ }
}
return false;
}
@@ -1074,7 +1062,7 @@
parentAST.tagAsHavingErrors();
return;
}
- break;
+ //$FALL-THROUGH$
default:
parent = parent.parent;
break;
@@ -1103,7 +1091,6 @@
case IProblem.LambdaDescriptorMentionsUnmentionable:
case IProblem.TargetTypeNotAFunctionalInterface:
case IProblem.illFormedParameterizationOfFunctionalInterface:
- case IProblem.MultipleFunctionalInterfaces:
case IProblem.NoGenericLambda:
return;
default:
@@ -1276,17 +1263,15 @@
public TypeBinding[] getMarkerInterfaces() {
if (this.expectedType instanceof IntersectionTypeBinding18) {
Set markerBindings = new LinkedHashSet();
- TypeBinding[] intersectionTypes = ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
+ IntersectionTypeBinding18 intersectionType = (IntersectionTypeBinding18)this.expectedType;
+ TypeBinding[] intersectionTypes = intersectionType.intersectingTypes;
+ TypeBinding samType = intersectionType.getSAMType(this.enclosingScope);
for (int i = 0,max = intersectionTypes.length; i < max; i++) {
TypeBinding typeBinding = intersectionTypes[i];
- MethodBinding methodBinding = typeBinding.getSingleAbstractMethod(this.scope, true);
- // Why doesn't getSingleAbstractMethod do as the javadoc says, and return null
- // when it is not a SAM type
- if (!(methodBinding instanceof ProblemMethodBinding && ((ProblemMethodBinding)methodBinding).problemId()==ProblemReasons.NoSuchSingleAbstractMethod)) {
- continue;
- }
- if (typeBinding.id == TypeIds.T_JavaIoSerializable) {
- // Serializable is captured as a bitflag
+ if (!typeBinding.isInterface() // only interfaces
+ || TypeBinding.equalsEquals(samType, typeBinding) // except for the samType itself
+ || typeBinding.id == TypeIds.T_JavaIoSerializable) // but Serializable is captured as a bitflag
+ {
continue;
}
markerBindings.add(typeBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 72025ff..4d34984 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -500,8 +500,18 @@
public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int ttlForFieldCheck) {
// message send as a receiver
- if ((nullStatus(flowInfo, flowContext) & FlowInfo.POTENTIALLY_NULL) != 0) // note that flowInfo is not used inside nullStatus(..)
- scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
+ int nullStatus = nullStatus(flowInfo, flowContext); // note that flowInfo is not used inside nullStatus(..)
+ if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) {
+ if(this.binding.returnType.isTypeVariable() && nullStatus == FlowInfo.FREE_TYPEVARIABLE && scope.environment().globalOptions.pessimisticNullAnalysisForFreeTypeVariablesEnabled) {
+ scope.problemReporter().methodReturnTypeFreeTypeVariableReference(this.binding, this);
+ } else {
+ scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
+ }
+ } else if ((this.resolvedType.tagBits & TagBits.AnnotationNonNull) != 0) {
+ NullAnnotationMatching nonNullStatus = NullAnnotationMatching.okNonNullStatus(this);
+ if (nonNullStatus.wantToReport())
+ nonNullStatus.report(scope);
+ }
return true; // done all possible checking
}
/**
@@ -749,7 +759,10 @@
// try to retrieve null status of this message send from an annotation of the called method:
long tagBits = this.binding.tagBits;
if ((tagBits & TagBits.AnnotationNullMASK) == 0L) // alternatively look for type annotation (will only be present in 1.8+):
- tagBits = this.binding.returnType.tagBits;
+ tagBits = this.binding.returnType.tagBits & TagBits.AnnotationNullMASK;
+ if(tagBits == 0L && this.binding.returnType.isFreeTypeVariable()) {
+ return FlowInfo.FREE_TYPEVARIABLE;
+ }
return FlowInfo.tagBitsToNullStatus(tagBits);
}
return FlowInfo.UNKNOWN;
@@ -1685,6 +1698,8 @@
if (value != null)
((InferenceContext18) value).cleanUp();
this.inferenceContexts = null;
+ this.outerInferenceContext = null;
+ this.solutionsPerTargetType = null;
}
public Expression[] arguments() {
return this.arguments;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
index 748dcd3..bed1a19 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
@@ -12,11 +12,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
@@ -37,6 +40,7 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
/**
* Performs matching of null type annotations.
@@ -45,10 +49,10 @@
*/
public class NullAnnotationMatching {
- public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(0, FlowInfo.UNKNOWN, null);
- public static final NullAnnotationMatching NULL_ANNOTATIONS_OK_NONNULL = new NullAnnotationMatching(0, FlowInfo.NON_NULL, null);
- public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(1, FlowInfo.UNKNOWN, null);
- public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(2, FlowInfo.UNKNOWN, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(Severity.OK, FlowInfo.UNKNOWN, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_OK_NONNULL = new NullAnnotationMatching(Severity.OK, FlowInfo.NON_NULL, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(Severity.UNCHECKED, FlowInfo.UNKNOWN, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(Severity.MISMATCH, FlowInfo.UNKNOWN, null);
public enum CheckMode {
/** in this mode we check normal assignment compatibility. */
@@ -87,23 +91,44 @@
}
}
- /** 0 = OK, 1 = unchecked, 2 = definite mismatch */
- public final int severity;
+ private enum Severity {
+ /** No problem detected. */
+ OK,
+ /** No real problem, but could issue an {@link IProblem#NonNullTypeVariableFromLegacyMethod} or similar. */
+ LEGACY_WARNING,
+ /** Need unchecked conversion from unannotated to annotated. */
+ UNCHECKED,
+ /** Definite nullity mismatch. */
+ MISMATCH;
+
+ public Severity max(Severity severity) {
+ if (compareTo(severity) < 0)
+ return severity;
+ return this;
+ }
+
+ public boolean isAnyMismatch() {
+ return compareTo(LEGACY_WARNING) > 0;
+ }
+ }
+
+ private final Severity severity;
/** If non-null this field holds the supertype of the provided type which was used for direct matching. */
public final TypeBinding superTypeHint;
public final int nullStatus;
- public NullAnnotationMatching(int severity, int nullStatus, TypeBinding superTypeHint) {
+ NullAnnotationMatching(Severity severity, int nullStatus, TypeBinding superTypeHint) {
this.severity = severity;
this.superTypeHint = superTypeHint;
this.nullStatus = nullStatus;
}
- public boolean isAnyMismatch() { return this.severity != 0; }
- public boolean isUnchecked() { return this.severity == 1; }
- public boolean isDefiniteMismatch() { return this.severity == 2; }
-
+ public boolean isAnyMismatch() { return this.severity.isAnyMismatch(); }
+ public boolean isUnchecked() { return this.severity == Severity.UNCHECKED; }
+ public boolean isDefiniteMismatch() { return this.severity == Severity.MISMATCH; }
+ public boolean wantToReport() { return this.severity == Severity.LEGACY_WARNING; }
+
public boolean isPotentiallyNullMismatch() {
return !isDefiniteMismatch() && this.nullStatus != -1 && (this.nullStatus & FlowInfo.POTENTIALLY_NULL) != 0;
}
@@ -133,12 +158,16 @@
return nullStatus; // if both branches disagree use the precomputed & merged nullStatus
}
lhsTagBits = var.type.tagBits & TagBits.AnnotationNullMASK;
- NullAnnotationMatching annotationStatus = analyse(var.type, providedType, nullStatus);
+ NullAnnotationMatching annotationStatus = analyse(var.type, providedType, null, null, nullStatus, expression, CheckMode.COMPATIBLE);
if (annotationStatus.isAnyMismatch()) {
flowContext.recordNullityMismatch(currentScope, expression, providedType, var.type, flowInfo, nullStatus, annotationStatus);
hasReported = true;
- } else if (annotationStatus.nullStatus != FlowInfo.UNKNOWN) {
- return annotationStatus.nullStatus;
+ } else {
+ if (annotationStatus.wantToReport())
+ annotationStatus.report(currentScope);
+ if (annotationStatus.nullStatus != FlowInfo.UNKNOWN) {
+ return annotationStatus.nullStatus;
+ }
}
}
if (lhsTagBits == TagBits.AnnotationNonNull && nullStatus != FlowInfo.NON_NULL) {
@@ -161,7 +190,7 @@
* @return a status object representing the severity of mismatching plus optionally a supertype hint
*/
public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, int nullStatus) {
- return analyse(requiredType, providedType, null, null, nullStatus, CheckMode.COMPATIBLE);
+ return analyse(requiredType, providedType, null, null, nullStatus, null, CheckMode.COMPATIBLE);
}
/**
* Find any mismatches between the two given types, which are caused by null type annotations.
@@ -171,19 +200,22 @@
* Pass null if not interested in these added checks.
* @param substitution TODO
* @param nullStatus we are only interested in NULL or NON_NULL, -1 indicates that we are in a recursion, where flow info is ignored
+ * @param providedExpression optionally holds the provided expression of type 'providedType'
* @param mode controls the kind of check performed (see {@link CheckMode}).
* @return a status object representing the severity of mismatching plus optionally a supertype hint
*/
- public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute, Substitution substitution, int nullStatus, CheckMode mode) {
+ public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute, Substitution substitution,
+ int nullStatus, Expression providedExpression, CheckMode mode)
+ {
if (!requiredType.enterRecursiveFunction())
return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
try {
- int severity = 0;
+ Severity severity = Severity.OK;
TypeBinding superTypeHint = null;
NullAnnotationMatching okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK;
if (areSameTypes(requiredType, providedType, providedSubstitute)) {
if ((requiredType.tagBits & TagBits.AnnotationNonNull) != 0)
- return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+ return okNonNullStatus(providedExpression);
return okStatus;
}
if (requiredType instanceof TypeVariableBinding && substitution != null && (mode == CheckMode.EXACT || mode == CheckMode.COMPATIBLE || mode == CheckMode.BOUND_SUPER_CHECK)) {
@@ -193,7 +225,7 @@
return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
if (areSameTypes(requiredType, providedType, providedSubstitute)) {
if ((requiredType.tagBits & TagBits.AnnotationNonNull) != 0)
- return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+ return okNonNullStatus(providedExpression);
return okStatus;
}
}
@@ -203,18 +235,18 @@
// during bound check against a type variable check the provided type against all upper bounds:
TypeBinding superClass = requiredType.superclass();
if (superClass != null && (superClass.hasNullTypeAnnotations() || substitution != null)) { // annotations may enter when substituting a nested type variable
- NullAnnotationMatching status = analyse(superClass, providedType, null, substitution, nullStatus, CheckMode.BOUND_SUPER_CHECK);
- severity = Math.max(severity, status.severity);
- if (severity == 2)
+ NullAnnotationMatching status = analyse(superClass, providedType, null, substitution, nullStatus, providedExpression, CheckMode.BOUND_SUPER_CHECK);
+ severity = severity.max(status.severity);
+ if (severity == Severity.MISMATCH)
return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
}
TypeBinding[] superInterfaces = requiredType.superInterfaces();
if (superInterfaces != null) {
for (int i = 0; i < superInterfaces.length; i++) {
if (superInterfaces[i].hasNullTypeAnnotations() || substitution != null) { // annotations may enter when substituting a nested type variable
- NullAnnotationMatching status = analyse(superInterfaces[i], providedType, null, substitution, nullStatus, CheckMode.BOUND_SUPER_CHECK);
- severity = Math.max(severity, status.severity);
- if (severity == 2)
+ NullAnnotationMatching status = analyse(superInterfaces[i], providedType, null, substitution, nullStatus, providedExpression, CheckMode.BOUND_SUPER_CHECK);
+ severity = severity.max(status.severity);
+ if (severity == Severity.MISMATCH)
return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
}
}
@@ -240,11 +272,24 @@
} else {
if (i > 0)
currentNullStatus = -1; // don't use beyond the outermost dimension
- severity = Math.max(severity, computeNullProblemSeverity(requiredBits, providedBits, currentNullStatus, i == 0 ? mode : mode.toDetail(), false));
- if (severity == 2)
+ Severity dimSeverity = computeNullProblemSeverity(requiredBits, providedBits, currentNullStatus, i == 0 ? mode : mode.toDetail(), false);
+ if (i > 0 && dimSeverity == Severity.UNCHECKED
+ && providedExpression instanceof ArrayAllocationExpression
+ && providedBits == 0 && requiredBits != 0)
+ {
+ Expression[] dimensions = ((ArrayAllocationExpression) providedExpression).dimensions;
+ Expression previousDim = dimensions[i-1];
+ if (previousDim instanceof IntLiteral && previousDim.constant.intValue() == 0) {
+ dimSeverity = Severity.OK; // element of empty dimension matches anything
+ nullStatus = -1;
+ break;
+ }
+ }
+ severity = severity.max(dimSeverity);
+ if (severity == Severity.MISMATCH)
return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH;
}
- if (severity == 0)
+ if (severity == Severity.OK)
nullStatus = -1;
}
} else if (providedType.id == TypeIds.T_null) {
@@ -258,16 +303,16 @@
// at toplevel (having a nullStatus) nullable matches all
} else {
long providedBits = providedNullTagBits(providedType);
- int s = computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode, requiredType.isTypeVariable());
- severity = Math.max(severity, s);
- if (severity == 0 && (providedBits & TagBits.AnnotationNonNull) != 0)
- okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+ Severity s = computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode, requiredType.isTypeVariable());
+ severity = severity.max(s);
+ if (!severity.isAnyMismatch() && (providedBits & TagBits.AnnotationNonNull) != 0)
+ okStatus = okNonNullStatus(providedExpression);
}
- if (severity < 2 && nullStatus != FlowInfo.NULL) { // null value has no details
+ if (severity != Severity.MISMATCH && nullStatus != FlowInfo.NULL) { // null value has no details
TypeBinding providedSuper = providedType.findSuperTypeOriginatingFrom(requiredType);
TypeBinding providedSubstituteSuper = providedSubstitute != null ? providedSubstitute.findSuperTypeOriginatingFrom(requiredType) : null;
- if(severity == 1 && requiredType.isTypeVariable() && providedType.isTypeVariable() && (providedSuper == requiredType || providedSubstituteSuper == requiredType)) { //$IDENTITY-COMPARISON$
- severity = 0;
+ if(severity == Severity.UNCHECKED && requiredType.isTypeVariable() && providedType.isTypeVariable() && (providedSuper == requiredType || providedSubstituteSuper == requiredType)) { //$IDENTITY-COMPARISON$
+ severity = Severity.OK;
}
if (providedSuper != providedType) //$IDENTITY-COMPARISON$
superTypeHint = providedSuper;
@@ -278,9 +323,9 @@
if (requiredArguments != null && providedArguments != null && requiredArguments.length == providedArguments.length) {
for (int i = 0; i < requiredArguments.length; i++) {
TypeBinding providedArgSubstitute = providedSubstitutes != null ? providedSubstitutes[i] : null;
- NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], providedArgSubstitute, substitution, -1, mode.toDetail());
- severity = Math.max(severity, status.severity);
- if (severity == 2)
+ NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], providedArgSubstitute, substitution, -1, providedExpression, mode.toDetail());
+ severity = severity.max(status.severity);
+ if (severity == Severity.MISMATCH)
return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
}
}
@@ -289,18 +334,45 @@
TypeBinding providedEnclosing = providedType.enclosingType();
if (requiredEnclosing != null && providedEnclosing != null) {
TypeBinding providedEnclSubstitute = providedSubstitute != null ? providedSubstitute.enclosingType() : null;
- NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, providedEnclSubstitute, substitution, -1, mode);
- severity = Math.max(severity, status.severity);
+ NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, providedEnclSubstitute, substitution, -1, providedExpression, mode);
+ severity = severity.max(status.severity);
}
}
}
- if (severity == 0)
+ if (!severity.isAnyMismatch())
return okStatus;
return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
} finally {
requiredType.exitRecursiveFunction();
}
}
+ public void report(Scope scope) {
+ // nop
+ }
+ public static NullAnnotationMatching okNonNullStatus(final Expression providedExpression) {
+ if (providedExpression instanceof MessageSend) {
+ final MethodBinding method = ((MessageSend) providedExpression).binding;
+ if (method != null && method.isValidBinding()) {
+ MethodBinding originalMethod = method.original();
+ TypeBinding originalDeclaringClass = originalMethod.declaringClass;
+ if (originalDeclaringClass instanceof BinaryTypeBinding
+ && ((BinaryTypeBinding) originalDeclaringClass).externalAnnotationStatus.isPotentiallyUnannotatedLib()
+ && originalMethod.returnType.isTypeVariable()
+ && (originalMethod.returnType.tagBits & TagBits.AnnotationNullMASK) == 0)
+ {
+ final int severity = ((BinaryTypeBinding) originalDeclaringClass).externalAnnotationStatus == ExternalAnnotationStatus.NO_EEA_FILE
+ ? ProblemSeverities.Warning : ProblemSeverities.Info; // reduce severity if not configured to for external annotations
+ return new NullAnnotationMatching(Severity.LEGACY_WARNING, FlowInfo.UNKNOWN, null) {
+ @Override
+ public void report(Scope scope) {
+ scope.problemReporter().nonNullTypeVariableInUnannotatedBinary(scope.environment(), method, providedExpression, severity);
+ }
+ };
+ }
+ }
+ }
+ return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+ }
/** Are both types identical wrt the unannotated type and any null type annotations? Only unstructured types and captures are considered. */
protected static boolean areSameTypes(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute) {
@@ -313,14 +385,14 @@
// when providing exactly the lower bound of the required type we're definitely fine:
TypeBinding lowerBound = ((CaptureBinding)requiredType).lowerBound;
if (lowerBound != null && areSameTypes(lowerBound, providedType, providedSubstitute))
- return true;
+ return (requiredType.tagBits & TagBits.AnnotationNullMASK) == (providedType.tagBits & TagBits.AnnotationNullMASK);
} else if (requiredType.kind() == Binding.TYPE_PARAMETER && requiredType == providedSubstitute) { //$IDENTITY-COMPARISON$
return true;
} else if (providedType instanceof CaptureBinding) {
// when requiring exactly the upper bound of the provided type we're fine, too:
TypeBinding upperBound = ((CaptureBinding)providedType).upperBound();
if (upperBound != null && areSameTypes(requiredType, upperBound, providedSubstitute))
- return true;
+ return (requiredType.tagBits & TagBits.AnnotationNullMASK) == (providedType.tagBits & TagBits.AnnotationNullMASK);
}
return false;
}
@@ -369,7 +441,8 @@
switch (mode) {
case BOUND_CHECK: // no pessimistic checks during boundcheck (we *have* the instantiation)
case BOUND_SUPER_CHECK:
- case OVERRIDE_RETURN: // allow covariance
+ case OVERRIDE: // no pessimistic checks during override check (comparing two *declarations*)
+ case OVERRIDE_RETURN:
break;
default:
return TagBits.AnnotationNonNull; // instantiation could require @NonNull
@@ -467,41 +540,41 @@
* @param requiredIsTypeVariable is the required type a type variable (possibly: "free type variable")?
* @return see {@link #severity} for interpretation of values
*/
- private static int computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, CheckMode mode, boolean requiredIsTypeVariable) {
+ private static Severity computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, CheckMode mode, boolean requiredIsTypeVariable) {
if (requiredBits == providedBits)
- return 0;
+ return Severity.OK;
if (requiredBits == 0) {
switch (mode) {
case COMPATIBLE:
case BOUND_CHECK:
case BOUND_SUPER_CHECK:
case EXACT:
- return 0;
+ return Severity.OK;
case OVERRIDE_RETURN:
if (providedBits == TagBits.AnnotationNonNull)
- return 0; // covariant redefinition to nonnull is good
+ return Severity.OK; // covariant redefinition to nonnull is good
if (!requiredIsTypeVariable)
- return 0; // refining an unconstrained non-TVB return to nullable is also legal
- return 1;
+ return Severity.OK; // refining an unconstrained non-TVB return to nullable is also legal
+ return Severity.UNCHECKED;
case OVERRIDE:
- return 1; // warn about dropped annotation
+ return Severity.UNCHECKED; // warn about dropped annotation
}
} else if (requiredBits == TagBits.AnnotationNullMASK) {
- return 0; // OK since LHS accepts either
+ return Severity.OK; // OK since LHS accepts either
} else if (requiredBits == TagBits.AnnotationNonNull) {
switch (mode) {
case COMPATIBLE:
case BOUND_SUPER_CHECK:
if (nullStatus == FlowInfo.NON_NULL)
- return 0; // OK by flow analysis
+ return Severity.OK; // OK by flow analysis
//$FALL-THROUGH$
case BOUND_CHECK:
case EXACT:
case OVERRIDE_RETURN:
case OVERRIDE:
if (providedBits == 0)
- return 1;
- return 2;
+ return Severity.UNCHECKED;
+ return Severity.MISMATCH;
}
} else if (requiredBits == TagBits.AnnotationNullable) {
@@ -509,17 +582,17 @@
case COMPATIBLE:
case OVERRIDE_RETURN:
case BOUND_SUPER_CHECK:
- return 0; // in these modes everything is compatible to nullable
+ return Severity.OK; // in these modes everything is compatible to nullable
case BOUND_CHECK:
case EXACT:
if (providedBits == 0)
- return 1;
- return 2;
+ return Severity.UNCHECKED;
+ return Severity.MISMATCH;
case OVERRIDE:
- return 2;
+ return Severity.MISMATCH;
}
}
- return 0; // shouldn't get here, requiredBits should be one of the listed cases
+ return Severity.OK; // shouldn't get here, requiredBits should be one of the listed cases
}
static class SearchContradictions extends TypeBindingVisitor {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 47c4410..d62204a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -377,6 +377,10 @@
}
}
}
+ if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 &&
+ this.binding.getTypeAnnotations() != Binding.NO_ANNOTATIONS) {
+ this.resolvedType = scope.environment().createAnnotatedType(this.resolvedType, this.binding.getTypeAnnotations());
+ }
}
return result;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
index a8cff6c..a80776c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -83,6 +83,10 @@
if ((field.type.tagBits & TagBits.AnnotationNullable) != 0) {
scope.problemReporter().dereferencingNullableExpression(sourcePosition, scope.environment());
return true;
+ }
+ if (field.type.isFreeTypeVariable()) {
+ scope.problemReporter().fieldFreeTypeVariableReference(field, sourcePosition);
+ return true;
}
if ((field.tagBits & TagBits.AnnotationNullable) != 0) {
scope.problemReporter().nullableFieldDereference(field, sourcePosition);
@@ -170,6 +174,8 @@
return FlowInfo.NON_NULL;
} else if (fieldBinding.isNullable()) {
return FlowInfo.POTENTIALLY_NULL;
+ } else if (fieldBinding.type.isFreeTypeVariable()) {
+ return FlowInfo.FREE_TYPEVARIABLE;
}
}
if (this.resolvedType != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index a7d145d..2fe6be3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -103,7 +103,7 @@
public int nameSourceStart;
public TypeBinding receiverType;
- private boolean haveReceiver;
+ public boolean haveReceiver;
public TypeBinding[] resolvedTypeArguments;
private boolean typeArgumentsHaveErrors;
@@ -264,8 +264,7 @@
// these cases are either too complicated, impossible to handle or result in significant code duplication
return (this.binding.isVarargs() ||
(isConstructorReference() && this.receiverType.syntheticOuterLocalVariables() != null && this.shouldCaptureInstance) ||
- this.expectedType instanceof IntersectionTypeBinding18 || // marker interfaces require alternate meta factory.
- this.expectedType.findSuperTypeOriginatingFrom(currentScope.getJavaIoSerializable()) != null || // serialization support.
+ this.expectedType instanceof IntersectionTypeBinding18 || // marker interfaces require alternate meta factory.
this.requiresBridges()); // bridges.
// To fix: We should opt for direct code generation wherever possible.
}
@@ -296,7 +295,9 @@
}
}
}
-
+ if (this.isSerializable) {
+ sourceType.addSyntheticMethod(this);
+ }
int pc = codeStream.position;
StringBuffer buffer = new StringBuffer();
int argumentsSize = 0;
@@ -342,6 +343,7 @@
}
if (this.syntheticAccessor != null) {
this.binding = sourceType.addSyntheticFactoryMethod(this.binding, this.syntheticAccessor, enclosingInstances);
+ this.syntheticAccessor = null; // add only once
}
}
}
@@ -849,7 +851,7 @@
public ReferenceExpression resolveExpressionExpecting(TypeBinding targetType, Scope scope, InferenceContext18 inferenceContext) {
if (this.exactMethodBinding != null) { // We may see inference variables in target type.
MethodBinding functionType = targetType.getSingleAbstractMethod(scope, true);
- if (functionType == null)
+ if (functionType == null || functionType.problemId() == ProblemReasons.NoSuchSingleAbstractMethod)
return null;
int n = functionType.parameters.length;
int k = this.exactMethodBinding.parameters.length;
@@ -990,7 +992,7 @@
final MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope, true);
if (sam == null || !sam.isValidBinding())
return false;
- if (this.typeArgumentsHaveErrors || this.lhs.resolvedType == null || !this.lhs.resolvedType.isValidBinding())
+ if (this.typeArgumentsHaveErrors || this.receiverType == null || !this.receiverType.isValidBinding())
return false;
int parametersLength = sam.parameters.length;
@@ -1104,7 +1106,14 @@
if (tSam == null || !tSam.isValidBinding())
return false;
TypeBinding r2 = tSam.returnType;
-
+
+ TypeBinding[] sParams = sSam.parameters;
+ TypeBinding[] tParams = tSam.parameters;
+ // Both must have the same number of parameters if we got this far
+ for (int i = 0; i < sParams.length; i++) {
+ if (TypeBinding.notEquals(sParams[i], tParams[i]))
+ return false;
+ }
if (r2.id == TypeIds.T_void)
return true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 9f7216e..c019c03 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -147,7 +147,7 @@
} else {
currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
}
- } else if (!isCompound && fieldBinding.isNonNull()
+ } else if (!isCompound && (fieldBinding.isNonNull() || fieldBinding.type.isTypeVariable())
&& TypeBinding.equalsEquals(fieldBinding.declaringClass, currentScope.enclosingReceiverType())) { // inherited fields are not tracked here
// record assignment for detecting uninitialized non-null fields:
flowInfo.markAsDefinitelyAssigned(fieldBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 12d85d5..e22b0fd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -42,6 +42,7 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
@@ -222,11 +223,15 @@
}
private void internalCheckAgainstNullTypeAnnotation(BlockScope scope, TypeBinding requiredType, Expression expression,
int nullStatus, FlowContext flowContext, FlowInfo flowInfo) {
- NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(requiredType, expression.resolvedType, nullStatus);
+ NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(requiredType, expression.resolvedType, null, null, nullStatus, expression, CheckMode.COMPATIBLE);
if (annotationStatus.isDefiniteMismatch()) {
scope.problemReporter().nullityMismatchingTypeAnnotation(expression, expression.resolvedType, requiredType, annotationStatus);
- } else if (annotationStatus.isUnchecked()) {
- flowContext.recordNullityMismatch(scope, expression, expression.resolvedType, requiredType, flowInfo, nullStatus, annotationStatus);
+ } else {
+ if (annotationStatus.wantToReport())
+ annotationStatus.report(scope);
+ if (annotationStatus.isUnchecked()) {
+ flowContext.recordNullityMismatch(scope, expression, expression.resolvedType, requiredType, flowInfo, nullStatus, annotationStatus);
+ }
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 0101b0d..77064d2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -857,7 +857,7 @@
if (variables != null && variables.length > rank) {
TypeBinding variable = variables[rank];
if (variable.hasNullTypeAnnotations()) {
- if (NullAnnotationMatching.analyse(variable, this.resolvedType, null, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch())
+ if (NullAnnotationMatching.analyse(variable, this.resolvedType, null, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch())
scope.problemReporter().nullityMismatchTypeArgument(variable, this.resolvedType, this);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index f8fc493..a215dda 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -129,6 +129,11 @@
if ((combinedTagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0)
this.continueLabel = null;
exitBranch.addInitializationsFrom(condInfo.initsWhenFalse());
+ actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+ condLoopContext.complainOnDeferredNullChecks(currentScope,
+ actionInfo, false);
+ loopingContext.complainOnDeferredNullChecks(currentScope,
+ actionInfo, false);
} else {
condLoopContext.complainOnDeferredFinalChecks(currentScope,
condInfo);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index 4828a69..5b5d2a1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -41,6 +41,7 @@
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.*;
@@ -94,6 +95,7 @@
private int enclosingNameAndTypeIndex;
private char[] enclosingMethod;
private ExternalAnnotationProvider annotationProvider;
+ private ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
private static String printTypeModifiers(int modifiers) {
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
@@ -546,6 +548,7 @@
* this is unexpected.
*/
public ZipFile setExternalAnnotationProvider(String basePath, String qualifiedBinaryTypeName, ZipFile zipFile, ZipFileProducer producer) throws IOException {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.NO_EEA_FILE;
String qualifiedBinaryFileName = qualifiedBinaryTypeName + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
if (zipFile == null) {
File annotationBase = new File(basePath);
@@ -553,6 +556,7 @@
try {
String filePath = annotationBase.getAbsolutePath()+'/'+qualifiedBinaryFileName;
this.annotationProvider = new ExternalAnnotationProvider(new FileInputStream(filePath), String.valueOf(getName()));
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
} catch (FileNotFoundException e) {
// expected, no need to report an error here
}
@@ -563,14 +567,22 @@
zipFile = (producer != null ? producer.produce() : new ZipFile(annotationBase));
}
ZipEntry entry = zipFile.getEntry(qualifiedBinaryFileName);
- if (entry != null)
+ if (entry != null) {
this.annotationProvider = new ExternalAnnotationProvider(zipFile.getInputStream(entry), String.valueOf(getName()));
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ }
return zipFile;
}
public boolean hasAnnotationProvider() {
return this.annotationProvider != null;
}
-
+public void markAsFromSource() {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.FROM_SOURCE;
+}
+@Override
+public ExternalAnnotationStatus getExternalAnnotationStatus() {
+ return this.externalAnnotationStatus;
+}
/**
* Conditionally add external annotations to the mix.
* If 'member' is given it must be either of IBinaryField or IBinaryMethod, in which case we're seeking annotations for that member.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
index cbb2bc1..f58c49c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,7 +30,7 @@
public class ExternalAnnotationProvider {
- public static final String ANNOTION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
+ public static final String ANNOTATION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
public static final String CLASS_PREFIX = "class "; //$NON-NLS-1$
public static final String SUPER_PREFIX = "super "; //$NON-NLS-1$
@@ -46,7 +46,7 @@
*/
public static final char NO_ANNOTATION = '@';
- static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
+ public static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
private static final String TYPE_PARAMETER_PREFIX = " <"; //$NON-NLS-1$
@@ -69,8 +69,7 @@
}
private void initialize(InputStream input) throws IOException {
- LineNumberReader reader = new LineNumberReader(new InputStreamReader(input));
- try {
+ try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(input))) {
assertClassHeader(reader.readLine(), this.typeName);
String line;
@@ -137,8 +136,6 @@
this.fieldAnnotationSources.put(selector+':'+rawSig, annotSig);
}
} while (((line = pendingLine) != null) || (line = reader.readLine()) != null);
- } finally {
- reader.close();
}
}
@@ -402,7 +399,7 @@
}
}
}
- return null;
+ return NO_ANNOTATIONS;
}
}
@@ -441,6 +438,19 @@
if ((depth == 0) && (i +1 < length) && (this.source[i+1] != Util.C_COLON))
pendingVariable = true;
break;
+ case Util.C_COLON :
+ if (depth == 0)
+ pendingVariable = true; // end of variable name
+ // skip optional bound ReferenceTypeSignature
+ i++; // peek next
+ while (i < length && this.source[i] == Util.C_ARRAY)
+ i++;
+ if (i < length && this.source[i] == Util.C_RESOLVED) {
+ while (i < length && this.source[i] != Util.C_NAME_END)
+ i++;
+ }
+ i--; // unget
+ break;
default:
if (pendingVariable) {
pendingVariable = false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
index 9fa7cbf..f6092ac 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -176,7 +176,7 @@
@Override
public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) {
- IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(currentTypeId);
+ IBinaryAnnotation[] normalAnnotations = this.isEmpty ? NO_ANNOTATIONS : super.getAnnotationsAtCursor(currentTypeId);
if (this.atDefaultLocation &&
!(currentTypeId == -1) && // never apply default on type variable use or wildcard
!(this.atTypeBound && currentTypeId == TypeIds.T_JavaLangObject)) // for CLIMB-to-top consider a j.l.Object type bound as no explicit type bound
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index eb58e53..50e87a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -45,8 +45,10 @@
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -2590,28 +2592,24 @@
public void generateSyntheticBodyForDeserializeLambda(SyntheticMethodBinding methodBinding,SyntheticMethodBinding[] syntheticMethodBindings) {
initializeMaxLocals(methodBinding);
- // Compute the list of the serializable lambdas from the full set of synthetic method bindings
- // Also compute a map of hashcodes to a list of serializable lambdas whose names share a hashcode
- List syntheticsForSerializableLambdas = new ArrayList();
- Map hashcodesToLambdas = new LinkedHashMap();
+ // Compute a map of hashcodes to a list of synthetic methods whose names share a hashcode
+ Map hashcodesTosynthetics = new LinkedHashMap();
for (int i=0,max=syntheticMethodBindings.length;i<max;i++) {
SyntheticMethodBinding syntheticMethodBinding = syntheticMethodBindings[i];
- if (syntheticMethodBinding.lambda!=null && syntheticMethodBinding.lambda.isSerializable) {
- syntheticsForSerializableLambdas.add(syntheticMethodBinding);
+ if (syntheticMethodBinding.lambda!=null && syntheticMethodBinding.lambda.isSerializable ||
+ syntheticMethodBinding.serializableMethodRef != null) {
// TODO can I use > Java 1.4 features here?
Integer hashcode = new Integer(new String(syntheticMethodBinding.selector).hashCode());
- List lambdasForThisHashcode = (List)hashcodesToLambdas.get(hashcode);
- if (hashcodesToLambdas.get(hashcode)==null) {
- lambdasForThisHashcode = new ArrayList();
- hashcodesToLambdas.put(hashcode,lambdasForThisHashcode);
+ List syntheticssForThisHashcode = (List)hashcodesTosynthetics.get(hashcode);
+ if (syntheticssForThisHashcode==null) {
+ syntheticssForThisHashcode = new ArrayList();
+ hashcodesTosynthetics.put(hashcode,syntheticssForThisHashcode);
}
- lambdasForThisHashcode.add(syntheticMethodBinding);
+ syntheticssForThisHashcode.add(syntheticMethodBinding);
}
}
- int lambdaCount = syntheticsForSerializableLambdas.size();
ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
-
// Generate the first switch, on method name hashcode
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodName, ConstantPool.GetImplMethodNameSignature);
@@ -2629,11 +2627,11 @@
BranchLabel label = new BranchLabel(this);
CaseLabel defaultLabel = new CaseLabel(this);
- int numberOfHashcodes = hashcodesToLambdas.size();
+ int numberOfHashcodes = hashcodesTosynthetics.size();
CaseLabel[] switchLabels = new CaseLabel[numberOfHashcodes];
int[] keys = new int[numberOfHashcodes];
int[] sortedIndexes = new int[numberOfHashcodes];
- Set hashcodes = hashcodesToLambdas.keySet();
+ Set hashcodes = hashcodesTosynthetics.keySet();
Iterator hashcodeIterator = hashcodes.iterator();
int index=0;
while (hashcodeIterator.hasNext()) {
@@ -2653,152 +2651,185 @@
index = 0;
while (hashcodeIterator.hasNext()) {
Integer hashcode = (Integer)hashcodeIterator.next();
- List lambdas = (List)hashcodesToLambdas.get(hashcode);
+ List synthetics = (List)hashcodesTosynthetics.get(hashcode);
switchLabels[index].place();
BranchLabel nextOne = new BranchLabel(this);
// Loop through all lambdas that share the same hashcode
- for (int j=0,max=lambdas.size();j<max;j++) {
- SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)lambdas.get(j);
+ // TODO: isn't doing this for just one of these enough because they all share
+ // the same name?
+ for (int j=0,max=synthetics.size();j<max;j++) {
+ SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)synthetics.get(j);
aload_1();
ldc(new String(syntheticMethodBinding.selector));
invokeStringEquals();
ifeq(nextOne);
- loadInt(index++);
+ loadInt(index);
istore_2();
goto_(label);
nextOne.place();
nextOne = new BranchLabel(this);
}
+ index++;
goto_(label);
}
defaultLabel.place();
label.place();
-
+ int syntheticsCount = hashcodes.size();
// Second block is switching on the lambda id, -1 is the error (unrecognized) case
- switchLabels = new CaseLabel[lambdaCount];
- keys = new int[lambdaCount];
- sortedIndexes = new int[lambdaCount];
+ switchLabels = new CaseLabel[syntheticsCount];
+ keys = new int[syntheticsCount];
+ sortedIndexes = new int[syntheticsCount];
BranchLabel errorLabel = new BranchLabel(this);
defaultLabel = new CaseLabel(this);
iload_2();
- for (int j=0;j<lambdaCount;j++) {
+ for (int j=0;j<syntheticsCount;j++) {
switchLabels[j] = new CaseLabel(this);
keys[j] = j;
sortedIndexes[j] = j;
}
- System.arraycopy(keys,0,(localKeysCopy = new int[lambdaCount]),0,lambdaCount);
+ System.arraycopy(keys,0,(localKeysCopy = new int[syntheticsCount]),0,syntheticsCount);
// TODO no need to sort here? They should all be in order
- sort(localKeysCopy, 0, lambdaCount-1, sortedIndexes);
+ sort(localKeysCopy, 0, syntheticsCount-1, sortedIndexes);
// TODO need to use a tableswitch at some size threshold?
lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
- for (int i=0;i<lambdaCount;i++) {
- SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)syntheticsForSerializableLambdas.get(i);
- switchLabels[i].place();
-
- // Compare ImplMethodKind
- aload_0();
- LambdaExpression lambdaEx = syntheticMethodBinding.lambda;
- MethodBinding mb = lambdaEx.binding;
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature);
- byte methodKind = 0;
- if (mb.isStatic()) {
- methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
- } else if (mb.isPrivate()) {
- methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
- } else {
- methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
- }
- bipush(methodKind);// TODO see table below
- if_icmpne(errorLabel);
-
- // Compare FunctionalInterfaceClass
- aload_0();
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature);
- String functionalInterface = null;
- final TypeBinding expectedType = lambdaEx.expectedType();
- if (expectedType instanceof IntersectionTypeBinding18) {
- functionalInterface = new String(((IntersectionTypeBinding18)expectedType).getSAMType(scope).constantPoolName());
- } else {
- functionalInterface = new String(expectedType.constantPoolName());
- }
- ldc(functionalInterface);// e.g. "com/foo/X$Foo"
- invokeObjectEquals();
- ifeq(errorLabel);
-
- // Compare FunctionalInterfaceMethodName
- aload_0();
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetFunctionalInterfaceMethodName, ConstantPool.GetFunctionalInterfaceMethodNameSignature);
- ldc(new String(lambdaEx.descriptor.selector)); // e.g. "m"
- invokeObjectEquals();
- ifeq(errorLabel);
-
- // Compare FunctionalInterfaceMethodSignature
- aload_0();
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetFunctionalInterfaceMethodSignature, ConstantPool.GetFunctionalInterfaceMethodSignatureSignature);
- ldc(new String(lambdaEx.descriptor.original().signature())); // e.g "()I"
- invokeObjectEquals();
- ifeq(errorLabel);
-
- // Compare ImplClass
- aload_0();
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature);
- ldc(new String(mb.declaringClass.constantPoolName())); // e.g. "com/foo/X"
- invokeObjectEquals();
- ifeq(errorLabel);
-
- // Compare ImplMethodSignature
- aload_0();
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature);
- ldc(new String(mb.signature())); // e.g. "(I)I"
- invokeObjectEquals();
- ifeq(errorLabel);
-
- // Captured arguments
- StringBuffer sig = new StringBuffer("("); //$NON-NLS-1$
- index = 0;
- if (lambdaEx.shouldCaptureInstance) {
+ hashcodeIterator = hashcodes.iterator();
+ int hashcodeIndex = 0;
+ while (hashcodeIterator.hasNext()) {
+ Integer hashcode = (Integer)hashcodeIterator.next();
+ List synthetics = (List)hashcodesTosynthetics.get(hashcode);
+ switchLabels[hashcodeIndex++].place();
+ BranchLabel nextOne = synthetics.size() > 1 ? new BranchLabel(this) : errorLabel;
+ // Loop through all lambdas that share the same hashcode
+ for (int j = 0, count = synthetics.size(); j < count; j++) {
+ SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
+ // Compare ImplMethodKind
aload_0();
- loadInt(index++);
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
- checkcast(mb.declaringClass);
- sig.append(mb.declaringClass.signature());
- }
-
- SyntheticArgumentBinding[] outerLocalVariables = lambdaEx.outerLocalVariables;
- for (int p=0,max=outerLocalVariables.length;p<max;p++) {
- aload_0();
- loadInt(index);
- invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
- ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
- TypeBinding varType = outerLocalVariables[p].type;
- if (varType.isBaseType()) {
- checkcast(scope.boxing(varType));
- generateUnboxingConversion(varType.id);
- if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
- index++;
- }
+ FunctionalExpression funcEx = syntheticMethodBinding.lambda != null ? syntheticMethodBinding.lambda
+ : syntheticMethodBinding.serializableMethodRef;
+ MethodBinding mb = funcEx.binding;
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature);
+ byte methodKind = 0;
+ if (mb.isStatic()) {
+ methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
+ } else if (mb.isPrivate()) {
+ methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
} else {
- checkcast(varType);
+ methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
}
- index++;
- sig.append(varType.signature());
+ bipush(methodKind);// TODO see table below
+ if_icmpne(nextOne);
+
+ // Compare FunctionalInterfaceClass
+ aload_0();
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature);
+ String functionalInterface = null;
+ final TypeBinding expectedType = funcEx.expectedType();
+ if (expectedType instanceof IntersectionTypeBinding18) {
+ functionalInterface = new String(
+ ((IntersectionTypeBinding18) expectedType).getSAMType(scope).constantPoolName());
+ } else {
+ functionalInterface = new String(expectedType.constantPoolName());
+ }
+ ldc(functionalInterface);// e.g. "com/foo/X$Foo"
+ invokeObjectEquals();
+ ifeq(nextOne);
+
+ // Compare FunctionalInterfaceMethodName
+ aload_0();
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetFunctionalInterfaceMethodName,
+ ConstantPool.GetFunctionalInterfaceMethodNameSignature);
+ ldc(new String(funcEx.descriptor.selector)); // e.g. "m"
+ invokeObjectEquals();
+ ifeq(nextOne);
+
+ // Compare FunctionalInterfaceMethodSignature
+ aload_0();
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetFunctionalInterfaceMethodSignature,
+ ConstantPool.GetFunctionalInterfaceMethodSignatureSignature);
+ ldc(new String(funcEx.descriptor.original().signature())); // e.g "()I"
+ invokeObjectEquals();
+ ifeq(nextOne);
+
+ // Compare ImplClass
+ aload_0();
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature);
+ ldc(new String(mb.declaringClass.constantPoolName())); // e.g. "com/foo/X"
+ invokeObjectEquals();
+ ifeq(nextOne);
+
+ // Compare ImplMethodSignature
+ aload_0();
+ invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature);
+ ldc(new String(mb.signature())); // e.g. "(I)I"
+ invokeObjectEquals();
+ ifeq(nextOne);
+
+ // Captured arguments
+ StringBuffer sig = new StringBuffer("("); //$NON-NLS-1$
+ index = 0;
+ boolean isLambda = funcEx instanceof LambdaExpression;
+ TypeBinding receiverType = null;
+ SyntheticArgumentBinding[] outerLocalVariables = null;
+ if (isLambda) {
+ LambdaExpression lambdaEx = (LambdaExpression) funcEx;
+ if (lambdaEx.shouldCaptureInstance)
+ receiverType = mb.declaringClass;
+ outerLocalVariables = lambdaEx.outerLocalVariables;
+ } else {
+ ReferenceExpression refEx = (ReferenceExpression)funcEx;
+ if (refEx.haveReceiver)
+ receiverType = ((ReferenceExpression)funcEx).receiverType;
+ // Should never have outer locals
+ }
+ if (receiverType != null) {
+ aload_0();
+ loadInt(index++);
+ invoke(Opcodes.OPC_invokevirtual, 1, 1,
+ ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
+ checkcast(isLambda ? mb.declaringClass : ((ReferenceExpression)funcEx).receiverType);
+ sig.append(mb.declaringClass.signature());
+ }
+ for (int p = 0, max = outerLocalVariables == null ? 0 : outerLocalVariables.length; p < max; p++) {
+ TypeBinding varType = outerLocalVariables[p].type;
+ aload_0();
+ loadInt(index);
+ invoke(Opcodes.OPC_invokevirtual, 1, 1,
+ ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+ ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
+ if (varType.isBaseType()) {
+ checkcast(scope.boxing(varType));
+ generateUnboxingConversion(varType.id);
+ if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
+ index++;
+ }
+ } else {
+ checkcast(varType);
+ }
+ index++;
+ sig.append(varType.signature());
+ }
+ sig.append(")"); //$NON-NLS-1$
+ if (funcEx.resolvedType instanceof IntersectionTypeBinding18) {
+ sig.append(((IntersectionTypeBinding18) funcEx.resolvedType).getSAMType(scope).signature());
+ } else {
+ sig.append(funcEx.resolvedType.signature());
+ }
+ // Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
+ invokeDynamic(funcEx.bootstrapMethodNumber, index, 1, funcEx.descriptor.selector,
+ sig.toString().toCharArray());
+ areturn();
+ if (j < count - 1) {
+ nextOne.place();
+ nextOne = j < count - 2 ? new BranchLabel(this) : errorLabel;
+ }
}
- sig.append(")"); //$NON-NLS-1$
- if (lambdaEx.resolvedType instanceof IntersectionTypeBinding18) {
- sig.append(((IntersectionTypeBinding18)lambdaEx.resolvedType).getSAMType(scope).signature());
- } else {
- sig.append(lambdaEx.resolvedType.signature());
- }
- // Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
- invokeDynamic(lambdaEx.bootstrapMethodNumber, index, 1, lambdaEx.descriptor.selector, sig.toString().toCharArray());
- areturn();
}
removeVariable(lvb1);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
index 4d58e4f..092fe6c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
package org.eclipse.jdt.internal.compiler.env;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
public interface IBinaryType extends IGenericType {
@@ -160,4 +161,9 @@
*/
ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member, LookupEnvironment environment);
+/**
+ * Answer whether a provider for external annotations is associated with this binary type.
+ */
+ExternalAnnotationStatus getExternalAnnotationStatus();
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index f43f037..bc79c2f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,7 @@
ICompilationUnit compilationUnit;
ISourceType[] sourceTypes;
AccessRestriction accessRestriction;
+ String externalAnnotationPath; // should be an absolute file system path
public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
this.binaryType = binaryType;
@@ -28,9 +29,10 @@
this.accessRestriction = accessRestriction;
}
- public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction) {
+ public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath) {
this.sourceTypes = sourceTypes;
this.accessRestriction = accessRestriction;
+ this.externalAnnotationPath = externalAnnotationPath;
}
/**
* Returns the associated access restriction, or null if none.
@@ -54,6 +56,10 @@
return this.compilationUnit;
}
+ public String getExternalAnnotationPath() {
+ return this.externalAnnotationPath;
+ }
+
/**
* Answer the unresolved source forms for the type or null if the
* receiver represents a compilation unit or binary type.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index 6b1a868..e75997d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -947,6 +947,10 @@
return;
}
if (flowInfo.isPotentiallyNull(local)) {
+ if(local.type.isFreeTypeVariable()) {
+ scope.problemReporter().localVariableFreeTypeVariableReference(local, location);
+ return;
+ }
scope.problemReporter().localVariablePotentialNullReference(local, location);
return;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index f1e5d43..382cb83 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -63,6 +63,8 @@
public final static int POTENTIALLY_NON_NULL = 32;
public final static int UNROOTED = 64; // marks a flowInfo that may be appended to another flowInfo (accepting incoming nulls/nonnulls, see UFI.iNBit/iNNBit).
+
+ public static final int FREE_TYPEVARIABLE = FlowInfo.POTENTIALLY_NULL | FlowInfo.POTENTIALLY_NON_NULL;
public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
static {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 3b49f17..ec758b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -161,6 +161,9 @@
* @param callerFlowInfo the flow info against which checks must be performed
*/
public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo) {
+ complainOnDeferredNullChecks(scope, callerFlowInfo, true);
+}
+public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo, boolean updateInitsOnBreak) {
for (int i = 0 ; i < this.innerFlowContextsCount ; i++) {
this.upstreamNullFlowInfo.
addPotentialNullInfoFrom(
@@ -433,9 +436,11 @@
}
}
// propagate breaks
- this.initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
- for (int i = 0; i < this.breakTargetsCount; i++) {
- this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+ if(updateInitsOnBreak) {
+ this.initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+ for (int i = 0; i < this.breakTargetsCount; i++) {
+ this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+ }
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 549f674..2f0b36c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -274,6 +274,9 @@
public static final String OPTION_SyntacticNullAnalysisForFields = "org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields"; //$NON-NLS-1$
public static final String OPTION_InheritNullAnnotations = "org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations"; //$NON-NLS-1$
public static final String OPTION_ReportNonnullParameterAnnotationDropped = "org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped"; //$NON-NLS-1$
+ public static final String OPTION_PessimisticNullAnalysisForFreeTypeVariables = "org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables"; //$NON-NLS-1$
+ public static final String OPTION_ReportNonNullTypeVariableFromLegacyInvocation = "org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation"; //$NON-NLS-1$
+
/**
* Possible values for configurable options
*/
@@ -394,6 +397,8 @@
public static final int UnusedTypeParameter = IrritantSet.GROUP2 | ASTNode.Bit17;
public static final int NonnullParameterAnnotationDropped = IrritantSet.GROUP2 | ASTNode.Bit18;
public static final int UnusedExceptionParameter = IrritantSet.GROUP2 | ASTNode.Bit19;
+ public static final int PessimisticNullAnalysisForFreeTypeVariables = IrritantSet.GROUP2 | ASTNode.Bit20;
+ public static final int NonNullTypeVariableFromLegacyInvocation = IrritantSet.GROUP2 | ASTNode.Bit21;
//{ObjectTeams: OT/J specific problems/irritants:
public static final int OTJFlag = IrritantSet.GROUP3;
@@ -604,11 +609,15 @@
/** Should immediate null-check for fields be considered during null analysis (syntactical match)? */
public boolean enableSyntacticNullAnalysisForFields;
+ /** Is the error level for pessimistic null analysis for free type variables different from "ignore"? */
+ public boolean pessimisticNullAnalysisForFreeTypeVariablesEnabled;
+
public boolean complainOnUninternedIdentityComparison;
public boolean emulateJavacBug8031744 = true;
/** Not directly configurable, derived from other options by LookupEnvironment.usesNullTypeAnnotations() */
public Boolean useNullTypeAnnotations = null;
+
// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
public final static String[] warningTokens = {
@@ -893,6 +902,10 @@
return OPTION_ReportRedundantNullAnnotation;
case NonnullParameterAnnotationDropped:
return OPTION_ReportNonnullParameterAnnotationDropped;
+ case PessimisticNullAnalysisForFreeTypeVariables:
+ return OPTION_PessimisticNullAnalysisForFreeTypeVariables;
+ case NonNullTypeVariableFromLegacyInvocation:
+ return OPTION_ReportNonNullTypeVariableFromLegacyInvocation;
}
return null;
}
@@ -1180,6 +1193,8 @@
case RedundantNullAnnotation :
case MissingNonNullByDefaultAnnotation:
case NonnullParameterAnnotationDropped:
+ case PessimisticNullAnalysisForFreeTypeVariables:
+ case NonNullTypeVariableFromLegacyInvocation:
return "null"; //$NON-NLS-1$
case FallthroughCase :
return "fallthrough"; //$NON-NLS-1$
@@ -1554,6 +1569,8 @@
optionsMap.put(OPTION_InheritNullAnnotations, this.inheritNullAnnotations ? ENABLED : DISABLED);
optionsMap.put(OPTION_ReportNonnullParameterAnnotationDropped, getSeverityString(NonnullParameterAnnotationDropped));
optionsMap.put(OPTION_ReportUninternedIdentityComparison, this.complainOnUninternedIdentityComparison ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_PessimisticNullAnalysisForFreeTypeVariables, getSeverityString(PessimisticNullAnalysisForFreeTypeVariables));
+ optionsMap.put(OPTION_ReportNonNullTypeVariableFromLegacyInvocation, getSeverityString(NonNullTypeVariableFromLegacyInvocation));
return optionsMap;
}
@@ -2143,6 +2160,13 @@
this.inheritNullAnnotations = ENABLED.equals(optionValue);
}
if ((optionValue = optionsMap.get(OPTION_ReportNonnullParameterAnnotationDropped)) != null) updateSeverity(NonnullParameterAnnotationDropped, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_PessimisticNullAnalysisForFreeTypeVariables)) != null) updateSeverity(PessimisticNullAnalysisForFreeTypeVariables, optionValue);
+ if (getSeverity(PessimisticNullAnalysisForFreeTypeVariables) == ProblemSeverities.Ignore) {
+ this.pessimisticNullAnalysisForFreeTypeVariablesEnabled = false;
+ } else {
+ this.pessimisticNullAnalysisForFreeTypeVariablesEnabled = true;
+ }
+ if ((optionValue = optionsMap.get(OPTION_ReportNonNullTypeVariableFromLegacyInvocation)) != null) updateSeverity(NonNullTypeVariableFromLegacyInvocation, optionValue);
}
// Javadoc options
@@ -2410,6 +2434,8 @@
buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$
buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$
buf.append("\n\t- Unused Type Parameter: ").append(getSeverityString(UnusedTypeParameter)); //$NON-NLS-1$
+ buf.append("\n\t- pessimistic null analysis for free type variables: ").append(getSeverityString(PessimisticNullAnalysisForFreeTypeVariables)); //$NON-NLS-1$
+ buf.append("\n\t- report unsafe nonnull return from legacy method: ").append(getSeverityString(NonNullTypeVariableFromLegacyInvocation)); //$NON-NLS-1$
//{ObjectTeams
buf.append("\n\t- decapsulation : ").append(this.decapsulation); //$NON-NLS-1$
buf.append("\n\t- report if not exactly one basecall in callin method : ").append(getSeverityString(NotExactlyOneBasecall)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
index 547352e..80db44d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -191,7 +191,9 @@
|CompilerOptions.UnclosedCloseable
|CompilerOptions.NullUncheckedConversion
|CompilerOptions.RedundantNullAnnotation
- |CompilerOptions.NonnullParameterAnnotationDropped);
+ |CompilerOptions.NonnullParameterAnnotationDropped
+ |CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables
+ |CompilerOptions.NonNullTypeVariableFromLegacyInvocation);
// default errors IF AnnotationBasedNullAnalysis is enabled:
COMPILER_DEFAULT_ERRORS.set(
CompilerOptions.NullSpecViolation
@@ -210,7 +212,9 @@
.set(CompilerOptions.NullUncheckedConversion)
.set(CompilerOptions.RedundantNullAnnotation)
.set(CompilerOptions.NonnullParameterAnnotationDropped)
- .set(CompilerOptions.MissingNonNullByDefaultAnnotation);
+ .set(CompilerOptions.MissingNonNullByDefaultAnnotation)
+ .set(CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables)
+ .set(CompilerOptions.NonNullTypeVariableFromLegacyInvocation);
RESTRICTION.set(CompilerOptions.DiscouragedReference);
STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 4ba51ba..a632887 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -155,8 +155,23 @@
private ReferenceBinding containerAnnotationType;
int defaultNullness = 0;
-
-
+ public enum ExternalAnnotationStatus {
+ FROM_SOURCE,
+ NOT_EEA_CONFIGURED,
+ NO_EEA_FILE,
+ TYPE_IS_ANNOTATED;
+ public boolean isPotentiallyUnannotatedLib() {
+ switch (this) {
+ case FROM_SOURCE:
+ case TYPE_IS_ANNOTATED:
+ return false;
+ default:
+ return true;
+ }
+ }
+ }
+ public ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED; // unless proven differently
+
//{ObjectTeams: support callout-to-field
/** Callout to field adds faked access method (set or get): */
@@ -292,7 +307,14 @@
return ((WildcardBinding) type).resolve();
case Binding.ARRAY_TYPE :
- resolveType(((ArrayBinding) type).leafComponentType, environment, convertGenericToRawType);
+ ArrayBinding arrayBinding = (ArrayBinding) type;
+ TypeBinding leafComponentType = arrayBinding.leafComponentType;
+ resolveType(leafComponentType, environment, convertGenericToRawType);
+ if (leafComponentType.hasNullTypeAnnotations() && environment.usesNullTypeAnnotations()) {
+ if (arrayBinding.nullTagBitsPerDimension == null)
+ arrayBinding.nullTagBitsPerDimension = new long[arrayBinding.dimensions+1];
+ arrayBinding.nullTagBitsPerDimension[arrayBinding.dimensions] = leafComponentType.tagBits & TagBits.AnnotationNullMASK;
+ }
break;
case Binding.TYPE_PARAMETER :
@@ -574,6 +596,10 @@
}
ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations(), Binding.NO_NULL_DEFAULT);
ITypeAnnotationWalker toplevelWalker = binaryType.enrichWithExternalAnnotationsFor(walker, null, this.environment);
+ this.externalAnnotationStatus = binaryType.getExternalAnnotationStatus();
+ if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && this.defaultNullness != 0) {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ }
char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4
this.tagBits |= binaryType.getTagBits();
@@ -663,6 +689,19 @@
this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
}
}
+ boolean canUseNullTypeAnnotations = this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
+ if (canUseNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
+ if (this.superclass != null && this.superclass.hasNullTypeAnnotations()) {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ } else {
+ for (TypeBinding ifc : this.superInterfaces) {
+ if (ifc.hasNullTypeAnnotations()) {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ break;
+ }
+ }
+ }
+ }
if (needFieldsAndMethods) {
IBinaryField[] iFields = binaryType.getFields();
@@ -699,7 +738,7 @@
ITypeAnnotationWalker methodWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
if (sourceLevel < ClassFileConstants.JDK1_8)
methodWalker = binaryType.enrichWithExternalAnnotationsFor(methodWalker, iMethods[i], this.environment);
- scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker);
+ scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker, canUseNullTypeAnnotations);
}
}
}
@@ -766,7 +805,7 @@
if (iFields != null) {
int size = iFields.length;
if (size > 0) {
- this.fields = new FieldBinding[size];
+ FieldBinding[] fields1 = new FieldBinding[size];
boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
boolean hasRestrictedAccess = hasRestrictedAccess();
int firstAnnotatedFieldIndex = -1;
@@ -806,7 +845,7 @@
field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
if (fieldSignature != null)
field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
- this.fields[i] = field;
+ fields1[i] = field;
//{ObjectTeams:
// field attributes:
if (binaryField instanceof FieldInfo)
@@ -816,6 +855,7 @@
addValueParameter(field);
// SH}
}
+ this.fields = fields1;
// second pass for reifying annotations, since may refer to fields being constructed (147875)
if (firstAnnotatedFieldIndex >= 0) {
for (int i = firstAnnotatedFieldIndex; i <size; i++) {
@@ -1163,15 +1203,16 @@
return NO_BINARY_METHODS;
}
- boolean hasRestrictedAccess = hasRestrictedAccess();
- this.methods = new MethodBinding[total];
+boolean hasRestrictedAccess = hasRestrictedAccess();
+ MethodBinding[] methods1 = new MethodBinding[total];
if (total == initialTotal) {
for (int i = 0; i < initialTotal; i++) {
MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
if (hasRestrictedAccess)
method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
- this.methods[i] = method;
+ methods1[i] = method;
}
+ this.methods = methods1;
return iMethods;
} else {
IBinaryMethod[] mappedBinaryMethods = new IBinaryMethod[total];
@@ -1181,9 +1222,10 @@
if (hasRestrictedAccess)
method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
mappedBinaryMethods[index] = iMethods[i];
- this.methods[index++] = method;
+ methods1[index++] = method;
}
}
+ this.methods = methods1;
return mappedBinaryMethods;
}
}
@@ -1254,6 +1296,8 @@
this.typeVariables = result;
for (int i = 0; i < rank; i++) {
initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeParameterBounds(isClassTypeParameter, i));
+ if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && result[i].hasNullTypeAnnotations())
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
}
return result;
}
@@ -1945,11 +1989,13 @@
return; // we know it's nonnull, no need to look for null *annotations* on enum constants.
}
- if (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+ if (!CharOperation.equals(this.fPackage.compoundName, TypeConstants.JAVA_LANG_ANNOTATION) // avoid dangerous re-entry via usesNullTypeAnnotations()
+ && this.environment.usesNullTypeAnnotations()) {
TypeBinding fieldType = fieldBinding.type;
if (fieldType != null
&& !fieldType.isBaseType()
&& (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
+ && fieldType.acceptsNonNullDefault()
&& hasNonNullDefaultFor(DefaultLocationField, true)) {
fieldBinding.type = this.environment.createAnnotatedType(fieldType, new AnnotationBinding[]{this.environment.getNonNullAnnotation()});
}
@@ -1983,12 +2029,14 @@
}
}
}
+ if (explicitNullness && this.externalAnnotationStatus.isPotentiallyUnannotatedLib())
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
if (!explicitNullness && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
fieldBinding.tagBits |= TagBits.AnnotationNonNull;
}
}
-private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker) {
+private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker, boolean useNullTypeAnnotations) {
if (!isPrototype()) throw new IllegalStateException();
if (isEnum()) {
int purpose = 0;
@@ -2077,6 +2125,18 @@
}
}
}
+ if (useNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
+ if (methodBinding.returnType.hasNullTypeAnnotations()) {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ } else {
+ for (TypeBinding parameter : parameters) {
+ if (parameter.hasNullTypeAnnotations()) {
+ this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+ break;
+ }
+ }
+ }
+ }
}
// pre: null annotation analysis is enabled
private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
index c51a617..09ffa02 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG.
+ * Copyright (c) 2013, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -318,19 +318,7 @@
static void inferInvocationApplicability(InferenceContext18 inferenceContext, MethodBinding method, TypeBinding[] arguments, boolean isDiamond, int checkType)
{
// 18.5.1
- TypeVariableBinding[] typeVariables = method.typeVariables;
- if (isDiamond) {
- TypeVariableBinding[] classTypeVariables = method.declaringClass.typeVariables();
- int l1 = typeVariables.length;
- int l2 = classTypeVariables.length;
- if (l1 == 0) {
- typeVariables = classTypeVariables;
- } else if (l2 != 0) {
- System.arraycopy(typeVariables, 0, typeVariables=new TypeVariableBinding[l1+l2], 0, l1);
- System.arraycopy(classTypeVariables, 0, typeVariables, l1, l2);
- }
- }
- TypeBinding[] parameters = method.parameters;
+ TypeVariableBinding[] typeVariables = method.getAllTypeVariables(isDiamond);
InferenceVariable[] inferenceVariables = inferenceContext.createInitialBoundSet(typeVariables); // creates initial bound set B
// check if varargs need special treatment:
@@ -340,7 +328,7 @@
int varArgPos = paramLength-1;
varArgsType = method.parameters[varArgPos];
}
- inferenceContext.createInitialConstraintsForParameters(parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType, method);
+ inferenceContext.createInitialConstraintsForParameters(method.parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType, method);
inferenceContext.addThrowsContraints(typeVariables, inferenceVariables, method.thrownExceptions);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
index 9daff30..7ce5578 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG.
+ * Copyright (c) 2013, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -184,10 +184,13 @@
return TRUE;
return FALSE;
}
- if (this.left instanceof InferenceVariable) {
+ if (this.left.id == TypeIds.T_null || this.right.id== TypeIds.T_null) {
+ return FALSE;
+ }
+ if (this.left instanceof InferenceVariable && !this.right.isPrimitiveType()) {
return new TypeBound((InferenceVariable) this.left, this.right, SAME, this.isSoft);
}
- if (this.right instanceof InferenceVariable) {
+ if (this.right instanceof InferenceVariable && !this.left.isPrimitiveType()) {
return new TypeBound((InferenceVariable) this.right, this.left, SAME, this.isSoft);
}
if ((this.left.isClass() || this.left.isInterface())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
new file mode 100644
index 0000000..781a451
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
+import org.eclipse.jdt.internal.compiler.util.Messages;
+
+/**
+ * Used for superimposing external annotations (served by an {@link ITypeAnnotationWalker})
+ * over signatures of a {@link SourceTypeBinding}.
+ */
+class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
+
+ public static void apply(SourceTypeBinding typeBinding, String externalAnnotationPath) {
+ ZipFile zipFile = null;
+ try {
+ File annotationBase = new File(externalAnnotationPath);
+ if (annotationBase.exists()) {
+ String binaryTypeName = String.valueOf(typeBinding.constantPoolName());
+ String relativeFileName = binaryTypeName.replace('.', '/')+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
+
+ InputStream input;
+ if (annotationBase.isDirectory()) {
+ input = new FileInputStream(externalAnnotationPath+'/'+relativeFileName);
+ } else {
+ zipFile = new ZipFile(externalAnnotationPath);
+ ZipEntry zipEntry = zipFile.getEntry(relativeFileName);
+ if (zipEntry == null)
+ return;
+ input = zipFile.getInputStream(zipEntry);
+ }
+ annotateType(typeBinding, new ExternalAnnotationProvider(input, binaryTypeName), typeBinding.environment);
+ }
+ } catch (FileNotFoundException e) {
+ // file not found is expected
+ } catch (IOException e) {
+ typeBinding.scope.problemReporter().abortDueToInternalError(Messages.bind(Messages.abort_externaAnnotationFile,
+ new String[] {String.valueOf(typeBinding.readableName()), externalAnnotationPath, e.getMessage()}));
+ } finally {
+ if (zipFile != null)
+ try {
+ zipFile.close();
+ } catch (IOException e) {
+ // nothing
+ }
+ }
+ }
+
+ static void annotateType(SourceTypeBinding binding, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ ITypeAnnotationWalker typeWalker = provider.forTypeHeader(environment);
+ if (typeWalker != null && typeWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ TypeVariableBinding[] typeParameters = binding.typeVariables();
+ for (int i = 0; i < typeParameters.length; i++) {
+ if (visitor.go(typeWalker.toTypeParameter(true, i)))
+ typeParameters[i] = visitor.superimpose(typeParameters[i], TypeVariableBinding.class);
+ }
+ }
+ binding.externalAnnotationProvider = provider; // for superimposing method signatures
+ }
+
+ public static void annotateFieldBinding(FieldBinding field, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ char[] fieldSignature = field.genericSignature();
+ if (fieldSignature == null && field.type != null)
+ fieldSignature = field.type.signature();
+ ITypeAnnotationWalker walker = provider.forField(field.name, fieldSignature, environment);
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ if (visitor.go(walker))
+ field.type = visitor.superimpose(field.type, TypeBinding.class);
+ }
+
+ public static void annotateMethodBinding(MethodBinding method, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ char[] methodSignature = method.genericSignature();
+ if (methodSignature == null)
+ methodSignature = method.signature();
+ ITypeAnnotationWalker walker = provider.forMethod(method.selector, methodSignature, environment);
+ if (walker != null && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ TypeVariableBinding[] typeParams = method.typeVariables;
+ for (short i = 0; i < typeParams.length; i++) {
+ if (visitor.go(walker.toTypeParameter(false, i)))
+ typeParams[i] = visitor.superimpose(typeParams[i], TypeVariableBinding.class);
+ }
+ if (!method.isConstructor()) {
+ if (visitor.go(walker.toMethodReturn()))
+ method.returnType = visitor.superimpose(method.returnType, TypeBinding.class);
+ }
+ TypeBinding[] parameters = method.parameters;
+ for (short i = 0; i < parameters.length; i++) {
+ if (visitor.go(walker.toMethodParameter(i)))
+ parameters[i] = visitor.superimpose(parameters[i], TypeBinding.class);
+ }
+ }
+ }
+
+ private ITypeAnnotationWalker currentWalker;
+ private TypeBinding typeReplacement;
+ private LookupEnvironment environment;
+ private boolean isReplacing;
+
+ ExternalAnnotationSuperimposer(LookupEnvironment environment) {
+ this.environment = environment;
+ }
+
+ /** for constructing a memento of the superimposer's current state. */
+ private ExternalAnnotationSuperimposer(TypeBinding typeReplacement, boolean isReplacing, ITypeAnnotationWalker walker) {
+ this.typeReplacement = typeReplacement;
+ this.isReplacing = isReplacing;
+ this.currentWalker = walker;
+ }
+ private ExternalAnnotationSuperimposer snapshot() {
+ ExternalAnnotationSuperimposer memento = new ExternalAnnotationSuperimposer(this.typeReplacement, this.isReplacing, this.currentWalker);
+ // soft reset:
+ this.typeReplacement = null;
+ this.isReplacing = false;
+ return memento;
+ }
+ private void restore(ExternalAnnotationSuperimposer memento) {
+ this.isReplacing = memento.isReplacing;
+ this.currentWalker = memento.currentWalker;
+ }
+
+ boolean go(ITypeAnnotationWalker walker) {
+ // hard reset:
+ reset();
+ this.typeReplacement = null;
+ this.isReplacing = false;
+ // and start anew:
+ this.currentWalker = walker;
+ return walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ }
+
+ <T extends TypeBinding> T superimpose(T type, Class<? extends T> cl) {
+ TypeBindingVisitor.visit(this, type);
+ if (cl.isInstance(this.typeReplacement))
+ return cl.cast(this.typeReplacement);
+ return type;
+ }
+
+ private TypeBinding goAndSuperimpose(ITypeAnnotationWalker walker, TypeBinding type) {
+ // no reset here
+ if (walker == ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER)
+ return type;
+ this.currentWalker = walker;
+
+ TypeBindingVisitor.visit(this, type);
+
+ if (this.typeReplacement == null)
+ return type;
+ this.isReplacing = true;
+ TypeBinding answer = this.typeReplacement;
+ this.typeReplacement = null;
+ return answer;
+ }
+
+ @Override
+ public boolean visit(ArrayBinding arrayBinding) {
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ int dims = arrayBinding.dimensions;
+ AnnotationBinding[][] annotsOnDims = new AnnotationBinding[dims][];
+ ITypeAnnotationWalker walker = this.currentWalker;
+ for (int i = 0; i < dims; i++) {
+ IBinaryAnnotation[] binaryAnnotations = walker.getAnnotationsAtCursor(arrayBinding.id);
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ annotsOnDims[i] = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.isReplacing = true;
+ } else {
+ annotsOnDims[i] = Binding.NO_ANNOTATIONS;
+ }
+ walker = walker.toNextArrayDimension();
+ }
+ TypeBinding leafComponentType = goAndSuperimpose(walker, arrayBinding.leafComponentType());
+ if (this.isReplacing) {
+ this.typeReplacement = this.environment.createArrayType(leafComponentType, dims, AnnotatableTypeSystem.flattenedAnnotations(annotsOnDims));
+ }
+ } finally {
+ restore(memento);
+ }
+ return false;
+ }
+ @Override
+ public boolean visit(BaseTypeBinding baseTypeBinding) {
+ return false; // no null annotations
+ }
+ @Override
+ public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) {
+ return false; // shouldn't occur in declarations
+ }
+ @Override
+ public boolean visit(ParameterizedTypeBinding parameterizedTypeBinding) {
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(parameterizedTypeBinding.id);
+ AnnotationBinding[] annotations = Binding.NO_ANNOTATIONS;
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.isReplacing = true;
+ }
+
+ TypeBinding[] typeArguments = parameterizedTypeBinding.typeArguments();
+ TypeBinding[] newArguments = new TypeBinding[typeArguments.length];
+ for (int i = 0; i < typeArguments.length; i++) {
+ newArguments[i] = goAndSuperimpose(memento.currentWalker.toTypeArgument(i), typeArguments[i]);
+ }
+ if (this.isReplacing)
+ this.typeReplacement = this.environment.createParameterizedType(parameterizedTypeBinding.genericType(), newArguments, parameterizedTypeBinding.enclosingType(), annotations);
+ return false;
+ } finally {
+ restore(memento);
+ }
+ }
+ @Override
+ public boolean visit(RawTypeBinding rawTypeBinding) {
+ return visit((ReferenceBinding)rawTypeBinding);
+ }
+ @Override
+ public boolean visit(ReferenceBinding referenceBinding) {
+ IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(referenceBinding.id);
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS)
+ this.typeReplacement = this.environment.createAnnotatedType(referenceBinding, BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null));
+ return false;
+ }
+ @Override
+ public boolean visit(TypeVariableBinding typeVariable) {
+ return visit((ReferenceBinding) typeVariable);
+ }
+ @Override
+ public boolean visit(WildcardBinding wildcardBinding) {
+ TypeBinding bound = wildcardBinding.bound;
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ if (bound != null) {
+ bound = goAndSuperimpose(memento.currentWalker.toWildcardBound(), bound);
+ }
+ IBinaryAnnotation[] binaryAnnotations = memento.currentWalker.getAnnotationsAtCursor(-1);
+ if (this.isReplacing || binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ TypeBinding[] otherBounds = wildcardBinding.otherBounds;
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ AnnotationBinding[] annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind, annotations);
+ } else {
+ this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind);
+ }
+ }
+ } finally {
+ restore(memento);
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
index 7247fc3..ad48663 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
@@ -306,7 +306,7 @@
ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(currentMethod, typeVariables);
substituteReturnType = substitute.returnType;
}
- if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, null, 0, CheckMode.OVERRIDE_RETURN).isAnyMismatch()) {
+ if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, null, 0, null, CheckMode.OVERRIDE_RETURN).isAnyMismatch()) {
if (srcMethod != null)
scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod,
this.environment.getNonNullAnnotationName());
@@ -437,7 +437,7 @@
if (useTypeAnnotations) {
TypeBinding inheritedParameter = inheritedMethod.parameters[i];
TypeBinding substituteParameter = substituteParameters != null ? substituteParameters[i] : null;
- if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedParameter, substituteParameter, null, 0, CheckMode.OVERRIDE).isAnyMismatch()) {
+ if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedParameter, substituteParameter, null, 0, null, CheckMode.OVERRIDE).isAnyMismatch()) {
if (currentArgument != null)
scope.problemReporter().illegalParameterRedefinition(currentArgument, inheritedMethod.declaringClass, inheritedParameter);
else
@@ -453,7 +453,7 @@
if (currentTypeVariables != Binding.NO_TYPE_VARIABLES && currentTypeVariables.length == inheritedTypeVariables.length) {
for (int i = 0; i < currentTypeVariables.length; i++) {
TypeVariableBinding inheritedVariable = inheritedTypeVariables[i];
- if (NullAnnotationMatching.analyse(inheritedVariable, currentTypeVariables[i], null, null, -1, CheckMode.BOUND_CHECK).isAnyMismatch())
+ if (NullAnnotationMatching.analyse(inheritedVariable, currentTypeVariables[i], null, null, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch())
scope.problemReporter().cannotRedefineTypeArgumentNullity(inheritedVariable, inheritedMethod, srcMethod.typeParameters()[i]);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
index 5fecda1..f197cfa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG, and others.
+ * Copyright (c) 2013, 2016 GK Software AG, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -497,10 +497,6 @@
if (withWildCards != null) {
t = ConstraintExpressionFormula.findGroundTargetType(this, skope, lambda, withWildCards);
}
- if (!t.isProperType(true) && t.isParameterizedType()) {
- // prevent already resolved inference variables from leaking into the lambda
- t = (ReferenceBinding) Scope.substitute(getResultSubstitution(this.currentBounds, false), t);
- }
MethodBinding functionType;
if (t != null && (functionType = t.getSingleAbstractMethod(skope, true)) != null && (lambda = lambda.resolveExpressionExpecting(t, this.scope, this)) != null) {
TypeBinding r = functionType.returnType;
@@ -540,9 +536,7 @@
this.inferenceKind = applicabilityKind;
if (innerContext != null)
innerContext.outerContext = this;
- inferInvocationApplicability(shallowMethod, argumentTypes, shallowMethod.isConstructor());
- if (!ConstraintExpressionFormula.inferPolyInvocationType(this, invocation, substF, shallowMethod))
- return false;
+ createInitialBoundSet(shallowMethod.getAllTypeVariables(shallowMethod.isConstructor())); // minimal preparation to work with inner inference variables
} finally {
resumeSuspendedInference(prevInvocation);
}
@@ -729,37 +723,43 @@
private boolean checkExpression(Expression expri, TypeBinding[] u, TypeBinding r1, TypeBinding[] v, TypeBinding r2)
throws InferenceFailureException {
if (expri instanceof LambdaExpression && !((LambdaExpression)expri).argumentsTypeElided()) {
+ for (int i = 0; i < u.length; i++) {
+ if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
+ return false;
+ }
if (r2.id == TypeIds.T_void)
return true;
LambdaExpression lambda = (LambdaExpression) expri;
Expression[] results = lambda.resultExpressions();
- if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope)
- && !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
- // "these rules are applied recursively to R1 and R2, for each result expression in expi."
- // (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
- for (int i = 0; i < results.length; i++) {
- if (!checkExpression(results[i], u, r1, v, r2))
- return false;
+ if (results != Expression.NO_EXPRESSIONS) {
+ if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope)
+ && !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
+ // "these rules are applied recursively to R1 and R2, for each result expression in expi."
+ // (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
+ for (int i = 0; i < results.length; i++) {
+ if (!checkExpression(results[i], u, r1, v, r2))
+ return false;
+ }
+ return true;
}
- return true;
- }
- checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
- // check: each result expression is a standalone expression of a primitive type
- for (int i = 0; i < results.length; i++) {
- if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
- break checkPrimitive1;
+ checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
+ // check: each result expression is a standalone expression of a primitive type
+ for (int i = 0; i < results.length; i++) {
+ if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
+ break checkPrimitive1;
+ }
+ return true;
}
- return true;
- }
- checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
- for (int i = 0; i < results.length; i++) {
- // for all expressions (not for any expression not)
- if (!(
- (!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) // standalone of a referencetype
- || results[i].isPolyExpression())) // or a poly
- break checkPrimitive2;
- }
- return true;
+ checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
+ for (int i = 0; i < results.length; i++) {
+ // for all expressions (not for any expression not)
+ if (!(
+ (!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) // standalone of a referencetype
+ || results[i].isPolyExpression())) // or a poly
+ break checkPrimitive2;
+ }
+ return true;
+ }
}
return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
} else if (expri instanceof ReferenceExpression && ((ReferenceExpression)expri).isExactMethodReference()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
index a93c1b5..929dbe6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
@@ -20,6 +20,7 @@
import java.util.Set;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -51,28 +52,24 @@
public TypeBinding clone(TypeBinding enclosingType) {
return new IntersectionTypeBinding18(this);
}
-
- public MethodBinding getSingleAbstractMethod(Scope scope, boolean replaceWildcards) {
- int index = replaceWildcards ? 0 : 1;
- if (this.singleAbstractMethod != null) {
- if (this.singleAbstractMethod[index] != null)
- return this.singleAbstractMethod[index];
- } else {
- this.singleAbstractMethod = new MethodBinding[2];
+
+ @Override
+ protected MethodBinding[] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
+ int typesLength = this.intersectingTypes.length;
+ MethodBinding[][] methods = new MethodBinding[typesLength][];
+ int contractsLength = 0;
+ for (int i = 0; i < typesLength; i++) {
+ methods[i] = this.intersectingTypes[i].getInterfaceAbstractContracts(scope);
+ contractsLength += methods[i].length;
}
- MethodBinding sam = samProblemBinding; // guilty unless proven innocent !
- for (int i = 0; i < this.length; i++) {
- MethodBinding method = this.intersectingTypes[i].getSingleAbstractMethod(scope, replaceWildcards);
- if (method != null) {
- if (method.isValidBinding()) {
- if (sam.isValidBinding())
- return this.singleAbstractMethod[index] = new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.IntersectionHasMultipleFunctionalInterfaces);
- else
- sam = method;
- }
- }
+ MethodBinding[] contracts = new MethodBinding[contractsLength];
+ int idx = 0;
+ for (int i = 0; i < typesLength; i++) {
+ int len = methods[i].length;
+ System.arraycopy(methods[i], 0, contracts, idx, len);
+ idx += len;
}
- return this.singleAbstractMethod[index] = sam; // I don't see a value in building the notional interface described in 9.8 - it appears just pedantic/normative - perhaps it plays a role in wildcard parameterized types ?
+ return contracts;
}
public boolean hasTypeBit(int bit) { // Stephan ??
@@ -256,21 +253,16 @@
}
public TypeBinding getSAMType(Scope scope) {
- TypeBinding samType = null;
for (int i = 0, max = this.intersectingTypes.length; i < max; i++) {
TypeBinding typeBinding = this.intersectingTypes[i];
MethodBinding methodBinding = typeBinding.getSingleAbstractMethod(scope, true);
// Why doesn't getSingleAbstractMethod do as the javadoc says, and return null
// when it is not a SAM type
- if (methodBinding instanceof ProblemMethodBinding && ((ProblemMethodBinding) methodBinding).problemId()==ProblemReasons.NoSuchSingleAbstractMethod) {
- continue;
+ if (methodBinding != null && methodBinding.problemId() != ProblemReasons.NoSuchSingleAbstractMethod) {
+ return typeBinding; // answer the first SAM we find
}
- if (samType != null) {
- return null; // There is more than one (!), so we don't know which
- }
- samType = typeBinding;
}
- return samType;
+ return null;
}
//{ObjectTeams: enable crossing package boundaries:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 7304f35..7b9c016 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -278,6 +278,12 @@
} else if (answer.isSourceType()) {
// the type was found as a source model
this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
+ ReferenceBinding binding = packageBinding.getType0(name);
+ String externalAnnotationPath = answer.getExternalAnnotationPath();
+ if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) {
+ ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath);
+ }
+ return binding;
}
return packageBinding.getType0(name);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index dd98267..8618213 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -119,6 +119,8 @@
public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
char[] signature;
public long tagBits;
+ // Used only for constructors
+ protected AnnotationBinding [] typeAnnotations = Binding.NO_ANNOTATIONS;
//{ObjectTeams:
public MethodModel model = null;
@@ -1177,6 +1179,22 @@
return null;
}
+public TypeVariableBinding[] getAllTypeVariables(boolean isDiamond) {
+ TypeVariableBinding[] allTypeVariables = this.typeVariables;
+ if (isDiamond) {
+ TypeVariableBinding[] classTypeVariables = this.declaringClass.typeVariables();
+ int l1 = allTypeVariables.length;
+ int l2 = classTypeVariables.length;
+ if (l1 == 0) {
+ allTypeVariables = classTypeVariables;
+ } else if (l2 != 0) {
+ System.arraycopy(allTypeVariables, 0, allTypeVariables=new TypeVariableBinding[l1+l2], 0, l1);
+ System.arraycopy(classTypeVariables, 0, allTypeVariables, l1, l2);
+ }
+ }
+ return allTypeVariables;
+}
+
/**
* Returns true if method got substituted parameter types
* (see ParameterizedMethodBinding)
@@ -1404,6 +1422,13 @@
buffer.append(')');
return buffer.toString().toCharArray();
}
+final public AnnotationBinding[] getTypeAnnotations() {
+ return this.typeAnnotations;
+}
+
+public void setTypeAnnotations(AnnotationBinding[] annotations) {
+ this.typeAnnotations = annotations;
+}
public void setAnnotations(AnnotationBinding[] annotations) {
this.declaringClass.storeAnnotations(this, annotations);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index 67e6e83..8d08f05 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -663,7 +663,7 @@
// the erasure of the return type and thrown types of m's type."
if (substitute)
type = Scope.substitute(this, type);
- return env.convertToRawType(type, true);
+ return env.convertToRawType(type.erasure(), true);
}
/*
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
index 3c3464c..04438a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
@@ -38,7 +38,7 @@
final int VarargsElementTypeNotVisible = 16;
final int NoSuchSingleAbstractMethod = 17;
final int NotAWellFormedParameterizedType = 18;
- final int IntersectionHasMultipleFunctionalInterfaces = 19;
+ // no longer in use: final int IntersectionHasMultipleFunctionalInterfaces = 19;
final int NonStaticOrAlienTypeReceiver = 20;
final int AttemptToBypassDirectSuper = 21; // super access within default method
final int DefectiveContainerAnnotationType = 22;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 0c878c4..9206ec8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2389,7 +2389,7 @@
return null;
}
// SH}
-private MethodBinding [] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
+protected MethodBinding [] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
if (!isInterface() || !isValidBinding()) {
throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 98f4f35..2d969cd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -2928,15 +2928,15 @@
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding()) {
if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
+ if (!skipOnDemand && !importBinding.onDemand) {
+ visible = null; // forget previous matches from on demand imports
+ skipOnDemand = true;
+ }
if (visible == null || !visible.contains(compatibleMethod)) {
ImportReference importReference = importBinding.reference;
if (importReference != null) {
importReference.bits |= ASTNode.Used;
}
- if (!skipOnDemand && !importBinding.onDemand) {
- visible = null; // forget previous matches from on demand imports
- skipOnDemand = true;
- }
if (visible == null)
visible = new ObjectVector(3);
visible.add(compatibleMethod);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 9004d2b..35e52b1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -66,12 +66,14 @@
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.ast.Expression.DecapsulationState;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WeavingScheme;
@@ -181,6 +183,8 @@
private int lambdaOrdinal = 0;
private ReferenceBinding containerAnnotationType = null;
+ public ExternalAnnotationProvider externalAnnotationProvider;
+
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
//{ObjectTeams: // share model from TypeDeclaration:
super(scope.referenceContext.getModel());
@@ -843,17 +847,47 @@
// Create a $deserializeLambda$ method if necessary, one is shared amongst all lambdas
if (lambda.isSerializable) {
- SyntheticMethodBinding[] deserializeLambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(TypeConstants.DESERIALIZE_LAMBDA);
- if (deserializeLambdaMethods == null) {
- SyntheticMethodBinding deserializeLambdaMethod = new SyntheticMethodBinding(this);
- this.synthetics[SourceTypeBinding.METHOD_EMUL].put(TypeConstants.DESERIALIZE_LAMBDA,deserializeLambdaMethods = new SyntheticMethodBinding[1]);
- deserializeLambdaMethods[0] = deserializeLambdaMethod;
- }
+ addDeserializeLambdaMethod();
}
return lambdaMethod;
}
+/*
+ * Add a synthetic method for the reference expression as a place holder for code generation
+ * only if the reference expression's target is serializable
+ *
+ */
+public SyntheticMethodBinding addSyntheticMethod(ReferenceExpression ref) {
+ if (!isPrototype()) throw new IllegalStateException();
+ if (!ref.isSerializable)
+ return null;
+ if (this.synthetics == null)
+ this.synthetics = new HashMap[MAX_SYNTHETICS];
+ if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
+ this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
+
+ SyntheticMethodBinding lambdaMethod = null;
+ SyntheticMethodBinding[] lambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(ref);
+ if (lambdaMethods == null) {
+ lambdaMethod = new SyntheticMethodBinding(ref, this);
+ this.synthetics[SourceTypeBinding.METHOD_EMUL].put(ref, lambdaMethods = new SyntheticMethodBinding[1]);
+ lambdaMethods[0] = lambdaMethod;
+ } else {
+ lambdaMethod = lambdaMethods[0];
+ }
+ // Create a $deserializeLambda$ method, one is shared amongst all lambdas
+ addDeserializeLambdaMethod();
+ return lambdaMethod;
+}
+private void addDeserializeLambdaMethod() {
+ SyntheticMethodBinding[] deserializeLambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(TypeConstants.DESERIALIZE_LAMBDA);
+ if (deserializeLambdaMethods == null) {
+ SyntheticMethodBinding deserializeLambdaMethod = new SyntheticMethodBinding(this);
+ this.synthetics[SourceTypeBinding.METHOD_EMUL].put(TypeConstants.DESERIALIZE_LAMBDA,deserializeLambdaMethods = new SyntheticMethodBinding[1]);
+ deserializeLambdaMethods[0] = deserializeLambdaMethod;
+ }
+}
/* Add a new synthetic access method for access to <targetMethod>.
* Must distinguish access method used for super access from others (need to use invokespecial bytecode)
Answer the new method or the existing method if one already existed.
@@ -2335,7 +2369,7 @@
// enum constants neither have a type declaration nor can they be null
field.tagBits |= TagBits.AnnotationNonNull;
} else {
- if (hasNonNullDefaultFor(DefaultLocationField, sourceLevel >= ClassFileConstants.JDK1_8)) {
+ if (hasNonNullDefaultFor(DefaultLocationField, this.environment.usesNullTypeAnnotations())) {
field.fillInDefaultNonNullness(fieldDecl, initializationScope);
}
// validate null annotation:
@@ -2346,6 +2380,9 @@
} finally {
initializationScope.initializedField = previousField;
}
+ if (this.externalAnnotationProvider != null) {
+ ExternalAnnotationSuperimposer.annotateFieldBinding(field, this.externalAnnotationProvider, this.environment);
+ }
//{ObjectTeams: copy-inherited fields and anchored types:
if (fieldDecls[f].getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
if (fieldDecls[f].type == null) // should not happen for non-enum types
@@ -2685,6 +2722,13 @@
rejectTypeAnnotatedVoidMethod(methodDecl);
}
}
+ } else {
+ if (sourceLevel >= ClassFileConstants.JDK1_8) {
+ Annotation [] annotations = methodDecl.annotations;
+ if (annotations != null && annotations.length != 0) {
+ ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations, false);
+ }
+ }
}
if (foundArgProblem) {
methodDecl.binding = null;
@@ -2727,6 +2771,9 @@
return method; // but its still unresolved with a null return type & is still connected to its method declaration
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ if (this.externalAnnotationProvider != null) {
+ ExternalAnnotationSuperimposer.annotateMethodBinding(method, this.externalAnnotationProvider, this.environment);
+ }
//{ObjectTeams: need role method bridges?
int abstractStatic = ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic;
if ( isRole()
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 6cd03d7..1b76da9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -23,6 +23,7 @@
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -43,7 +44,11 @@
public MethodBinding targetMethod; // method or constructor
public TypeBinding targetEnumType; // enum type
public LambdaExpression lambda;
-
+ /**
+ * Method reference expression whose target FI is Serializable. Should be set when
+ * purpose is {@link #SerializableMethodReference}
+ */
+ public ReferenceExpression serializableMethodRef;
public int purpose;
// fields used to generate enum constants when too many
@@ -67,11 +72,16 @@
public static final int ArrayClone = 15; // X[]::clone
public static final int FactoryMethod = 16; // for indy call to private constructor.
public static final int DeserializeLambda = 17; // For supporting lambda deserialization.
+ /**
+ * Serves as a placeholder for a method reference whose target FI is Serializable.
+ * Is never directly materialized in bytecode
+ */
+ public static final int SerializableMethodReference = 18;
//{ObjectTeams: other purposes:
- public final static int InferredCalloutToField = 18; // calling an inferred callout-to-field
- public final static int RoleMethodBridgeOuter = 19; // a team-level bridge method towards a private role method (for callout)
- public final static int RoleMethodBridgeInner = 20; // a role-level bridge method towards a private role method (for callout)
- public final static int MethodDecapsulation = 21;
+ public final static int InferredCalloutToField = 19; // calling an inferred callout-to-field
+ public final static int RoleMethodBridgeOuter = 20; // a team-level bridge method towards a private role method (for callout)
+ public final static int RoleMethodBridgeInner = 21; // a role-level bridge method towards a private role method (for callout)
+ public final static int MethodDecapsulation = 22;
// SH}
public int sourceStart = 0; // start position of the matching declaration
@@ -491,6 +501,21 @@
this.index = methodId;
}
+ public SyntheticMethodBinding(ReferenceExpression ref, SourceTypeBinding declaringClass) {
+ this.serializableMethodRef = ref;
+ this.declaringClass = declaringClass;
+ this.selector = ref.binding.selector;
+ this.modifiers = ref.binding.modifiers;
+ this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved) | (ref.binding.tagBits & TagBits.HasParameterAnnotations);
+ this.returnType = ref.binding.returnType;
+ this.parameters = ref.binding.parameters;
+ this.thrownExceptions = ref.binding.thrownExceptions;
+ this.purpose = SyntheticMethodBinding.SerializableMethodReference;
+ SyntheticMethodBinding[] knownAccessMethods = declaringClass.syntheticMethods();
+ int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+ this.index = methodId;
+ }
+
public SyntheticMethodBinding(MethodBinding privateConstructor, MethodBinding publicConstructor, char[] selector, TypeBinding[] enclosingInstances, SourceTypeBinding declaringClass) {
this.declaringClass = declaringClass;
this.selector = selector;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 23fbd34..4546476 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1663,11 +1663,12 @@
// SH}
/**
- * Return the single abstract method of a functional interface, or null, if the receiver is not a functional interface as defined in JLS 9.8.
+ * Return the single abstract method of a functional interface, or one of {@code null} or {@link ReferenceBinding#samProblemBinding}, if the receiver is not a functional interface as defined in JLS 9.8.
+ * In particular {@code null} is answered if the receiver is not a reference type, or is a problem type.
* @param scope scope
* @param replaceWildcards Should wildcards be replaced following JLS 9.8? Say false for lambdas with explicit argument types which should apply 18.5.3
*
- * @return The single abstract method of a functional interface, or null, if the receiver is not a functional interface.
+ * @return The single abstract method of a functional interface, or one of {@code null} or {@link ReferenceBinding#samProblemBinding}, if the receiver is not a functional interface.
*/
public MethodBinding getSingleAbstractMethod(Scope scope, boolean replaceWildcards) {
return null;
@@ -1780,4 +1781,8 @@
public long updateTagBits() {
return this.tagBits & TagBits.HasNullTypeAnnotation; // subclasses to override
}
+
+public boolean isFreeTypeVariable() {
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
index 99f1bae..faca34a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,6 +18,10 @@
private SimpleLookupTable visitedCache;
+ public void reset() {
+ this.visitedCache = null;
+ }
+
public boolean visit(BaseTypeBinding baseTypeBinding) {
return true; // continue traversal.
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index baa1c68..b3d6f59 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -126,6 +126,7 @@
// Constant compound names
char[][] JAVA_LANG = {JAVA, LANG};
char[][] JAVA_IO = {JAVA, IO};
+ char[][] JAVA_LANG_ANNOTATION = {JAVA, LANG, ANNOTATION};
char[][] JAVA_LANG_ANNOTATION_ANNOTATION = {JAVA, LANG, ANNOTATION, "Annotation".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
index cbf69ab..769e8f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
@@ -234,22 +234,25 @@
}
}
}
- if (type.id == TypeIds.NoId) {
- if (type.hasTypeAnnotations())
- throw new IllegalStateException();
- int typesLength = this.types.length;
- if (this.typeid == typesLength)
- System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
- this.types[type.id = this.typeid++] = new TypeBinding[4];
- if (urb != null)
+ try {
+ if (type.id == TypeIds.NoId) {
+ if (type.hasTypeAnnotations())
+ throw new IllegalStateException();
+ int typesLength = this.types.length;
+ if (this.typeid == typesLength)
+ System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
+ this.types[type.id = this.typeid++] = new TypeBinding[4];
+ } else {
+ TypeBinding nakedType = this.types[type.id] == null ? null : this.types[type.id][0];
+ if (type.hasTypeAnnotations() && nakedType == null)
+ throw new IllegalStateException();
+ if (nakedType != null)
+ return nakedType;
+ this.types[type.id] = new TypeBinding[4]; // well known type, assigned id elsewhere.
+ }
+ } finally {
+ if (urb != null && urb.id == TypeIds.NoId)
urb.id = type.id;
- } else {
- TypeBinding nakedType = this.types[type.id] == null ? null : this.types[type.id][0];
- if (type.hasTypeAnnotations() && nakedType == null)
- throw new IllegalStateException();
- if (nakedType != null)
- return nakedType;
- this.types[type.id] = new TypeBinding[4]; // well known type, assigned id elsewhere.
}
return this.types[type.id][0] = type;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 8147618..5e723f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -44,10 +44,10 @@
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
-import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus;
@@ -248,7 +248,7 @@
}
}
if (location != null && checkNullAnnotations) {
- if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch()) {
+ if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch()) {
scope.problemReporter().nullityMismatchTypeArgument(this, argumentType, location);
haveReportedNullProblem = true;
}
@@ -309,7 +309,7 @@
}
}
if (location != null && checkNullAnnotations) {
- if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch()) {
+ if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch()) {
scope.problemReporter().nullityMismatchTypeArgument(this, argumentType, location);
haveReportedNullProblem = true;
}
@@ -1190,4 +1190,11 @@
}
return super.updateTagBits();
}
+
+ @Override
+ public boolean isFreeTypeVariable() {
+ return this.environment.usesNullTypeAnnotations()
+ && this.environment.globalOptions.pessimisticNullAnalysisForFreeTypeVariablesEnabled
+ && (this.tagBits & TagBits.AnnotationNullMASK) == 0;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
index 614d5ac..1d1a5bb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2009 IBM Corporation and others.
+# Copyright (c) 2000, 2016 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -39,6 +39,7 @@
abort_missingCode = Missing code implementation in the compiler
abort_againstSourceModel = Cannot compile against source model {0} issued from {1}
abort_invalidOpcode = SANITY CHECK: Invalid opcode {0} at pc {1} for stackmap table attribute for method {2}
+abort_externaAnnotationFile = Failed to read external annotations for {0} from {1} due to an exception: {2}
### accept
accept_cannot = Cannot accept the compilation unit:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
index a43819c..3927198 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -50,6 +50,8 @@
/* When temporarily switching policies, store here the original root policy (for temporary resume). */
private IErrorHandlingPolicy rootPolicy;
+ protected boolean suppressTagging = false;
+
//{ObjectTeams: support for passing a rechecker:
public IProblemRechecker rechecker;
// SH}
@@ -323,7 +325,9 @@
//{ObjectTeams: problems with a rechecker are considered "optional", don't tag the reference context
if (!requireRecheck)
// SH}
- referenceContext.tagAsHavingErrors();
+ if (!this.suppressTagging || this.options.treatOptionalErrorAsFatal) {
+ referenceContext.tagAsHavingErrors();
+ }
// should abort ?
int abortLevel;
if ((abortLevel = this.policy.stopOnFirstError() ? ProblemSeverities.AbortCompilation : severity & ProblemSeverities.Abort) != 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 59c3bcd..4353449 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -468,8 +468,6 @@
case IProblem.CannotImplementIncompatibleNullness:
case IProblem.ConflictingNullAnnotations:
case IProblem.ConflictingInheritedNullAnnotations:
- case IProblem.NullNotCompatibleToFreeTypeVariable:
- case IProblem.NullityMismatchAgainstFreeTypeVariable:
case IProblem.NullityMismatchingTypeAnnotation:
case IProblem.NullityMismatchingTypeAnnotationSuperHint:
case IProblem.NullityMismatchTypeArgument:
@@ -483,6 +481,18 @@
case IProblem.ContradictoryNullAnnotationsInferredFunctionType:
return CompilerOptions.NullSpecViolation;
+ case IProblem.NullNotCompatibleToFreeTypeVariable:
+ case IProblem.NullityMismatchAgainstFreeTypeVariable:
+ case IProblem.UncheckedAccessOfValueOfFreeTypeVariable:
+ case IProblem.RequiredNonNullButProvidedFreeTypeVariable:
+ case IProblem.UninitializedFreeTypeVariableField:
+ case IProblem.UninitializedFreeTypeVariableFieldHintMissingDefault:
+ return CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables;
+
+ case IProblem.NonNullTypeVariableFromLegacyMethod:
+ case IProblem.NonNullMethodTypeVariableFromLegacyMethod:
+ return CompilerOptions.NonNullTypeVariableFromLegacyInvocation;
+
case IProblem.ParameterLackingNonNullAnnotation:
return CompilerOptions.NonnullParameterAnnotationDropped;
@@ -815,6 +825,8 @@
case CompilerOptions.UnusedObjectAllocation :
case CompilerOptions.UnclosedCloseable :
case CompilerOptions.PotentiallyUnclosedCloseable :
+ case CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables :
+ case CompilerOptions.NonNullTypeVariableFromLegacyInvocation :
return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
case CompilerOptions.OverriddenPackageDefaultMethod :
@@ -1344,6 +1356,15 @@
location.sourceStart,
location.sourceEnd);
}
+public void bytecodeExceeds64KLimit(MethodBinding method, int start, int end) {
+ this.handle(
+ IProblem.BytecodeExceeds64KLimit,
+ new String[] {new String(method.selector), typesAsString(method, false)},
+ new String[] {new String(method.selector), typesAsString(method, true)},
+ ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
+ start,
+ end);
+}
public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) {
MethodBinding method = location.binding;
if (location.isConstructor()) {
@@ -1355,24 +1376,11 @@
location.sourceStart,
location.sourceEnd);
} else {
- this.handle(
- IProblem.BytecodeExceeds64KLimit,
- new String[] {new String(location.selector), typesAsString(method, false)},
- new String[] {new String(location.selector), typesAsString(method, true)},
- ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
- location.sourceStart,
- location.sourceEnd);
+ bytecodeExceeds64KLimit(method, location.sourceStart, location.sourceEnd);
}
}
public void bytecodeExceeds64KLimit(LambdaExpression location) {
- MethodBinding method = location.binding;
- this.handle(
- IProblem.BytecodeExceeds64KLimit,
- new String[] {new String(method.selector), typesAsString(method, false)},
- new String[] {new String(method.selector), typesAsString(method, true)},
- ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
- location.sourceStart,
- location.diagnosticsSourceEnd());
+ bytecodeExceeds64KLimit(location.binding, location.sourceStart, location.diagnosticsSourceEnd());
}
public void bytecodeExceeds64KLimit(TypeDeclaration location) {
this.handle(
@@ -1459,7 +1467,7 @@
}
public void cannotImportPackage(ImportReference importRef) {
String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
- this.handle(
+ this.handleUntagged(
IProblem.CannotImportPackage,
arguments,
arguments,
@@ -1816,7 +1824,7 @@
}
public void conflictingImport(ImportReference importRef) {
String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
- this.handle(
+ this.handleUntagged(
IProblem.ConflictingImport,
arguments,
arguments,
@@ -2036,7 +2044,7 @@
}
public void duplicateImport(ImportReference importRef) {
String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
- this.handle(
+ this.handleUntagged(
IProblem.DuplicateImport,
arguments,
arguments,
@@ -2700,6 +2708,20 @@
problemEndPosition);
}
+protected void handleUntagged(
+ int problemId,
+ String[] problemArguments,
+ String[] messageArguments,
+ int problemStartPosition,
+ int problemEndPosition) {
+ boolean oldSuppressing = this.suppressTagging;
+ this.suppressTagging = true;
+ try {
+ this.handle(problemId, problemArguments, messageArguments, problemStartPosition, problemEndPosition);
+ } finally {
+ this.suppressTagging = oldSuppressing;
+ }
+}
public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
this.handle(
IProblem.MaskedCatch,
@@ -3363,7 +3385,7 @@
shortArguments = new String[] {new String(field.declaringClass.leafComponentType().shortReadableName())};
break;
}
- this.handle(
+ this.handleUntagged(
id,
readableArguments,
shortArguments,
@@ -3377,7 +3399,7 @@
? ((ProblemReferenceBinding) expectedImport).compoundName
: importRef.tokens;
String[] arguments = new String[]{CharOperation.toString(tokens)};
- this.handle(
+ this.handleUntagged(
IProblem.ImportNotFound,
arguments,
arguments,
@@ -3388,7 +3410,7 @@
if (expectedImport.problemId() == ProblemReasons.InvalidTypeForStaticImport) {
char[][] tokens = importRef.tokens;
String[] arguments = new String[]{CharOperation.toString(tokens)};
- this.handle(
+ this.handleUntagged(
IProblem.InvalidTypeForStaticImport,
arguments,
arguments,
@@ -6439,7 +6461,54 @@
nodeSourceEnd(local, location));
}
+public void fieldFreeTypeVariableReference(FieldBinding variable, long position) {
+ char[][] nullableName = this.options.nullableAnnotationName;
+ String[] arguments = new String[] {new String(variable.type.readableName()),
+ new String(nullableName[nullableName.length-1])};
+ this.handle(
+ IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+ arguments,
+ arguments,
+ (int)(position >>> 32),
+ (int)position);
+}
+
+
+public void localVariableFreeTypeVariableReference(LocalVariableBinding local, ASTNode location) {
+ int severity = computeSeverity(IProblem.UncheckedAccessOfValueOfFreeTypeVariable);
+ if (severity == ProblemSeverities.Ignore) return;
+ char[][] nullableName = this.options.nullableAnnotationName;
+ String[] arguments = new String[] {new String(local.type.readableName()),
+ new String(nullableName[nullableName.length-1])};
+ this.handle(
+ IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+ arguments,
+ arguments,
+ severity,
+ nodeSourceStart(local, location),
+ nodeSourceEnd(local, location));
+}
+
+public void methodReturnTypeFreeTypeVariableReference(MethodBinding method, ASTNode location) {
+ int severity = computeSeverity(IProblem.UncheckedAccessOfValueOfFreeTypeVariable);
+ if (severity == ProblemSeverities.Ignore) return;
+ char[][] nullableName = this.options.nullableAnnotationName;
+ String[] arguments = new String[] {new String(method.returnType.readableName()),
+ new String(nullableName[nullableName.length-1])};
+ this.handle(
+ IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+ arguments,
+ arguments,
+ location.sourceStart,
+ location.sourceEnd);
+}
+
+
public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) {
+ if(local.type.isFreeTypeVariable()) {
+ localVariableFreeTypeVariableReference(local, location);
+ return;
+ }
if (location instanceof Expression && (((Expression)location).implicitConversion & TypeIds.UNBOXING) != 0) {
potentialNullUnboxing(location, local.type);
return;
@@ -8834,6 +8903,20 @@
}
public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
char[][] nonNullAnnotationName = this.options.nonNullAnnotationName;
+ if(!field.isNonNull()) {
+ String[] arguments = new String[] {
+ new String(field.readableName()),
+ new String(field.type.readableName()),
+ new String(nonNullAnnotationName[nonNullAnnotationName.length-1])
+ };
+ this.handle(
+ methodHasMissingSwitchDefault() ? IProblem.UninitializedFreeTypeVariableFieldHintMissingDefault : IProblem.UninitializedFreeTypeVariableField,
+ arguments,
+ arguments,
+ nodeSourceStart(field, location),
+ nodeSourceEnd(field, location));
+ return;
+ }
String[] arguments = new String[] {
new String(nonNullAnnotationName[nonNullAnnotationName.length-1]),
new String(field.readableName())
@@ -9964,6 +10047,10 @@
if (var == null && expression instanceof Reference) {
var = ((Reference)expression).lastFieldBinding();
}
+ if(var != null && var.type.isFreeTypeVariable()) {
+ nullityMismatchVariableIsFreeTypeVariable(var, expression);
+ return;
+ }
if (var != null && var.isNullable()) {
nullityMismatchSpecdNullable(expression, requiredType, annotationName);
return;
@@ -13663,6 +13750,21 @@
// SH}
+private void nullityMismatchIsFreeTypeVariable(TypeBinding providedType, int sourceStart, int sourceEnd) {
+ char[][] nullableName = this.options.nullableAnnotationName;
+ char[][] nonNullName = this.options.nonNullAnnotationName;
+ String[] arguments = new String[] {
+ new String(nonNullName[nonNullName.length-1]),
+ new String(providedType.readableName()),
+ new String(nullableName[nullableName.length-1])};
+ this.handle(IProblem.RequiredNonNullButProvidedFreeTypeVariable, arguments, arguments, sourceStart, sourceEnd);
+}
+public void nullityMismatchVariableIsFreeTypeVariable(VariableBinding variable, ASTNode location) {
+ int severity = computeSeverity(IProblem.RequiredNonNullButProvidedFreeTypeVariable);
+ if (severity == ProblemSeverities.Ignore) return;
+ nullityMismatchIsFreeTypeVariable(variable.type, nodeSourceStart(variable, location),
+ nodeSourceEnd(variable, location));
+}
public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
int sourceStart = argument.type.sourceStart;
if (argument.annotations != null) {
@@ -14189,6 +14291,11 @@
&& (requiredType.tagBits & TagBits.AnnotationNonNull) != 0
&& (providedType.tagBits & TagBits.AnnotationNullable) == 0)
{
+ if(this.options.pessimisticNullAnalysisForFreeTypeVariablesEnabled && providedType.isTypeVariable() && !providedType.hasNullTypeAnnotations()) {
+ nullityMismatchIsFreeTypeVariable(providedType, expression.sourceStart, expression.sourceEnd);
+ return;
+ }
+
nullityMismatchPotentiallyNull(expression, requiredType, this.options.nonNullAnnotationName);
return;
}
@@ -14284,7 +14391,54 @@
ProblemSeverities.Warning,
reference.sourceStart, reference.sourceEnd);
}
+public void nonNullTypeVariableInUnannotatedBinary(LookupEnvironment environment, MethodBinding method, Expression expression, int providedSeverity) {
+ TypeBinding declaredReturnType = method.original().returnType;
+ int severity = computeSeverity(IProblem.NonNullTypeVariableFromLegacyMethod);
+ if ((severity & ProblemSeverities.CoreSeverityMASK) == ProblemSeverities.Warning)
+ severity = providedSeverity; // leverage the greater precision from our caller
+ if (declaredReturnType instanceof TypeVariableBinding) { // paranoia check
+ TypeVariableBinding typeVariable = (TypeVariableBinding) declaredReturnType;
+ TypeBinding declaringClass = method.declaringClass;
+ char[][] nonNullName = this.options.nonNullAnnotationName;
+ String shortNonNullName = String.valueOf(nonNullName[nonNullName.length-1]);
+
+ if (typeVariable.declaringElement instanceof ReferenceBinding) {
+ String[] arguments = new String[] {
+ shortNonNullName,
+ String.valueOf(declaringClass.nullAnnotatedReadableName(this.options, false)),
+ String.valueOf(declaringClass.original().readableName())};
+ String[] shortArguments = {
+ shortNonNullName,
+ String.valueOf(declaringClass.nullAnnotatedReadableName(this.options, true)),
+ String.valueOf(declaringClass.original().shortReadableName()) };
+ this.handle(IProblem.NonNullTypeVariableFromLegacyMethod,
+ arguments,
+ shortArguments,
+ severity,
+ expression.sourceStart,
+ expression.sourceEnd);
+ } else if (typeVariable.declaringElement instanceof MethodBinding && method instanceof ParameterizedGenericMethodBinding) {
+ TypeBinding substitution = ((ParameterizedGenericMethodBinding) method).typeArguments[typeVariable.rank];
+ String[] arguments = new String[] {
+ shortNonNullName,
+ String.valueOf(typeVariable.readableName()),
+ String.valueOf(substitution.nullAnnotatedReadableName(this.options, false)),
+ String.valueOf(declaringClass.original().readableName())};
+ String[] shortArguments = {
+ shortNonNullName,
+ String.valueOf(typeVariable.shortReadableName()),
+ String.valueOf(substitution.nullAnnotatedReadableName(this.options, true)),
+ String.valueOf(declaringClass.original().shortReadableName()) };
+ this.handle(IProblem.NonNullMethodTypeVariableFromLegacyMethod,
+ arguments,
+ shortArguments,
+ severity,
+ expression.sourceStart,
+ expression.sourceEnd);
+ }
+ }
+}
public void dereferencingNullableExpression(Expression expression) {
if (expression instanceof MessageSend) {
MessageSend send = (MessageSend) expression;
@@ -14340,14 +14494,6 @@
typeReference.sourceEnd);
}
-public void multipleFunctionalInterfaces(FunctionalExpression functionalExpression) {
- this.handle(
- IProblem.MultipleFunctionalInterfaces,
- NoArgument,
- NoArgument,
- functionalExpression.sourceStart,
- functionalExpression.diagnosticsSourceEnd());
-}
public void lambdaRedeclaresArgument(Argument argument) {
String[] arguments = new String[] {new String(argument.name)};
this.handle(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
index c6e2e21..dca13cc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -31,4 +31,6 @@
//{ObjectTeams: signal problem that should be ignored, but yet recorded to match potential @SuppressWarnings
final int IgnoredGenerated = 2048;
// SH}
+
+ final int CoreSeverityMASK = Warning | Error | Info | Ignore;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 353784d..03f3c63 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2015 IBM Corporation and others.
+# Copyright (c) 2000, 2016 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -759,7 +759,7 @@
892 = Base types are not allowed in intersection cast operator
893 = Arrays are not allowed in intersection cast operator
894 = Duplicate type in intersection cast operator
-895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
+#[obsolete] 895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
896 = Static methods are allowed in interfaces only at source level 1.8 or above
897 = Duplicate annotation of non-repeatable type @{0}. Only annotation types marked @Repeatable can be used multiple times at one target.
@@ -834,6 +834,13 @@
973 = Contradictory null annotations: function type was inferred as ''{2} ({4})'', but only one of ''@{0}'' and ''@{1}'' can be effective at any location
974 = The return type is incompatible with the free type variable ''{1}'' returned from {0} (mismatching null constraints)
975 = Cannot redefine null constraints of type variable ''{0}'' declared in ''{1}''
+976 = Potential null pointer access: this expression has type ''{0}'', a free type variable that may represent a ''@{1}'' type
+977 = The field {0} may not have been initialized, whereas its type ''{1}'' is a free type variable that may represent a ''@{2}'' type
+978 = The field {0} may not have been initialized, whereas its type ''{1}'' is a free type variable that may represent a ''@{2}'' type. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem
+979 = Null type safety: required ''@{0}'' but this expression has type ''{1}'', a free type variable that may represent a ''@{2}'' type
+980 = Unsafe interpretation of method return type as ''@{0}'' based on the receiver type ''{1}''. Type ''{2}'' doesn't seem to be designed with null type annotations in mind
+981 = Unsafe interpretation of method return type as ''@{0}'' based on substitution ''{1}={2}''. Declaring type ''{3}'' doesn't seem to be designed with null type annotations in mind
+
# Java 8
1001 = Syntax error, modifiers and annotations are not allowed for the lambda parameter {0} as its type is elided
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
index 5eded19..317d830 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -100,6 +100,7 @@
public static String abort_invalidOpcode;
public static String abort_missingCode;
public static String abort_againstSourceModel;
+ public static String abort_externaAnnotationFile;
public static String accept_cannot;
public static String parser_incorrectPath;
public static String parser_moveFiles;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
index 5475581..0e8f6db 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2015 BEA Systems, Inc.
+ * Copyright (c) 2005, 2011 BEA Systems, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -28,7 +28,6 @@
*/
class AnnotationBinding implements IAnnotationBinding {
static final AnnotationBinding[] NoAnnotations = new AnnotationBinding[0];
- static final AnnotationBinding[][] NoAnnotationsOnDimensions = new AnnotationBinding[0][];
private org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding binding;
private BindingResolver bindingResolver;
private String key;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
index f1caf75..ea9f555 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -299,6 +299,9 @@
* Returns the binding representing the element type of this array type,
* or <code>null</code> if this is not an array type binding. The element
* type of an array type is never itself an array type.
+ *
+ * To get the type annotations on dimensions, clients should repeatedly
+ * call getComponentType() and get the type annotations from there.
*
* @return the element type binding, or <code>null</code> if this is
* not an array type
@@ -563,6 +566,9 @@
* <li>java.lang.String</li>
* </ul>
* </p>
+ * To get the type annotations on dimensions, clients should repeatedly call
+ * {@link #getComponentType()} and get the type annotations from there.
+
* @return type annotations specified on this type reference, or an empty array if
* no type use annotations are found.
* @see #getTypeDeclaration()
@@ -572,23 +578,6 @@
public IAnnotationBinding[] getTypeAnnotations();
/**
- * Returns the type use annotations on dimensions, or the empty array if there
- * are no annotations on dimensions.
- *
- * <p>
- * Since JLS8, (Section 9.7.4) type annotations can appear at array dimensions. These annotations
- * are returned in a 2-d array with each row containing annotations for that dimension. If only some
- * of the dimensions have type annotations, the rows corresponding to the dimensions without
- * annotations will have an empty single dimensional array.
- * </p>
- *
- * @return type annotations specified on the dimensions of this type reference, or an empty array if
- * either there is no dimension or no type use annotation is found on the dimensions.
- * @since 3.12
- */
- public IAnnotationBinding[][] getTypeAnnotationsOnDimensions();
-
- /**
* Returns the type arguments of this generic type instance, or the
* empty list for other type bindings.
* <p>
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
index ec5abf0..b4a9fdf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
@@ -785,10 +785,6 @@
return AnnotationBinding.NoAnnotations;
}
- @Override
- public IAnnotationBinding[][] getTypeAnnotationsOnDimensions() {
- return AnnotationBinding.NoAnnotationsOnDimensions;
- }
//{ObjectTeams: new lookup-functions
public org.eclipse.jdt.internal.compiler.lookup.TypeBinding getResolvedBinding() {
return this.binding;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index 7a26dbd..5d02bab 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -83,7 +83,6 @@
private IVariableBinding[] fields;
private IAnnotationBinding[] annotations;
private IAnnotationBinding[] typeAnnotations;
- private IAnnotationBinding[][] typeAnnotationsOnDimensions;
private IMethodBinding[] methods;
private ITypeBinding[] members;
private ITypeBinding[] interfaces;
@@ -176,34 +175,6 @@
return AnnotationBinding.NoAnnotations;
}
- private IAnnotationBinding[][] resolveAnnotationBindingsOnDimensions(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) {
- int length = internalAnnotations == null ? 0 : internalAnnotations.length;
- if (length != 0) {
- IAnnotationBinding[][] dimAnnotations = new IAnnotationBinding[length][];
- int row = 0;
- List <IAnnotationBinding> tmpList = new ArrayList<>();
- for (int i = 0; i < length; i++) {
- org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
- if (internalAnnotation == null) {
- if (tmpList.size() > 0) {
- dimAnnotations[row] = tmpList.toArray(new AnnotationBinding[0]);
- tmpList.clear();
- } else {
- dimAnnotations[row] = AnnotationBinding.NoAnnotations;
- }
- ++row;
- }
- IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
- if (annotationInstance == null) {
- continue;
- }
- tmpList.add(annotationInstance);
- }
- System.arraycopy(dimAnnotations, 0, (dimAnnotations = new IAnnotationBinding[row][]), 0, row);
- return dimAnnotations;
- }
- return AnnotationBinding.NoAnnotationsOnDimensions;
- }
/*
* @see ITypeBinding#getBinaryName()
* @since 3.0
@@ -1713,17 +1684,6 @@
return this.typeAnnotations;
}
- /*
- * (non-Javadoc)
- * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeAnnotationsOnDimensions()
- */
- public IAnnotationBinding[][] getTypeAnnotationsOnDimensions() {
- if (this.typeAnnotationsOnDimensions == null) {
- this.typeAnnotationsOnDimensions = resolveAnnotationBindingsOnDimensions(this.binding.getTypeAnnotations());
- }
- return this.typeAnnotationsOnDimensions;
- }
-
static class LocalTypeBinding extends TypeBinding {
private IBinding declaringMember;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
index 4687630..950f481 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,6 +27,7 @@
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.core.util.Util;
/**
@@ -197,4 +198,8 @@
public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member, LookupEnvironment environment) {
return walker;
}
+@Override
+public ExternalAnnotationStatus getExternalAnnotationStatus() {
+ return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
+}
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index 6a2d05a..2e24b5a 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -73,7 +73,7 @@
* FORMATTER / Option to align groups of members independently if they are separated by a certain number of blank lines
* - option id: "org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines"
* - possible values: "<n>", where n is a positive integer
- * - default: "99"
+ * - default: {@code Integer.MAX_VALUE}
* </pre>
* @since 3.12
*/
@@ -213,6 +213,18 @@
public static final String FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.alignment_for_expressions_in_array_initializer"; //$NON-NLS-1$
/**
* <pre>
+ * FORMATTER / Option for alignment of initialization, termination, and increment expressions in 'for'
+ * loop header
+ * - option id: "org.eclipse.jdt.core.formatter.alignment_for_for_loop_header"
+ * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+ * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+ * </pre>
+ * @see #createAlignmentValue(boolean, int, int)
+ * @since 3.12
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER = JavaCore.PLUGIN_ID + ".formatter.alignment_for_expressions_in_for_loop_header"; //$NON-NLS-1$
+ /**
+ * <pre>
* FORMATTER / Option for alignment of method declaration
* - option id: "org.eclipse.jdt.core.formatter.alignment_for_method_declaration"
* - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -235,6 +247,17 @@
public static final String FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_multiple_fields";//$NON-NLS-1$
/**
* <pre>
+ * FORMATTER / Option for alignment of type arguments in parameterized type references
+ * - option id: "org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references"
+ * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+ * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+ * </pre>
+ * @see #createAlignmentValue(boolean, int, int)
+ * @since 3.12
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES = JavaCore.PLUGIN_ID + ".formatter.alignment_for_parameterized_type_references"; //$NON-NLS-1$
+ /**
+ * <pre>
* FORMATTER / Option for alignment of parameters in constructor declaration
* - option id: "org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration"
* - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -334,6 +357,28 @@
public static final String FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_throws_clause_in_method_declaration"; //$NON-NLS-1$
/**
* <pre>
+ * FORMATTER / Option for alignment of type arguments in method invocations and references
+ * - option id: "org.eclipse.jdt.core.formatter.alignment_for_type_arguments"
+ * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+ * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+ * </pre>
+ * @see #createAlignmentValue(boolean, int, int)
+ * @since 3.12
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_type_arguments"; //$NON-NLS-1$
+ /**
+ * <pre>
+ * FORMATTER / Option for alignment of type parameters in method and type declarations
+ * - option id: "org.eclipse.jdt.core.formatter.alignment_for_type_parameters"
+ * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+ * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+ * </pre>
+ * @see #createAlignmentValue(boolean, int, int)
+ * @since 3.12
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_type_parameters"; //$NON-NLS-1$
+ /**
+ * <pre>
* FORMATTER / Option for alignment of exceptions declared in a Union Type in the argument of a multicatch statement
* - option id: "org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch"
* - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -639,6 +684,161 @@
/**
* <pre>
+ * FORMATTER / Option to position parentheses in method declarations
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_method_declaration"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_NOT_EMPY
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_method_delcaration"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in method invocations
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_NOT_EMPY
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_method_invocation"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in enum constant declarations
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_NOT_EMPY
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_enum_constant_declaration"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in 'if' and 'while' statements
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_if_while_statement"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in 'for' statements
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statement"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_for_statment"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in 'switch' statements
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_switch_statement"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in try clauses
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_try_clause"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in catch clauses
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_catch_clause"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in annotations
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_NOT_EMPY
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_annotation"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Option to position parentheses in lambda declarations
+ * - option id: "org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration"
+ * - possible values: { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+ * - default: END_OF_LINE
+ * </pre>
+ * @see #COMMON_LINES
+ * @see #SEPARATE_LINES_IF_NOT_EMPY
+ * @see #SEPARATE_LINES_IF_WRAPPED
+ * @see #SEPARATE_LINES
+ * @see #PRESERVE_POSITIONS
+ * @since 3.12
+ */
+ public static final String FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_lambda_declaration"; //$NON-NLS-1$
+
+ /**
+ * <pre>
* FORMATTER / Option to control whether blank lines are cleared inside comments
* - option id: "org.eclipse.jdt.core.formatter.comment.clear_blank_lines"
* - possible values: { TRUE, FALSE }
@@ -1364,6 +1564,19 @@
/**
* <pre>
+ * FORMATTER / Option to insert a new line after an annotation on an enum constant declaration
+ * - option id: "org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ * </pre>
+ * @see JavaCore#INSERT
+ * @see JavaCore#DO_NOT_INSERT
+ * @since 3.12
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_annotation_on_enum_constant";//$NON-NLS-1$
+
+ /**
+ * <pre>
* FORMATTER / Option to insert a new line after an annotation on a field declaration
* - option id: "org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field"
* - possible values: { INSERT, DO_NOT_INSERT }
@@ -3816,6 +4029,32 @@
public static final String FORMATTER_WRAP_BEFORE_OR_OPERATOR_MULTICATCH = JavaCore.PLUGIN_ID + ".formatter.wrap_before_or_operator_multicatch"; //$NON-NLS-1$
/**
* <pre>
+ * FORMATTER / Option to wrap before the '?' and ':' operators in conditional expressions
+ * - option id: "org.eclipse.jdt.core.formatter.wrap_before_conditional_operator"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ * </pre>
+ * This option is used only if the option {@link #FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION} is set.
+ * @see #TRUE
+ * @see #FALSE
+ * @since 3.12
+ */
+ public static final String FORMATTER_WRAP_BEFORE_CONDITIONAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_conditional_operator"; //$NON-NLS-1$
+ /**
+ * <pre>
+ * FORMATTER / Option to wrap before the assignment operator
+ * - option id: "org.eclipse.jdt.core.formatter.wrap_before_assignment_operator"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ * </pre>
+ * This option is used only if the option {@link #FORMATTER_ALIGNMENT_FOR_ASSIGNMENT} is set.
+ * @see #TRUE
+ * @see #FALSE
+ * @since 3.12
+ */
+ public static final String FORMATTER_WRAP_BEFORE_ASSIGNMENT_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_assignment_operator"; //$NON-NLS-1$
+ /**
+ * <pre>
* FORMATTER / Option to wrap outer expressions in nested expressions
* - option id: "org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested"
* - possible values: { TRUE, FALSE }
@@ -3940,6 +4179,98 @@
* @since 3.0
*/
public static final String NEXT_LINE_SHIFTED = "next_line_shifted"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Value to keep always parentheses on common lines with their contents..
+ * </pre>
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+ * @since 3.12
+ */
+ public static final String COMMON_LINES = "common_lines"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Value to keep always parentheses on common lines with their contents..
+ * </pre>
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+ * @since 3.12
+ */
+ public static final String SEPARATE_LINES_IF_NOT_EMPY = "separate_lines_if_not_empty"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Value to keep always parentheses on common lines with their contents..
+ * </pre>
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+ * @since 3.12
+ */
+ public static final String SEPARATE_LINES_IF_WRAPPED = "separate_lines_if_wrapped"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Value to keep always parentheses on common lines with their contents..
+ * </pre>
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+ * @since 3.12
+ */
+ public static final String SEPARATE_LINES = "separate_lines"; //$NON-NLS-1$
+
+ /**
+ * <pre>
+ * FORMATTER / Value to set a closing parenthesis position to same line or next
+ * line depending on what was in the original source.
+ * </pre>
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+ * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+ * @since 3.12
+ */
+ public static final String PRESERVE_POSITIONS = "preserve_positions"; //$NON-NLS-1$
+
/**
* <pre>
* FORMATTER / Value to set an option to true.
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
index 24ba74e..e6cf535 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
@@ -196,14 +196,15 @@
this.tm.remove(commentIndex);
List<Token> lastStructure = this.lastLineComment.getInternalStructure();
lastStructure.addAll(structure);
- structure = lastStructure;
- commentToken = merged;
+ merged.setInternalStructure(lastStructure);
+ this.lastLineComment = merged;
} else {
+ commentToken.setInternalStructure(structure);
+ handleCompilerTags(commentToken, commentIndex);
+ preserveWhitespace(commentToken, commentIndex);
+ this.lastLineComment = commentToken;
this.lastLineCommentPosition = positionInLine;
}
- commentToken.setInternalStructure(structure);
- preserveWhitespace(commentToken, commentIndex);
- this.lastLineComment = commentToken;
}
private void preserveWhitespace(Token commentToken, int commentIndex) {
@@ -286,6 +287,28 @@
}
}
+ private void handleCompilerTags(Token commentToken, int commentIndex) {
+ final String commentText = this.tm.toString(commentToken);
+ final List<Token> structure = commentToken.getInternalStructure();
+ if (commentText.startsWith("//$FALL-THROUGH$") //$NON-NLS-1$
+ || commentText.startsWith("//$IDENTITY-COMPARISON$")) { //$NON-NLS-1$
+ structure.get(1).clearSpaceBefore();
+ }
+ if (commentText.contains("//$IDENTITY-COMPARISON$")) { //$NON-NLS-1$
+ // make sure the whole line is not broken
+ Token token = commentToken;
+ for (int i = commentIndex; i > 0; i--) {
+ Token left = this.tm.get(i - 1);
+ if (this.tm.countLineBreaksBetween(left, token) > 0)
+ break;
+ token.clearLineBreaksBefore();
+ left.clearLineBreaksAfter();
+ token.setWrapPolicy(WrapPolicy.DISABLE_WRAP);
+ token = left;
+ }
+ }
+ }
+
private List<Token> findStringLiteralsInLine(int lastTokenIndex) {
List<Token> stringLiterals = new ArrayList<>();
Token previous = this.tm.get(lastTokenIndex);
@@ -336,11 +359,6 @@
sourcePosition++;
}
}
-
- if (this.tm.getSource().startsWith("$FALL-THROUGH$", result.get(0).originalEnd + 1)) { //$NON-NLS-1$
- result.get(1).clearSpaceBefore();
- }
-
return result;
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index 6b19e91..a789695 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -130,9 +130,11 @@
public int alignment_for_conditional_expression;
public int alignment_for_enum_constants;
public int alignment_for_expressions_in_array_initializer;
+ public int alignment_for_expressions_in_for_loop_header;
public int alignment_for_method_declaration;
// TODO following option cannot be set in preferences dialog (but it's used by old.CodeFormatter)
public int alignment_for_multiple_fields;
+ public int alignment_for_parameterized_type_references;
public int alignment_for_parameters_in_constructor_declaration;
public int alignment_for_parameters_in_method_declaration;
public int alignment_for_selector_in_method_invocation;
@@ -141,6 +143,8 @@
public int alignment_for_superinterfaces_in_type_declaration;
public int alignment_for_throws_clause_in_constructor_declaration;
public int alignment_for_throws_clause_in_method_declaration;
+ public int alignment_for_type_arguments;
+ public int alignment_for_type_parameters;
public int alignment_for_resources_in_try;
public int alignment_for_union_type_in_multicatch;
@@ -160,6 +164,17 @@
public String brace_position_for_type_declaration;
public String brace_position_for_switch;
+ public String parenthesis_positions_in_method_declaration;
+ public String parenthesis_positions_in_method_invocation;
+ public String parenthesis_positions_in_enum_constant_declaration;
+ public String parenthesis_positions_in_if_while_statement;
+ public String parenthesis_positions_in_for_statement;
+ public String parenthesis_positions_in_switch_statement;
+ public String parenthesis_positions_in_try_clause;
+ public String parenthesis_positions_in_catch_clause;
+ public String parenthesis_positions_in_annotation;
+ public String parenthesis_positions_in_lambda_declaration;
+
public int continuation_indentation;
public int continuation_indentation_for_array_initializer;
@@ -214,6 +229,7 @@
public boolean insert_new_line_after_annotation_on_type;
public boolean insert_new_line_after_type_annotation;
+ public boolean insert_new_line_after_annotation_on_enum_constant;
public boolean insert_new_line_after_annotation_on_field;
public boolean insert_new_line_after_annotation_on_method;
public boolean insert_new_line_after_annotation_on_package;
@@ -414,6 +430,8 @@
public boolean use_tabs_only_for_leading_indentations;
public boolean wrap_before_binary_operator;
public boolean wrap_before_or_operator_multicatch;
+ public boolean wrap_before_conditional_operator;
+ public boolean wrap_before_assignment_operator;
public boolean wrap_outer_expressions_when_nested;
public int initial_indentation_level;
@@ -447,8 +465,10 @@
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION, getAlignment(this.alignment_for_conditional_expression));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS, getAlignment(this.alignment_for_enum_constants));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER, getAlignment(this.alignment_for_expressions_in_array_initializer));
+ options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER, getAlignment(this.alignment_for_expressions_in_for_loop_header));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION, getAlignment(this.alignment_for_method_declaration));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS, getAlignment(this.alignment_for_multiple_fields));
+ options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES, getAlignment(this.alignment_for_parameterized_type_references));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_parameters_in_constructor_declaration));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_parameters_in_method_declaration));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_RESOURCES_IN_TRY, getAlignment(this.alignment_for_resources_in_try));
@@ -458,6 +478,8 @@
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_TYPE_DECLARATION, getAlignment(this.alignment_for_superinterfaces_in_type_declaration));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_constructor_declaration));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_method_declaration));
+ options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_TYPE_ARGUMENTS, getAlignment(this.alignment_for_type_arguments));
+ options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_TYPE_PARAMETERS, getAlignment(this.alignment_for_type_parameters));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_UNION_TYPE_IN_MULTICATCH, getAlignment(this.alignment_for_union_type_in_multicatch));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, this.align_type_members_on_columns ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_FIELDS_GROUPING_BLANK_LINES, Integer.toString(this.align_fields_grouping_blank_lines));
@@ -473,6 +495,16 @@
options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION, this.brace_position_for_type_declaration);