Merge branch 'master' at M5 into 'OT_BETA_JAVA8'
diff --git a/features/org.eclipse.objectteams.otdt.core.patch/feature.xml b/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
index bf18403..839b7cf 100644
--- a/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
+++ b/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
@@ -59,7 +59,7 @@
</url>
<requires>
- <import feature="org.eclipse.jdt" version="3.9.0.v20121210-132935-8-8tFyYFNOfwKDedebWWejRS5834" patch="true"/>
+ <import feature="org.eclipse.jdt" version="3.9.0.v20121210-132935-8-8uFyYFNOfwKNWRqxYHNBDV3834" patch="true"/>
</requires>
<plugin
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 a08cfcf..4e51e16 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
-Bundle-Version: 3.8.1
+Bundle-Version: 3.8.2
Bundle-ClassPath: jdtcoretestscompiler.jar
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index fbdfee3..2d3a6d0 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -20,6 +20,6 @@
</parent>
<groupId>eclipse.jdt.core</groupId>
<artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
- <version>3.8.1-SNAPSHOT</version>
+ <version>3.8.2-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
index 5836c0d..acf4695 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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 @@
* bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
* bug 384663 - Package Based Annotation Compilation Error in JDT 3.8/4.2 (works in 3.7.2)
* bug 386356 - Type mismatch error with annotations and generics
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -10462,7 +10463,7 @@
"}\n" +
"class E3 {\n" +
" @p.NonNull\n" +
- " private int E3;\n" +
+ " private Object E3 = new Object();\n" +
"}\n" +
"class E4 {\n" +
" @Deprecated\n" +
@@ -10502,8 +10503,8 @@
"The value of the field E2.E2 is not used\n" +
"----------\n" +
"4. ERROR in Example.java (at line 15)\n" +
- " private int E3;\n" +
- " ^^\n" +
+ " private Object E3 = new Object();\n" +
+ " ^^\n" +
"The value of the field E3.E3 is not used\n" +
"----------\n",
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
@@ -10759,4 +10760,80 @@
});
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=398657
+public void test398657() throws Exception {
+ if (this.complianceLevel != ClassFileConstants.JDK1_5) {
+ return;
+ }
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+ this.runConformTest(
+ new String[] {
+ "p/Annot.java",
+ "package p;\n" +
+ "public @interface Annot {\n" +
+ " static public enum E { A }\n" +
+ " E getEnum();\n" +
+ "}",
+ "X.java",
+ "import static p.Annot.E.*;\n" +
+ "import p.Annot;" +
+ "@Annot(getEnum=A)\n" +
+ "public class X {}"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null,
+ true);
+
+ String expectedOutput =
+ " Inner classes:\n" +
+ " [inner class info: #22 p/Annot$E, outer class info: #24 p/Annot\n" +
+ " inner name: #26 E, accessflags: 16409 public static final]\n";
+
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator +"X.class", "X", expectedOutput, ClassFileBytesDisassembler.DETAILED);
+}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=398657
+public void test398657_2() throws Exception {
+ if (this.complianceLevel != ClassFileConstants.JDK1_5) {
+ return;
+ }
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+ this.runConformTest(
+ new String[] {
+ "p/Y.java",
+ "package p;\n" +
+ "public class Y {\n" +
+ " static public @interface Annot {\n" +
+ " int id();\n" +
+ " }\n" +
+ "}",
+ "X.java",
+ "import p.Y.Annot;\n" +
+ "@Annot(id=4)\n" +
+ "public class X {}"
+ },
+ "",
+ null,
+ true,
+ null,
+ options,
+ null,
+ true);
+
+ String expectedOutput =
+ " Inner classes:\n" +
+ " [inner class info: #21 p/Y$Annot, outer class info: #23 p/Y\n" +
+ " inner name: #25 Annot, accessflags: 9737 public abstract static]\n";
+
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator +"X.class", "X", expectedOutput, ClassFileBytesDisassembler.DETAILED);
+}
}
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 898776f..c7fa688 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
@@ -27,6 +27,7 @@
* bug 375366 - ECJ ignores unusedParameterIncludeDocCommentReference unless enableJavadoc option is set
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -2000,6 +2001,7 @@
" <option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" +
" <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.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" +
@@ -2021,6 +2023,7 @@
" <option key=\"org.eclipse.jdt.core.compiler.problem.staticAccessReceiver\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.suppressWarnings\" value=\"enabled\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation\" value=\"ignore\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.tasks\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" +
@@ -12704,13 +12707,18 @@
" ^^^^^^\n" +
"Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
"----------\n" +
- "2 problems (2 warnings)",
+ "3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "3 problems (3 warnings)",
true);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
// -err option - regression tests to check option nullAnnot
-// Null warnings because of annotations, null spec violations configured as errors
+// Null warnings because of annotations, null spec violations plus one specific problem configured as errors
public void test314_warn_options() {
this.runNegativeTest(
new String[] {
@@ -12735,7 +12743,7 @@
"\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ " -sourcepath \"" + OUTPUT_DIR + "\""
+ " -1.5"
- + " -err:+nullAnnot -warn:-null -proc:none -d \"" + OUTPUT_DIR + "\"",
+ + " -err:+nullAnnot -warn:-null -err:+nonnullNotRepeated -proc:none -d \"" + OUTPUT_DIR + "\"",
"",
"----------\n" +
"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
@@ -12748,7 +12756,12 @@
" ^^^^^^\n" +
"Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
"----------\n" +
- "2 problems (2 errors)",
+ "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "3 problems (3 errors)",
true);
}
@@ -13734,6 +13747,60 @@
" ^^^^^^\n" +
"Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
"----------\n" +
+ "3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "3 problems (2 errors, 1 warning)",
+ false/*don't flush*/);
+}
+
+// Bug 375366 - ECJ ignores unusedParameterIncludeDocCommentReference unless enableJavadoc option is set
+// property file enables null annotation support, one optional warning disabled
+public void testBug375366d() throws IOException {
+ createOutputTestDirectory("regression/.settings");
+ Util.createFile(OUTPUT_DIR+"/.settings/org.eclipse.jdt.core.prefs",
+ "eclipse.preferences.version=1\n" +
+ "org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled\n" +
+ "org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=ignore\n");
+ this.runNegativeTest(
+ new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+ " return this;\n" +
+ " }\n" +
+ "}\n" +
+ "class Y extends X {\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ "}\n",
+ "org/eclipse/jdt/annotation/NonNull.java",
+ NONNULL_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/Nullable.java",
+ NULLABLE_ANNOTATION_CONTENT,
+ "org/eclipse/jdt/annotation/NonNullByDefault.java",
+ NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+ },
+ "\"" + OUTPUT_DIR + File.separator + "p" + File.separator + "X.java\""
+ + " -sourcepath \"" + OUTPUT_DIR + "\""
+ + " -1.5"
+ + " -properties " + OUTPUT_DIR + File.separator +".settings" + File.separator + "org.eclipse.jdt.core.prefs "
+ + " -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The return type is incompatible with the @NonNull return from X.foo(Object, Object)\n" +
+ "----------\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" +
+ " @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+ " ^^^^^^\n" +
+ "Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" +
+ "----------\n" +
"2 problems (2 errors)",
false/*don't flush*/);
}
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 acf06fa..458e1a6 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
@@ -23,6 +23,9 @@
* bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
* bug 382347 - [1.8][compiler] Compiler accepts incorrect default method inheritance
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
@@ -772,6 +775,9 @@
expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("NonNullExpressionComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ 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("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
@@ -784,6 +790,7 @@
expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("NullableFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -840,6 +847,8 @@
expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullExpression", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullSpecdField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -933,6 +942,8 @@
expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
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));
+ expectedProblemAttributes.put("UninitializedNonNullFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("UnmatchedBracket", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("UnnecessaryArgumentCast", DEPRECATED);
expectedProblemAttributes.put("UnnecessaryCast", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
@@ -942,6 +953,7 @@
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("UnreachableCatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("UnresolvedVariable", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeRawConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
@@ -1590,7 +1602,10 @@
expectedProblemAttributes.put("NonGenericConstructor", SKIP);
expectedProblemAttributes.put("NonGenericMethod", SKIP);
expectedProblemAttributes.put("NonGenericType", SKIP);
+ expectedProblemAttributes.put("NonNullExpressionComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ 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("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
expectedProblemAttributes.put("NonStaticContextForEnumMemberType", SKIP);
@@ -1602,6 +1617,7 @@
expectedProblemAttributes.put("NotVisibleField", SKIP);
expectedProblemAttributes.put("NotVisibleMethod", SKIP);
expectedProblemAttributes.put("NotVisibleType", SKIP);
+ expectedProblemAttributes.put("NullableFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
expectedProblemAttributes.put("NullityMismatchingTypeAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("NullityMismatchingTypeAnnotationUnchecked", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION));
expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
@@ -1620,7 +1636,7 @@
expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
- expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
+ expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED));
expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("ParameterMismatch", SKIP);
expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", SKIP);
@@ -1658,6 +1674,8 @@
expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullExpression", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullSpecdField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
@@ -1751,6 +1769,8 @@
expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", SKIP);
expectedProblemAttributes.put("UninitializedLocalVariable", SKIP);
expectedProblemAttributes.put("UninitializedLocalVariableHintMissingDefault", SKIP);
+ expectedProblemAttributes.put("UninitializedNonNullField", SKIP);
+ expectedProblemAttributes.put("UninitializedNonNullFieldHintMissingDefault", SKIP);
expectedProblemAttributes.put("UnmatchedBracket", SKIP);
expectedProblemAttributes.put("UnnecessaryArgumentCast", SKIP);
expectedProblemAttributes.put("UnnecessaryCast", new ProblemAttributes(JavaCore.COMPILER_PB_UNNECESSARY_TYPE_CHECK));
@@ -1760,6 +1780,7 @@
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(JavaCore.COMPILER_PB_UNQUALIFIED_FIELD_ACCESS));
expectedProblemAttributes.put("UnreachableCatch", SKIP);
expectedProblemAttributes.put("UnresolvedVariable", SKIP);
+ expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeRawConstructorInvocation", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ForeachStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ForeachStatementTest.java
index e0188b3..3f4ff0d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ForeachStatementTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ForeachStatementTest.java
@@ -12,6 +12,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
* Bug 388800 - [1.8] adjust tests to 1.8 JRE
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -44,7 +45,7 @@
// 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[] { "test000" };
+// TESTS_NAMES = new String[] { "test055" };
// TESTS_NUMBERS = new int[] { 50, 51, 52, 53 };
// TESTS_RANGE = new int[] { 34, 38 };
}
@@ -2829,7 +2830,7 @@
"2. WARNING in X.java (at line 10)\n" +
" for (Set<String> BUG : new Set[] { x, y }) {\n" +
" ^^^^^^^^^^^^^^^^^^\n" +
- "Type safety: The expression of type Set[] needs unchecked conversion to conform to Set<String>[]\n" +
+ "Type safety: Elements of type Set need unchecked conversion to conform to Set<String>\n" +
"----------\n" +
"3. WARNING in X.java (at line 14)\n" +
" Set [] set = new Set[] { x, y };\n" +
@@ -2839,7 +2840,7 @@
"4. WARNING in X.java (at line 15)\n" +
" for (Set<String> BUG : set) {\n" +
" ^^^\n" +
- "Type safety: The expression of type Set[] needs unchecked conversion to conform to Set<String>[]\n" +
+ "Type safety: Elements of type Set need unchecked conversion to conform to Set<String>\n" +
"----------\n" +
"5. ERROR in X.java (at line 20)\n" +
" Zork z;\n" +
@@ -2847,6 +2848,77 @@
"Zork cannot be resolved to a type\n" +
"----------\n");
}
+// https://bugs.eclipse.org/393719
+// like test054 but suppressing the warnings.
+public void test055() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.HashSet;\n" +
+ "import java.util.Set;\n" +
+ "public class X {\n" +
+ " void foo() {\n" +
+ " HashSet<String> x = new HashSet<String>();\n" +
+ " x.add(\"a\");\n" +
+ " HashSet<Integer> y = new HashSet<Integer>();\n" +
+ " y.add(1);\n" +
+ " @SuppressWarnings(\"unchecked\") Set<String> [] OK= new Set[] { x, y };\n" +
+ " for (@SuppressWarnings(\"unchecked\") Set<String> BUG : new Set[] { x, y }) {\n" +
+ " for (String str : BUG)\n" +
+ " System.out.println(str);\n" +
+ " }\n" +
+ " @SuppressWarnings({\"rawtypes\", \"unchecked\"}) Set [] set = new Set[] { x, y };\n" +
+ " for (@SuppressWarnings(\"unchecked\") Set<String> BUG : set) {\n" +
+ " for (String str : BUG)\n" +
+ " System.out.println(str);\n" +
+ " }\n" +
+ " }\n" +
+ " Zork z;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 20)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
+// https://bugs.eclipse.org/393719
+// "unchecked" warning against the collection (raw Iterable)
+public void test056() throws Exception {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "public class X {\n" +
+ " void testRawType(@SuppressWarnings(\"rawtypes\") List<List> lists) {\n" +
+ " List<String> stringList = lists.get(0); // (1)\n" +
+ " for (List<String> strings : lists) // (2)\n" +
+ " stringList = strings;\n" +
+ " for (@SuppressWarnings(\"unchecked\") List<String> strings : lists) // no warning\n" +
+ " stringList = strings;\n" +
+ " System.out.println(stringList.get(0));\n" +
+ " }\n" +
+ " Zork z;\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " List<String> stringList = lists.get(0); // (1)\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Type safety: The expression of type List needs unchecked conversion to conform to List<String>\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 5)\n" +
+ " for (List<String> strings : lists) // (2)\n" +
+ " ^^^^^\n" +
+ "Type safety: Elements of type List need unchecked conversion to conform to List<String>\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 11)\n" +
+ " Zork z;\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
public static Class testClass() {
return ForeachStatementTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index ffc6b67..8721046 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -28,7 +30,7 @@
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which does not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "test347426" };
+// TESTS_NAMES = new String[] { "testBug395002_combined" };
// TESTS_NAMES = new String[] { "test1464" };
// TESTS_NUMBERS = new int[] { 1465 };
// TESTS_RANGE = new int[] { 1097, -1 };
@@ -2649,4 +2651,170 @@
"----------\n",
null, true, customOptions);
}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// version with intermediate assignment, always worked
+public void testBug395002_1() {
+ runConformTest(new String[] {
+ "Client.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "public class Client {\n" +
+ " <A extends SelfBound<?,A>> void foo3(A arg3) {\n" +
+ " SelfBound<?, A> var3 = arg3;\n" +
+ " SelfBound<? extends SelfBound<?, A>, ?> var4 = var3;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// version with direct assignment to local
+public void testBug395002_2() {
+ runConformTest(new String[] {
+ "Client.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "public class Client {\n" +
+ " <A extends SelfBound<?,A>> void foo2(A arg2) {\n" +
+ " SelfBound<? extends SelfBound<?, A>, ?> var2 = arg2;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// version with direct assignment to field
+public void testBug395002_3() {
+ runConformTest(new String[] {
+ "Client.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "public class Client<A extends SelfBound<?,A>> {\n" +
+ " SelfBound<? extends SelfBound<?, A>, ?> field2;\n" +
+ " void foo2(A arg2) {\n" +
+ " field2 = arg2;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// version with argument passing
+public void testBug395002_4() {
+ runConformTest(new String[] {
+ "Client.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "public class Client<A extends SelfBound<?,A>> {\n" +
+ " void bar(SelfBound<? extends SelfBound<?, A>, ?> argBar) {};\n" +
+ " void foo2(A arg2) {\n" +
+ " bar(arg2);\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// original problem with invocation of generic type
+public void testBug395002_full() {
+ runConformTest(new String[] {
+ "Bug.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "class Test<X extends SelfBound<? extends Y, ?>, Y> {\n" +
+ "}\n" +
+ "public class Bug<A extends SelfBound<?, A>> {\n" +
+ " public Bug() {\n" +
+ " new Test<A, SelfBound<?, A>>();\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+// combined version with direct assignment to local + original problem w/ invocation of generic type
+public void testBug395002_combined() {
+ runConformTest(new String[] {
+ "Client.java",
+ "interface SelfBound<S extends SelfBound<S, T>, T> {\n" +
+ "}\n" +
+ "class Test<X extends SelfBound<? extends Y, ?>, Y> {\n" +
+ "}\n" +
+ "public class Client {\n" +
+ " <A extends SelfBound<?,A>> void foo2(A arg2) {\n" +
+ " Object o = new Test<A, SelfBound<?, A>>();\n" +
+ " SelfBound<? extends SelfBound<?, A>, ?> var2 = arg2;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
+public void test397888a() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedTypeParameter, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedParameter, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
+ CompilerOptions.ENABLED);
+
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "/***\n" +
+ " * @param <T>\n" +
+ " */\n" +
+ "public class X <T> {\n"+
+ "/***\n" +
+ " * @param <S>\n" +
+ " */\n" +
+ " public <S> void ph(int i) {\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " public <S> void ph(int i) {\n" +
+ " ^\n" +
+ "The value of the parameter i is not used\n" +
+ "----------\n",
+ null, true, customOptions);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
+public void test397888b() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedTypeParameter, CompilerOptions.ERROR);
+ customOptions.put(CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
+ CompilerOptions.DISABLED);
+
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "/***\n" +
+ " * @param <T>\n" +
+ " */\n" +
+ "public class X <T> {\n"+
+ "/***\n" +
+ " * @param <S>\n" +
+ " */\n" +
+ "public <S> void ph() {\n"+
+ "}\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " public class X <T> {\n" +
+ " ^\n" +
+ "Unused type parameter T\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " public <S> void ph() {\n" +
+ " ^\n" +
+ "Unused type parameter S\n" +
+ "----------\n",
+ null, true, customOptions);
+}
}
\ No newline at end of file
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 fc2e484..05b8a39 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
@@ -28,7 +28,7 @@
// 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[] { "testBug388281_09" };
+// TESTS_NAMES = new String[] { "test_nullable_field_10e" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -41,6 +41,101 @@
return NullAnnotationTest.class;
}
+
+protected void setUp() throws Exception {
+ super.setUp();
+ if (this.LIBS == null) {
+ String[] defaultLibs = getDefaultClassPaths();
+ int len = defaultLibs.length;
+ this.LIBS = new String[len+1];
+ System.arraycopy(defaultLibs, 0, this.LIBS, 0, len);
+ File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation"));
+ if (bundleFile.isDirectory())
+ this.LIBS[len] = bundleFile.getPath()+"/bin";
+ else
+ this.LIBS[len] = bundleFile.getPath();
+ }
+}
+// Conditionally augment problem detection settings
+static boolean setNullRelatedOptions = true;
+protected Map getCompilerOptions() {
+ Map defaultOptions = super.getCompilerOptions();
+ if (setNullRelatedOptions) {
+ defaultOptions.put(JavaCore.COMPILER_PB_NULL_REFERENCE, JavaCore.ERROR);
+ defaultOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
+ defaultOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.ERROR);
+ defaultOptions.put(JavaCore.COMPILER_PB_INCLUDE_ASSERTS_IN_NULL_ANALYSIS, JavaCore.ENABLED);
+
+ defaultOptions.put(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION_FOR_INTERFACE_METHOD_IMPLEMENTATION, JavaCore.DISABLED);
+
+ // enable null annotations:
+ defaultOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+ // leave other new options at these defaults:
+// defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, JavaCore.ERROR);
+// defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, JavaCore.ERROR);
+// defaultOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.WARNING);
+
+// defaultOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.eclipse.jdt.annotation.Nullable");
+// defaultOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.eclipse.jdt.annotation.NonNull");
+ }
+ return defaultOptions;
+}
+void runNegativeTestWithLibs(String[] testFiles, String expectedErrorLog) {
+ runNegativeTest(
+ testFiles,
+ expectedErrorLog,
+ this.LIBS,
+ false /*shouldFlush*/);
+}
+void runNegativeTestWithLibs(boolean shouldFlushOutputDirectory, String[] testFiles, Map customOptions, String expectedErrorLog) {
+ runNegativeTest(
+ shouldFlushOutputDirectory,
+ testFiles,
+ this.LIBS,
+ customOptions,
+ expectedErrorLog,
+ // runtime options
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+void runNegativeTestWithLibs(String[] testFiles, Map customOptions, String expectedErrorLog) {
+ runNegativeTestWithLibs(false /* flush output directory */, testFiles, customOptions, expectedErrorLog);
+}
+void runConformTestWithLibs(String[] testFiles, Map customOptions, String expectedCompilerLog) {
+ runConformTestWithLibs(false /* flush output directory */, testFiles, customOptions, expectedCompilerLog);
+}
+void runConformTestWithLibs(String[] testFiles, Map customOptions, String expectedCompilerLog, String expectedOutput) {
+ runConformTest(
+ false, /* flush output directory */
+ testFiles,
+ this.LIBS,
+ customOptions,
+ expectedCompilerLog,
+ expectedOutput,
+ "",/* expected error */
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+void runConformTestWithLibs(boolean shouldFlushOutputDirectory, String[] testFiles, Map customOptions, String expectedCompilerLog) {
+ runConformTest(
+ shouldFlushOutputDirectory,
+ testFiles,
+ this.LIBS,
+ customOptions,
+ expectedCompilerLog,
+ "",/* expected output */
+ "",/* expected error */
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+void runConformTest(String[] testFiles, Map customOptions, String expectedOutputString) {
+ runConformTest(
+ testFiles,
+ expectedOutputString,
+ null /*classLibraries*/,
+ true /*shouldFlushOutputDirectory*/,
+ null /*vmArguments*/,
+ customOptions,
+ null /*customRequestor*/);
+
+}
// a nullable argument is dereferenced without a check
public void test_nullable_paramter_001() {
runNegativeTest(
@@ -945,7 +1040,12 @@
},
options,
"----------\n" +
- "1. ERROR in XSub.java (at line 3)\n" +
+ "1. WARNING in XSub.java (at line 3)\n" +
+ " public void printObject(Object o) { super.printObject(o); }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n" +
+ "2. ERROR in XSub.java (at line 3)\n" +
" public void printObject(Object o) { super.printObject(o); }\n" +
" ^\n" +
"Null type safety: The expression of type Object needs unchecked conversion to conform to \'@NonNull Object\'\n" +
@@ -1081,6 +1181,7 @@
public void test_parameter_specification_inheritance_013() {
Map customOptions = getCompilerOptions();
customOptions.put(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION, JavaCore.ERROR);
+ customOptions.put(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED, JavaCore.IGNORE);
runNegativeTestWithLibs(
new String[] {
"p1/X.java",
@@ -1218,6 +1319,95 @@
null/*vmArgs*/);
}
+// a method relaxes the parameter null specification from @NonNull to un-annotated
+// see https://bugs.eclipse.org/381443
+// issue configured as error
+public void test_parameter_specification_inheritance_016() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED, JavaCore.ERROR);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " void foo(@NonNull String s) { System.out.println(s); }\n" +
+ "}\n",
+ "XSub.java",
+ "public class XSub extends X {\n" +
+ " @Override\n" +
+ " public void foo(String s) { if (s != null) super.foo(s); }\n" +
+ " void bar() { foo(null); }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in XSub.java (at line 3)\n" +
+ " public void foo(String s) { if (s != null) super.foo(s); }\n" +
+ " ^^^^^^\n" +
+ "Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" +
+ "----------\n");
+}
+
+// a class inherits two methods with different spec: one non-null param & one unannotated param
+// widening reported as warning by default
+// see https://bugs.eclipse.org/381443
+public void test_parameter_specification_inheritance_017() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void foo(String s) { System.out.println(s); }\n" +
+ "}\n",
+ "IX.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public interface IX {\n" +
+ " void foo(@NonNull String s);\n" +
+ "}\n",
+ "XSub.java",
+ "public class XSub extends X implements IX {\n" +
+ " void bar() { foo(null); }\n" +
+ " static void zork(XSub sub) {\n" +
+ " sub.foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in XSub.java (at line 1)\n" +
+ " public class XSub extends X implements IX {\n" +
+ " ^^^^\n" +
+ "Missing non-null annotation: inherited method from IX declares this parameter as @NonNull\n" +
+ "----------\n");
+}
+
+// a class inherits two methods with different spec: one non-null param & one unannotated param
+// opt to accept this widening
+// see https://bugs.eclipse.org/381443
+public void test_parameter_specification_inheritance_018() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED, JavaCore.IGNORE);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public void foo(String s) { System.out.println(s); }\n" +
+ "}\n",
+ "IX.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public interface IX {\n" +
+ " void foo(@NonNull String s);\n" +
+ "}\n",
+ "XSub.java",
+ "public class XSub extends X implements IX {\n" +
+ " void bar() { foo(null); }\n" +
+ " static void zork(XSub sub) {\n" +
+ " sub.foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "");
+}
+
// a nullable return value is dereferenced without a check
public void test_nullable_return_001() {
runNegativeTestWithLibs(
@@ -1422,7 +1612,12 @@
"1. ERROR in X.java (at line 7)\n" +
" if (getObject() == null)\n" +
" ^^^^^^^^^^^\n" +
- "Redundant null check: The method getObject() cannot return null\n" +
+ "Null comparison always yields false: The method getObject() cannot return null\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 8)\n" +
+ " throw new RuntimeException();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
"----------\n");
}
// a result from a nonnull method is directly checked for null (from local): redundant
@@ -2573,6 +2768,87 @@
"----------\n");
}
+// default nullness applied to fields, class-level:
+public void test_default_nullness_016() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class X {\n" +
+ " Object foo;\n" +
+ " void doFoo() {\n" +
+ " foo = null;\n" +
+ " }\n" +
+ " class Inner {\n" +
+ " Object iFoo;\n" +
+ " void diFoo(@Nullable Object arg) {\n" +
+ " iFoo = arg;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " Object foo;\n" +
+ " ^^^\n" +
+ "The @NonNull field foo may not have been initialized\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " foo = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 9)\n" +
+ " Object iFoo;\n" +
+ " ^^^^\n" +
+ "The @NonNull field iFoo may not have been initialized\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 11)\n" +
+ " iFoo = arg;\n" +
+ " ^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is specified as @Nullable\n" +
+ "----------\n");
+}
+
+// default nullness applied to fields, method level applied to local class + redundant annotation
+public void test_default_nullness_017() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_UNUSED_PRIVATE_MEMBER, JavaCore.IGNORE);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNullByDefault\n" +
+ " Object doFoo() {\n" +
+ " class Local {\n" +
+ " Object foo;\n" +
+ " @NonNull Object goo;\n" +
+ " };" +
+ " return new Local();\n" +
+ " }\n" +
+ "}\n",
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " Object foo;\n" +
+ " ^^^\n" +
+ "The @NonNull field foo may not have been initialized\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 7)\n" +
+ " @NonNull Object goo;\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The nullness annotation is redundant with a default that applies to this location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " @NonNull Object goo;\n" +
+ " ^^^\n" +
+ "The @NonNull field goo may not have been initialized\n" +
+ "----------\n");
+}
+
// redundant default annotations - class vs. inner class
public void test_redundant_annotation_01() {
Map customOptions = getCompilerOptions();
@@ -2892,6 +3168,27 @@
"----------\n");
}
+// contradictory null annotations on a field
+public void test_contradictory_annotations_02() {
+ Map customOptions = getCompilerOptions();
+ runNegativeTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " @NonNull @Nullable Object o;\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. ERROR in p2\\Y.java (at line 4)\n" +
+ " @NonNull @Nullable Object o;\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n");
+}
+
// a nonnull variable is dereferenced in a loop
public void test_nonnull_var_in_constrol_structure_1() {
Map customOptions = getCompilerOptions();
@@ -3399,6 +3696,1339 @@
"Dead code\n" +
"----------\n");
}
+// access to a non-null field
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_1() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o = new Object();\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// a non-null field is not properly initialized
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o;\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " @NonNull Object o;\n" +
+ " ^\n" +
+ "The @NonNull field o may not have been initialized\n" +
+ "----------\n");
+}
+
+// a non-null field is not properly initialized - explicit constructor
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2a() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o;\n" +
+ " X (boolean b) { // only potentially initialized\n" +
+ " if (b)\n" +
+ " o = this;\n" +
+ " }\n" +
+ " X (@NonNull Object other) {\n" + // no problem
+ " o = other;\n" +
+ " }\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " X (boolean b) { // only potentially initialized\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "The @NonNull field o may not have been initialized\n" +
+ "----------\n");
+}
+
+// a non-null field is not properly initialized - explicit constructor - incomplete switch
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2b() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "enum Color { BLACK, GREEN }\n" +
+ "public class X {\n" +
+ " @NonNull Object o;\n" +
+ " X (Color c) { // only potentially initialized\n" +
+ " switch (c) {\n" +
+ " case BLACK: o = this; break;\n" +
+ " case GREEN: o = new Object(); break;\n" +
+ " }\n" +
+ " }\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " X (Color c) { // only potentially initialized\n" +
+ " ^^^^^^^^^^^\n" +
+ "The @NonNull field o 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");
+}
+
+// a non-null static field is not properly initialized
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2c() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " static @NonNull Object o;\n" +
+ " static {\n" +
+ " if (new Object().hashCode() == 42)\n" +
+ " o = new Object();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " static @NonNull Object o;\n" +
+ " ^\n" +
+ "The @NonNull field o may not have been initialized\n" +
+ "----------\n");
+}
+
+// a non-null static field is properly initialized
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2d() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " static @NonNull Object o;\n" +
+ " static {\n" +
+ " o = new Object();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// a non-null field is properly initialized - using this.f reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_2e() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object f;\n" +
+ " {\n" +
+ " this.f = new Object();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// a non-null field is initialized to null
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_3() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o = null;\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " @NonNull Object o = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// a non-null field is assigned to null
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_4() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o = new Object();\n" +
+ " void breakIt1() {\n" +
+ " o = null;\n" +
+ " }\n" +
+ " void breakIt2() {\n" +
+ " this.o = null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " this.o = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+// a non-null field is checked for null
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_5() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o = new Object();\n" +
+ " boolean checkIt1() {\n" +
+ " return o == null;\n" +
+ " }\n" +
+ " boolean checkIt() {\n" +
+ " return this.o != null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return o == null;\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o is declared as @NonNull\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " return this.o != null;\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n");
+}
+
+// a non-null field is checked for null twice - method call inbetween
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_6() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Object o = new Object();\n" +
+ " boolean checkIt1() {\n" +
+ " if (o != null)\n" +
+ " System.out.print(\"not null\");\n" +
+ " System.out.print(\"continue\");\n" +
+ " return this.o == null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if (o != null)\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " return this.o == null;\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o is declared as @NonNull\n" +
+ "----------\n");
+}
+
+// a non-null field is accessed via a qualified name reference - static field
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_7() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class Objects {\n" +
+ " static @NonNull Object o = new Object();\n" +
+ "}\n" +
+ "public class X {\n" +
+ " @NonNull Object getIt1() {\n" +
+ " if (Objects.o != null) // redundant\n" +
+ " System.out.print(\"not null\");\n" +
+ " System.out.print(\"continue\");\n" +
+ " return Objects.o;\n" +
+ " }\n" +
+ " @NonNull Object getIt2() {\n" +
+ " if (null != Objects.o) // redundant\n" +
+ " System.out.print(\"not null\");\n" +
+ " System.out.print(\"continue\");\n" +
+ " return Objects.o;\n" +
+ " }\n" +
+ " String getIt3() {\n" +
+ " return Objects.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " if (Objects.o != null) // redundant\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 13)\n" +
+ " if (null != Objects.o) // redundant\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n");
+}
+
+// a non-null field is accessed via a qualified name reference - instance field
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_8() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class Objects {\n" +
+ " @NonNull Object o = new Object();\n" +
+ "}\n" +
+ "public class X {\n" +
+ " @NonNull Object getIt1(@NonNull Objects objs) {\n" +
+ " if (objs.o == null) // always false\n" +
+ " System.out.print(\"not null\");\n" +
+ " System.out.print(\"continue\");\n" +
+ " return objs.o;\n" +
+ " }\n" +
+ " String getIt2(@NonNull Objects objs) {\n" +
+ " return objs.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " if (objs.o == null) // always false\n" +
+ " ^\n" +
+ "Null comparison always yields false: The field o is declared as @NonNull\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 8)\n" +
+ " System.out.print(\"not null\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n");
+}
+
+// a non-null field is accessed via an indirect field reference - instance field
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_9() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class Objects {\n" +
+ " @NonNull Object o = new Object();\n" +
+ "}\n" +
+ "public class X {\n" +
+ " Objects objs = new Objects();\n" +
+ " @NonNull Object getIt1() {\n" +
+ " if (this.objs.o != null) // redundant\n" +
+ " System.out.print(\"not null\");\n" +
+ " System.out.print(\"continue\");\n" +
+ " if (getObjs().o != null) // redundant\n" +
+ " System.out.print(\"not null\");\n" +
+ " return this.objs.o;\n" +
+ " }\n" +
+ " Objects getObjs() { return this.objs; }\n" +
+ " String getIt2() {\n" +
+ " return this.objs.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (this.objs.o != null) // redundant\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " if (getObjs().o != null) // redundant\n" +
+ " ^\n" +
+ "Redundant null check: The field o is declared as @NonNull\n" +
+ "----------\n");
+}
+
+// trying to assign null to a nonnull field via a single / a qualified name reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_11() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class Objects {\n" +
+ " @NonNull Object o = new Object();\n" +
+ " void test0(@Nullable Object x) {\n" +
+ " o = x;\n" +
+ " }\n" +
+ "}\n" +
+ "public class X {\n" +
+ " void test(@NonNull Objects objs) {\n" +
+ " objs.o = null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " o = x;\n" +
+ " ^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is specified as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " objs.o = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
+ "----------\n");
+}
+
+// @NonNull is applied to a field with primitive type
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_12() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull int o = 1;\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " @NonNull int o = 1;\n" +
+ " ^^^^^^^^^^^^\n" +
+ "The nullness annotation @NonNull is not applicable for the primitive type int\n" +
+ "----------\n");
+}
+
+// A final field is initialized to non-null, treat as effectively @NonNull
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void _test_nonnull_field_13() {
+ // withdrawn as of https://bugs.eclipse.org/331649#c75
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " final String s1 = \"\";\n" +
+ " @NonNull String s2;\n" +
+ " X() {\n" +
+ " s2 = s1;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// A field in a different CU is implicitly @NonNull (by type default) - that class is read from binary
+// Assignment to other @NonNull field should not raise a warning
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_14() {
+ runConformTestWithLibs(
+ new String[] {
+ "p1/X.java",
+ "package p1;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "@NonNullByDefault\n" +
+ "public class X {\n" +
+ " public String s1 = \"\";\n" +
+ "}\n",
+ },
+ null /*customOptions*/,
+ "");
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import p1.X;\n" +
+ "public class Y {\n" +
+ " @NonNull String s2 = \"\";\n" +
+ " void foo(X other) {\n" +
+ " s2 = other.s1;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// A field in a different CU is implicitly @NonNull (by package default) - that class is read from binary
+// Assignment to other @NonNull field should not raise a warning
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nonnull_field_14b() {
+ runConformTestWithLibs(
+ new String[] {
+ "p1/package-info.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "package p1;\n",
+ "p1/X.java",
+ "package p1;\n" +
+ "public class X {\n" +
+ " public String s1 = \"\";\n" +
+ "}\n",
+ },
+ null /*customOptions*/,
+ "");
+ runConformTestWithLibs(
+ new String[] {
+ "p2/Y.java",
+ "package p2;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import p1.X;\n" +
+ "public class Y {\n" +
+ " @NonNull String s2 = \"\";\n" +
+ " void foo(X other) {\n" +
+ " s2 = other.s1;\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// access to a nullable field - field reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_1() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " public String oString() {\n" +
+ " return this.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return this.o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+// access to a nullable field - single name reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " public String oString() {\n" +
+ " return o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+// access to a nullable field - qualified name reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_3() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " @Nullable X other;\n" +
+ " public String oString() {\n" +
+ " return other.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " return other.o.toString();\n" +
+ " ^^^^^\n" +
+ "Potential null pointer access: The field other is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " return other.o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+// access to a nullable field - qualified name reference - multiple segments
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_3m() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " @Nullable X other;\n" +
+ " public String oString() {\n" +
+ " return other.other.o.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " return other.other.o.toString();\n" +
+ " ^^^^^\n" +
+ "Potential null pointer access: The field other is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " return other.other.o.toString();\n" +
+ " ^^^^^\n" +
+ "Potential null pointer access: The field other is declared as @Nullable\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 6)\n" +
+ " return other.other.o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+// access to a nullable field - dereference after check
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_4() {
+ // currently no flow analysis for fields is implemented,
+ // but the direct sequence of null-check + dereference is optionally supported as a special case
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " public String oString() {\n" +
+ " if (this.o != null)\n" +
+ " return this.o.toString();\n" + // silent after check
+ " if (o != null)\n" +
+ " return o.toString();\n" + // silent after check
+ " return \"\";\n" +
+ " }\n" +
+ " public String oString2() {\n" +
+ " String local = o.toString();\n" +
+ " if (this.o != null) {\n" +
+ " this.toString();\n" + // method call wipes null info
+ " return this.o.toString(); // warn here\n" +
+ " }\n" +
+ " return \"\";\n" +
+ " }\n" +
+ "}\n"
+ },
+ options /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " String local = o.toString();\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 15)\n" +
+ " return this.o.toString(); // warn here\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// access to a nullable field - intermediate component in a QNR
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_5() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull Y y = new Y();\n" +
+ " public String oString() {\n" +
+ " return y.z.o.toString(); // pot.NPE on z\n" +
+ " }\n" +
+ "}\n",
+ "Y.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " @Nullable Z z = new Z();\n" +
+ "}\n",
+ "Z.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Z {\n" +
+ " @NonNull Object o = new Object();\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return y.z.o.toString(); // pot.NPE on z\n" +
+ " ^\n" +
+ "Potential null pointer access: The field z is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// access to a nullable field - intermediate component in a QNR - inverse of test_nullable_field_5
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_6() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Y y = new Y();\n" +
+ " public String oString() {\n" +
+ " return y.z.o.toString(); // pot.NPE on y and o\n" +
+ " }\n" +
+ "}\n",
+ "Y.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " @NonNull Z z = new Z();\n" +
+ "}\n",
+ "Z.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Z {\n" +
+ " Object dummy;\n" + // ensure different interal fieldId
+ " @Nullable Object o = new Object();\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return y.z.o.toString(); // pot.NPE on y and o\n" +
+ " ^\n" +
+ "Potential null pointer access: The field y is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " return y.z.o.toString(); // pot.NPE on y and o\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// access to a nullable field - intermediate component in a double field reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_7() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Y y = new Y();\n" +
+ " public String oString() {\n" +
+ " return this.y.o.toString(); // pot.NPE on y and o\n" +
+ " }\n" +
+ "}\n",
+ "Y.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " @Nullable Object o = new Object();\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return this.y.o.toString(); // pot.NPE on y and o\n" +
+ " ^\n" +
+ "Potential null pointer access: The field y is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " return this.y.o.toString(); // pot.NPE on y and o\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// static access to a nullable field - qualified name reference
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_8() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable static final Object o = null;\n" +
+ " public void foo() {\n" +
+ " if (X.o == null){\n" +
+ " System.out.println(X.o);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "");
+}
+
+// illegal use of @Nullable for a field of primitive type
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_9() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable int i;\n" +
+ "}\n"
+ },
+ null /*customOptions*/,
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " @Nullable int i;\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "The nullness annotation @Nullable is not applicable for the primitive type int\n" +
+ "----------\n");
+}
+
+// protected access to nullable fields - different kinds of references
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10a() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1, o2, o3;\n" +
+ " @NonNull X x = new X();\n" +
+ " public void foo(X other) {\n" +
+ " if (other.o1 != null){\n" + // qualified reference -> block
+ " System.out.println(other.o1.toString());\n" +
+ " }\n" +
+ " if (this.o2 != null)\n" + // field reference -> statement
+ " System.out.println(o2.toString());\n" +
+ " if (this.o2 != null)\n" + // identical field references
+ " System.out.println(this.o2.toString());\n" +
+ " System.out.println (null != o3 ? o3.toString() : \"nothing\");\n" + // ternary
+ " if (this.x.o1 != null)\n" + // nested field reference ...
+ " System.out.println(x.o1.toString());\n" + // ... equiv qualified name reference
+ " if (x.o1 != null)\n" + // qualified name reference ...
+ " System.out.println(this.x.o1.toString());\n" +// ... equiv nested field reference
+ " if (this.x.o1 != null)\n" + // identical nested field references
+ " System.out.println(this.x.o1.toString());\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "");
+}
+
+// protected access to nullable fields - different kinds of references - option not enabled
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10b() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.DISABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1, o2, o3;\n" +
+ " @NonNull X x = new X();\n" +
+ " public void foo(X other) {\n" +
+ " if (other.o1 != null){\n" + // qualified reference -> block
+ " System.out.println(other.o1.toString());\n" +
+ " }\n" +
+ " if (this.o2 != null)\n" + // field reference -> statement
+ " System.out.println(o2.toString());\n" +
+ " if (this.o2 != null)\n" + // identical field references
+ " System.out.println(this.o2.toString());\n" +
+ " System.out.println (null != o3 ? o3.toString() : \"nothing\");\n" + // ternary
+ " if (this.x.o1 != null)\n" + // nested field reference ...
+ " System.out.println(x.o1.toString());\n" + // ... equiv qualified name reference
+ " if (x.o1 != null)\n" + // qualified name reference ...
+ " System.out.println(this.x.o1.toString());\n" +// ... equiv nested field reference
+ " if (this.x.o1 != null)\n" + // identical nested field references
+ " System.out.println(this.x.o1.toString());\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " System.out.println(other.o1.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " System.out.println(o2.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 12)\n" +
+ " System.out.println(this.o2.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 13)\n" +
+ " System.out.println (null != o3 ? o3.toString() : \"nothing\");\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o3 is declared as @Nullable\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 15)\n" +
+ " System.out.println(x.o1.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 17)\n" +
+ " System.out.println(this.x.o1.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 19)\n" +
+ " System.out.println(this.x.o1.toString());\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// protected access to nullable fields - different boolean operators
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10c() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1, o2, o3;\n" +
+ " public void foo(X other) {\n" +
+ " if (o1 != null && o2 != null & o3 != null) \n" + // conjunction: OK
+ " System.out.println(o2.toString());\n" +
+ " if (o1 != null || o2 != null || o3 != null) \n" +
+ " System.out.println(o2.toString()); // warn here: disjunktion is no protection\n" +
+ " if (!(o1 != null)) \n" +
+ " System.out.println(o1.toString()); // warn here: negation is no protection\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " System.out.println(o2.toString()); // warn here: disjunktion is no protection\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " System.out.println(o1.toString()); // warn here: negation is no protection\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// protected access to nullable fields - assignment as expression
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10d() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1;\n" +
+ " public void foo(@NonNull X other, X last) {\n" +
+ " o1 = other;\n" + // reference test case: assignment as statement
+ " if (o1 == last) \n" + // no expiry
+ " System.out.println(o1.toString());\n" +
+ " if ((o1 = other) == last) \n" + // no expiry
+ " System.out.println(o1.toString());\n" +
+ " if ((o1 = other) == last) {\n" +
+ " o1 = null;\n" + // expire here
+ " System.out.println(o1.toString()); // info is expired\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " System.out.println(o1.toString()); // info is expired\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// protected access to nullable fields - distinguish local and field
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10e() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class Y {\n" +
+ " @Nullable Object o2;\n" +
+ " void bar(Object o2) {\n" +
+ " if (o2 != null)\n" +
+ " System.out.println(this.o2.toString()); // field access is not protected\n" +
+ " }\n" +
+ "}\n" +
+ "public class X {\n" +
+ " @NonNull Y o1 = new Y();\n" +
+ " public void foo() {\n" +
+ " Y o1 = new Y();\n" +
+ " if (o1.o2 != null) \n" + // check via local
+ " System.out.println(this.o1.o2.toString()); // field access via other field not protected\n" +
+ " if (this.o1.o2 != null) \n" + // check via field
+ " System.out.println(o1.o2.toString()); // field access via local not protected\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. WARNING in X.java (at line 4)\n" +
+ " void bar(Object o2) {\n" +
+ " ^^\n" +
+ "The parameter o2 is hiding a field from type Y\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " System.out.println(this.o2.toString()); // field access is not protected\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 12)\n" +
+ " Y o1 = new Y();\n" +
+ " ^^\n" +
+ "The local variable o1 is hiding a field from type X\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 14)\n" +
+ " System.out.println(this.o1.o2.toString()); // field access via other field not protected\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 16)\n" +
+ " System.out.println(o1.o2.toString()); // field access via local not protected\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// protected access to nullable fields - duplicate comparison
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_10f() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1;\n" +
+ " public void foo(X other) {\n" +
+ " if (o1 != null && o1 != null) // second term is redundant\n" +
+ " System.out.println(o1.toString());\n" +
+ " if (o1 != null)\n" +
+ " if (o1 != null) // this if is redundant\n" +
+ " System.out.println(o1.toString());\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if (o1 != null && o1 != null) // second term is redundant\n" +
+ " ^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " if (o1 != null) // this if is redundant\n" +
+ " ^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n");
+}
+
+// combined test from comment 20 in https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_11() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class X {\n" +
+ " @Nullable Object o;\n" +
+ " public @NonNull Object foo(X x) {\n" +
+ " return x.o != null ? x.o : new Object();\n" +
+ " }\n" +
+ " public void goo(X x) {\n" +
+ " if (x.o != null) {\n" +
+ " x.o.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " public void boo(X x) {\n" +
+ " if (x.o instanceof String) {\n" +
+ " x.o.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " public void zoo(X x) {\n" +
+ " x.o = new Object();\n" +
+ " System.out.println(\"hashCode of new Object = \" + x.o.hashCode());\n" +
+ " }\n" +
+ " public void doo(X x) {\n" +
+ " x.o = foo(x); // foo is guaranteed to return @NonNull Object.\n" +
+ " System.out.println(\"hashCode of new Object = \" + x.o.hashCode());\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "");
+}
+
+// combined test from comment 20 in https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+// - version with 'this' field references
+public void test_nullable_field_11a() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "class X {\n" +
+ " @Nullable Object o;\n" +
+ " public @NonNull Object foo() {\n" +
+ " return o != null ? o : new Object();\n" +
+ " }\n" +
+ " public void goo() {\n" +
+ " if (o != null) {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " public void boo() {\n" +
+ " if (o instanceof String) {\n" +
+ " o.toString();\n" +
+ " }\n" +
+ " }\n" +
+ " public void zoo() {\n" +
+ " o = new Object();\n" +
+ " System.out.println(\"hashCode of new Object = \" + o.hashCode());\n" +
+ " }\n" +
+ " public void doo() {\n" +
+ " o = foo(); // foo is guaranteed to return @NonNull Object.\n" +
+ " System.out.println(\"hashCode of new Object = \" + o.hashCode());\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "");
+}
+
+// protected access to nullable field - expiration of information
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_12() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1, o2, o3, o4;\n" +
+ " public void foo(X other) {\n" +
+ " if (other.o1 != null){\n" +
+ " System.out.println(goo()+other.o1.toString()); // warn here: expired by call to goo()\n" +
+ " }\n" +
+ " Object x = o2 != null ? o2 : o1;\n" +
+ " System.out.println(o2.toString()); // warn here: not protected\n" +
+ " if (o3 != null) /*nop*/;\n" +
+ " System.out.println(o3.toString()); // warn here: expired by empty statement\n" +
+ " if (o4 != null && hoo())\n" +
+ " System.out.println(o4.toString()); // warn here: expired by call to hoo()\n" +
+ " }\n" +
+ " String goo() { return \"\"; }\n" +
+ " boolean hoo() { return false; }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " System.out.println(goo()+other.o1.toString()); // warn here: expired by call to goo()\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o1 is declared as @Nullable\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " System.out.println(o2.toString()); // warn here: not protected\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o2 is declared as @Nullable\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 11)\n" +
+ " System.out.println(o3.toString()); // warn here: expired by empty statement\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o3 is declared as @Nullable\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 13)\n" +
+ " System.out.println(o4.toString()); // warn here: expired by call to hoo()\n" +
+ " ^^\n" +
+ "Potential null pointer access: The field o4 is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// example from comment 47
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_13() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o1;\n" +
+ " @NonNull Object o2 = new Object();\n" +
+ " public void foo(X other) {\n" +
+ " if (other.o1 == null){\n" +
+ " this.o2 = other.o1; // warn here: assign @Nullable to @NonNull\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " this.o2 = other.o1; // warn here: assign @Nullable to @NonNull\n" +
+ " ^^^^^^^^\n" +
+ "Null type mismatch: required \'@NonNull Object\' but the provided value is specified as @Nullable\n" +
+ "----------\n");
+}
+
+// access to a nullable field - protected by check against a @NonNull value
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_14() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " public String oString(@NonNull Object a) {\n" +
+ " if (this.o == a)\n" +
+ " return this.o.toString();\n" + // silent after check
+ " return \"\";\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "");
+}
+
+// access to a nullable field - not protected by negative check against a @NonNull value
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331649
+public void test_nullable_field_14a() {
+ Map options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS, JavaCore.ENABLED);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @Nullable Object o = new Object();\n" +
+ " public String oString(@NonNull Object a) {\n" +
+ " if (this.o != a)\n" +
+ " return this.o.toString(); // warn here, check has no effect\n" +
+ " return \"\";\n" +
+ " }\n" +
+ "}\n"
+ },
+ options,
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " return this.o.toString(); // warn here, check has no effect\n" +
+ " ^\n" +
+ "Potential null pointer access: The field o is declared as @Nullable\n" +
+ "----------\n");
+}
+
+// an enum is declared within the scope of a null-default
+// https://bugs.eclipse.org/331649#c61
+public void test_enum_field_01() {
+ runConformTestWithLibs(
+ new String[] {
+ "tests/X.java",
+ "package tests;\n" +
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public class X {\n" +
+ " enum A { B }\n" +
+ " public static void main(String ... args) {\n" +
+ " System.out.println(A.B);\n" +
+ " }\n" +
+ "}\n"
+ },
+ null,
+ "",
+ "B");
+}
+
+// Bug 380896 - Enum constants not recognised as being NonNull.
+// see also https://bugs.eclipse.org/331649#c61
+public void test_enum_field_02() {
+ runConformTestWithLibs(
+ new String[] {
+ "tests/X.java",
+ "package tests;\n" +
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " enum A { B }\n" +
+ " public static void main(String ... args) {\n" +
+ " test(A.B);\n" +
+ " }\n" +
+ " static void test(@NonNull A a) {\n" +
+ " System.out.println(a.ordinal());\n" +
+ " }\n" +
+ "}\n"
+ },
+ null,
+ "",
+ "0");
+}
+
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=372011
// Test whether @NonNullByDefault on a binary package or an enclosing type is respected from enclosed elements.
public void testBug372011() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
index ffa67b4..21bdbfb 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
@@ -11,6 +11,7 @@
* bug 320170
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 386181 - [compiler][null] wrong transition in UnconditionalFlowInfo.mergedWith()
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -38,6 +39,7 @@
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
/**
@@ -1022,7 +1024,7 @@
public PackageBinding getPackage() {
return null;
}
- public boolean isCompatibleWith(TypeBinding right) {
+ public boolean isCompatibleWith(TypeBinding right, Scope captureScope) {
return false;
}
public char[] qualifiedSourceName() {
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 077a446..6245e57 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
@@ -24,6 +24,9 @@
* bug 367879 - Incorrect "Potential null pointer access" warning on statement after try-with-resources within try-finally
* bug 383690 - [compiler] location of error re uninitialized final field should be aligned
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 376263 - Bogus "Potential null pointer access" warning
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -32,6 +35,7 @@
import junit.framework.Test;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
@@ -53,6 +57,7 @@
static {
// TESTS_NAMES = new String[] { "testBug345305_14" };
// TESTS_NAMES = new String[] { "test0515_try_finally" };
+// TESTS_NAMES = new String[] { "testBug376263" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -9634,9 +9639,9 @@
"X.java",
"public class X {\n" +
"\n" +
- " void foo() {\n" +
+ " void foo(Object that) {\n" +
" Object o = new Object();\n" +
- " while (this != null) {\n" +
+ " while (that != null) {\n" +
" try {\n" +
" o = null;\n" +
" break;\n" +
@@ -9653,7 +9658,7 @@
" ^\n" +
"Null comparison always yields false: The variable o cannot be null at this location\n" +
"----------\n" +
- "2. WARNING in X.java (at line 13)\n" +
+ "2. WARNING in X.java (at line 13)\n" +
" if (o == null) return;\n" +
" ^^^^^^^\n" +
"Dead code\n" +
@@ -15623,6 +15628,190 @@
"",/* expected error */
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
}
+public void testBug376263() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
+ runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " private int x;\n" +
+ "\n" +
+ " static void test(Test[] array) {\n" +
+ " Test elem = null;\n" +
+ " int i = 0;\n" +
+ " while (i < array.length) {\n" +
+ " if (i == 0) {\n" +
+ " elem = array[0];\n" +
+ " }\n" +
+ " if (elem != null) {\n" +
+ " while (true) {\n" +
+ " if (elem.x >= 0 || i >= array.length) { // should not warn here\n" +
+ " break;\n" +
+ " }\n" +
+ " elem = array[i++];\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ },
+ "",
+ null/*classLibraries*/,
+ true/*shouldFlush*/,
+ null/*vmArgs*/,
+ customOptions,
+ null/*requestor*/);
+}
+//object/array allocation
+public void testExpressions01() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void foo() {\n" +
+ " if (new Object() == null)\n" +
+ " System.out.println(\"null\");\n" +
+ " }\n" +
+ " void goo() {\n" +
+ " if (null != this.new I())\n" +
+ " System.out.println(\"nonnull\");\n" +
+ " }\n" +
+ " void hoo() {\n" +
+ " if (null != new Object[3])\n" +
+ " System.out.println(\"nonnull\");\n" +
+ " }\n" +
+ " class I {}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " if (new Object() == null)\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Null comparison always yields false: this expression cannot be null\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 4)\n" +
+ " System.out.println(\"null\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " if (null != this.new I())\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 11)\n" +
+ " if (null != new Object[3])\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n"
+ );
+}
+//'this' expressions (incl. qualif.)
+public void testExpressions02() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void foo() {\n" +
+ " if (this == null)\n" +
+ " System.out.println(\"null\");\n" +
+ " }\n" +
+ " class I {\n" +
+ " void goo() {\n" +
+ " if (null != X.this)\n" +
+ " System.out.println(\"nonnull\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " if (this == null)\n" +
+ " ^^^^\n" +
+ "Null comparison always yields false: this expression cannot be null\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 4)\n" +
+ " System.out.println(\"null\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 8)\n" +
+ " if (null != X.this)\n" +
+ " ^^^^^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n"
+ );
+}
+//various non-null expressions: class-literal, string-literal, casted 'this'
+public void testExpressions03() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void foo() {\n" +
+ " if (X.class == null)\n" +
+ " System.out.println(\"null\");\n" +
+ " }\n" +
+ " void goo() {\n" +
+ " if (null != \"STRING\")\n" +
+ " System.out.println(\"nonnull\");\n" +
+ " if (null == (Object)this)\n" +
+ " System.out.println(\"I'm null\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " if (X.class == null)\n" +
+ " ^^^^^^^\n" +
+ "Null comparison always yields false: this expression cannot be null\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 4)\n" +
+ " System.out.println(\"null\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " if (null != \"STRING\")\n" +
+ " ^^^^^^^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 9)\n" +
+ " if (null == (Object)this)\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Null comparison always yields false: this expression cannot be null\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 10)\n" +
+ " System.out.println(\"I\'m null\");\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n"
+ );
+}
+
+//a non-null ternary expression
+public void testExpressions04() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void foo(boolean b) {\n" +
+ " Object o1 = new Object();\n" +
+ " Object o2 = new Object();\n" +
+ " if ((b ? o1 : o2) != null)\n" +
+ " System.out.println(\"null\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if ((b ? o1 : o2) != null)\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Redundant null check: this expression cannot be null\n" +
+ "----------\n"
+ );
+}
// Bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
// simplified: only try-finally involved
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 6ced2f5..25fcd68 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.8.1
+Bundle-Version: 3.8.2
Bundle-ClassPath: jdtcoretestsmodel.jar
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 36df8eb..1415479 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>eclipse.jdt.core</groupId>
<artifactId>org.eclipse.jdt.core.tests.model</artifactId>
- <version>3.8.1-SNAPSHOT</version>
+ <version>3.8.2-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
index 5a94b55..77ade14 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2012 IBM Corporation and others.
+ * Copyright (c) 2004, 2013 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 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.*;
@@ -1194,6 +1195,31 @@
"LX;@LX~MyAnnot;",
bindings);
}
+
+ /*
+ * Ensures that the correct IBinding is created for package-info.class's IType
+ */
+ public void testCreateBindings24() throws CoreException {
+ createClassFile(
+ "/P/lib",
+ "pack/package-info.class",
+ "@Deprecated\n" +
+ "package pack;");
+ IJavaProject javaProject = getJavaProject("P");
+ IPackageFragment pack = javaProject.findPackageFragment(new Path("/P/lib/pack"));
+ IType type = pack.getClassFile("package-info.class").getType();
+ ASTParser parser = ASTParser.newParser(JLS3_INTERNAL);
+ parser.setProject(javaProject);
+ IJavaElement[] elements = new IJavaElement[] {type};
+ IBinding[] bindings = parser.createBindings(elements, null);
+ assertBindingsEqual(
+ "Lpack/package-info;",
+ bindings);
+ IAnnotationBinding[] annotations = ((ITypeBinding) bindings[0]).getAnnotations();
+ assertBindingsEqual(
+ "@Ljava/lang/Deprecated;",
+ annotations);
+ }
/*
* Ensures that the IJavaElement of an IBinding representing a field is correct.
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
index ee7353c..82c0dc8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -351,15 +351,14 @@
/*
* Ensures that the source of a .class file is implicetely attached when prj=src=bin
* (regression test for bug 41444 [navigation] error dialog on opening class file)
+ *
+ * Note: The test case is being modified as part of fix for bug
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=398490
*/
public void testClassFileInOutput() throws CoreException {
IClassFile classFile = getClassFile("AttachSourceTests/src/A.class");
String source = classFile.getSource();
- assertSourceEquals(
- "Unexpected source",
- "public class A {\n" +
- "}",
- source);
+ assertNull("Unexpected source", source);
}
/**
* Retrieves the source code for "A.class", which is
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
index 613c598..fdadfe7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -93,6 +93,7 @@
suite.addTest(new AttachedJavadocTests("testBug354766_2"));
suite.addTest(new AttachedJavadocTests("testBug394967"));
suite.addTest(new AttachedJavadocTests("testBug394382"));
+ suite.addTest(new AttachedJavadocTests("testBug398272"));
return suite;
}
@@ -1150,4 +1151,15 @@
this.project.setRawClasspath(oldClasspath, null);
}
}
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=398272
+ public void testBug398272() throws JavaModelException {
+ IPackageFragment packageFragment = this.root.getPackageFragment("p1.p2.p3.p4"); //$NON-NLS-1$
+ assertNotNull("Should not be null", packageFragment); //$NON-NLS-1$
+ try {
+ String javadoc = packageFragment.getAttachedJavadoc(new NullProgressMonitor()); //$NON-NLS-1$
+ assertNull("Javadoc should be null", javadoc); //$NON-NLS-1$
+ } catch(JavaModelException jme) {
+ fail("Should not throw Java Model Exception");
+ }
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
index c00cad2..ecd021f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -344,6 +344,7 @@
suite.addTest(new ClasspathTests("testBug287164"));
suite.addTest(new ClasspathTests("testBug220928a"));
suite.addTest(new ClasspathTests("testBug220928b"));
+ suite.addTest(new ClasspathTests("testBug396299"));
return suite;
}
public void setUpSuite() throws Exception {
@@ -7420,4 +7421,43 @@
deleteProject("P");
}
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=396299
+public void testBug396299() throws Exception {
+ boolean autoBuild = getWorkspace().isAutoBuilding();
+ IWorkspaceDescription preferences = getWorkspace().getDescription();
+ try {
+ JavaModelManager.EclipsePreferencesListener prefListener = new JavaModelManager.EclipsePreferencesListener();
+ preferences.setAutoBuilding(true);
+ getWorkspace().setDescription(preferences);
+
+ JavaProject proj1 = (JavaProject) this.createJavaProject("P1", new String[] {}, "");
+ addLibrary(proj1, "abc.jar", null, new String[] {
+ "p/X.java",
+ "package p;\n" +
+ "public class X {}\n"},
+ JavaCore.VERSION_1_4);
+ proj1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_4);
+
+ Map map = proj1.getOptions(false);
+ map.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.WARNING);
+ proj1.setOptions(map);
+
+ IEclipsePreferences eclipsePreferences = proj1.getEclipsePreferences();
+ eclipsePreferences.addPreferenceChangeListener(prefListener);
+ simulateExitRestart();
+ waitForAutoBuild();
+ assertMarkers("Unexpected markers", "", proj1);
+ map = proj1.getOptions(false);
+ map.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_1);
+ proj1.setOptions(map);
+
+ assertMarkers("Unexpected markers",
+ "Incompatible .class files version in required binaries. Project \'P1\' is targeting a 1.1 runtime, but is compiled against \'P1/abc.jar\' which requires a 1.4 runtime", proj1);
+ eclipsePreferences.removePreferenceChangeListener(prefListener);
+ } finally {
+ preferences.setAutoBuilding(autoBuild);
+ getWorkspace().setDescription(preferences);
+ deleteProject("P1");
+ }
+}
}
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 2f8c3af..c2b7869 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
@@ -30,19 +30,25 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.CompletionContext;
+import org.eclipse.jdt.core.CompletionProposal;
+import org.eclipse.jdt.core.CompletionRequestor;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.internal.codeassist.InternalCompletionContext;
import org.eclipse.jdt.internal.codeassist.RelevanceConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
public class CompletionTests2 extends ModifyingResourceTests implements RelevanceConstants {
@@ -5981,4 +5987,64 @@
deleteProject("P");
}
}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=397070
+public void testBug397070() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/test/Completion.java",
+ "package test;\n" +
+ "public class Completion implements {}\n" +
+ "public interface Completion2 extends {}\n" +
+ "public class Completion3 extends {}\n" +
+ "}\n");
+
+ class CompletionRequestor2 extends CompletionRequestor {
+ SourceType type = null;
+ public void acceptContext(CompletionContext con) {
+ this.type = null;
+ if (con instanceof InternalCompletionContext) {
+ InternalCompletionContext context = (InternalCompletionContext) con;
+ IJavaElement element = context.getEnclosingElement();
+ if (element instanceof org.eclipse.jdt.internal.core.SourceType) {
+ this.type = (SourceType) element;
+ }
+ }
+ }
+ public boolean isExtendedContextRequired() {
+ return true;
+ }
+ public SourceType getType() {
+ return this.type;
+ }
+ public void accept(CompletionProposal proposal) {
+ // Do nothing
+ }
+ }
+
+ CompletionRequestor2 requestor = new CompletionRequestor2();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "Completion implements ";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ try {
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ SourceType type = requestor.getType();
+ String[] names = type.getSuperInterfaceTypeSignatures();
+ assertEquals("Incorrect syper interface signature", 0, names.length);
+
+ completeBehind = "Completion2 extends ";
+ cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ type = requestor.getType();
+ names = type.getSuperInterfaceTypeSignatures();
+ assertEquals("Incorrect syper interface signature", 0, names.length);
+
+ completeBehind = "Completion3 extends ";
+ cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+ type = requestor.getType();
+ assertNull("Incorrect syper class signature", type.getSuperclassTypeSignature());
+ } catch (IllegalArgumentException iae) {
+ fail("Invalid completion context");
+ }
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchScopeTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchScopeTests.java
index 52af315..23cf2f2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchScopeTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchScopeTests.java
@@ -10,10 +10,13 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.HashMap;
import junit.framework.Test;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
@@ -24,6 +27,7 @@
import org.eclipse.jdt.core.tests.model.AbstractJavaSearchTests.JavaSearchResultCollector;
import org.eclipse.jdt.core.tests.model.AbstractJavaSearchTests.TypeNameMatchCollector;
import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.index.IndexLocation;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
/**
@@ -1096,4 +1100,22 @@
}
}
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=397818
+public void testBug397818() throws CoreException {
+ try {
+ createJavaProject("P1", new String[] {"src"}, new String[] {}, "bin");
+
+ createFolder("/P1/new folder");
+ IFile newFile = createFile("/P1/new folder/testindex.index", "");
+ try {
+ URL newURL = newFile.getLocationURI().toURL();
+ IndexLocation indexLoc = IndexLocation.createIndexLocation(newURL);
+ assertTrue("Malformed index location", indexLoc.getIndexFile().exists());
+ } catch (MalformedURLException e) {
+ fail("Malformed index location");
+ }
+ } finally {
+ deleteProject("P1");
+ }
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SuiteOfTestCases.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SuiteOfTestCases.java
index 25fb7e5..4a7250f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SuiteOfTestCases.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SuiteOfTestCases.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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,21 +12,25 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.Set;
+import org.eclipse.test.internal.performance.PerformanceMeterFactory;
+
+import junit.extensions.TestSetup;
import junit.framework.Protectable;
import junit.framework.Test;
import junit.framework.TestResult;
import junit.framework.TestSuite;
/**
- * A test case class that can be set up (using the setUpSuite() method) and tore down (using the teardDownSuite() method)
+ * A test case class that can be set up (using the setUpSuite() method) and torn down (using the tearDownSuite() method)
* once for all test cases of this class.
*/
public class SuiteOfTestCases extends org.eclipse.jdt.core.tests.junit.extension.TestCase {
/*
* A test suite that initialize the test case's fields once, then that copies the values
- * of these fields intto each subsequent test case.
+ * of these fields into each subsequent test case.
*/
public static class Suite extends TestSuite {
public SuiteOfTestCases currentTestCase;
@@ -120,4 +124,31 @@
*/
public void tearDownSuite() throws Exception {
}
+
+ /**
+ * Decorate an individual test with setUpSuite/tearDownSuite, so that the test can be run standalone.
+ * This method is called by the Eclipse JUnit test runner when a test is re-run from the JUnit view's context menu.
+ */
+ public static Test setUpTest(Test test) {
+ if (!(test instanceof SuiteOfTestCases))
+ return test;
+
+ final SuiteOfTestCases suiteOfTestCases = (SuiteOfTestCases) test;
+ return new TestSetup(test) {
+ protected void setUp() throws Exception {
+ // reset the PerformanceMeterFactory, so that the same scenario can be run again:
+ Field field = PerformanceMeterFactory.class.getDeclaredField("fScenarios");
+ field.setAccessible(true);
+ Set set = (Set) field.get(null);
+ set.clear();
+
+ suiteOfTestCases.setUpSuite();
+ }
+
+ protected void tearDown() throws Exception {
+ suiteOfTestCases.tearDownSuite();
+ }
+ };
+ }
+
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
index 7d01596..d791a49 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
@@ -1,12 +1,13 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM Corporation - initial API and implementation
+ * IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for Bug 378024 - Ordering of comments between imports not preserved
*******************************************************************************/
package org.eclipse.jdt.core.tests.rewrite.describing;
@@ -65,6 +66,10 @@
}
public static Test suite() {
+// System.err.println("Warning, only part of the ImportRewriteTest are being executed!");
+// Suite suite = new Suite(ImportRewriteTest.class.getName());
+// suite.addTest(new ImportRewriteTest("testRemoveImports1"));
+// return suite;
return allTests();
}
@@ -1913,6 +1918,7 @@
"import java.util.Map.*;\n" +
"\n" +
"/* lead 2*/import java.io.PrintWriter.*; // test2\n" +
+ "\n" +
"/* lead 3*/ import java.util.Map.SomethingElse; // test3\n" +
"// commen 3\n" +
"\n" +
@@ -1973,6 +1979,7 @@
"\n" +
"// comment 1\n" +
"/* lead 2*/import java.io.PrintWriter.*; // test2\n" +
+ "\n" +
"/* lead 1*/ import java.util.*; // test1\n" +
"import java.util.Map.*;\n" +
"/* lead 3*/ import java.util.Map.SomethingElse; // test3\n" +
@@ -2032,11 +2039,8 @@
"package pack1;\n" +
"\n" +
"// comment 1\n" +
- "/* lead 2*/" +
- "import java.util.*;\n" +
+ "/* lead 2*//* lead 1*/ import java.util.*; // test1\n" +
"// test2\n" +
- "/* lead 1*/ \n" +
- "// test1\n" +
"/* lead 3*/ \n" +
"// test3\n" +
"// commen 3\n" +
@@ -2096,8 +2100,7 @@
"\n" +
"// comment 1\n" +
"/* lead 1*/ " +
- "import java.util.Map.*;\n" +
- "// test1\n" +
+ "import java.util.Map.*; // test1\n" +
"/* lead 2*/\n" +
"// test2\n" +
"/* lead 3*/ \n" +
@@ -2159,10 +2162,9 @@
"// comment 1\n" +
"/* lead 2*/import java.io.PrintWriter.*; // test2\n" +
"\n" +
- "/* lead 1*/ \n" +
+ "/* lead 1*/ import java.util.*;\n" +
" // test1\n" +
"// commen 3\n" +
- "import java.util.*;\n" +
"\n" +
"public class C {\n" +
" public static void main(String[] args) {\n" +
@@ -2178,6 +2180,1392 @@
assertEqualString(cu.getSource(), buf.toString());
}
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376930
+ // separating comment should not prevent folding into *-import
+ public void testBug376930_5e() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "import java.util.Map;\n" +
+ "/* comment leading Map.Entry */\n" +
+ "import java.util.Map.Entry;\n" +
+ "\n" +
+ "public class C {\n" +
+ " public static void main(String[] args) {\n" +
+ " HashMap h;\n" +
+ "\n" +
+ " Map.Entry e= null;\n" +
+ " Entry e2= null;\n" +
+ "\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "javax", "org", "com" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, true);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "import java.util.*;\n" +
+ "/* comment leading Map.Entry */\n" +
+ "import java.util.Map.Entry;\n" +
+ "\n" +
+ "public class C {\n" +
+ " public static void main(String[] args) {\n" +
+ " HashMap h;\n" +
+ "\n" +
+ " Map.Entry e= null;\n" +
+ " Entry e2= null;\n" +
+ "\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ public void testBug378024() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * keep me with List\n" +
+ " *\n" +
+ " */\n" +
+ "import java.awt.List;// test1\n" +
+ "/*\n" +
+ " * keep me with Serializable\n" +
+ " */\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * keep me with HashMap\n" +
+ " */\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.awt", "java.io", "java.util" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * keep me with List\n" +
+ " *\n" +
+ " */\n" +
+ "import java.awt.List;// test1\n\n" +
+ "/*\n" +
+ " * keep me with Serializable\n" +
+ " */\n" +
+ "import java.io.Serializable;// test2\n\n" +
+ "/*\n" +
+ " * keep me with HashMap\n" +
+ " */\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ public void testBug378024b() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "import java.awt.List;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 1, 1, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "import java.awt.*;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "import java.io.*;// test2\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "import java.util.*;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // leading and trailing comments always move with imports.
+ // comments in between stay where they are
+ public void testBug378024c() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // leading and trailing comments always move with imports.
+ // comments in between stay where they are
+ public void testBug378024c_1() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // leading and trailing comments always move with imports, even if they get folded.
+ // comments in between stay where they are
+ public void testBug378024c_2() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 1, 1, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.*;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.*;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "//lead 3\n" +
+ "import java.util.*;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // not adding an import should preserve its comments and put them at the end.
+ public void testBug378024d() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 1, 1, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.*;// test1\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.*;// test3\n" +
+ "// commen 3\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // adding a new import should not disturb comments and import should be added in its group
+ public void testBug378024e() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.io.PrintWriter");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.*;\n" +
+ "// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // removing an import should preserve its comments at the end, and adding a new import should not disturb
+ // existing comments
+ public void testBug378024e_1() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.PrintWriter");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "import java.io.PrintWriter;\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // folding imports because of a newly added import should preserve comments
+ public void testBug378024f() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.io.PrintWriter");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.*;\n" +
+ "// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // folding imports because of a newly added import should preserve comments
+ public void testBug378024f_1() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * keep me with List\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * keep me with Serializable\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * keep me with Serializable 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 3\n" +
+ "import java.io.PrintWriter;// test3\n" +
+ "/*\n" +
+ " * keep me with PrintWriter\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me\n" +
+ " */\n" +
+ "\n" +
+ "//lead 4\n" +
+ "import java.util.HashMap;// test4\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 2, 2, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.io.PrintWriter");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * keep me with List\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "//lead 4\n" +
+ "import java.util.HashMap;// test4\n" +
+ "// commen 3\n" +
+ "/*\n" +
+ " * keep me with Serializable\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "// lead 3\n" +
+ "import java.io.*;// test3\n" +
+ "/*\n" +
+ " * keep me with PrintWriter\n" +
+ " */\n" +
+ "// test2\n" +
+ "/*\n" +
+ " * keep me with Serializable 2\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me\n" +
+ " */\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // Re-ordering imports and converting them to *
+ public void testBug378024g() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.awt", "java.util", "java.io", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 1, 1, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+
+ apply(imports);
+
+ StringBuffer buf2 = new StringBuffer();
+ buf2.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.*;// test1\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.*;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.*;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " List l = new List();\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf2.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // Preserve comments when imports are removed in case the restoring of imports is enabled
+ // This will test changes in org.eclipse.jdt.internal.core.dom.rewrite.ImportRewriteAnalyzer.removeImport(String, boolean)
+ public void testBug378024h() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, true);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.removeImport("java.awt.List");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "\n" +
+ "// lead 1\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // Preserve comments when imports are removed in case the restoring of imports is enabled
+ public void testBug378024h_1() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/* i am with List */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, true);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.removeImport("java.awt.List");
+ imports.addImport("java.util.List");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "/* i am with List */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "import java.util.List;\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // Preserve comments when imports are unfolded.
+ public void testBug378024i() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "import java.awt.*;// test1\n" +
+ "/* i am with List */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.*;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.*;// test3\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " HashMap e= null;\n" +
+ " PrintWriter p= null;\n" +
+ " List l= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.io.PrintWriter");
+ imports.addImport("java.io.Serializable");
+ imports.addImport("java.util.HashMap");
+ imports.addImport("java.util.Map");
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/* i am with List */\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.PrintWriter;// test2\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "import java.io.Serializable;\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "// commen 3\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " HashMap e= null;\n" +
+ " PrintWriter p= null;\n" +
+ " List l= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378024
+ // Preserve comments when imports are folded but a member type import is present
+ public void testBug378024j() throws Exception {
+ IPackageFragment pack1 = this.sourceFolder.createPackageFragment("pack1", false, null);
+ StringBuffer buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "import java.awt.List;// test1\n" +
+ "/* i am with List */\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.HashMap;// test3\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "\n" +
+ "/*keep me with Map.Entry*/\n" +
+ "import java.util.Map.Entry;// member type import\n" +
+ "/*keep me with Map.Entry 2*/\n" +
+ "\n" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "\n" +
+ "// lead 2\n" +
+ "import java.io.Serializable;// test2\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ ICompilationUnit cu = pack1.createCompilationUnit("C.java", buf.toString(), false, null);
+
+ String[] order = new String[] { "java", "java.util", "com", "pack" };
+
+ ImportRewrite imports= newImportsRewrite(cu, order, 1, 1, false);
+ imports.setUseContextToFilterImplicitImports(true);
+ imports.addImport("java.awt.List");
+ imports.addImport("java.util.HashMap");
+ imports.addImport("java.util.Map.Entry");
+ imports.addImport("java.io.Serializable");
+
+ apply(imports);
+
+ buf = new StringBuffer();
+ buf.append(
+ "package pack1;\n" +
+ "\n" +
+ "// comment 1\n" +
+ "/*\n" +
+ " * don't move me 1\n" +
+ " *\n" +
+ " */\n" +
+ "// lead 1\n" +
+ "import java.awt.*;// test1\n" +
+ "/* i am with List */\n" +
+ "\n" +
+ "//lead 3\n" +
+ "import java.util.*;// test3\n" +
+ "/*\n" +
+ " * don't move me 3\n" +
+ " */\n" +
+ "/*keep me with Map.Entry*/\n" +
+ "import java.util.Map.Entry;// member type import\n" +
+ "/*keep me with Map.Entry 2*/\n" +
+ "/*\n" +
+ " * don't move me 2\n" +
+ " */" +
+ "/*\n" +
+ " * don't move me 4\n" +
+ " */\n" +
+ "// lead 2\n" +
+ "import java.io.*;// test2\n" +
+ "// commen 3\n" +
+ "\n" +
+ "public class C implements Serializable{\n" +
+ " public static void main(String[] args) {\n" +
+ " Map e= null;\n" +
+ " }\n" +
+ "}");
+ assertEqualString(cu.getSource(), buf.toString());
+ }
+
private void assertAddedAndRemoved(ImportRewrite imports, String[] expectedAdded, String[] expectedRemoved, String[] expectedAddedStatic, String[] expectedRemovedStatic) {
assertEqualStringsIgnoreOrder(imports.getAddedImports(), expectedAdded);
assertEqualStringsIgnoreOrder(imports.getAddedStaticImports(), expectedAddedStatic);
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 71ee1d4..c53992b 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -24,6 +24,7 @@
* bug 374605 - Unreasonable warning for enum-based switch statements
* bug 375366 - ECJ ignores unusedParameterIncludeDocCommentReference unless enableJavadoc option is set
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.batch;
@@ -1698,21 +1699,21 @@
return false;
}
switch(majorVersion) {
- case 45 : // 1.0 and 1.1
+ case ClassFileConstants.MAJOR_VERSION_1_1 : // 1.0 and 1.1
return ClassFileConstants.JDK1_1 >= minimalSupportedVersion;
- case 46 : // 1.2
+ case ClassFileConstants.MAJOR_VERSION_1_2 : // 1.2
return ClassFileConstants.JDK1_2 >= minimalSupportedVersion;
- case 47 : // 1.3
+ case ClassFileConstants.MAJOR_VERSION_1_3 : // 1.3
return ClassFileConstants.JDK1_3 >= minimalSupportedVersion;
- case 48 : // 1.4
+ case ClassFileConstants.MAJOR_VERSION_1_4 : // 1.4
return ClassFileConstants.JDK1_4 >= minimalSupportedVersion;
- case 49 : // 1.5
+ case ClassFileConstants.MAJOR_VERSION_1_5 : // 1.5
return ClassFileConstants.JDK1_5 >= minimalSupportedVersion;
- case 50 : // 1.6
+ case ClassFileConstants.MAJOR_VERSION_1_6 : // 1.6
return ClassFileConstants.JDK1_6 >= minimalSupportedVersion;
- case 51 : // 1.7
+ case ClassFileConstants.MAJOR_VERSION_1_7 : // 1.7
return ClassFileConstants.JDK1_7 >= minimalSupportedVersion;
- case 52 : // 1.8
+ case ClassFileConstants.MAJOR_VERSION_1_8: // 1.8
return ClassFileConstants.JDK1_8 >= minimalSupportedVersion;
}
// unknown version
@@ -3845,6 +3846,9 @@
} else if (token.equals("nullUncheckedConversion")) { //$NON-NLS-1$
setSeverity(CompilerOptions.OPTION_ReportNullUncheckedConversion, severity, isEnabling);
return;
+ } else if (token.equals("nonnullNotRepeated")) { //$NON-NLS-1$
+ setSeverity(CompilerOptions.OPTION_ReportNonnullParameterAnnotationDropped, severity, isEnabling);
+ return;
}
break;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index c310896..82402e5 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -28,8 +28,8 @@
###{ObjectTeams:
otdtc.name = Extension for Object Teams
-otdtc.version = 2.2.0 M4
-otdtc.copyright = Copyright by TU Berlin, Fraunhofer FIRST and others, 2004, 2012.
+otdtc.version = 2.2.0 M5
+otdtc.copyright = Copyright by TU Berlin, Fraunhofer FIRST and others, 2004, 2013.
### SH}
### progress
progress.compiling = Compiling
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
index 387755d..42ff67e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
@@ -183,7 +183,9 @@
protected static boolean hasEmptyName(TypeReference reference, ASTNode assistNode) {
if (reference == null) return false;
- if (reference.sourceStart <= assistNode.sourceStart && assistNode.sourceEnd <= reference.sourceEnd) return false;
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=397070
+ if (reference != assistNode &&
+ reference.sourceStart <= assistNode.sourceStart && assistNode.sourceEnd <= reference.sourceEnd) return false;
if (reference instanceof CompletionOnSingleTypeReference ||
reference instanceof CompletionOnQualifiedTypeReference ||
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 f8d10da..4cc9a7b 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
@@ -155,10 +155,19 @@
* UninitializedLocalVariableHintMissingDefault
* UninitializedBlankFinalFieldHintMissingDefault
* ShouldReturnValueHintMissingDefault
+ * NullableFieldReference
+ * UninitializedNonNullField
+ * UninitializedNonNullFieldHintMissingDefault
+ * NonNullMessageSendComparisonYieldsFalse
+ * RedundantNullCheckOnNonNullSpecdField
+ * NonNullSpecdFieldComparisonYieldsFalse
+ * NonNullExpressionComparisonYieldsFalse
+ * RedundantNullCheckOnNonNullExpression
* IllegalModifierForInterfaceDefaultMethod
* InheritedDefaultMethodConflictsWithOtherInherited
* ConflictingNullAnnotations
* ConflictingInheritedNullAnnotations
+ * UnsafeElementTypeConversion
* ArrayReferencePotentialNullReference
* DereferencingNullableExpression
* NullityMismatchingTypeAnnotation
@@ -1204,6 +1213,9 @@
/** @since 3.8 */
int MethodNameClashHidden = MethodRelated + 584;
+ /** @since 3.9 */
+ int UnsafeElementTypeConversion = TypeRelated + 585;
+
/**
* 1.5 Syntax errors (when source level < 1.5)
*/
@@ -1353,6 +1365,14 @@
int IllegalArrayOfUnionType = TypeRelated + 662;
/**
+ * Null analysis for other kinds of expressions, syntactically nonnull
+ */
+ /** @since 3.9 */
+ int NonNullExpressionComparisonYieldsFalse = Internal + 670;
+ /** @since 3.9 */
+ int RedundantNullCheckOnNonNullExpression = Internal + 671;
+
+ /**
* Corrupted binaries
*/
/** @since 3.1 */
@@ -1543,6 +1563,8 @@
int RedundantNullAnnotation = MethodRelated + 922;
/** @since 3.8 */
int IllegalAnnotationForBaseType = TypeRelated + 923;
+ /** @since 3.9 */
+ int NullableFieldReference = FieldRelated + 924;
/** @since 3.8 */
int RedundantNullDefaultAnnotation = Internal + 925; // shouldn't actually occur any more after bug 366063
/** @since 3.8 */
@@ -1562,6 +1584,16 @@
/** @since 3.8 */
int RequiredNonNullButProvidedSpecdNullable = Internal + 933;
/** @since 3.9 */
+ int UninitializedNonNullField = FieldRelated + 934;
+ /** @since 3.9 */
+ int UninitializedNonNullFieldHintMissingDefault = FieldRelated + 935;
+ /** @since 3.9 */
+ int NonNullMessageSendComparisonYieldsFalse = Internal + 936;
+ /** @since 3.9 */
+ int RedundantNullCheckOnNonNullSpecdField = Internal + 937;
+ /** @since 3.9 */
+ int NonNullSpecdFieldComparisonYieldsFalse = Internal + 938;
+ /** @since 3.9 */
int ConflictingNullAnnotations = MethodRelated + 939;
/** @since 3.9 */
int ConflictingInheritedNullAnnotations = MethodRelated + 940;
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 98937ea..834c85a 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, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -1963,6 +1963,9 @@
this.contentsOffset = startingContentsOffset;
return;
}
+ if (annotationTypeBinding.isMemberType()) {
+ this.recordInnerClasses(annotationTypeBinding);
+ }
final int typeIndex = this.constantPool.literalIndex(annotationTypeBinding.signature());
this.contents[this.contentsOffset++] = (byte) (typeIndex >> 8);
this.contents[this.contentsOffset++] = (byte) typeIndex;
@@ -2176,6 +2179,12 @@
if (defaultValueBinding == null) {
this.contentsOffset = attributeOffset;
} else {
+ if (defaultValueBinding.isMemberType()) {
+ this.recordInnerClasses(defaultValueBinding);
+ }
+ if (memberValuePairReturnType.isMemberType()) {
+ this.recordInnerClasses(memberValuePairReturnType);
+ }
if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
// automatic wrapping
if (this.contentsOffset + 3 >= this.contents.length) {
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 c58e345..46e4ad2 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, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -21,6 +21,7 @@
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 374605 - Unreasonable warning for enum-based switch statements
* bug 384870 - [compiler] @Deprecated annotation not detected if preceded by other annotation
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -134,6 +135,7 @@
// for local decls
public static final int IsTypeElided = Bit2; // type elided lambda argument.
public static final int IsArgument = Bit3;
+ public static final int IsForeachElementVariable = Bit5;
public static final int IsLocalDeclarationReachable = Bit31;
// for name refs or local decls
@@ -548,8 +550,9 @@
return false;
ReferenceBinding refType = (ReferenceBinding) type;
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780
- if (refType instanceof TypeVariableBinding) {
+ if ((this.bits & ASTNode.InsideJavadoc) == 0 && refType instanceof TypeVariableBinding) {
refType.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
}
// ignore references insing Javadoc comments
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index a9765bf..b83edc9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -16,6 +16,7 @@
* Stephan Herrmann - Contributions for
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -838,6 +839,10 @@
FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField);
recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
}
+ if ((sourceField.tagBits & TAGBITS_NULLABLE_OR_NONNULL) == TAGBITS_NULLABLE_OR_NONNULL) {
+ scope.problemReporter().contradictoryNullAnnotations(this);
+ sourceField.tagBits &= ~TAGBITS_NULLABLE_OR_NONNULL; // avoid secondary problems
+ }
break;
case Binding.LOCAL :
LocalVariableBinding variable = (LocalVariableBinding) this.recipient;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
index 24e87d4..fe0f568 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
@@ -13,6 +13,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -188,6 +189,11 @@
codeStream.arrayAtPut(this.resolvedType.id, false);
}
+
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ return FlowInfo.UNKNOWN;
+}
+
public StringBuffer printExpression(int indent, StringBuffer output) {
this.receiver.printExpression(0, output).append('[');
return this.position.printExpression(0, output).append(']');
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index da88a12..75b294a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -22,12 +22,16 @@
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
@@ -85,9 +89,10 @@
}
FlowInfo preInitInfo = null;
+ CompilerOptions compilerOptions = currentScope.compilerOptions();
boolean shouldAnalyseResource = local != null
&& flowInfo.reachMode() == FlowInfo.REACHABLE
- && currentScope.compilerOptions().analyseResourceLeaks
+ && compilerOptions.analyseResourceLeaks
//{ObjectTeams: notably lift methods of Closeable roles would trigger warnings against synthetic code
&& !currentScope.isGeneratedScope()
// SH}
@@ -108,14 +113,29 @@
else
FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression);
- int nullStatus = this.expression.nullStatus(flowInfo);
+ int nullStatus = this.expression.nullStatus(flowInfo, flowContext);
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
if (nullStatus == FlowInfo.NULL) {
flowContext.recordUsingNullReference(currentScope, local, this.lhs,
FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
}
}
- nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, local, nullStatus, this.expression, this.expression.resolvedType);
+ if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
+ VariableBinding var = this.lhs.nullAnnotatedVariableBinding();
+ if (var != null) {
+ nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, var, nullStatus, this.expression, this.expression.resolvedType);
+ if (nullStatus == FlowInfo.NON_NULL
+ && var instanceof FieldBinding
+ && this.lhs instanceof Reference
+ && compilerOptions.enableSyntacticNullAnalysisForFields)
+ {
+ int timeToLive = (this.bits & InsideExpressionStatement) != 0
+ ? 2 // assignment is statement: make info survives the end of this statement
+ : 1; // assignment is expression: expire on next event.
+ flowContext.recordNullCheckedFieldReference((Reference) this.lhs, timeToLive);
+ }
+ }
+ }
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
flowInfo.markNullStatus(local, nullStatus);
if (flowContext.initsOnFinally != null)
@@ -167,8 +187,8 @@
return null;
}
-public int nullStatus(FlowInfo flowInfo) {
- return this.expression.nullStatus(flowInfo);
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ return this.expression.nullStatus(flowInfo, flowContext);
}
public StringBuffer print(int indent, StringBuffer output) {
@@ -227,7 +247,7 @@
scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType);
}
if (this.expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType)
- || rhsType.isCompatibleWith(lhsType)) {
+ || rhsType.isCompatibleWith(lhsType, scope)) {
this.expression.computeConversion(scope, lhsType, rhsType);
checkAssignment(scope, lhsType, rhsType);
if (this.expression instanceof CastExpression
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index 1a1a367..1c4eaa1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -10,6 +10,7 @@
* Technical University Berlin - extended API and implementation
* Stephan Herrmann - Contribution for
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -71,8 +72,15 @@
} else {
this.left.checkNPE(currentScope, flowContext, flowInfo);
flowInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) != AND) {
+ flowContext.expireNullCheckedFieldInfo();
+ }
this.right.checkNPE(currentScope, flowContext, flowInfo);
- return this.right.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ flowInfo = this.right.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) != AND) {
+ flowContext.expireNullCheckedFieldInfo();
+ }
+ return flowInfo;
}
} finally {
// account for exception possibly thrown by arithmetics
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index f9e073e..8cf78aa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -14,6 +14,7 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -47,6 +48,7 @@
// empty block
if (this.statements == null) return flowInfo;
int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED;
+ boolean enableSyntacticNullAnalysisForFields = currentScope.compilerOptions().enableSyntacticNullAnalysisForFields;
for (int i = 0, max = this.statements.length; i < max; i++) {
Statement stat = this.statements[i];
if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
@@ -55,6 +57,9 @@
// record the effect of stat on the finally block of an enclosing try-finally, if any:
if (flowContext.initsOnFinally != null)
flowContext.mergeFinallyNullInfo(flowInfo);
+ if (enableSyntacticNullAnalysisForFields) {
+ flowContext.expireNullCheckedFieldInfo();
+ }
}
if (this.explicitDeclarations > 0) {
// if block has its own scope analyze tracking vars now:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 7390524..72b57cf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -17,6 +17,8 @@
* Stephan Herrmann - Contributions for
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -168,7 +170,7 @@
// double d = (float) n; // cast to float is unnecessary
if (castedExpressionType == null || rhs.resolvedType.isBaseType()) return;
//if (castedExpressionType.id == T_null) return; // tolerate null expression cast
- if (castedExpressionType.isCompatibleWith(expectedType)) {
+ if (castedExpressionType.isCompatibleWith(expectedType, scope)) {
scope.problemReporter().unnecessaryCast(rhs);
}
}
@@ -552,8 +554,8 @@
return this.expression.localVariableBinding();
}
-public int nullStatus(FlowInfo flowInfo) {
- return this.expression.nullStatus(flowInfo);
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ return this.expression.nullStatus(flowInfo, flowContext);
}
/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
index fb166d1..e46fbaa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
@@ -9,6 +9,8 @@
* IBM Corporation - initial API and implementation
* Technical University Berlin - extended API and implementation
* Patrick Wienands <pwienands@abit.de> - Contribution for bug 393749
+ * Stephan Herrmann - Contribution for
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -77,17 +79,23 @@
flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn);
FieldBinding[] fields = this.scope.enclosingSourceType().fields();
for (int i = 0, count = fields.length; i < count; i++) {
- FieldBinding field;
- if ((field = fields[i]).isStatic()
- && field.isFinal()
+ FieldBinding field = fields[i];
//{ObjectTeams: don't check copied fields:
- && (field.copyInheritanceSrc == null)
+ if (field.copyInheritanceSrc != null) continue;
// SH}
- && (!flowInfo.isDefinitelyAssigned(fields[i]))) {
- this.scope.problemReporter().uninitializedBlankFinalField(
- field,
- this.scope.referenceType().declarationOf(field.original()));
- // can complain against the field decl, since only one <clinit>
+ if (field.isStatic()) {
+ if (!flowInfo.isDefinitelyAssigned(field)) {
+ if (field.isFinal()) {
+ this.scope.problemReporter().uninitializedBlankFinalField(
+ field,
+ this.scope.referenceType().declarationOf(field.original()));
+ // can complain against the field decl, since only one <clinit>
+ } else if (field.isNonNull()) {
+ this.scope.problemReporter().uninitializedNonNullField(
+ field,
+ this.scope.referenceType().declarationOf(field.original()));
+ }
+ }
}
}
// check static initializers thrown exceptions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
index 11074dd..3ab010e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -77,7 +78,7 @@
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
-public int nullStatus(FlowInfo flowInfo) {
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
return FlowInfo.NON_NULL;
// we may have complained on checkNPE, but we avoid duplicate error
}
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 3dc331b..1f1c38f 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
@@ -17,6 +17,7 @@
* bug 354554 - [null] conditional with redundant condition yields weak error message
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -85,6 +86,14 @@
this.trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo);
trueFlowInfo = this.valueIfTrue.analyseCode(currentScope, flowContext, trueFlowInfo);
+ // may need to fetch this null status before expireNullCheckedFieldInfo():
+ int preComputedTrueNullStatus = -1;
+ if (currentScope.compilerOptions().enableSyntacticNullAnalysisForFields) {
+ preComputedTrueNullStatus = this.valueIfTrue.nullStatus(trueFlowInfo, flowContext);
+ // wipe information that was meant only for valueIfTrue:
+ flowContext.expireNullCheckedFieldInfo();
+ }
+
// process the if-false part
FlowInfo falseFlowInfo = flowInfo.initsWhenFalse().copy();
if (isConditionOptimizedTrue) {
@@ -104,10 +113,14 @@
FlowInfo mergedInfo;
if (isConditionOptimizedTrue){
mergedInfo = trueFlowInfo.addPotentialInitializationsFrom(falseFlowInfo);
- this.nullStatus = this.valueIfTrue.nullStatus(trueFlowInfo);
+ if (preComputedTrueNullStatus != -1) {
+ this.nullStatus = preComputedTrueNullStatus;
+ } else {
+ this.nullStatus = this.valueIfTrue.nullStatus(trueFlowInfo, flowContext);
+ }
} else if (isConditionOptimizedFalse) {
mergedInfo = falseFlowInfo.addPotentialInitializationsFrom(trueFlowInfo);
- this.nullStatus = this.valueIfFalse.nullStatus(falseFlowInfo);
+ this.nullStatus = this.valueIfFalse.nullStatus(falseFlowInfo, flowContext);
} else {
// this block must meet two conflicting requirements (see https://bugs.eclipse.org/324178):
// (1) For null analysis of "Object o2 = (o1 != null) ? o1 : new Object();" we need to distinguish
@@ -120,7 +133,7 @@
// (regardless of the evaluation of the condition).
// to support (1) use the infos of both branches originating from the condition for computing the nullStatus:
- computeNullStatus(trueFlowInfo, falseFlowInfo);
+ computeNullStatus(preComputedTrueNullStatus, trueFlowInfo, falseFlowInfo, flowContext);
// to support (2) we split the true/false branches according to their inner structure. Consider this:
// if (b ? false : (true && (v = false))) return v; -- ok
@@ -163,11 +176,13 @@
return mergedInfo;
}
- private void computeNullStatus(FlowInfo trueBranchInfo, FlowInfo falseBranchInfo) {
+ private void computeNullStatus(int ifTrueNullStatus, FlowInfo trueBranchInfo, FlowInfo falseBranchInfo, FlowContext flowContext) {
// given that the condition cannot be optimized to a constant
// we now merge the nullStatus from both branches:
- int ifTrueNullStatus = this.valueIfTrue.nullStatus(trueBranchInfo);
- int ifFalseNullStatus = this.valueIfFalse.nullStatus(falseBranchInfo);
+ if (ifTrueNullStatus == -1) { // has this status been pre-computed?
+ ifTrueNullStatus = this.valueIfTrue.nullStatus(trueBranchInfo, flowContext);
+ }
+ int ifFalseNullStatus = this.valueIfFalse.nullStatus(falseBranchInfo, flowContext);
if (ifTrueNullStatus == ifFalseNullStatus) {
this.nullStatus = ifTrueNullStatus;
@@ -384,7 +399,7 @@
codeStream.recordPositionsFrom(pc, this.sourceEnd);
}
- public int nullStatus(FlowInfo flowInfo) {
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
return this.nullStatus;
}
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 09211de..1202ec2 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
@@ -16,6 +16,8 @@
* bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 383690 - [compiler] location of error re uninitialized final field should be aligned
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -275,12 +277,16 @@
// propagate to statements
if (this.statements != null) {
+ boolean enableSyntacticNullAnalysisForFields = this.scope.compilerOptions().enableSyntacticNullAnalysisForFields;
int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE;
for (int i = 0, count = this.statements.length; i < count; i++) {
Statement stat = this.statements[i];
if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo);
}
+ if (enableSyntacticNullAnalysisForFields) {
+ constructorContext.expireNullCheckedFieldInfo();
+ }
}
}
// check for missing returning path
@@ -293,7 +299,7 @@
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=235781
// flowInfo.setReachMode(initialReachMode);
- // check missing blank final field initializations
+ // check missing blank final field initializations (plus @NonNull)
if ((this.constructorCall != null)
//{ObjectTeams: no checking for some more cases:
// don't need to check tsuper ctors:
@@ -305,15 +311,21 @@
flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn);
FieldBinding[] fields = this.binding.declaringClass.fields();
for (int i = 0, count = fields.length; i < count; i++) {
- FieldBinding field;
- if ((!(field = fields[i]).isStatic())
- && field.isFinal()
- && (!flowInfo.isDefinitelyAssigned(fields[i]))) {
- this.scope.problemReporter().uninitializedBlankFinalField(
- field,
- ((this.bits & ASTNode.IsDefaultConstructor) != 0)
- ? (ASTNode) this.scope.referenceType().declarationOf(field.original())
- : this);
+ FieldBinding field = fields[i];
+ if (!field.isStatic() && !flowInfo.isDefinitelyAssigned(field)) {
+ if (field.isFinal()) {
+ this.scope.problemReporter().uninitializedBlankFinalField(
+ field,
+ ((this.bits & ASTNode.IsDefaultConstructor) != 0)
+ ? (ASTNode) this.scope.referenceType().declarationOf(field.original())
+ : this);
+ } else if (field.isNonNull()) {
+ this.scope.problemReporter().uninitializedNonNullField(
+ field,
+ ((this.bits & ASTNode.IsDefaultConstructor) != 0)
+ ? (ASTNode) this.scope.referenceType().declarationOf(field.original())
+ : this);
+ }
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index ef9274b..d3c3303 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -7,7 +7,10 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
+ * Stephan Herrmann - Contributions for
+ * bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -24,28 +27,67 @@
super(left,right,operator);
}
private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
- int rightStatus = this.right.nullStatus(flowInfo);
- int leftStatus = this.left.nullStatus(flowInfo);
- // check if either is a method annotated @NonNull and compared to null:
+
+ // collect null status of child nodes:
+ int rightStatus = this.right.nullStatus(flowInfo, flowContext);
+ int leftStatus = this.left.nullStatus(flowInfo, flowContext);
+
+ boolean leftNonNullChecked = false;
+ boolean rightNonNullChecked = false;
+
+ // check if either is a non-local expression known to be nonnull and compared to null, candidates are
+ // - method/field annotated @NonNull
+ // - allocation expression, some literals, this reference (see inside expressionNonNullComparison(..))
+ // these checks do not leverage the flowInfo.
+ boolean checkEquality = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
if (leftStatus == FlowInfo.NON_NULL && rightStatus == FlowInfo.NULL) {
- if (this.left instanceof MessageSend) {
- scope.problemReporter().messageSendRedundantCheckOnNonNull(((MessageSend) this.left).binding, this.left);
- }
- // TODO: handle all kinds of expressions (cf. also https://bugs.eclipse.org/364326)
+ leftNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.left, checkEquality);
} else if (leftStatus == FlowInfo.NULL && rightStatus == FlowInfo.NON_NULL) {
- if (this.right instanceof MessageSend) {
- scope.problemReporter().messageSendRedundantCheckOnNonNull(((MessageSend) this.right).binding, this.right);
+ rightNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.right, checkEquality);
+ }
+
+ // perform flowInfo-based checks for variables and record info for syntactic null analysis for fields:
+ if (!leftNonNullChecked) {
+ LocalVariableBinding local = this.left.localVariableBinding();
+ if (local != null) {
+ if ((local.type.tagBits & TagBits.IsBaseType) == 0) {
+ checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, rightStatus, this.left);
+ }
+ } else if (this.left instanceof Reference
+ && ((!checkEquality && rightStatus == FlowInfo.NULL) || (checkEquality && rightStatus == FlowInfo.NON_NULL))
+ && scope.compilerOptions().enableSyntacticNullAnalysisForFields)
+ {
+ FieldBinding field = ((Reference)this.left).lastFieldBinding();
+ if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) {
+ flowContext.recordNullCheckedFieldReference((Reference) this.left, 1);
+ }
}
- // TODO: handle all kinds of expressions (cf. also https://bugs.eclipse.org/364326)
+ }
+ if (!rightNonNullChecked) {
+ LocalVariableBinding local = this.right.localVariableBinding();
+ if (local != null) {
+ if ((local.type.tagBits & TagBits.IsBaseType) == 0) {
+ checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, leftStatus, this.right);
+ }
+ } else if (this.right instanceof Reference
+ && ((!checkEquality && leftStatus == FlowInfo.NULL) || (checkEquality && leftStatus == FlowInfo.NON_NULL))
+ && scope.compilerOptions().enableSyntacticNullAnalysisForFields)
+ {
+ FieldBinding field = ((Reference)this.right).lastFieldBinding();
+ if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) {
+ flowContext.recordNullCheckedFieldReference((Reference) this.right, 1);
+ }
+ }
}
- LocalVariableBinding local = this.left.localVariableBinding();
- if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
- checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, rightStatus, this.left);
- }
- local = this.right.localVariableBinding();
- if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
- checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, leftStatus, this.right);
+ // handle reachability:
+ if (leftNonNullChecked || rightNonNullChecked) {
+ // above checks have not propagated unreachable into the corresponding branch, do it now:
+ if (checkEquality) {
+ initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
+ } else {
+ initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
+ }
}
}
private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index 065f139..b3e10c8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -597,17 +597,9 @@
// all constructors with role parameters need to be copied,
// because subteams with declared lifting require control over all code
// in the super-call chain.
- if (RoleTypeBinding.hasNonExternalizedRoleParameter(this.binding))
- {
- boolean needsLifting = ((ConstructorDeclaration)methodDeclaration).needsLifting;
- tsuperMethod = DeclaredLifting.copyTeamConstructorForDeclaredLifting(
- scope, this.binding, argumentTypes, needsLifting);
- } else {
- tsuperMethod = DeclaredLifting.maybeCreateTurningCtor(
- scope.referenceType(),
- this.binding,
- new AstGenerator(this.sourceStart, this.sourceEnd));
- }
+ tsuperMethod = DeclaredLifting.createCopyOrTurningCtor(scope, this.binding, argumentTypes,
+ ((ConstructorDeclaration)methodDeclaration).needsLifting,
+ new AstGenerator(this.sourceStart, this.sourceEnd));
if (tsuperMethod != null)
tsuperArgs = AstEdit.extendTypeArray(
argumentTypes,
@@ -719,8 +711,7 @@
// Now create a chaining ctor for this self call:
// (only now we have the types of all actual arguments).
MethodBinding newBinding;
- newBinding = DeclaredLifting.copyTeamConstructorForDeclaredLifting(
- scope, ctor, argumentTypes, ctorDecl.needsLifting);
+ newBinding = DeclaredLifting.createCopyOrTurningCtor(scope, ctor, argumentTypes, ctorDecl.needsLifting, new AstGenerator(this));
if (newBinding != null)
this.binding = newBinding;
break;
@@ -739,8 +730,7 @@
// ie., create a copy of the super ctor with lifting:
MethodBinding newBinding;
- newBinding = DeclaredLifting.copyTeamConstructorForDeclaredLifting(
- scope, ctor, adjustedArgtypes, ctorDecl.needsLifting);
+ newBinding = DeclaredLifting.createCopyOrTurningCtor(scope, ctor, adjustedArgtypes, ctorDecl.needsLifting, new AstGenerator(this));
if (newBinding != null) {
this.binding = newBinding;
TypeBinding markerType = this.binding.parameters[this.binding.parameters.length-1];
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 0b11ed7..a592b96 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
@@ -17,6 +17,8 @@
* Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
* bug 292478 - Report potentially null across variable assignment
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -50,6 +52,7 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
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.ShouldNotImplement;
import org.eclipse.jdt.internal.compiler.util.Messages;
@@ -709,14 +712,21 @@
{ return false; }
// SH}
/**
- * Check the local variable of this expression, if any, against potential NPEs
- * given a flow context and an upstream flow info. If so, report the risk to
- * the context. Marks the local as checked, which affects the flow info.
+ * Check this expression against potential NPEs, which may occur:
+ * <ul>
+ * <li>if the expression is the receiver in a field access, qualified allocation, array reference or message send
+ * incl. implicit message sends like it happens for the collection in a foreach statement.</li>
+ * <li>if the expression is subject to unboxing</li>
+ * <li>if the expression is the exception in a throw statement</li>
+ * </ul>
+ * If a risk of NPE is detected report it to the context.
+ * If the expression denotes a local variable, mark it as checked, which affects the flow info.
* @param scope the scope of the analysis
* @param flowContext the current flow context
* @param flowInfo the upstream flow info; caveat: may get modified
+ * @return could this expression be checked by the current implementation?
*/
-public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
if (this.resolvedType != null) {
if ((this.resolvedType.tagBits & TagBits.AnnotationNonNull) != 0) {
return; // no danger
@@ -743,7 +753,9 @@
if (flowContext.initsOnFinally != null) {
flowContext.markFinallyNullStatus(local, FlowInfo.NON_NULL);
}
+ return true;
}
+ return false; // not checked
}
public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
@@ -1065,7 +1077,7 @@
this.bits |= ASTNode.IsNonNull;
}
-public int nullStatus(FlowInfo flowInfo) {
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
if (/* (this.bits & IsNonNull) != 0 || */
this.constant != null && this.constant != Constant.NotAConstant)
@@ -1312,4 +1324,13 @@
public void traverse(ASTVisitor visitor, ClassScope scope) {
// nothing to do
}
+
+/**
+ * Used on the lhs of an assignment for detecting null spec violation.
+ * If this expression represents a null-annotated variable return the variable binding,
+ * otherwise null.
+*/
+public VariableBinding nullAnnotatedVariableBinding() {
+ return null;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 12f1ba6..7326bce 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -13,6 +13,9 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -118,6 +121,16 @@
.unconditionalInits();
flowInfo.markAsDefinitelyAssigned(this.binding);
}
+ if (this.initialization != null) {
+ if (this.binding.isNonNull()) {
+ int nullStatus = this.initialization.nullStatus(flowInfo, flowContext);
+ // check against annotation @NonNull:
+ if (nullStatus != FlowInfo.NON_NULL) {
+ char[][] annotationName = initializationScope.environment().getNonNullAnnotationName();
+ initializationScope.problemReporter().nullityMismatch(this.initialization, this.initialization.resolvedType, this.binding.type, nullStatus, annotationName);
+ }
+ }
+ }
return flowInfo;
}
@@ -282,7 +295,7 @@
if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
- || initializationType.isCompatibleWith(fieldType)) {
+ || initializationType.isCompatibleWith(fieldType, classScope)) {
this.initialization.computeConversion(initializationScope, fieldType, initializationType);
if (initializationType.needsUncheckedConversion(fieldType)) {
initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType);
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 70fe09a..506a1a1 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
@@ -8,9 +8,12 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -27,6 +30,7 @@
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
@@ -41,6 +45,7 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
@@ -154,6 +159,14 @@
// assigning a final field outside an initializer or constructor or wrong reference
currentScope.problemReporter().cannotAssignToFinalField(this.binding, this);
}
+ } else if (this.binding.isNonNull()) {
+ // in a context where it can be assigned?
+ if ( !isCompound
+ && this.receiver.isThis()
+ && !(this.receiver instanceof QualifiedThisReference)
+ && ((this.receiver.bits & ASTNode.ParenthesizedMASK) == 0)) { // (this).x is forbidden
+ flowInfo.markAsDefinitelyAssigned(this.binding);
+ }
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
if (!this.binding.isStatic()) {
@@ -196,6 +209,13 @@
return flowInfo;
}
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (flowContext.isNullcheckedFieldAccess(this)) {
+ return true; // enough seen
+ }
+ return checkNullableFieldDereference(scope, this.binding, this.nameSourcePosition);
+}
+
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
*/
@@ -478,6 +498,58 @@
public TypeBinding[] genericTypeArguments() {
return null;
}
+
+public boolean isEquivalent(Reference reference) {
+ // only consider field references relative to "this":
+ if (this.receiver.isThis() && !(this.receiver instanceof QualifiedThisReference)) {
+ // current is a simple "this.f1"
+ char[] otherToken = null;
+ // matching 'reference' could be "f1" or "this.f1":
+ if (reference instanceof SingleNameReference) {
+ otherToken = ((SingleNameReference) reference).token;
+ } else if (reference instanceof FieldReference) {
+ FieldReference fr = (FieldReference) reference;
+ if (fr.receiver.isThis() && !(fr.receiver instanceof QualifiedThisReference)) {
+ otherToken = fr.token;
+ }
+ }
+ return otherToken != null && CharOperation.equals(this.token, otherToken);
+ } else {
+ // search deeper for "this" inside:
+ char[][] thisTokens = getThisFieldTokens(1);
+ if (thisTokens == null) {
+ return false;
+ }
+ // other can be "this.f1.f2", too, or "f1.f2":
+ char[][] otherTokens = null;
+ if (reference instanceof FieldReference) {
+ otherTokens = ((FieldReference) reference).getThisFieldTokens(1);
+ } else if (reference instanceof QualifiedNameReference) {
+ if (((QualifiedNameReference)reference).binding instanceof LocalVariableBinding)
+ return false; // initial variable mismatch: local (from f1.f2) vs. field (from this.f1.f2)
+ otherTokens = ((QualifiedNameReference) reference).tokens;
+ }
+ return CharOperation.equals(thisTokens, otherTokens);
+ }
+}
+
+private char[][] getThisFieldTokens(int nestingCount) {
+ char[][] result = null;
+ if (this.receiver.isThis() && ! (this.receiver instanceof QualifiedThisReference)) {
+ // found an inner-most this-reference, start building the token array:
+ result = new char[nestingCount][];
+ // fill it front to tail while traveling back out:
+ result[0] = this.token;
+ } else if (this.receiver instanceof FieldReference) {
+ result = ((FieldReference)this.receiver).getThisFieldTokens(nestingCount+1);
+ if (result != null) {
+ // front to tail: outermost is last:
+ result[result.length-nestingCount] = this.token;
+ }
+ }
+ return result;
+}
+
public boolean isSuperAccess() {
return this.receiver.isSuper();
}
@@ -486,6 +558,10 @@
return this.receiver != null && this.receiver.isTypeReference();
}
+public FieldBinding lastFieldBinding() {
+ return this.binding;
+}
+
/*
* No need to emulate access to protected fields since not implicitly accessed
*/
@@ -573,9 +649,6 @@
&& this.binding.declaringClass.isRole();
}
// SH}
-public int nullStatus(FlowInfo flowInfo) {
- return FlowInfo.UNKNOWN;
-}
public Constant optimizedBooleanConstant() {
switch (this.resolvedType.id) {
@@ -832,4 +905,12 @@
}
visitor.endVisit(this, scope);
}
+
+public VariableBinding nullAnnotatedVariableBinding() {
+ if (this.binding != null
+ && ((this.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0)) {
+ return this.binding;
+ }
+ return null;
+}
}
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 50632b6..cb28d42 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
@@ -13,6 +13,7 @@
* bug 370930 - NonNull annotation not considered for enhanced for loops
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -443,7 +444,7 @@
&& !this.scope.isBoxingCompatibleWith(this.collectionElementType, elementType)) {
this.scope.problemReporter().notCompatibleTypesErrorInForeach(this.collection, this.collectionElementType, elementType);
} else if (this.collectionElementType.needsUncheckedConversion(elementType)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321085
- this.scope.problemReporter().unsafeTypeConversion(this.collection, collectionType, upperScope.createArrayType(elementType, 1));
+ this.scope.problemReporter().unsafeElementTypeConversion(this.collection, this.collectionElementType, elementType);
}
// :giro
if (Config.getLoweringRequired())
@@ -534,6 +535,8 @@
if (!this.collectionElementType.isCompatibleWith(elementType)
&& !this.scope.isBoxingCompatibleWith(this.collectionElementType, elementType)) {
this.scope.problemReporter().notCompatibleTypesErrorInForeach(this.collection, this.collectionElementType, elementType);
+ } else if (this.collectionElementType.needsUncheckedConversion(elementType)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=393719
+ this.scope.problemReporter().unsafeElementTypeConversion(this.collection, this.collectionElementType, elementType);
}
// :giro
if (Config.getLoweringRequired())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 858ed84..60de061 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -11,6 +11,7 @@
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -104,6 +105,8 @@
}
thenFlowInfo = this.thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
}
+ // any null check from the condition is now expired
+ flowContext.expireNullCheckedFieldInfo();
// code gen: optimizing the jump around the ELSE part
if ((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) {
this.bits |= ASTNode.ThenExit;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 045210d..7054549 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -10,6 +10,8 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -74,6 +76,12 @@
// no impact upon enclosing try context
return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
}
+ if (this.expression instanceof Reference && currentScope.compilerOptions().enableSyntacticNullAnalysisForFields) {
+ FieldBinding field = ((Reference)this.expression).lastFieldBinding();
+ if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) {
+ flowContext.recordNullCheckedFieldReference((Reference) this.expression, 1);
+ }
+ }
return this.expression.analyseCode(currentScope, flowContext, flowInfo).
unconditionalInits();
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index 51d7a75..96edbc1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -660,6 +660,11 @@
TypeBinding paramBindind = param.internalResolveType(scope);
if (paramBindind != null && paramBindind.isValidBinding()) {
if (paramBindind.isTypeVariable()) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
+ if (scope.compilerOptions().reportUnusedParameterIncludeDocCommentReference) {
+ TypeVariableBinding typeVariableBinding = (TypeVariableBinding) paramBindind;
+ typeVariableBinding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
+ }
// Verify duplicated tags
boolean duplicate = false;
for (int j = 0; j < i && !duplicate; j++) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index 7d4d4aa..d88906a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -24,6 +24,8 @@
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
* bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -165,7 +167,7 @@
else
FakedTrackingVariable.cleanUpAfterAssignment(currentScope, Binding.LOCAL, this.initialization);
- int nullStatus = this.initialization.nullStatus(flowInfo);
+ int nullStatus = this.initialization.nullStatus(flowInfo, flowContext);
if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
this.bits |= FirstAssignmentToLocal;
} else {
@@ -350,7 +352,7 @@
if (variableType != initializationType) // must call before computeConversion() and typeMismatchError()
scope.compilationUnitScope().recordTypeConversion(variableType, initializationType);
if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, variableType)
- || initializationType.isCompatibleWith(variableType)) {
+ || initializationType.isCompatibleWith(variableType, scope)) {
this.initialization.computeConversion(scope, variableType, initializationType);
if (initializationType.needsUncheckedConversion(variableType)) {
scope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, variableType);
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 596ed9b..f32170f 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
@@ -28,6 +28,8 @@
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
* bug 381445 - [compiler][resource] Can the resource leak check be made aware of Closeables.closeQuietly?
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -279,6 +281,7 @@
// SH}
// account for pot. exceptions thrown by method execution
flowContext.recordAbruptExit();
+ flowContext.expireNullCheckedFieldInfo(); // no longer trust this info after any message send
return flowInfo;
}
//{ObjectTeams: checkBaseCallsIfSuper
@@ -317,11 +320,11 @@
return flowInfo;
}
// SH}
-public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
- if ((nullStatus(flowInfo) & FlowInfo.POTENTIALLY_NULL) != 0) // note that flowInfo is not used inside nullStatus(..)
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ // 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);
- else
- super.checkNPE(scope, flowContext, flowInfo);
+ return true; // done all possible checking
}
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
@@ -424,6 +427,10 @@
if (this.syntheticAccessor == null){
TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
if (isStatic){
+//{ObjectTeams: role method via the class-part:
+ if (constantPoolDeclaringClass.isRole())
+ constantPoolDeclaringClass = ((ReferenceBinding)constantPoolDeclaringClass).getRealClass();
+// SH}
codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
//{ObjectTeams: decapsulated methods will not be private in the JVM any more:
/* orig:
@@ -548,7 +555,7 @@
}
// SH}
}
-public int nullStatus(FlowInfo flowInfo) {
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
if (this.binding.isValidBinding()) {
// try to retrieve null status of this message send from an annotation of the called method:
long tagBits = this.binding.tagBits;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index 0774d2d..4a198ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -18,6 +18,7 @@
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -172,12 +173,16 @@
}
// propagate to statements
if (this.statements != null) {
+ boolean enableSyntacticNullAnalysisForFields = this.scope.compilerOptions().enableSyntacticNullAnalysisForFields;
int complaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE;
for (int i = 0, count = this.statements.length; i < count; i++) {
Statement stat = this.statements[i];
if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
flowInfo = stat.analyseCode(this.scope, methodContext, flowInfo);
}
+ if (enableSyntacticNullAnalysisForFields) {
+ methodContext.expireNullCheckedFieldInfo();
+ }
}
} else {
// method with empty body should not be flagged as static.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
index f81e561..b83dba8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
@@ -13,6 +13,8 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -72,12 +74,23 @@
this.bits |= Binding.TYPE | Binding.VARIABLE; // restrictiveFlag
}
+/**
+ * Use this method only when sure that the current reference is <strong>not</strong>
+ * a chain of several fields (QualifiedNameReference with more than one field).
+ * Otherwise use {@link #lastFieldBinding()}.
+ */
public FieldBinding fieldBinding() {
//this method should be sent ONLY after a check against isFieldReference()
//check its use doing senders.........
return (FieldBinding) this.binding ;
}
+public FieldBinding lastFieldBinding() {
+ if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD)
+ return fieldBinding(); // most subclasses only refer to one field anyway
+ return null;
+}
+
public boolean isSuperAccess() {
return false;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
index aa77770..5e5bbbd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
@@ -7,11 +7,14 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -49,7 +52,7 @@
return TypeBinding.NULL;
}
- public int nullStatus(FlowInfo flowInfo) {
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
return FlowInfo.NULL;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index 443391d..111714a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * Stephan Herrmann - Contributions for
+ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -41,13 +43,16 @@
// need to be careful of scenario:
// (x || y) || !z, if passing the left info to the right, it would be swapped by the !
FlowInfo mergedInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ flowContext.expireNullCheckedFieldInfo();
mergedInfo = this.right.analyseCode(currentScope, flowContext, mergedInfo);
+ flowContext.expireNullCheckedFieldInfo();
this.mergedInitStateIndex =
currentScope.methodScope().recordInitializationStates(mergedInfo);
return mergedInfo;
}
FlowInfo leftInfo = this.left.analyseCode(currentScope, flowContext, flowInfo);
+ flowContext.expireNullCheckedFieldInfo();
// need to be careful of scenario:
// (x || y) || !z, if passing the left info to the right, it would be swapped by the !
@@ -63,6 +68,7 @@
}
}
rightInfo = this.right.analyseCode(currentScope, flowContext, rightInfo);
+ flowContext.expireNullCheckedFieldInfo();
if ((this.left.implicitConversion & TypeIds.UNBOXING) != 0) {
this.left.checkNPE(currentScope, flowContext, flowInfo);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
index f43174d..8cd4584 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
@@ -8,9 +8,12 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Perry James - nullStatus method improvement (165346)
+ * Stephan Herrmann - Contribution for
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -1556,7 +1559,7 @@
return "unknown operator"; //$NON-NLS-1$
}
- public int nullStatus(FlowInfo flowInfo) {
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
return FlowInfo.NON_NULL;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index a831231..df16240 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -19,6 +19,8 @@
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -143,7 +145,7 @@
localBinding.useFlag = LocalVariableBinding.FAKE_USED;
}
if (needValue) {
- checkNPE(currentScope, flowContext, flowInfo, true);
+ checkInternalNPE(currentScope, flowContext, flowInfo, true);
}
}
@@ -204,6 +206,7 @@
}
}
}
+ // note: not covering def.assign for @NonNull: QNR cannot provably refer to a variable of the current object
manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, -1 /*write-access*/, flowInfo);
return flowInfo;
@@ -249,10 +252,10 @@
} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
localBinding.useFlag = LocalVariableBinding.FAKE_USED;
}
- if (needValue) {
- checkNPE(currentScope, flowContext, flowInfo, true);
- }
}
+ if (needValue) {
+ checkInternalNPE(currentScope, flowContext, flowInfo, true);
+ }
if (needValue) {
manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
// only for first binding (if value needed only)
@@ -268,9 +271,8 @@
return flowInfo;
}
-public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) {
- // cannot override localVariableBinding because this would project o.m onto o when
- // analyzing assignments
+/* check if any dot in this QNR may trigger an NPE. */
+private void checkInternalNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) {
if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) {
LocalVariableBinding local = (LocalVariableBinding) this.binding;
if (local != null &&
@@ -287,6 +289,38 @@
}
}
}
+ if (this.otherBindings != null) {
+ if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) {
+ // is the first field dereferenced annotated Nullable? If so, report immediately
+ checkNullableFieldDereference(scope, (FieldBinding) this.binding, this.sourcePositions[0]);
+ }
+ // look for annotated fields, they do not depend on flow context -> check immediately:
+ int length = this.otherBindings.length - 1; // don't check the last binding
+ for (int i = 0; i < length; i++) {
+ checkNullableFieldDereference(scope, this.otherBindings[i], this.sourcePositions[i+1]);
+ }
+ }
+}
+
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (super.checkNPE(scope, flowContext, flowInfo)) {
+ return true;
+ }
+ FieldBinding fieldBinding = null;
+ long position = 0L;
+ if (this.otherBindings == null) {
+ if ((this.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+ fieldBinding = (FieldBinding) this.binding;
+ position = this.sourcePositions[0];
+ }
+ } else {
+ fieldBinding = this.otherBindings[this.otherBindings.length - 1];
+ position = this.sourcePositions[this.sourcePositions.length - 1];
+ }
+ if (fieldBinding != null) {
+ return checkNullableFieldDereference(scope, fieldBinding, position);
+ }
+ return false;
}
/**
@@ -908,12 +942,45 @@
setSyntheticAccessor(baseclassField, idx, new SyntheticMethodBinding(fakedAccessorBinding, SyntheticMethodBinding.InferredCalloutToField));
}
// SH}
+
+public boolean isEquivalent(Reference reference) {
+ if (reference instanceof FieldReference) {
+ return reference.isEquivalent(this); // comparison FR <-> QNR is implemented only once
+ }
+ if (!(reference instanceof QualifiedNameReference)) return false;
+ // straight-forward test of equality of two QNRs:
+ QualifiedNameReference qualifiedReference = (QualifiedNameReference) reference;
+ if (this.tokens.length != qualifiedReference.tokens.length) return false;
+ if (this.binding != qualifiedReference.binding) return false;
+ if (this.otherBindings != null) {
+ if (qualifiedReference.otherBindings == null) return false;
+ int len = this.otherBindings.length;
+ if (len != qualifiedReference.otherBindings.length) return false;
+ for (int i=0; i<len; i++) {
+ if (this.otherBindings[i] != qualifiedReference.otherBindings[i]) return false;
+ }
+ } else if (qualifiedReference.otherBindings != null) {
+ return false;
+ }
+ return true;
+}
+
public boolean isFieldAccess() {
if (this.otherBindings != null) {
return true;
}
return (this.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD;
}
+
+public FieldBinding lastFieldBinding() {
+ if (this.otherBindings != null) {
+ return this.otherBindings[this.otherBindings.length - 1];
+ } else if (this.binding != null && (this.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+ return (FieldBinding) this.binding;
+ }
+ return null;
+}
+
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
//If inlinable field, forget the access emulation, the code gen will directly target it
if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) {
@@ -1017,10 +1084,6 @@
}
}
-public int nullStatus(FlowInfo flowInfo) {
- return FlowInfo.UNKNOWN;
-}
-
public Constant optimizedBooleanConstant() {
switch (this.resolvedType.id) {
case T_boolean :
@@ -1306,4 +1369,19 @@
public char[][] getName() {
return this.tokens;
}
+
+public VariableBinding nullAnnotatedVariableBinding() {
+ if (this.binding != null && isFieldAccess()) {
+ FieldBinding fieldBinding;
+ if (this.otherBindings == null) {
+ fieldBinding = (FieldBinding) this.binding;
+ } else {
+ fieldBinding = this.otherBindings[this.otherBindings.length - 1];
+ }
+ if (fieldBinding.isNullable() || fieldBinding.isNonNull()) {
+ return fieldBinding;
+ }
+ }
+ return null;
+}
}
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 d228167..6b4e021 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, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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,8 @@
* Technical University Berlin - extended API and implementation
* Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
* bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -45,7 +47,6 @@
* Why: inferred callout to field must be created with proper type, possibly involving lifting.
*
* @author stephan
- * @version $Id: Reference.java 23404 2010-02-03 14:10:22Z stephan $
*/
public abstract class Reference extends Expression {
//{ObjectTeams: store expected type to support infering callout-to-field
@@ -67,6 +68,21 @@
return flowInfo;
}
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (flowContext.isNullcheckedFieldAccess(this)) {
+ return true; // enough seen
+ }
+ return super.checkNPE(scope, flowContext, flowInfo);
+}
+
+protected boolean checkNullableFieldDereference(Scope scope, FieldBinding field, long sourcePosition) {
+ if ((field.tagBits & TagBits.AnnotationNullable) != 0) {
+ scope.problemReporter().nullableFieldDereference(field, sourcePosition);
+ return true;
+ }
+ return false;
+}
+
public FieldBinding fieldBinding() {
//this method should be sent one FIELD-tagged references
// (ref.bits & BindingIds.FIELD != 0)()
@@ -121,6 +137,7 @@
public abstract void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired);
+// FIXME(SH): obsolete after merge??
public int nullStatus(FlowInfo flowInfo) {
if (this.resolvedType != null) {
if ((this.resolvedType.tagBits & TagBits.AnnotationNonNull) != 0)
@@ -131,6 +148,34 @@
return FlowInfo.UNKNOWN;
}
+/**
+ * Is the given reference equivalent to the receiver,
+ * meaning that both denote the same path of field reads?
+ * Used from {@link FlowContext#isNullcheckedFieldAccess(Reference)}.
+ */
+public boolean isEquivalent(Reference reference) {
+ return false;
+}
+
+public FieldBinding lastFieldBinding() {
+ // override to answer the field designated by the entire reference
+ // (as opposed to fieldBinding() which answers the first field in a QNR)
+ return null;
+}
+
+public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ FieldBinding fieldBinding = lastFieldBinding();
+ if (fieldBinding != null) {
+ if (fieldBinding.isNonNull() || flowContext.isNullcheckedFieldAccess(this)) {
+ return FlowInfo.NON_NULL;
+ } else if (fieldBinding.isNullable()) {
+ return FlowInfo.POTENTIALLY_NULL;
+ }
+ return FlowInfo.UNKNOWN;
+ }
+ return super.nullStatus(flowInfo, flowContext);
+}
+
/* report if a private field is only read from a 'special operator',
* i.e., in a postIncrement expression or a compound assignment,
* where the information is never flowing out off the field. */
@@ -217,6 +262,7 @@
// through copy inheritance this code could be executed within a different package!
if (depth == 0)
return -1; // neither a team field, nor an access across packages
+ this.bits = (this.bits & ~DepthMASK) | ((depth & 0xFF) << DepthSHIFT);
}
return depth;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index 9b70190..fc52146 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -22,6 +22,7 @@
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
@@ -63,7 +64,7 @@
this.expression.checkNPE(currentScope, flowContext, flowInfo);
}
if (flowInfo.reachMode() == FlowInfo.REACHABLE)
- checkAgainstNullAnnotation(currentScope, flowContext, this.expression.nullStatus(flowInfo));
+ checkAgainstNullAnnotation(currentScope, flowContext, this.expression.nullStatus(flowInfo, flowContext));
if (currentScope.compilerOptions().analyseResourceLeaks) {
FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression, flowInfo, flowContext);
if (trackingVariable != null) {
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 ef8681a..6b1da3c 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
@@ -11,10 +11,13 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 292478 - Report potentially null across variable assignment,
- * Contribution for bug 185682 - Increment/decrement operators mark local variables as read
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 292478 - Report potentially null across variable assignment,
+ * bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -64,7 +67,6 @@
*
* What: wrap role type in resolveType().
*
- * @version $Id: SingleNameReference.java 23404 2010-02-03 14:10:22Z stephan $
*/
public class SingleNameReference extends NameReference implements OperatorIds {
@@ -142,6 +144,9 @@
} else {
currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
}
+ } else if (!isCompound && fieldBinding.isNonNull()) {
+ // record assignment for detecting uninitialized non-null fields:
+ flowInfo.markAsDefinitelyAssigned(fieldBinding);
}
if (!fieldBinding.isStatic()) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
@@ -267,6 +272,17 @@
}
+public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (!super.checkNPE(scope, flowContext, flowInfo)) {
+ VariableBinding var = nullAnnotatedVariableBinding();
+ if (var instanceof FieldBinding) {
+ checkNullableFieldDereference(scope, (FieldBinding) var, ((long)this.sourceStart<<32)+this.sourceEnd);
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
*/
@@ -828,6 +844,19 @@
return null;
}
+public boolean isEquivalent(Reference reference) {
+ char[] otherToken = null;
+ if (reference instanceof SingleNameReference) {
+ otherToken = ((SingleNameReference) reference).token;
+ } else if (reference instanceof FieldReference) {
+ // test for comparison "f1" vs. "this.f1":
+ FieldReference fr = (FieldReference) reference;
+ if (fr.receiver.isThis() && !(fr.receiver instanceof QualifiedThisReference))
+ otherToken = fr.token;
+ }
+ return otherToken != null && CharOperation.equals(this.token, otherToken);
+}
+
/**
* Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
* or thru a cast expression etc...
@@ -842,6 +871,16 @@
return null;
}
+public VariableBinding nullAnnotatedVariableBinding() {
+ switch (this.bits & ASTNode.RestrictiveFlagMASK) {
+ case Binding.FIELD : // reading a field
+ case Binding.LOCAL : // reading a local variable
+ if ((((VariableBinding)this.binding).tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0)
+ return (VariableBinding) this.binding;
+ }
+ return null;
+}
+
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
//If inlinable field, forget the access emulation, the code gen will directly target it
if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) {
@@ -904,21 +943,6 @@
}
}
-public int nullStatus(FlowInfo flowInfo) {
- if (this.constant != null && this.constant != Constant.NotAConstant) {
- return FlowInfo.NON_NULL; // constant expression cannot be null
- }
- switch (this.bits & ASTNode.RestrictiveFlagMASK) {
- case Binding.FIELD : // reading a field
- return FlowInfo.UNKNOWN;
- case Binding.LOCAL : // reading a local variable
- LocalVariableBinding local = (LocalVariableBinding) this.binding;
- if (local != null)
- return flowInfo.nullStatus(local);
- }
- return FlowInfo.NON_NULL; // never get there
-}
-
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
*/
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 f2c21f5..f20901e 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
@@ -21,6 +21,8 @@
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 370930 - NonNull annotation not considered for enhanced for loops
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -130,7 +132,7 @@
if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) {
TypeBinding expectedType = methodBinding.parameters[i];
Expression argument = arguments[i];
- int nullStatus = argument.nullStatus(flowInfo); // slight loss of precision: should also use the null info from the receiver.
+ int nullStatus = argument.nullStatus(flowInfo, flowContext); // slight loss of precision: should also use the null info from the receiver.
if (nullStatus != FlowInfo.NON_NULL) // if required non-null is not provided
flowContext.recordNullityMismatch(currentScope, argument, argument.resolvedType, expectedType, nullStatus);
}
@@ -139,22 +141,20 @@
}
}
-/** Check null-ness of 'local' against a possible null annotation */
+/** Check null-ness of 'var' against a possible null annotation */
protected int checkAssignmentAgainstNullAnnotation(BlockScope currentScope, FlowContext flowContext,
- LocalVariableBinding local, int nullStatus, Expression expression, TypeBinding providedType)
+ VariableBinding var, int nullStatus, Expression expression, TypeBinding providedType)
{
- if (local != null) {
- int severity = 0;
- if ((local.tagBits & TagBits.AnnotationNonNull) != 0
- && nullStatus != FlowInfo.NON_NULL) {
- flowContext.recordNullityMismatch(currentScope, expression, providedType, local.type, nullStatus);
- return FlowInfo.NON_NULL;
- } else if ((severity = findNullTypeAnnotationMismatch(local.type, providedType)) > 0) {
- currentScope.problemReporter().nullityMismatchingTypeAnnotation(expression, providedType, local.type, severity==1, currentScope.environment());
- } else if ((local.tagBits & TagBits.AnnotationNullable) != 0
- && nullStatus == FlowInfo.UNKNOWN) { // provided a legacy type?
- return FlowInfo.POTENTIALLY_NULL; // -> use more specific info from the annotation
- }
+ int severity = 0;
+ if ((var.tagBits & TagBits.AnnotationNonNull) != 0
+ && nullStatus != FlowInfo.NON_NULL) {
+ flowContext.recordNullityMismatch(currentScope, expression, providedType, var.type, nullStatus);
+ return FlowInfo.NON_NULL;
+ } else if ((severity = findNullTypeAnnotationMismatch(var.type, providedType)) > 0) {
+ currentScope.problemReporter().nullityMismatchingTypeAnnotation(expression, providedType, var.type, severity==1, currentScope.environment());
+ } else if ((var.tagBits & TagBits.AnnotationNullable) != 0
+ && nullStatus == FlowInfo.UNKNOWN) { // provided a legacy type?
+ return FlowInfo.POTENTIALLY_NULL; // -> use more specific info from the annotation
}
return nullStatus;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
index 670959b..26327c4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
@@ -4,12 +4,14 @@
* 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
- * $Id: ThisReference.java 23404 2010-02-03 14:10:22Z stephan $
*
* Contributors:
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -25,8 +27,6 @@
* OTDT changes:
*
* What: if it's not an ImplicitThis, wrap the type if its a role.
- *
- * @version $Id: ThisReference.java 23404 2010-02-03 14:10:22Z stephan $
*/
public class ThisReference extends Reference {
@@ -67,6 +67,10 @@
return true;
}
+ public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ return true; // never problematic
+ }
+
/*
* @see Reference#generateAssignment(...)
*/
@@ -109,10 +113,6 @@
return true ;
}
- public int nullStatus(FlowInfo flowInfo) {
- return FlowInfo.NON_NULL;
- }
-
public StringBuffer printExpression(int indent, StringBuffer output){
if (isImplicitThis()) return output;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index bd55f53..1a10865 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -782,7 +782,9 @@
sourceType); //declaringClass
constructor.binding.tagBits |= (inheritedConstructorBinding.tagBits & TagBits.HasMissingType);
constructor.binding.modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
- if (inheritedConstructorBinding.parameterNonNullness != null) { // this implies that annotation based null analysis is enabled
+ if (inheritedConstructorBinding.parameterNonNullness != null // this implies that annotation based null analysis is enabled
+ && argumentsLength > 0)
+ {
// copy nullness info from inherited constructor to the new constructor:
int len = inheritedConstructorBinding.parameterNonNullness.length;
System.arraycopy(inheritedConstructorBinding.parameterNonNullness, 0,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
index 5512e73..a99dd24 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -213,7 +213,7 @@
if (!ProblemAnchorBinding.checkAnchor(scope, this.type, anchors[0], this.name))
return;
if (anchors[0] instanceof FieldBinding && anchors[0].isValidBinding())
- FieldModel.getModel((FieldBinding)anchors[0]).addUsageRank(this.binding.rank);
+ FieldModel.getModel(((FieldBinding)anchors[0]).original()).addUsageRank(this.binding.rank);
// FIXME(SH): else store this in the AnchorListAttribute!
int boundCnt = 0;
if (this.bounds != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index 261bf8e..81b9323 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -33,9 +35,11 @@
FlowInfo flowInfo) {
this.expression.checkNPE(currentScope, flowContext, flowInfo);
if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
- return this.expression.
+ flowInfo = this.expression.
analyseCode(currentScope, flowContext, flowInfo).
asNegatedCondition();
+ flowContext.expireNullCheckedFieldInfo();
+ return flowInfo;
} else {
return this.expression.
analyseCode(currentScope, flowContext, flowInfo);
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 3d3afc0..438d880 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
@@ -35,6 +35,8 @@
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.core.compiler.ISMAPConstants;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticOTMethodBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleFieldAccess;
@@ -2823,6 +2825,25 @@
syntheticArgType,
false /*not only exact match (that is, allow compatible)*/,
denyEnclosingArgInConstructorCall);
+//{ObjectTeams: find enclosing via a team anchor?
+ if (emulationPath == null && RoleTypeBinding.isRoleWithExplicitAnchor(targetType)) {
+ ITeamAnchor anchor = ((DependentTypeBinding)targetType)._teamAnchor;
+ ITeamAnchor[] path = anchor.getBestNamePath();
+ if ((((VariableBinding)path[0]).modifiers & ClassFileConstants.AccStatic) == 0) {
+ Object[] path1 = currentScope.getEmulationPath(anchor.getFirstDeclaringClass(), true, false);
+ emulationPath = new Object[path1.length + path.length];
+ System.arraycopy(path1, 0, emulationPath, 0, path1.length);
+ System.arraycopy(path, 0, emulationPath, path1.length, path.length);
+ } else {
+ byte opcode = Opcodes.OPC_getstatic;
+ for(ITeamAnchor field : path) {
+ fieldAccess(opcode, (FieldBinding)field, ((FieldBinding)field).getDeclaringClass().getRealClass());
+ opcode = Opcodes.OPC_getfield;
+ }
+ return;
+ }
+ }
+// SH}
generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope);
}
}
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 2998097..d8e5ddd 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
@@ -13,6 +13,7 @@
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
@@ -70,6 +71,12 @@
// array to store the provided and expected types from the potential error location (for display in error messages):
public TypeBinding[][] providedExpectedTypes = null;
+ // record field references known to be non-null
+ // this array will never shrink, only grow. reset happens by nulling the first cell
+ // adding elements after reset ensures that the valid part of the array is always null-terminated
+ private Reference[] nullCheckedFieldReferences = null;
+ private int timeToLiveForNullCheckInfo = -1;
+
public static final int DEFER_NULL_DIAGNOSTIC = 0x1;
public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2;
/**
@@ -109,9 +116,74 @@
}
this.initsOnFinally = parent.initsOnFinally;
this.conditionalLevel = parent.conditionalLevel;
+ this.nullCheckedFieldReferences = parent.nullCheckedFieldReferences; // re-use list if there is one
}
}
+/**
+ * Record that a reference to a field has been seen in a non-null state.
+ *
+ * @param reference Can be a SingleNameReference, a FieldReference or a QualifiedNameReference resolving to a field
+ * @param timeToLive control how many expire events are needed to expire this information
+ */
+public void recordNullCheckedFieldReference(Reference reference, int timeToLive) {
+ this.timeToLiveForNullCheckInfo = timeToLive;
+ if (this.nullCheckedFieldReferences == null) {
+ // first entry:
+ this.nullCheckedFieldReferences = new Reference[2];
+ this.nullCheckedFieldReferences[0] = reference;
+ } else {
+ int len = this.nullCheckedFieldReferences.length;
+ // insert into first empty slot:
+ for (int i=0; i<len; i++) {
+ if (this.nullCheckedFieldReferences[i] == null) {
+ this.nullCheckedFieldReferences[i] = reference;
+ if (i+1 < len) {
+ this.nullCheckedFieldReferences[i+1] = null; // lazily mark next as empty
+ }
+ return;
+ }
+ }
+ // grow array:
+ System.arraycopy(this.nullCheckedFieldReferences, 0, this.nullCheckedFieldReferences=new Reference[len+2], 0, len);
+ this.nullCheckedFieldReferences[len] = reference;
+ }
+}
+/**
+ * Forget any information about fields that were previously known to be non-null.
+ *
+ * Will only cause any effect if CompilerOptions.enableSyntacticNullAnalysisForFields
+ * (implicitly by guards before calls to {@link #recordNullCheckedFieldReference(Reference, int)}).
+ */
+public void expireNullCheckedFieldInfo() {
+ if (this.nullCheckedFieldReferences != null) {
+ if (--this.timeToLiveForNullCheckInfo == 0) {
+ this.nullCheckedFieldReferences[0] = null; // lazily wipe
+ }
+ }
+}
+
+/**
+ * Is the given field reference equivalent to a reference that is freshly known to be non-null?
+ * Can only return true if CompilerOptions.enableSyntacticNullAnalysisForFields
+ * (implicitly by guards before calls to {@link #recordNullCheckedFieldReference(Reference, int)}).
+ */
+public boolean isNullcheckedFieldAccess(Reference reference) {
+ if (this.nullCheckedFieldReferences == null) // always null unless CompilerOptions.enableSyntacticNullAnalysisForFields
+ return false;
+ int len = this.nullCheckedFieldReferences.length;
+ for (int i=0; i<len; i++) {
+ Reference checked = this.nullCheckedFieldReferences[i];
+ if (checked == null) {
+ return false;
+ }
+ if (checked.isEquivalent(reference)) {
+ return true;
+ }
+ }
+ return false;
+}
+
public BranchLabel breakLabel() {
return null;
}
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 5020e8a..5dcf13a 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
@@ -15,6 +15,7 @@
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
* bug 385626 - @NonNull fails across loop boundaries
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
+ * bug 376263 - Bogus "Potential null pointer access" warning
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
@@ -148,6 +149,7 @@
addPotentialNullInfoFrom(this.innerFlowInfos[i]);
}
this.innerFlowContextsCount = 0;
+ FlowInfo upstreamCopy = this.upstreamNullFlowInfo.copy();
UnconditionalFlowInfo flowInfo = this.upstreamNullFlowInfo.
addPotentialNullInfoFrom(callerFlowInfo.unconditionalInitsWithoutSideEffect());
if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) {
@@ -277,8 +279,12 @@
default:
// never happens
}
- this.parent.recordUsingNullReference(scope, local, location,
- this.nullCheckTypes[i], flowInfo);
+ // https://bugs.eclipse.org/376263: avoid further deferring if the upstream info
+ // already has definite information (which might get lost for deferred checking).
+ if (!(this.nullCheckTypes[i] == MAY_NULL && upstreamCopy.isDefinitelyNonNull(local))) {
+ this.parent.recordUsingNullReference(scope, local, location,
+ this.nullCheckTypes[i], flowInfo);
+ }
}
}
else {
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 f0aef68..ca5d788 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
@@ -23,6 +23,8 @@
* bug 366063 - Compiler should not add synthetic @NonNull annotations
* bug 374605 - Unreasonable warning for enum-based switch statements
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+ * bug 383368 - [compiler][null] syntactic null analysis for field references
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.impl;
@@ -245,7 +247,9 @@
static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$
static final char[][] DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNullByDefault".toCharArray()); //$NON-NLS-1$
public static final String OPTION_ReportMissingNonNullByDefaultAnnotation = "org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation"; //$NON-NLS-1$
+ 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$
/**
* Possible values for configurable options
*/
@@ -360,6 +364,7 @@
public static final int MissingNonNullByDefaultAnnotation = IrritantSet.GROUP2 | ASTNode.Bit15;
public static final int MissingDefaultCase = IrritantSet.GROUP2 | ASTNode.Bit16;
public static final int UnusedTypeParameter = IrritantSet.GROUP2 | ASTNode.Bit17;
+ public static final int NonnullParameterAnnotationDropped = IrritantSet.GROUP2 | ASTNode.Bit18;
//{ObjectTeams: OT/J specific problems/irritants:
public static final int OTJFlag = IrritantSet.GROUP3;
@@ -547,6 +552,9 @@
/** Should null annotations of overridden methods be inherited? */
public boolean inheritNullAnnotations;
+ /** Should immediate null-check for fields be considered during null analysis (syntactical match)? */
+ public boolean enableSyntacticNullAnalysisForFields;
+
// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
public final static String[] warningTokens = {
"all", //$NON-NLS-1$
@@ -824,6 +832,8 @@
return OPTION_ReportNullUncheckedConversion;
case RedundantNullAnnotation :
return OPTION_ReportRedundantNullAnnotation;
+ case NonnullParameterAnnotationDropped:
+ return OPTION_ReportNonnullParameterAnnotationDropped;
}
return null;
}
@@ -1030,8 +1040,10 @@
OPTION_ReportNullAnnotationInferenceConflict,
OPTION_ReportNullUncheckedConversion,
OPTION_ReportRedundantNullAnnotation,
+ OPTION_SyntacticNullAnalysisForFields,
OPTION_ReportUnusedTypeParameter,
- OPTION_InheritNullAnnotations
+ OPTION_InheritNullAnnotations,
+ OPTION_ReportNonnullParameterAnnotationDropped
};
return result;
}
@@ -1101,6 +1113,7 @@
case NullUncheckedConversion :
case RedundantNullAnnotation :
case MissingNonNullByDefaultAnnotation:
+ case NonnullParameterAnnotationDropped:
return "null"; //$NON-NLS-1$
case FallthroughCase :
return "fallthrough"; //$NON-NLS-1$
@@ -1463,7 +1476,9 @@
optionsMap.put(OPTION_NonNullByDefaultAnnotationName, String.valueOf(CharOperation.concatWith(this.nonNullByDefaultAnnotationName, '.')));
optionsMap.put(OPTION_ReportMissingNonNullByDefaultAnnotation, getSeverityString(MissingNonNullByDefaultAnnotation));
optionsMap.put(OPTION_ReportUnusedTypeParameter, getSeverityString(UnusedTypeParameter));
+ optionsMap.put(OPTION_SyntacticNullAnalysisForFields, this.enableSyntacticNullAnalysisForFields ? ENABLED : DISABLED);
optionsMap.put(OPTION_InheritNullAnnotations, this.inheritNullAnnotations ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_ReportNonnullParameterAnnotationDropped, getSeverityString(NonnullParameterAnnotationDropped));
return optionsMap;
}
@@ -1622,6 +1637,7 @@
this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
this.nonNullByDefaultAnnotationName = DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME;
this.intendedDefaultNonNullness = 0;
+ this.enableSyntacticNullAnalysisForFields = false;
this.inheritNullAnnotations = false;
this.analyseResourceLeaks = true;
@@ -2000,9 +2016,13 @@
this.nonNullByDefaultAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
}
if ((optionValue = optionsMap.get(OPTION_ReportMissingNonNullByDefaultAnnotation)) != null) updateSeverity(MissingNonNullByDefaultAnnotation, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_SyntacticNullAnalysisForFields)) != null) {
+ this.enableSyntacticNullAnalysisForFields = ENABLED.equals(optionValue);
+ }
if ((optionValue = optionsMap.get(OPTION_InheritNullAnnotations)) != null) {
this.inheritNullAnnotations = ENABLED.equals(optionValue);
}
+ if ((optionValue = optionsMap.get(OPTION_ReportNonnullParameterAnnotationDropped)) != null) updateSeverity(NonnullParameterAnnotationDropped, optionValue);
}
// Javadoc options
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 8efc755..dba49a4 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
@@ -14,6 +14,7 @@
* bug 370639 - [compiler][resource] restore the default for resource leak warnings
* bug 265744 - Enum switch should warn about missing default
* bug 374605 - Unreasonable warning for enum-based switch statements
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.impl;
@@ -186,7 +187,8 @@
|CompilerOptions.Tasks
|CompilerOptions.UnclosedCloseable
|CompilerOptions.NullUncheckedConversion
- |CompilerOptions.RedundantNullAnnotation);
+ |CompilerOptions.RedundantNullAnnotation
+ |CompilerOptions.NonnullParameterAnnotationDropped);
// default errors IF AnnotationBasedNullAnalysis is enabled:
COMPILER_DEFAULT_ERRORS.set(
CompilerOptions.NullSpecViolation
@@ -203,7 +205,8 @@
.set(CompilerOptions.NullSpecViolation)
.set(CompilerOptions.NullAnnotationInferenceConflict)
.set(CompilerOptions.NullUncheckedConversion)
- .set(CompilerOptions.RedundantNullAnnotation);
+ .set(CompilerOptions.RedundantNullAnnotation)
+ .set(CompilerOptions.NonnullParameterAnnotationDropped);
RESTRICTION.set(CompilerOptions.DiscouragedReference);
STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index be06999..1774795 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -13,6 +13,7 @@
* IBM Corporation - initial API and implementation
* Technical University Berlin - extended API and implementation
* Stephan Herrmann - Contribution for
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -194,7 +195,7 @@
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
-public boolean isCompatibleWith(TypeBinding otherType) {
+public boolean isCompatibleWith(TypeBinding otherType, Scope captureScope) {
if (this == otherType)
return true;
@@ -221,7 +222,7 @@
TypeBinding otherLowerBound;
if ((otherLowerBound = otherCapture.lowerBound) != null) {
if (!otherLowerBound.isArrayType()) return false;
- return isCompatibleWith(otherLowerBound);
+ return isCompatibleWith(otherLowerBound, captureScope);
}
}
return false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
index 40c9075..1e11782 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -150,7 +152,7 @@
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
- public final boolean isCompatibleWith(TypeBinding left) {
+ public final boolean isCompatibleWith(TypeBinding left, Scope captureScope) {
if (this == left)
return true;
int right2left = this.id + (left.id<<4);
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 623bc8b..96196d7 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
@@ -22,6 +22,7 @@
* bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
* bug 388800 - [1.8][compiler] detect default methods in class files
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -655,6 +656,12 @@
this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames));
}
}
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ for (int i = 0; i <size; i++) {
+ IBinaryField binaryField = iFields[i];
+ scanFieldForNullAnnotation(binaryField, this.fields[i]);
+ }
+ }
}
}
}
@@ -1588,6 +1595,42 @@
}
return this.storedAnnotations;
}
+
+void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding) {
+ // global option is checked by caller
+ char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
+ char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
+ if (nullableAnnotationName == null || nonNullAnnotationName == null)
+ return; // not well-configured to use null annotations
+
+ if (fieldBinding.type == null || fieldBinding.type.isBaseType())
+ return; // null annotations are only applied to reference types
+
+ boolean explicitNullness = false;
+ IBinaryAnnotation[] annotations = field.getAnnotations();
+ if (annotations != null) {
+ for (int i = 0; i < annotations.length; i++) {
+ char[] annotationTypeName = annotations[i].getTypeName();
+ if (annotationTypeName[0] != Util.C_RESOLVED)
+ continue;
+ char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
+ if (CharOperation.equals(typeName, nonNullAnnotationName)) {
+ fieldBinding.tagBits |= TagBits.AnnotationNonNull;
+ explicitNullness = true;
+ break;
+ }
+ if (CharOperation.equals(typeName, nullableAnnotationName)) {
+ fieldBinding.tagBits |= TagBits.AnnotationNullable;
+ explicitNullness = true;
+ break;
+ }
+ }
+ }
+ if (!explicitNullness && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ fieldBinding.tagBits |= TagBits.AnnotationNonNull;
+ }
+}
+
void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) {
if (!this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
return;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index e02ff4f..f18fac1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -636,6 +636,14 @@
}
// binding is a ReferenceBinding
if (!binding.isValidBinding()) {
+//{ObjectTeams: let decapsulation see into nested levels of invisible types:
+ if (binding.problemId() == ProblemReasons.NotVisible
+ && invocationSite instanceof Expression
+ && ((Expression)invocationSite).getBaseclassDecapsulation().isAllowed())
+ {
+ binding = ((ProblemReferenceBinding)binding).closestMatch;
+ } else {
+// orig:
if (problemFieldBinding != null) {
return problemFieldBinding;
}
@@ -643,6 +651,9 @@
CharOperation.subarray(compoundName, 0, currentIndex),
(ReferenceBinding)((ReferenceBinding)binding).closestMatch(),
binding.problemId());
+// ;giro
+ }
+// SH}
}
if (invocationSite instanceof ASTNode) {
referenceBinding = (ReferenceBinding) binding;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 51b3c56..4c6d589 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -16,6 +16,7 @@
* Bug 349326 - [1.7] new warning for missing try-with-resources
* Bug 358903 - Filter practically unimportant resource leak warnings
* Bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class
+ * Bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -1634,7 +1635,7 @@
sourceType.tagBits |= (superType.tagBits & TagBits.HierarchyHasProblems); // propagate if missing supertpye
sourceType.superclass = superType;
// bound check (in case of bogus definition of Enum type)
- if (refTypeVariables[0].boundCheck(superType, sourceType) != TypeConstants.OK) {
+ if (refTypeVariables[0].boundCheck(superType, sourceType, this) != TypeConstants.OK) {
problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
}
return !foundCycle;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index ec6aba8..792d9a2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -244,7 +244,7 @@
}
//{ObjectTeams: role files: (a) classes never match the name of the unit: prepended __OT__!
-// (b) always check for matching file name (also protected)
+// (b) always check for matching file name (also protected), except for purely copied role files
boolean isRole = typeDecl.isRole() ;
if ( (typeDecl.modifiers & ClassFileConstants.AccPublic) != 0
|| typeDecl.isRole()) // (b) check independently of publicness
@@ -258,7 +258,8 @@
:giro */
if ((mainTypeName = this.referenceContext.getMainTypeName()) != null // mainTypeName == null means that implementor of ICompilationUnit decided to return null
&& !CharOperation.equals(mainTypeName, typeDecl.name)
- && !(isRole && !typeDecl.isInterface())) // (a): ignore role classes
+ && !(isRole && !typeDecl.isInterface()) // (a): ignore role classes
+ && !typeDecl.isPurelyCopied) // (has no file)
{
if (typeDecl.isRole()) // (b) : more specific message
problemReporter().roleFileMismatchingName(this.referenceContext, typeDecl);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index cb5b676..4288443 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -8,9 +8,11 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
+ * bug 185682 - Increment/decrement operators mark local variables as read
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -299,6 +301,17 @@
return fieldConstant;
}
+public void fillInDefaultNonNullness(FieldDeclaration sourceField, Scope scope) {
+ if ( this.type != null
+ && !this.type.isBaseType()
+ && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
+ {
+ this.tagBits |= TagBits.AnnotationNonNull;
+ } else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
+ scope.problemReporter().nullAnnotationIsRedundant(sourceField);
+ }
+}
+
/**
* X<T> t --> LX<TT;>;
*/
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 640cb61..15c5d19 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
@@ -311,10 +311,8 @@
}
}
if (shouldComplain) {
- boolean needNonNull = false;
char[][] annotationName;
if (inheritedNonNullNess == Boolean.TRUE) {
- needNonNull = true;
annotationName = environment.getNonNullAnnotationName();
} else {
annotationName = environment.getNullableAnnotationName();
@@ -331,17 +329,24 @@
} else {
scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
}
- } else if (inheritedNonNullNess == Boolean.FALSE // unannotated conflics only with inherited @Nullable
- && currentNonNullNess == null)
+ } else if (currentNonNullNess == null)
{
- if (currentArgument != null) {
- scope.problemReporter().parameterLackingNullAnnotation(
+ // unannotated strictly conflicts only with inherited @Nullable
+ if (inheritedNonNullNess == Boolean.FALSE) {
+ if (currentArgument != null) {
+ scope.problemReporter().parameterLackingNullableAnnotation(
+ currentArgument,
+ inheritedMethod.declaringClass,
+ annotationName);
+ } else {
+ scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
+ }
+ } else if (inheritedNonNullNess == Boolean.TRUE) {
+ // not strictly a conflict, but a configurable warning is given anyway:
+ scope.problemReporter().parameterLackingNonnullAnnotation(
currentArgument,
inheritedMethod.declaringClass,
- needNonNull,
annotationName);
- } else {
- scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 1d2b9dd..e23a0b9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -14,6 +14,7 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365859 - [compiler][null] distinguish warnings based on flow analysis vs. null annotations
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -196,14 +197,6 @@
}
}
- public boolean isNonNull() {
- return (this.tagBits & TagBits.AnnotationNonNull) != 0;
- }
-
- public boolean isNullable() {
- return (this.tagBits & TagBits.AnnotationNullable) != 0;
- }
-
// Answer whether the variable binding is a secret variable added for code gen purposes
public boolean isSecret() {
//{ObjectTeams: _OT$ variables are secret, too.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
index 2ee3d87..be2b5f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -18,6 +18,7 @@
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* bug 388795 - [compiler] detection of name clash depends on order of super interfaces
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 388739 - [1.8][compiler] consider default methods when detecting whether a class needs to be declared abstract
* bug 390883 - [1.8][compiler] Unable to override default method
*******************************************************************************/
@@ -748,6 +749,70 @@
}
}
}
+
+MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
+ if (inheritedMethod == null) return null;
+//{ObjectTeams: use source-level params in case of enhanced callin methods:
+/* orig:
+ if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match
+ :giro */
+ if (currentMethod.getSourceParamLength() != inheritedMethod.getSourceParamLength()) return null; // no match
+// SH}
+
+ // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved
+ if (currentMethod.declaringClass instanceof BinaryTypeBinding)
+ ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod);
+ if (inheritedMethod.declaringClass instanceof BinaryTypeBinding)
+ ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod);
+
+ TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables;
+ int inheritedLength = inheritedTypeVariables.length;
+ if (inheritedLength == 0) return inheritedMethod; // no substitution needed
+ TypeVariableBinding[] typeVariables = currentMethod.typeVariables;
+ int length = typeVariables.length;
+ if (length == 0)
+ return inheritedMethod.asRawMethod(this.environment);
+ if (length != inheritedLength)
+ return inheritedMethod; // no match JLS 8.4.2
+
+ // interface I { <T> void foo(T t); }
+ // class X implements I { public <T extends I> void foo(T t) {} }
+ // for the above case, we do not want to answer the substitute method since its not a match
+ TypeBinding[] arguments = new TypeBinding[length];
+ System.arraycopy(typeVariables, 0, arguments, 0, length);
+ ParameterizedGenericMethodBinding substitute =
+ this.environment.createParameterizedGenericMethod(inheritedMethod, arguments);
+ for (int i = 0; i < inheritedLength; i++) {
+ TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i];
+ TypeBinding argument = arguments[i];
+ if (argument instanceof TypeVariableBinding) {
+ TypeVariableBinding typeVariable = (TypeVariableBinding) argument;
+ if (typeVariable.firstBound == inheritedTypeVariable.firstBound) {
+ if (typeVariable.firstBound == null)
+ continue; // both are null
+ } else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) {
+ if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass())
+ return inheritedMethod; // not a match
+ }
+ if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass)
+ return inheritedMethod; // not a match
+ int interfaceLength = inheritedTypeVariable.superInterfaces.length;
+ ReferenceBinding[] interfaces = typeVariable.superInterfaces;
+ if (interfaceLength != interfaces.length)
+ return inheritedMethod; // not a match
+ next : for (int j = 0; j < interfaceLength; j++) {
+ TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]);
+ for (int k = 0; k < interfaceLength; k++)
+ if (superType == interfaces[k])
+ continue next;
+ return inheritedMethod; // not a match
+ }
+ } else if (inheritedTypeVariable.boundCheck(substitute, argument, this.type.scope) != TypeConstants.OK) {
+ return inheritedMethod;
+ }
+ }
+ return substitute;
+}
boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) {
if (!inherited.areParameterErasuresEqual(otherInherited))
return false;
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 8531ba8..7dccd2c 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
@@ -8,7 +8,9 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Technical University Berlin - extended API and implementation
- * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
+ * Stephan Herrmann - Contributions for
+ * bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -132,9 +134,9 @@
if (actualReceiverType instanceof ReferenceBinding)
actualReceiverRefType = (ReferenceBinding) actualReceiverType;
}
- switch (typeVariable.boundCheck(substitution, substituteForChecks, actualReceiverRefType)) {
+ switch (typeVariable.boundCheck(substitution, substituteForChecks, actualReceiverRefType, scope)) {
/* orig:
- switch (typeVariable.boundCheck(substitution, substituteForChecks)) {
+ switch (typeVariable.boundCheck(substitution, substituteForChecks, scope)) {
:giro */
// SH}
case TypeConstants.MISMATCH :
@@ -288,7 +290,7 @@
if (substitute != null) continue nextTypeParameter; // already inferred previously
TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS);
if (bounds == null) continue nextTypeParameter;
- TypeBinding[] glb = Scope.greaterLowerBound(bounds);
+ TypeBinding[] glb = Scope.greaterLowerBound(bounds, scope);
TypeBinding mostSpecificSubstitute = null;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=341795 - Per 15.12.2.8, we should fully apply glb
if (glb != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 586bed9..f807238 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -15,6 +15,7 @@
* Technical University Berlin - extended API and implementation
* Stephan Herrmann - Contributions for
* bug 349326 - [1.7] new warning for missing try-with-resources
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -116,7 +117,7 @@
TypeVariableBinding[] typeVariables = this.type.typeVariables();
if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases
for (int i = 0, length = typeVariables.length; i < length; i++) {
- if (typeVariables[i].boundCheck(this, this.arguments[i]) != TypeConstants.OK) {
+ if (typeVariables[i].boundCheck(this, this.arguments[i], scope) != TypeConstants.OK) {
hasErrors = true;
if ((this.arguments[i].tagBits & TagBits.HasMissingType) == 0) {
// do not report secondary error, if type reference already got complained against
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 8bd7821..6170f27 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
@@ -20,6 +20,7 @@
* bug 358903 - Filter practically unimportant resource leak warnings
* bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
@@ -319,6 +320,8 @@
// some subclasses share an existing model
protected ReferenceBinding(TypeModel model) {
this.model = model;
+ if (model != null && model.getBinding() == null)
+ model.setBinding(this);
}
// SH}
@@ -1439,15 +1442,15 @@
* In addition to improving performance, caching also ensures there is no infinite regression
* since per nature, the compatibility check is recursive through parameterized type arguments (122775)
*/
-public boolean isCompatibleWith(TypeBinding otherType) {
+public boolean isCompatibleWith(TypeBinding otherType, /*@Nullable*/ Scope captureScope) {
//{ObjectTeams: behind the facade introduce new parameter useObjectShortcut.
- return isCompatibleWith(otherType, true);
+ return isCompatibleWith(otherType, true, captureScope);
}
// version which does not consider everything conform to Object:
-public boolean isStrictlyCompatibleWith(TypeBinding otherType) {
- return isCompatibleWith(otherType, false);
+public boolean isStrictlyCompatibleWith(TypeBinding otherType, /*@Nullable*/ Scope captureScope) {
+ return isCompatibleWith(otherType, false, captureScope);
}
-public boolean isCompatibleWith(TypeBinding otherType, boolean useObjectShortcut) {
+public boolean isCompatibleWith(TypeBinding otherType, boolean useObjectShortcut, /*@Nullable*/ Scope captureScope) {
// SH}
if (otherType == this)
return true;
@@ -1471,13 +1474,21 @@
this.compatibleCache.put(otherType, Boolean.FALSE); // protect from recursive call
//{ObjectTeams: propagate:
/* orig:
- if (isCompatibleWith0(otherType)) {
+ if (isCompatibleWith0(otherType, captureScope)) {
:giro */
- if (isCompatibleWith0(otherType, useObjectShortcut)) {
+ if (isCompatibleWith0(otherType, useObjectShortcut, captureScope)) {
// SH}
this.compatibleCache.put(otherType, Boolean.TRUE);
return true;
}
+ if (captureScope == null
+ && this instanceof TypeVariableBinding
+ && ((TypeVariableBinding)this).firstBound instanceof ParameterizedTypeBinding) {
+ // see https://bugs.eclipse.org/395002#c9
+ // in this case a subsequent check with captureScope != null may actually get
+ // a better result, reset this info to ensure we're not blocking that re-check.
+ this.compatibleCache.put(otherType, null);
+ }
return false;
}
@@ -1496,7 +1507,7 @@
* Answer true if the receiver type can be assigned to the argument type (right)
*/
//{ObjectTeams: new parameter useObjectShortcut
-private boolean isCompatibleWith0(TypeBinding otherType, boolean useObjectShortcut) {
+private boolean isCompatibleWith0(TypeBinding otherType, boolean useObjectShortcut, /*@Nullable*/ Scope captureScope) {
// SH}
if (otherType == this)
return true;
@@ -1540,8 +1551,17 @@
// above if same erasure
}
ReferenceBinding otherReferenceType = (ReferenceBinding) otherType;
- if (otherReferenceType.isInterface()) // could be annotation type
- return implementsInterface(otherReferenceType, true);
+ if (otherReferenceType.isInterface()) { // could be annotation type
+ if (implementsInterface(otherReferenceType, true))
+ return true;
+ if (this instanceof TypeVariableBinding && captureScope != null) {
+ TypeVariableBinding typeVariable = (TypeVariableBinding) this;
+ if (typeVariable.firstBound instanceof ParameterizedTypeBinding) {
+ TypeBinding bound = typeVariable.firstBound.capture(captureScope, -1); // no position needed as this capture will never escape this context
+ return bound.isCompatibleWith(otherReferenceType);
+ }
+ }
+ }
//{ObjectTeams: only leave if we have checked for java.lang.Object above:
/* orig:
if (isInterface()) // Explicit conversion from an interface
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 cd9ea32..b0e8181 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
@@ -16,6 +16,7 @@
* Stephan Herrmann - Contributions for
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 387612 - Unreachable catch block...exception is never thrown from the try
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -356,7 +357,7 @@
}
// 5.1.10
- public static TypeBinding[] greaterLowerBound(TypeBinding[] types) {
+ public static TypeBinding[] greaterLowerBound(TypeBinding[] types, /*@Nullable*/ Scope scope) {
if (types == null) return null;
int length = types.length;
if (length == 0) return null;
@@ -369,7 +370,7 @@
if (i == j) continue;
TypeBinding jType = result[j];
if (jType == null) continue;
- if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
+ if (iType.isCompatibleWith(jType, scope)) { // if Vi <: Vj, Vj is removed
if (result == types) { // defensive copy
System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
}
@@ -491,7 +492,7 @@
TypeBinding [] bounds = new TypeBinding[1 + substitutedOtherBounds.length];
bounds[0] = substitutedBound;
System.arraycopy(substitutedOtherBounds, 0, bounds, 1, substitutedOtherBounds.length);
- TypeBinding[] glb = Scope.greaterLowerBound(bounds); // re-evaluate
+ TypeBinding[] glb = Scope.greaterLowerBound(bounds, null); // re-evaluate
if (glb != null && glb != bounds) {
substitutedBound = glb[0];
if (glb.length == 1) {
@@ -3770,7 +3771,7 @@
case Wildcard.SUPER :
// ? super U, ? super V
if (wildU.boundKind == Wildcard.SUPER) {
- TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound}, this);
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
}
@@ -3786,7 +3787,7 @@
return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
// U, ? super V
case Wildcard.SUPER :
- TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound}, this);
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
case Wildcard.UNBOUND :
@@ -3804,7 +3805,7 @@
return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
// U, ? super V
case Wildcard.SUPER :
- TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v}, this);
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
case Wildcard.UNBOUND :
@@ -4603,7 +4604,7 @@
private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, LookupEnvironment env, boolean tieBreakingVarargsMethods) {
// only called if env.options.sourceLevel >= ClassFileConstants.JDK1_5
- if (arg.isCompatibleWith(param))
+ if (arg.isCompatibleWith(param, this))
return COMPATIBLE;
if (tieBreakingVarargsMethods && (this.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7 || !CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation)) {
/* 15.12.2.5 Choosing the Most Specific Method, ... One variable arity member method named m is more specific than
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 68508c9..6425389 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
@@ -21,6 +21,8 @@
* bug 384663 - Package Based Annotation Compilation Error in JDT 3.8/4.2 (works in 3.7.2)
* bug 386356 - Type mismatch error with annotations and generics
* bug 388281 - [compiler][null] inheritance of null annotations as an option
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 380896 - [compiler][null] Enum constants not recognised as being NonNull.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -52,7 +54,6 @@
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
-import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.RoleFileCache;
@@ -1442,6 +1443,9 @@
}
//{ObjectTeams: ROFI if it is a team, the member might be a role file still to be found:
public ReferenceBinding getMemberType(char[] name) {
+ if (this.notFoundMemberNames != null && this.notFoundMemberNames.includes(name))
+ return null;
+
ReferenceBinding result = super.getMemberType(name);
if (result != null) {
// is it a member in a different file?
@@ -1455,33 +1459,31 @@
}
return result;
}
-// FIXME(SH): needed for 1.7.7-otjld-5f, but causes more problems.
-// Note: since State-Management has been restructured, things *might*
-// be different by now.
- if ( isTeam()
- && !StateHelper.hasState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)
- && StateHelper.isReadyToProcess(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY))
- {
- if ( Dependencies.ensureBindingState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)
- && StateHelper.hasState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY))
- {
- ReferenceBinding member = getMemberType(name); // try again for copied roles.
- if (member != null && (member.tagBits & TagBits.HasMissingType) == 0)
- return member;
+ if (isTeam() && !StateHelper.hasState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)) {
+ if (StateHelper.isReadyToProcess(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)) {
+ if ( Dependencies.ensureBindingState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)
+ && StateHelper.hasState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY))
+ {
+ ReferenceBinding member = getMemberType(name); // try again for copied roles.
+ if (member != null && (member.tagBits & TagBits.HasMissingType) == 0)
+ return member;
+ }
}
+ ReferenceBinding member = CopyInheritance.checkCopyLateRoleFile(this, name);
+ if (member != null)
+ return member;
}
- if (!isTeam() || this.teamPackage == null)
- return null;
- if (this.notFoundMemberNames != null && this.notFoundMemberNames.includes(name)) {
- return null;
+ if (isTeam() && this.teamPackage != null) {
+ ReferenceBinding member = findTypeInTeamPackage(name);
+ if (member != null)
+ return member;
}
- ReferenceBinding res = findTypeInTeamPackage(name);
- if (res == null) {
- if (this.notFoundMemberNames == null)
- this.notFoundMemberNames = new SimpleSetOfCharArray();
- this.notFoundMemberNames.add(name);
+ if (StateHelper.hasState(this, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)) {
+ if (this.notFoundMemberNames == null)
+ this.notFoundMemberNames = new SimpleSetOfCharArray();
+ this.notFoundMemberNames.add(name);
}
- return res;
+ return null;
}
SimpleSetOfCharArray notFoundMemberNames;
@@ -1549,27 +1551,13 @@
// teamModel.liftingEnv.init(teamModel.getAst());
}
} else if (teamModel.getState() >= ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY) {
- return checkCopyLateRoleFile(teamModel, name);
+ TypeDeclaration roleDecl = CopyInheritance.internalCheckCopyLateRoleFile(this, name);
+ if (roleDecl != null)
+ return roleDecl.binding;
}
}
return result;
}
-private ReferenceBinding checkCopyLateRoleFile(TeamModel teamModel, char[] name) {
- ReferenceBinding superTeam = superclass(); // FIXME(SH): tsuper teams
- if ( superTeam != null
- && !TypeAnalyzer.isOrgObjectteamsTeam(superTeam)
- && !teamModel._isCopyingLateRole
- && !OTNameUtils.isTSuperMarkerInterface(name))
- {
- ReferenceBinding tsuperRole = superTeam.getMemberType(name);
- if ( tsuperRole != null && tsuperRole.isRole() && tsuperRole.isValidBinding()
- && !tsuperRole.isLocalType())
- {
- return CopyInheritance.copyLateRole(teamModel.getAst(), tsuperRole);
- }
- }
- return null;
-}
//SH}
/* Answer the synthetic field for <actualOuterLocalVariable>
* or null if one does not exist.
@@ -2004,75 +1992,91 @@
if (fieldDecls[f].binding != field)
continue;
- MethodScope initializationScope = field.isStatic()
- ? this.scope.referenceContext.staticInitializerScope
- : this.scope.referenceContext.initializerScope;
- FieldBinding previousField = initializationScope.initializedField;
- try {
- initializationScope.initializedField = field;
- FieldDeclaration fieldDecl = fieldDecls[f];
- TypeBinding fieldType =
- fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
- ? initializationScope.environment().convertToRawType(this, false /*do not force conversion of enclosing types*/) // enum constant is implicitly of declaring enum type
- : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
- field.type = fieldType;
- field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
- if (fieldType == null) {
- fieldDecl.binding = null;
- return null;
- }
- if (fieldType == TypeBinding.VOID) {
- this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecl);
- fieldDecl.binding = null;
- return null;
- }
- if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) {
- this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecl);
- fieldDecl.binding = null;
- return null;
- }
- if ((fieldType.tagBits & TagBits.HasMissingType) != 0) {
- field.tagBits |= TagBits.HasMissingType;
- }
- TypeBinding leafType = fieldType.leafComponentType();
- if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
- field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
- }
- } finally {
- initializationScope.initializedField = previousField;
+ MethodScope initializationScope = field.isStatic()
+ ? this.scope.referenceContext.staticInitializerScope
+ : this.scope.referenceContext.initializerScope;
+ FieldBinding previousField = initializationScope.initializedField;
+ try {
+ initializationScope.initializedField = field;
+ FieldDeclaration fieldDecl = fieldDecls[f];
+ TypeBinding fieldType =
+ fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
+ ? initializationScope.environment().convertToRawType(this, false /*do not force conversion of enclosing types*/) // enum constant is implicitly of declaring enum type
+ : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
+ field.type = fieldType;
+ field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ if (fieldType == null) {
+ fieldDecl.binding = null;
+ return null;
}
+ if (fieldType == TypeBinding.VOID) {
+ this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecl);
+ fieldDecl.binding = null;
+ return null;
+ }
+ if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) {
+ this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecl);
+ fieldDecl.binding = null;
+ return null;
+ }
+ if ((fieldType.tagBits & TagBits.HasMissingType) != 0) {
+ field.tagBits |= TagBits.HasMissingType;
+ }
+ TypeBinding leafType = fieldType.leafComponentType();
+ if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
+ field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ }
+
+ // apply null default:
+ LookupEnvironment environment = this.scope.environment();
+ if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ // enum constants neither have a type declaration nor can they be null
+ field.tagBits |= TagBits.AnnotationNonNull;
+ } else {
+ initializeNullDefault();
+ if (hasNonNullDefault()) {
+ field.fillInDefaultNonNullness(fieldDecl, initializationScope);
+ }
+ // validate null annotation:
+ this.scope.validateNullAnnotation(field.tagBits, fieldDecl.type, fieldDecl.annotations);
+ }
+ }
+ } finally {
+ initializationScope.initializedField = previousField;
+ }
//{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
- throw new InternalCompilerError("Field "+fieldDecls[f]+" has no type in "+this);
+ if (fieldDecls[f].getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
+ if (fieldDecls[f].type == null) // should not happen for non-enum types
+ throw new InternalCompilerError("Field "+fieldDecls[f]+" has no type in "+this);
- field.copyInheritanceSrc = fieldDecls[f].copyInheritanceSrc;
- field.maybeSetFieldTypeAnchorAttribute();
- // anchored to tthis?
- field.type = RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.scope, field.type, fieldDecls[f].type);
- if (field.couldBeTeamAnchor()) {
- // link decl and binding via model
- // for early resolving from TeamAnchor.hasSameBestNameAs()
- FieldModel.getModel(fieldDecls[f]).setBinding(field);
- }
+ field.copyInheritanceSrc = fieldDecls[f].copyInheritanceSrc;
+ field.maybeSetFieldTypeAnchorAttribute();
+ // anchored to tthis?
+ field.type = RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.scope, field.type, fieldDecls[f].type);
+ if (field.couldBeTeamAnchor()) {
+ // link decl and binding via model
+ // for early resolving from TeamAnchor.hasSameBestNameAs()
+ FieldModel.getModel(fieldDecls[f]).setBinding(field);
}
- // need role field bridges?
- if ( isRole()
- && ((field.modifiers & ClassFileConstants.AccPrivate) != 0)
- && !CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, field.name))
- {
- MethodBinding inner;
- ReferenceBinding originalRole = field.declaringClass;
- if (field.copyInheritanceSrc != null)
- originalRole = field.copyInheritanceSrc.declaringClass;
- inner = FieldModel.getDecapsulatingFieldAccessor(this, field, true/*isGetter*/);
+ }
+ // need role field bridges?
+ if ( isRole()
+ && ((field.modifiers & ClassFileConstants.AccPrivate) != 0)
+ && !CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, field.name))
+ {
+ MethodBinding inner;
+ ReferenceBinding originalRole = field.declaringClass;
+ if (field.copyInheritanceSrc != null)
+ originalRole = field.copyInheritanceSrc.declaringClass;
+ inner = FieldModel.getDecapsulatingFieldAccessor(this, field, true/*isGetter*/);
+ ((SourceTypeBinding) enclosingType()).addSyntheticRoleMethodBridge(this, originalRole, inner, SyntheticMethodBinding.RoleMethodBridgeOuter);
+ if (!field.isFinal()) { // no setter for final (includes all static role fields)
+ // otherwise we would have to handle different signatures (w/ w/o role arg), which we currently don't
+ inner = FieldModel.getDecapsulatingFieldAccessor(this, field, false/*isGetter*/);
((SourceTypeBinding) enclosingType()).addSyntheticRoleMethodBridge(this, originalRole, inner, SyntheticMethodBinding.RoleMethodBridgeOuter);
- if (!field.isFinal()) { // no setter for final (includes all static role fields)
- // otherwise we would have to handle different signatures (w/ w/o role arg), which we currently don't
- inner = FieldModel.getDecapsulatingFieldAccessor(this, field, false/*isGetter*/);
- ((SourceTypeBinding) enclosingType()).addSyntheticRoleMethodBridge(this, originalRole, inner, SyntheticMethodBinding.RoleMethodBridgeOuter);
- }
}
+ }
// SH}
return field;
}
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 febc18d..34763d8 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
@@ -15,6 +15,7 @@
* Technical University Berlin - extended API and implementation
* Stephen Herrmann <stephan@cs.tu-berlin.de> - Contributions for
* bug 317046 - Exception during debugging when hover mouse over a field
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
@@ -483,7 +484,11 @@
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
-public abstract boolean isCompatibleWith(TypeBinding right);
+public boolean isCompatibleWith(TypeBinding right) {
+ return isCompatibleWith(right, null); // delegate from the old signature to the new implementation:
+}
+// version that allows to capture a type bound using 'scope':
+public abstract boolean isCompatibleWith(TypeBinding right, /*@Nullable*/ Scope scope);
public boolean isEnum() {
return false;
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 c5cd451..71c2791 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
@@ -13,6 +13,7 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
* bug 358903 - Filter practically unimportant resource leak warnings
+ * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -64,12 +65,26 @@
* Returns true if the argument type satisfies all bounds of the type parameter
*/
//{ObjectTeams: added optional argument actualReceiverType:
- public int boundCheck(Substitution substitution, TypeBinding argumentType) {
- return boundCheck(substitution, argumentType, null);
+ public int boundCheck(Substitution substitution, TypeBinding argumentType, Scope scope) {
+ return boundCheck(substitution, argumentType, null, scope);
}
- public int boundCheck(Substitution substitution, TypeBinding argumentType, ReferenceBinding actualReceiverType) {
+ public int boundCheck(Substitution substitution, TypeBinding argumentType, ReferenceBinding actualReceiverType, Scope scope) {
+ int code = internalBoundCheck(substitution, argumentType, actualReceiverType, scope);
// SH}
-
+ if (code == TypeConstants.MISMATCH) {
+ if (argumentType instanceof TypeVariableBinding && scope != null) {
+ TypeBinding bound = ((TypeVariableBinding)argumentType).firstBound;
+ if (bound instanceof ParameterizedTypeBinding) {
+ int code2 = boundCheck(substitution, bound.capture(scope, -1), scope); // no position needed as this capture will never escape this context
+ return Math.min(code, code2);
+ }
+ }
+ }
+ return code;
+ }
+//{ObjectTeams: added optional argument actualReceiverType:
+ private int internalBoundCheck(Substitution substitution, TypeBinding argumentType, ReferenceBinding actualReceiverType, Scope scope) {
+// SH}
if (argumentType == TypeBinding.NULL || argumentType == this) {
return TypeConstants.OK;
}
@@ -93,7 +108,7 @@
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superclass) : this.superclass;
if (substitutedSuperType.id != TypeIds.T_JavaLangObject) {
if (isArrayBound) {
- if (!wildcardBound.isCompatibleWith(substitutedSuperType))
+ if (!wildcardBound.isCompatibleWith(substitutedSuperType, scope))
return TypeConstants.MISMATCH;
} else {
TypeBinding match = wildcardBound.findSuperTypeOriginatingFrom(substitutedSuperType);
@@ -120,7 +135,7 @@
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces[i]) : this.superInterfaces[i];
if (isArrayBound) {
- if (!wildcardBound.isCompatibleWith(substitutedSuperType))
+ if (!wildcardBound.isCompatibleWith(substitutedSuperType, scope))
return TypeConstants.MISMATCH;
} else {
TypeBinding match = wildcardBound.findSuperTypeOriginatingFrom(substitutedSuperType);
@@ -140,7 +155,7 @@
// if the wildcard is lower-bounded by a type variable that has no relevant upper bound there's nothing to check here (bug 282152):
if (wildcard.bound.isTypeVariable() && ((TypeVariableBinding)wildcard.bound).superclass.id == TypeIds.T_JavaLangObject)
break;
- return boundCheck(substitution, wildcard.bound);
+ return boundCheck(substitution, wildcard.bound, scope);
case Wildcard.UNBOUND :
break;
@@ -151,7 +166,7 @@
if (this.superclass.id != TypeIds.T_JavaLangObject) {
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superclass) : this.superclass;
if (substitutedSuperType != argumentType) {
- if (!argumentType.isCompatibleWith(substitutedSuperType)) {
+ if (!argumentType.isCompatibleWith(substitutedSuperType, scope)) {
return TypeConstants.MISMATCH;
}
TypeBinding match = argumentType.findSuperTypeOriginatingFrom(substitutedSuperType);
@@ -206,7 +221,7 @@
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces[i]) : this.superInterfaces[i];
if (substitutedSuperType != argumentType) {
- if (!argumentType.isCompatibleWith(substitutedSuperType)) {
+ if (!argumentType.isCompatibleWith(substitutedSuperType, scope)) {
return TypeConstants.MISMATCH;
}
TypeBinding match = argumentType.findSuperTypeOriginatingFrom(substitutedSuperType);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java
index fe6d35d..57952ea 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -21,8 +21,14 @@
public ReferenceBinding getAnnotationType() {
if (this.typeUnresolved) { // the type is resolved when requested
- this.type = (ReferenceBinding) BinaryTypeBinding.resolveType(this.type, this.env, false /* no raw conversion for now */);
- // annotation type are never parameterized
+ boolean wasToleratingMissingTypeProcessingAnnotations = this.env.mayTolerateMissingType;
+ this.env.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=388042
+ try {
+ this.type = (ReferenceBinding) BinaryTypeBinding.resolveType(this.type, this.env, false /* no raw conversion for now */);
+ // annotation types are never parameterized
+ } finally {
+ this.env.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
+ }
this.typeUnresolved = false;
}
return this.type;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index 002af31..217afd8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -9,6 +9,8 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 331649 - [compiler][null] consider null annotations for fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -75,7 +77,17 @@
public final boolean isEffectivelyFinal() {
return (this.tagBits & TagBits.IsEffectivelyFinal) != 0;
}
-
+
+ /** Answer true if null annotations are enabled and this field is specified @NonNull */
+ public boolean isNonNull() {
+ return (this.tagBits & TagBits.AnnotationNonNull) != 0;
+ }
+
+ /** Answer true if null annotations are enabled and this field is specified @Nullable */
+ public boolean isNullable() {
+ return (this.tagBits & TagBits.AnnotationNullable) != 0;
+ }
+
public char[] readableName() {
//{ObjectTeams: pretty printing for generated names:
if (CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, this.name))
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index ce39db1..4d166e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -17,6 +17,7 @@
* Stephan Herrmann - Contributions for
* bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
* bug 374605 - Unreasonable warning for enum-based switch statements
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
* bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
@@ -4065,6 +4066,10 @@
this.expressionLengthPtr--;
final Expression collection = this.expressionStack[this.expressionPtr--];
statement.collection = collection;
+ // https://bugs.eclipse.org/393719 - [compiler] inconsistent warnings on iteration variables
+ // let declaration(Source)End include the collection to achieve that @SuppressWarnings affects this part, too:
+ statement.elementVariable.declarationSourceEnd = collection.sourceEnd;
+ statement.elementVariable.declarationEnd = collection.sourceEnd;
statement.sourceEnd = this.rParenPos;
if(!this.statementRecoveryActivated &&
@@ -4081,6 +4086,7 @@
LocalDeclaration localDeclaration = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
localDeclaration.declarationSourceEnd = localDeclaration.declarationEnd;
+ localDeclaration.bits |= ASTNode.IsForeachElementVariable;
int extraDims = this.intStack[this.intPtr--];
this.identifierPtr--;
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 7a2ce40..2acb2ca 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
@@ -28,6 +28,10 @@
* bug 382347 - [1.8][compiler] Compiler accepts incorrect default method inheritance
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* bug 376053 - [compiler][resource] Strange potential resource leak problems
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null
* bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
* bug 388739 - [1.8][compiler] consider default methods when detecting whether a class needs to be declared abstract
* Jesper S Moller <jesper@selskabet.org> - Contributions for
@@ -60,6 +64,7 @@
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
@@ -92,6 +97,7 @@
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
@@ -332,6 +338,7 @@
case IProblem.UnsafeRawConstructorInvocation:
case IProblem.UnsafeRawMethodInvocation:
case IProblem.UnsafeTypeConversion:
+ case IProblem.UnsafeElementTypeConversion:
case IProblem.UnsafeRawFieldAssignment:
case IProblem.UnsafeGenericCast:
case IProblem.UnsafeReturnTypeOverride:
@@ -370,6 +377,7 @@
return CompilerOptions.VarargsArgumentNeedCast;
case IProblem.NullLocalVariableReference:
+ case IProblem.NullableFieldReference:
return CompilerOptions.NullReference;
case IProblem.PotentialNullLocalVariableReference:
@@ -384,9 +392,14 @@
case IProblem.NonNullLocalVariableComparisonYieldsFalse:
case IProblem.NullLocalVariableComparisonYieldsFalse:
case IProblem.NullLocalVariableInstanceofYieldsFalse:
+ case IProblem.RedundantNullCheckOnNonNullExpression:
+ case IProblem.NonNullExpressionComparisonYieldsFalse:
case IProblem.RedundantNullCheckOnNonNullMessageSend:
case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
+ case IProblem.NonNullMessageSendComparisonYieldsFalse:
+ case IProblem.RedundantNullCheckOnNonNullSpecdField:
+ case IProblem.NonNullSpecdFieldComparisonYieldsFalse:
return CompilerOptions.RedundantNullCheck;
case IProblem.RequiredNonNullButProvidedNull:
@@ -394,14 +407,18 @@
case IProblem.IllegalReturnNullityRedefinition:
case IProblem.IllegalRedefinitionToNonNullParameter:
case IProblem.IllegalDefinitionToNonNullParameter:
- case IProblem.ParameterLackingNonNullAnnotation:
case IProblem.ParameterLackingNullableAnnotation:
case IProblem.CannotImplementIncompatibleNullness:
+ case IProblem.UninitializedNonNullField:
+ case IProblem.UninitializedNonNullFieldHintMissingDefault:
case IProblem.ConflictingNullAnnotations:
case IProblem.ConflictingInheritedNullAnnotations:
case IProblem.NullityMismatchingTypeAnnotation:
return CompilerOptions.NullSpecViolation;
+ case IProblem.ParameterLackingNonNullAnnotation:
+ return CompilerOptions.NonnullParameterAnnotationDropped;
+
case IProblem.RequiredNonNullButProvidedPotentialNull:
return CompilerOptions.NullAnnotationInferenceConflict;
case IProblem.RequiredNonNullButProvidedUnknown:
@@ -805,6 +822,7 @@
case CompilerOptions.NullAnnotationInferenceConflict :
case CompilerOptions.NullUncheckedConversion :
case CompilerOptions.MissingNonNullByDefaultAnnotation:
+ case CompilerOptions.NonnullParameterAnnotationDropped:
return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
case CompilerOptions.RedundantNullAnnotation :
return CategorizedProblem.CAT_UNNECESSARY_CODE;
@@ -5939,6 +5957,92 @@
nodeSourceEnd(local, location));
}
+/**
+ * @param expr expression being compared for null or nonnull
+ * @param checkForNull true if checking for null, false if checking for nonnull
+ */
+public boolean expressionNonNullComparison(Expression expr, boolean checkForNull) {
+ int problemId = 0;
+ Binding binding = null;
+ String[] arguments = null;
+ int start = 0, end = 0;
+
+ Expression location = expr;
+ // unwrap uninteresting nodes:
+ while (true) {
+ if (expr instanceof Assignment)
+ return false; // don't report against the assignment, but the variable
+ else if (expr instanceof CastExpression)
+ expr = ((CastExpression) expr).expression;
+ else
+ break;
+ }
+ // check all those kinds of expressions that can possible answer NON_NULL from nullStatus():
+ if (expr instanceof MessageSend) {
+ problemId = checkForNull
+ ? IProblem.NonNullMessageSendComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullMessageSend;
+ MethodBinding method = ((MessageSend)expr).binding;
+ binding = method;
+ arguments = new String[] { new String(method.shortReadableName()) };
+ start = location.sourceStart;
+ end = location.sourceEnd;
+ } else if (expr instanceof Reference && !(expr instanceof ThisReference) && !(expr instanceof ArrayReference)) {
+ FieldBinding field = ((Reference)expr).lastFieldBinding();
+ if (field == null) {
+ return false;
+ }
+ if (field.isNonNull()) {
+ problemId = checkForNull
+ ? IProblem.NonNullSpecdFieldComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullSpecdField;
+ char[][] nonNullName = this.options.nonNullAnnotationName;
+ arguments = new String[] { new String(field.name),
+ new String(nonNullName[nonNullName.length-1]) };
+ }
+ binding = field;
+ start = nodeSourceStart(binding, location);
+ end = nodeSourceEnd(binding, location);
+ } else if (expr instanceof AllocationExpression
+ || expr instanceof ArrayAllocationExpression
+ || expr instanceof ArrayInitializer
+ || expr instanceof ClassLiteralAccess
+ || expr instanceof ThisReference) {
+ // fall through to bottom
+ } else if (expr instanceof Literal
+ || expr instanceof ConditionalExpression) {
+ if (expr instanceof NullLiteral) {
+ needImplementation(location); // reported as nonnull??
+ return false;
+ }
+ if (expr.resolvedType != null && expr.resolvedType.isBaseType()) {
+ // false alarm, auto(un)boxing is involved
+ return false;
+ }
+ // fall through to bottom
+ } else if (expr instanceof BinaryExpression) {
+ if ((expr.bits & ASTNode.ReturnTypeIDMASK) != TypeIds.T_JavaLangString) {
+ // false alarm, primitive types involved, must be auto(un)boxing?
+ return false;
+ }
+ // fall through to bottom
+ } else {
+ needImplementation(expr); // want to see if we get here
+ return false;
+ }
+ if (problemId == 0) {
+ // standard case, fill in details now
+ problemId = checkForNull
+ ? IProblem.NonNullExpressionComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullExpression;
+ start = location.sourceStart;
+ end = location.sourceEnd;
+ arguments = NoArgument;
+ }
+ this.handle(problemId, arguments, arguments, start, end);
+ return true;
+}
+
public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) {
int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse);
if (severity == ProblemSeverities.Ignore) return;
@@ -5994,6 +6098,18 @@
nodeSourceEnd(local, location));
}
+public void nullableFieldDereference(VariableBinding variable, long position) {
+ String[] arguments = new String[] {new String(variable.name)};
+ char[][] nullableName = this.options.nullableAnnotationName;
+ arguments = new String[] {new String(variable.name), new String(nullableName[nullableName.length-1])};
+ this.handle(
+ IProblem.NullableFieldReference,
+ arguments,
+ arguments,
+ (int)(position >>> 32),
+ (int)(position));
+}
+
public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) {
int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable);
if (severity == ProblemSeverities.Ignore) return;
@@ -8161,6 +8277,19 @@
nodeSourceStart(field, location),
nodeSourceEnd(field, location));
}
+public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
+ char[][] nonNullAnnotationName = this.options.nonNullAnnotationName;
+ String[] arguments = new String[] {
+ new String(nonNullAnnotationName[nonNullAnnotationName.length-1]),
+ new String(field.readableName())
+ };
+ this.handle(
+ methodHasMissingSwitchDefault() ? IProblem.UninitializedNonNullFieldHintMissingDefault : IProblem.UninitializedNonNullField,
+ arguments,
+ arguments,
+ nodeSourceStart(field, location),
+ nodeSourceEnd(field, location));
+}
public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location) {
binding.tagBits |= TagBits.NotInitialized;
String[] arguments = new String[] {new String(binding.readableName())};
@@ -8548,6 +8677,21 @@
expression.sourceStart,
expression.sourceEnd);
}
+public void unsafeElementTypeConversion(Expression expression, TypeBinding expressionType, TypeBinding expectedType) {
+ if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259
+ int severity = computeSeverity(IProblem.UnsafeElementTypeConversion);
+ if (severity == ProblemSeverities.Ignore) return;
+ if (!this.options.reportUnavoidableGenericTypeProblems && expression.forcedToBeRaw(this.referenceContext)) {
+ return;
+ }
+ this.handle(
+ IProblem.UnsafeElementTypeConversion,
+ new String[] { new String(expressionType.readableName()), new String(expectedType.readableName()), new String(expectedType.erasure().readableName()) },
+ new String[] { new String(expressionType.shortReadableName()), new String(expectedType.shortReadableName()), new String(expectedType.erasure().shortReadableName()) },
+ severity,
+ expression.sourceStart,
+ expression.sourceEnd);
+}
public void unusedArgument(LocalDeclaration localDecl) {
int severity = computeSeverity(IProblem.ArgumentIsNeverUsed);
if (severity == ProblemSeverities.Ignore) return;
@@ -9184,15 +9328,14 @@
return;
}
if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) {
- if (expression instanceof SingleNameReference) {
- SingleNameReference snr = (SingleNameReference) expression;
- if (snr.binding instanceof LocalVariableBinding) {
- if (((LocalVariableBinding)snr.binding).isNullable()) {
+ VariableBinding var = expression.localVariableBinding();
+ if (var == null && expression instanceof Reference) {
+ var = ((Reference)expression).lastFieldBinding();
+ }
+ if (var != null && var.isNullable()) {
nullityMismatchSpecdNullable(expression, requiredType, annotationName);
return;
}
- }
- }
nullityMismatchPotentiallyNull(expression, requiredType, annotationName);
return;
}
@@ -11493,6 +11636,20 @@
String[] args = { new String(binding.readableName()) };
this.handle(IProblem.CallinToDeprecated, args, args, spec.sourceStart, spec.sourceEnd);
}
+
+public void invisibleMethod(MethodSpec spec, MethodBinding method) {
+ this.handle(
+ IProblem.NotVisibleMethod,
+ new String[] {
+ new String(method.declaringClass.readableName()),
+ new String(method.selector), typesAsString(method, false)},
+ new String[] {
+ new String(method.declaringClass.shortReadableName()),
+ new String(method.selector), typesAsString(method, true)},
+ spec.sourceStart,
+ spec.sourceEnd);
+}
+
// -- 4.2 --
public void callinInNonRole(ReferenceBinding declaringClass, AbstractMethodDeclaration method) {
String[] args = new String[] {
@@ -12858,14 +13015,30 @@
argument.type.sourceEnd);
}
}
-public void parameterLackingNullAnnotation(Argument argument, ReferenceBinding declaringClass, boolean needNonNull, char[][] inheritedAnnotationName) {
+public void parameterLackingNullableAnnotation(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
this.handle(
- needNonNull ? IProblem.ParameterLackingNonNullAnnotation : IProblem.ParameterLackingNullableAnnotation,
+ IProblem.ParameterLackingNullableAnnotation,
new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
argument.type.sourceStart,
argument.type.sourceEnd);
}
+public void parameterLackingNonnullAnnotation(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
+ int sourceStart = 0, sourceEnd = 0;
+ if (argument != null) {
+ sourceStart = argument.type.sourceStart;
+ sourceEnd = argument.type.sourceEnd;
+ } else if (this.referenceContext instanceof TypeDeclaration) {
+ sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart;
+ sourceEnd = ((TypeDeclaration) this.referenceContext).sourceEnd;
+ }
+ this.handle(
+ IProblem.ParameterLackingNonNullAnnotation,
+ new String[] { new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
+ new String[] { new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
+ sourceStart,
+ sourceEnd);
+}
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl, MethodBinding inheritedMethod, char[][] nonNullAnnotationName) {
MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl;
StringBuffer methodSignature = new StringBuffer();
@@ -12950,6 +13123,13 @@
this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
}
+public void nullAnnotationIsRedundant(FieldDeclaration sourceField) {
+ Annotation annotation = findAnnotation(sourceField.annotations, TypeIds.T_ConfiguredAnnotationNonNull);
+ int sourceStart = annotation != null ? annotation.sourceStart : sourceField.type.sourceStart;
+ int sourceEnd = sourceField.type.sourceEnd;
+ this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
+}
+
public void nullDefaultAnnotationIsRedundant(ASTNode location, Annotation[] annotations, Binding outer) {
Annotation annotation = findAnnotation(annotations, TypeIds.T_ConfiguredAnnotationNonNullByDefault);
int start = annotation != null ? annotation.sourceStart : location.sourceStart;
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 d5bb0df..f4883e5 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
@@ -26,6 +26,10 @@
# bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
# bug 382347 - [1.8][compiler] Compiler accepts incorrect default method inheritance
# bug 388281 - [compiler][null] inheritance of null annotations as an option
+# bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+# bug 393719 - [compiler] inconsistent warnings on iteration variables
+# bug 331649 - [compiler][null] consider null annotations for fields
+# bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null
# bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
# Jesper S Moller <jesper@selskabet.org> - Contributions for
# bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
@@ -543,6 +547,7 @@
580 = Type mismatch: cannot convert from element type {0} to {1}
581 = Can only iterate over an array or an instance of java.lang.Iterable
582 = Can only iterate over an array or an instance of java.util.Collection
+585 = Type safety: Elements of type {0} need unchecked conversion to conform to {1}
### SOURCE LEVEL
590 = Syntax error, type parameters are only available if source level is 1.5 or greater
@@ -619,6 +624,10 @@
### MORE TYPE RELATED
662 = Illegal attempt to create arrays of union types
+### NULL ANALYSIS FOR OTHER EXPRESSIONS
+670 = Null comparison always yields false: this expression cannot be null
+671 = Redundant null check: this expression cannot be null
+
### CORRUPTED BINARIES
700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2}
@@ -708,13 +717,14 @@
914 = The return type is incompatible with the @{1} return from {0}
915 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
916 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
-917 = Missing non-null annotation: inherited method from {1} declares this parameter as @{2}
+917 = Missing non-null annotation: inherited method from {0} declares this parameter as @{1}
918 = Missing nullable annotation: inherited method from {1} declares this parameter as @{2}
919 = Potential null pointer access: The method {0} may return null
920 = Redundant null check: The method {0} cannot return null
921 = The method {0} from {1} cannot implement the corresponding method from {2} due to incompatible nullness constraints
922 = The nullness annotation is redundant with a default that applies to this location
923 = The nullness annotation @{0} is not applicable for the primitive type {1}
+924 = Potential null pointer access: The field {0} is declared as @{1}
925 = Nullness default is redundant with the global default
926 = Nullness default is redundant with a default specified for the enclosing package {0}
927 = Nullness default is redundant with a default specified for the enclosing type {0}
@@ -724,6 +734,11 @@
931 = Redundant null check: The variable {0} is specified as @{1}
932 = Null comparison always yields false: The variable {0} is specified as @{1}
933 = Null type mismatch: required ''{0}'' but the provided value is specified as @{1}
+934 = The @{0} field {1} may not have been initialized
+935 = The @{0} field {1} may not have been initialized. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem
+936 = Null comparison always yields false: The method {0} cannot return null
+937 = Redundant null check: The field {0} is declared as @{1}
+938 = Null comparison always yields false: The field {0} is declared as @{1}
939 = The default ''@{0}'' conflicts with the inherited ''@{1}'' annotation in the overridden method from {2}
940 = Conflict between inherited null annotations ''@{0}'' declared in {1} versus ''@{2}'' declared in {3}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/CompilerVersion.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/CompilerVersion.java
new file mode 100644
index 0000000..babd222
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/CompilerVersion.java
@@ -0,0 +1,30 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Development Tooling"-Software.
+ *
+ * Copyright 2012 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
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.core.compiler;
+
+import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
+
+/**
+ * @since 3.9 (OTDT 2.2)
+ */
+public class CompilerVersion {
+ /**
+ * Define whether the compiler should generate byte code suitable for dynamic weaving.
+ */
+ public static void setDynamicWeaving(boolean useDynamicWeaving) {
+ CallinImplementorDyn.DYNAMIC_WEAVING = useDynamicWeaving;
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/IOTConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/IOTConstants.java
index 6cec0da..217680d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/IOTConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/IOTConstants.java
@@ -248,6 +248,12 @@
"objectteams".toCharArray(),
"otre".toCharArray(),
"OTREInternalError".toCharArray()};
+ /**
+ * @since 3.9 (OT 2.2)
+ */
+ public static final char[][] SNEAKY_EXCEPTION = new char[][]{ORG, OBJECTTEAMS,
+ "SneakyException".toCharArray()};
+
// Type IDs (cf. type TypeIds)
public static final int T_OrgObjectTeamsITeam = 100;
@@ -296,5 +302,4 @@
public static final char[] QUERY_MODULE_SUFFIX = "_Queries__OT__".toCharArray();
// decapsulation accessor prefix:
public static final char[] OT_DECAPS = "_OT$decaps$".toCharArray();
-
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
index 0dcde9a..4c824f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
@@ -152,7 +152,7 @@
}
@Override
- public int nullStatus(FlowInfo flowInfo) {
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
return FlowInfo.UNKNOWN;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
index d254881..4f2e105 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
@@ -1,10 +1,10 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2003, 2008 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2003, 2013 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
- * Germany.
+ * Germany, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -324,8 +324,20 @@
receiverClass = receiverClass.enclosingType();
}
}
- if (this.resolvedMethod != null && !this.resolvedMethod.isValidBinding() && this.resolvedMethod.declaringClass == null)
- this.resolvedMethod.declaringClass = receiverClass; // needed for computeUniqueKey (via CallinCalloutBinding.computeUniqueKey)
+ if (this.resolvedMethod != null) {
+ if (this.resolvedMethod.isValidBinding()) {
+ // check visibility of role-side in callin:
+ if (!isBaseSide
+ && scope.referenceContext() instanceof CallinMappingDeclaration
+ && !this.resolvedMethod.canBeSeenBy(this, scope))
+ {
+ scope.problemReporter().invisibleMethod(this, this.resolvedMethod);
+ this.resolvedMethod = new ProblemMethodBinding(this.resolvedMethod, this.selector, this.parameters, ProblemReasons.NotVisible);
+ }
+ }
+ if (!this.resolvedMethod.isValidBinding() && this.resolvedMethod.declaringClass == null)
+ this.resolvedMethod.declaringClass = receiverClass; // needed for computeUniqueKey (via CallinCalloutBinding.computeUniqueKey)
+ }
return this.resolvedMethod;
}
@@ -646,8 +658,15 @@
StringBuffer buffer = new StringBuffer();
buffer.append('(');
- // manual retrenching:
- int offset = method.isCallin() ? MethodSignatureEnhancer.ENHANCING_ARG_LEN : 0;
+ // synthetic args for static role method?
+ MethodBinding orig = method.copyInheritanceSrc != null ? method.copyInheritanceSrc : method; // normalize to copyInhSrc so reading a callin-attr. from bytes can more easily find the method
+ if (CallinImplementorDyn.DYNAMIC_WEAVING && orig.declaringClass.isRole() && orig.isStatic()) {
+ buffer.append('I');
+ buffer.append(String.valueOf(orig.declaringClass.enclosingType().signature()));
+ }
+ // manual retrenching?
+ boolean shouldRetrench = !CallinImplementorDyn.DYNAMIC_WEAVING && method.isCallin();
+ int offset = shouldRetrench ? MethodSignatureEnhancer.ENHANCING_ARG_LEN : 0;
int paramLen = method.parameters.length;
for (int i = offset; i < paramLen; i++) {
// 'weaken' to that erasure that was used in the tsuper version:
@@ -655,7 +674,7 @@
buffer.append(targetParameter.signature());
}
buffer.append(')');
- TypeBinding sourceReturnType = method.isCallin()
+ TypeBinding sourceReturnType = shouldRetrench
? MethodModel.getReturnType(method)
: method.returnType;
// 'weaken' to that erasure that was used in the tsuper version:
@@ -724,7 +743,7 @@
return null;
}
public boolean isSuperAccess() {
- return false;
+ return true; // grant access to inherited methods
}
public boolean isTypeAccess() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialLiftExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialLiftExpression.java
index 9d59444..9ebd25f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialLiftExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialLiftExpression.java
@@ -202,10 +202,11 @@
private MessageSend genLiftCall(BlockScope scope, TypeBinding providedType) {
MessageSend liftCall = Lifting.liftCall(scope, this.teamExpr, this.expression, providedType, this.expectedType, this.requireReverseOperation);
liftCall.actualReceiverType = this.teamExpr.resolveType(scope);
- liftCall.binding = ((ReferenceBinding)this.teamExpr.resolvedType).getMethod(scope, liftCall.selector);
+ if (this.teamExpr.resolvedType instanceof ReferenceBinding) // i.e. not-null
+ liftCall.binding = ((ReferenceBinding)this.teamExpr.resolvedType).getMethod(scope, liftCall.selector);
if (liftCall.binding == null) // can't process (analyze,generate) if lift method is missing
{
- if (TeamModel.hasRoFiCache((ReferenceBinding)liftCall.actualReceiverType))
+ if (liftCall.actualReceiverType != null && TeamModel.hasRoFiCache((ReferenceBinding)liftCall.actualReceiverType))
scope.problemReporter().unresolvedLifting(this, providedType, this.expectedType);
else
scope.problemReporter().referenceContext.tagAsHavingErrors();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialTranslationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialTranslationExpression.java
index 13fea82..584a97e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialTranslationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/PotentialTranslationExpression.java
@@ -80,8 +80,8 @@
/** Simply forward. */
@Override
- public int nullStatus(FlowInfo flowInfo) {
- return this.expression.nullStatus(flowInfo);
+ public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ return this.expression.nullStatus(flowInfo, flowContext);
}
/** Simply forward. */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
index 94a64a0..47196d4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
@@ -1,16 +1,15 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2006, 2013 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
- * Germany.
+ * Germany, 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
* http://www.eclipse.org/legal/epl-v10.html
- * $Id: TypeAnchorReference.java 23401 2010-02-02 23:56:05Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -49,11 +48,16 @@
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.TThisBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
@@ -85,9 +89,8 @@
* the receiver expression. In that case also resolveType and generateCode are supported.
*
* @author stephan
- * @version $Id: TypeAnchorReference.java 23401 2010-02-02 23:56:05Z stephan $
*/
-public class TypeAnchorReference extends TypeReference {
+public class TypeAnchorReference extends TypeReference implements InvocationSite {
// either NameReference or FieldReference
public Reference anchor;
@@ -161,6 +164,8 @@
return ((SingleNameReference)this.anchor).token;
if (this.anchor instanceof QualifiedBaseReference)
return IOTConstants.BASE;
+ if (this.anchor instanceof FieldReference)
+ return ((FieldReference)this.anchor).token;
char[][] tokens = ((QualifiedNameReference)this.anchor).tokens;
return tokens[tokens.length-1];
}
@@ -230,6 +235,7 @@
currentToken = singleAnchor.token;
currentAnchor = findVariable(
scope, currentToken, scope.isStatic(), singleAnchor.sourceStart, singleAnchor.sourceEnd);
+ this.anchor.bits |= (this.bits & DepthMASK);
// could be ProblemAnchorBinding
} else if (reference instanceof FieldReference) {
FieldReference fieldRef = (FieldReference)reference;
@@ -296,17 +302,30 @@
haveReportedProblem = currentAnchor == null;
}
if (currentAnchor != null) {
-
- // find more fields:
- for (int i = j; i < tokens.length; i++) {
- currentPos = qualifiedAnchor.sourcePositions[i];
- currentToken = tokens[i];
- FieldBinding nextField = currentAnchor.getFieldOfType(currentToken, /*static*/false, true);
- if (nextField == null || !nextField.hasValidReferenceType()) {
+ if (!currentAnchor.hasValidReferenceType()) {
+ if (j < tokens.length) // would need to process more tokens?
currentAnchor = null; // replace with problem binding below
- break;
+ } else {
+ // find more fields:
+ for (int i = j; i < tokens.length; i++) {
+ TypeBinding fieldType = currentAnchor.getResolvedType().leafComponentType();
+ if (fieldType instanceof SourceTypeBinding) {
+ SourceTypeBinding stb = (SourceTypeBinding)fieldType;
+ if ((stb.scope != null)
+ && (stb.scope.compilationUnitScope() != scope.compilationUnitScope())
+ && (stb.tagBits & (TagBits.BeginHierarchyCheck|TagBits.EndHierarchyCheck)) == (TagBits.BeginHierarchyCheck|TagBits.EndHierarchyCheck)
+ && StateHelper.isReadyToProcess(stb, ITranslationStates.STATE_LENV_DONE_FIELDS_AND_METHODS))
+ Dependencies.ensureBindingState(stb, ITranslationStates.STATE_LENV_DONE_FIELDS_AND_METHODS);
+ }
+ currentPos = qualifiedAnchor.sourcePositions[i];
+ currentToken = tokens[i];
+ FieldBinding nextField = currentAnchor.getFieldOfType(currentToken, /*static*/false, true);
+ if (nextField == null || !nextField.hasValidReferenceType()) {
+ currentAnchor = null; // replace with problem binding below
+ break;
+ }
+ currentAnchor = nextField.setPathPrefix(currentAnchor);
}
- currentAnchor = nextField.setPathPrefix(currentAnchor);
}
}
}
@@ -398,13 +417,15 @@
private ITeamAnchor findVariable(Scope scope, char[] token, boolean isStaticScope, int start, int end)
{
- ITeamAnchor anchorBinding = null;
- Scope currentScope = scope;
- scopes: while (currentScope != null) {
- switch (currentScope.kind) {
+ if (scope instanceof ClassScope && ((ClassScope)scope).superTypeReference != null) {
+ scope.problemReporter().extendingExternalizedRole(((ClassScope)scope).superTypeReference);
+ return null;
+ }
+ VariableBinding anchorBinding = null;
+ switch (scope.kind) {
case Scope.METHOD_SCOPE:
// check arguments for possible anchor:
- AbstractMethodDeclaration method = ((MethodScope)currentScope).referenceMethod();
+ AbstractMethodDeclaration method = ((MethodScope)scope).referenceMethod();
if (method != null) {
Argument[] arguments = method.arguments;
if (arguments != null)
@@ -416,20 +437,13 @@
//$FALL-THROUGH$
case Scope.BLOCK_SCOPE:
case Scope.BINDING_SCOPE:
- anchorBinding = currentScope.findVariable(token);
+ anchorBinding = scope.findVariable(token);
break;
- case Scope.CLASS_SCOPE:
- ReferenceBinding classType = currentScope.enclosingSourceType();
- if (classType.isSynthInterface())
- classType = classType.getRealClass();
- anchorBinding = TypeAnalyzer.findField(classType, token, isStaticScope, true);
- isStaticScope = classType.isStatic(); // travelling out of this type
- if (!classType.isLocalType())
- break scopes; // don't walk out any further, findField already takes care of direct class-nesting
- }
- if (anchorBinding != null)
- break;
- currentScope = currentScope.parent;
+ }
+ if (anchorBinding == null) {
+ Binding binding = scope.getBinding(token, Binding.VARIABLE, this, true);
+ if (binding instanceof VariableBinding)
+ anchorBinding = (VariableBinding) binding;
}
return checkAnchor(scope, this.anchor, token, start, end, anchorBinding);
}
@@ -437,10 +451,7 @@
// post: return is either a valid anchor or null and problem has been reported.
private ITeamAnchor checkAnchor(Scope scope, Reference reference, char[] token, int start, int end, ITeamAnchor anchorBinding) {
if (anchorBinding == null) {
- if (scope instanceof ClassScope && ((ClassScope)scope).superTypeReference != null)
- scope.problemReporter().extendingExternalizedRole(((ClassScope)scope).superTypeReference);
- else
- scope.problemReporter().typeAnchorNotFound(token, start, end);
+ scope.problemReporter().typeAnchorNotFound(token, start, end);
return null;
}
if (anchorBinding instanceof ProblemFieldBinding) {
@@ -569,4 +580,33 @@
}
}
}
+
+ // === implement InvocationSite: ===
+
+ public TypeBinding[] genericTypeArguments() {
+ return Binding.NO_TYPES;
+ }
+
+ public boolean isSuperAccess() {
+ return false;
+ }
+
+ public boolean isTypeAccess() {
+ return false;
+ }
+
+ public void setActualReceiverType(ReferenceBinding receiverType) {
+ // TODO Auto-generated method stub
+ }
+
+ public void setDepth(int depth) {
+ this.bits &= ~DepthMASK; // flush previous depth if any
+ if (depth > 0) {
+ this.bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+ }
+ }
+
+ public void setFieldIndex(int depth) {
+ // ignored
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTDynCallinBindingsAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTDynCallinBindingsAttribute.java
index 62a2308..c622712 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTDynCallinBindingsAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTDynCallinBindingsAttribute.java
@@ -241,9 +241,9 @@
MethodSpec baseSpec = baseMethodSpecs[i];
int baseFlags = 0;
if (baseSpec.isCallin())
- baseFlags |= BaseMethod.STATIC;
- if (baseSpec.isStatic())
baseFlags |= BaseMethod.CALLIN;
+ if (baseSpec.isStatic())
+ baseFlags |= BaseMethod.STATIC;
mapping.addBaseMethod(i, baseSpec.selector, baseSpec.signature(), baseSpec.resolvedMethod.declaringClass.constantPoolName(), baseSpec.getCallinId(this.theTeam), baseFlags, baseSpec.getTranslationFlags());
}
mapping.setSMAPinfo(callinDecl);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateMemento.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateMemento.java
index ce83aa5..2e9f3fb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateMemento.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateMemento.java
@@ -223,8 +223,7 @@
public void runPendingJobs(int state) {
List<Runnable> jobs;
synchronized (this) {
- jobs = this._pendingJobs.get(state);
- this._pendingJobs.remove(state);
+ jobs = this._pendingJobs.remove(state);
}
if (jobs != null)
for (Runnable job : jobs)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
index fd0ac5b..7525a9d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
@@ -24,6 +24,7 @@
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
/**
* @author stephan
@@ -40,16 +41,16 @@
TypeBinding requiredType)
{
this._teamExpr = teamExpr;
- return (MessageSend)translateArray(scope, expression, providedType, requiredType, /*isLifting*/true);
+ return (MessageSend)translateArray(scope, expression, providedType, requiredType, /*isLifting*/true, /*deferredResolve*/false);
}
/* implement hook. */
Expression translation(
Expression rhs,
TypeBinding providedType,
- TypeBinding requiredType)
+ TypeBinding requiredType, AstGenerator gen)
{
- return Lifting.liftCall(this._scope, this._teamExpr, rhs, providedType, requiredType, false);
+ return Lifting.liftCall(this._scope, gen.thisReference(), rhs, providedType, requiredType, false);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
index 09edc8a..21a7bb5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
@@ -44,19 +44,21 @@
BlockScope scope,
Expression expression,
TypeBinding providedType,
- TypeBinding requiredType)
+ TypeBinding requiredType,
+ boolean deferredResolve)
{
// TODO (SH): check if we need to use the team anchor of a RoleTypeBinding
// as receiver for the translation call.
ReferenceBinding teamBinding = ((ReferenceBinding)providedType.leafComponentType()).enclosingType();
if (this._teamExpr == null)
this._teamExpr = new AstGenerator(expression).qualifiedThisReference(teamBinding);
- this._teamExpr.resolveType(scope);
- return translateArray(scope, expression, providedType, requiredType, /*isLifting*/false);
+ if (!deferredResolve)
+ this._teamExpr.resolveType(scope);
+ return translateArray(scope, expression, providedType, requiredType, /*isLifting*/false, deferredResolve);
}
/* implement hook. */
- Expression translation(Expression rhs, TypeBinding providedType, TypeBinding requiredType) {
+ Expression translation(Expression rhs, TypeBinding providedType, TypeBinding requiredType, AstGenerator gen) {
return new Lowering().lowerExpression(this._scope, rhs, providedType, requiredType, this._teamExpr, false);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
index 60fde27..4718fd9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
@@ -36,6 +36,7 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstConverter;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator.IRunInScope;
/**
* This class handles the common part of array lifting and lowering.
@@ -86,17 +87,36 @@
* @param providedType given type of expression
* @param requiredType this should be produced by translation
* @param isLifting is a lifting translation required (else == lowering)
+ * @param deferredResolve if true we set up a special message send for custom resolving
* @return a message send to the appropriate translation method.
*/
- Expression translateArray(BlockScope scope, Expression expression, TypeBinding providedType, TypeBinding requiredType, boolean isLifting) {
+ Expression translateArray(BlockScope scope, Expression expression,
+ TypeBinding providedType, TypeBinding requiredType,
+ boolean isLifting, boolean deferredResolve)
+ {
this._scope = scope;
this._expression = expression;
MethodBinding methodBinding = ensureTransformMethod(
scope, this._teamExpr, providedType, requiredType, isLifting);
+ // if expression is resolved but teamExpression is unresolved schedule special resolving:
+ IRunInScope hook = null;
+ if (!isLifting && deferredResolve && expression.resolvedType != null && this._teamExpr.resolvedType == null) {
+ hook = new IRunInScope() { public void run(BlockScope blockScope) {
+ // resolving this expression was deferred:
+ ArrayTranslations.this._teamExpr.resolve(blockScope);
+ }};
+ }
+
AstGenerator gen = new AstGenerator(expression.sourceStart, expression.sourceEnd);
- MessageSend send = gen.messageSend(
+ MessageSend send = (hook != null)
+ ? gen.messageSendWithResolveHook(
+ this._teamExpr,
+ methodBinding.selector,
+ new Expression[] {expression},
+ hook)
+ : gen.messageSend(
this._teamExpr,
methodBinding.selector,
new Expression[] {expression});
@@ -356,7 +376,7 @@
{
return new Assignment(
lhsReference,
- translation(rhsReference, this._providedType.leafComponentType(), this._requiredType.leafComponentType()),
+ translation(rhsReference, this._providedType.leafComponentType(), this._requiredType.leafComponentType(), gen),
0);
}
else
@@ -384,9 +404,10 @@
* @param rhs
* @param providedType
* @param requiredType
+ * @param gen generator for creating new AST nodes
* @return expression translating a single object
*/
- abstract Expression translation(Expression rhs, TypeBinding providedType, TypeBinding requiredType);
+ abstract Expression translation(Expression rhs, TypeBinding providedType, TypeBinding requiredType, AstGenerator gen);
private MethodDeclaration generateTransformArrayMethod(
TypeDeclaration teamType,
char[] transformMethodName,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/DeclaredLifting.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/DeclaredLifting.java
index 141e466..90c62dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/DeclaredLifting.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/DeclaredLifting.java
@@ -408,6 +408,27 @@
return ((MemberTypeBinding)type).enclosingType() == enclosingTeam.erasure();
return false;
}
+
+ /**
+ * A team constructor copied for declared lifting requests access to targetMethod.
+ * This can happen in two ways:
+ * - create a new copy of the target constructor
+ * - create a turning constructor that delegates to the target constructor using a real super call.
+ * The strategy is chosen by searching the argument types for role types.
+ */
+ public static MethodBinding createCopyOrTurningCtor(Scope scope,
+ MethodBinding targetConstructor,
+ TypeBinding[] argumentTypes,
+ boolean needsLifting,
+ AstGenerator gen)
+ {
+ if (RoleTypeBinding.hasNonExternalizedRoleParameter(targetConstructor))
+ return copyTeamConstructorForDeclaredLifting(
+ scope, targetConstructor, argumentTypes, needsLifting);
+ else
+ return maybeCreateTurningCtor(scope.referenceType(), targetConstructor, gen);
+ }
+
/**
* Copy a team constructor such that the copy is suitable for chaining
* previous super calls through a chain of tsuper-calls. This enables
@@ -577,8 +598,7 @@
if (roleType != null)
{
// compatibility only through lifting, need to copy the constructor for this selfcall
- return copyTeamConstructorForDeclaredLifting(
- scope, selfcall, mergeSelfcallArgs(providedArgs, parameters), needsLifting);
+ return createCopyOrTurningCtor(scope, selfcall, mergeSelfcallArgs(providedArgs, parameters), needsLifting, gen);
}
} else if (RoleTypeBinding.isRoleWithoutExplicitAnchor(parameters[i])) {
hasProblematicArg = true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lifting.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lifting.java
index 3b7c7c4..caf2d21 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lifting.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lifting.java
@@ -44,6 +44,7 @@
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.RoleInitializationMethod;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
@@ -829,13 +830,23 @@
RoleTypeBinding baseRole = (RoleTypeBinding)baseClass;
if (!baseRole.hasExplicitAnchor())
return this._gen.emptyStatement();
+ NameReference anchorRef;
+ ITeamAnchor[] bestNamePath = baseRole._teamAnchor.getBestNamePath();
+ if (bestNamePath.length == 1) {
+ anchorRef = this._gen.singleNameReference(baseRole._teamAnchor.internalName());
+ } else {
+ char[][] names = new char[bestNamePath.length][];
+ for(int i=0; i<names.length; i++)
+ names[i] = bestNamePath[i].internalName();
+ anchorRef = this._gen.qualifiedNameReference(names);
+ }
return this._gen.ifStatement(
new EqualExpression(
this._gen.messageSend(
this._gen.baseNameReference(BASE),
_OT_GETTEAM,
null),
- this._gen.singleNameReference(baseRole._teamAnchor.internalName()),
+ anchorRef,
OperatorIds.NOT_EQUAL),
this._gen.block(new Statement[] {
this._gen.throwStatement(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
index d332642..dcf6146 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
@@ -74,12 +74,23 @@
* @return translation expression
*/
public Expression lowerExpression(
- BlockScope scope,
+ final BlockScope scope,
final Expression expression,
+ TypeBinding unloweredType,
+ TypeBinding requiredType,
+ final Expression teamExpression,
+ boolean needNullCheck)
+ {
+ return lowerExpression(scope, expression, unloweredType, requiredType, teamExpression, needNullCheck, false);
+ }
+ public Expression lowerExpression(
+ final BlockScope scope,
+ final Expression expression,
TypeBinding unloweredType,
TypeBinding requiredType,
- Expression teamExpression,
- boolean needNullCheck)
+ final Expression teamExpression,
+ boolean needNullCheck,
+ boolean deferredResolve)
{
// Note, this method is responsible for 'resolving' all AST nodes it generates!
@@ -116,7 +127,8 @@
scope,
unloweredExpression,
unloweredType,
- requiredType);
+ requiredType,
+ deferredResolve);
}
else
{
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
index 84919f6..3222e95 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
@@ -36,6 +36,7 @@
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
@@ -383,8 +384,9 @@
ReferenceBinding declaringClass = method.declaringClass;
TypeBinding[] parameters = method.parameters;
for (int j = 0; j < parameters.length; j++) {
- if ( isRoleWithoutExplicitAnchor(parameters[j])
- && ((ReferenceBinding)parameters[j]).enclosingType() == declaringClass)
+ TypeBinding leafType = parameters[j].leafComponentType();
+ if ( isRoleWithoutExplicitAnchor(leafType)
+ && ((ReferenceBinding)leafType).enclosingType() == declaringClass)
return true;
}
return false;
@@ -760,7 +762,7 @@
* The former is relevant for type-checking. the latter serves mainly for code generation
* and for determining overriding.
*/
- public boolean isCompatibleWith(TypeBinding right) {
+ public boolean isCompatibleWith(TypeBinding right, /*@Nullable*/ Scope captureScope) {
if (right == this)
return true;
if (!(right instanceof ReferenceBinding))
@@ -786,7 +788,7 @@
{
ReferenceBinding leftStrengthened = this._teamAnchor.getMemberTypeOfType(internalName());
if (leftStrengthened != this)
- return leftStrengthened.isCompatibleWith(right);
+ return leftStrengthened.isCompatibleWith(right, captureScope);
}
else if (TeamModel.areTypesCompatible(
this._staticallyKnownTeam,
@@ -801,7 +803,7 @@
// check the role types:
if (this._staticallyKnownRoleType.
- isCompatibleWith(rightRole._staticallyKnownRoleType))
+ isCompatibleWith(rightRole._staticallyKnownRoleType, captureScope))
return true;
}
if ( referenceBinding.isInterface()
@@ -809,7 +811,7 @@
return true;
if ( this._staticallyKnownRoleClass == null
- && this._staticallyKnownRoleType.isCompatibleWith(referenceBinding, false))
+ && this._staticallyKnownRoleType.isCompatibleWith(referenceBinding, false, captureScope))
{
checkAmbiguousObjectLower(referenceBinding);
return true; // this case is wittnessed by: "this=RoleIfc", right="Object"; other examples?
@@ -817,7 +819,7 @@
// do we need the class part instead of the interface part?
if ( (this._staticallyKnownRoleClass != null)
- && this._staticallyKnownRoleClass.isStrictlyCompatibleWith(referenceBinding)
+ && this._staticallyKnownRoleClass.isStrictlyCompatibleWith(referenceBinding, captureScope)
&& !TeamModel.isTeamContainingRole(this._staticallyKnownTeam, referenceBinding))
{
// Cast from a role to its non-role superclass
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
index e2bad21..2227e79 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
@@ -18,6 +18,7 @@
import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccPublic;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -33,11 +34,14 @@
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -50,12 +54,14 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialLiftExpression;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialLowerExpression;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialRoleReceiverExpression;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrivateRoleMethodCall;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.OTDynCallinBindingsAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lowering;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
@@ -64,9 +70,9 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.PredicateGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.ReplaceResultReferenceVisitor;
-import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstClone;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
/**
* This class translates callin binding to the dynamic weaving strategy.
@@ -105,7 +111,7 @@
static final char[] ARGUMENTS = "arguments".toCharArray(); //$NON-NLS-1$
static final char[] _OT_RESULT = "_OT$result".toCharArray(); //$NON-NLS-1$
static final char[] RESULT = "result".toCharArray(); //$NON-NLS-1$
- static final String LOCAL_ROLE = "local$"; //$NON-NLS-1$
+ static final String LOCAL_ROLE = "local$role$"; //$NON-NLS-1$
// for call next:
private static final char[] BASE_CALL_ARGS = "baseCallArguments".toCharArray(); //$NON-NLS-1$
@@ -117,6 +123,8 @@
protected static final String OT_LOCAL = "_OT$local$"; //$NON-NLS-1$
+ static final char[] CATCH_ARG = "_OT$caughtException".toCharArray(); //$NON-NLS-1$
+
private RoleModel _role;
private ClassScope _roleScope;
@@ -346,13 +354,20 @@
MethodModel.getModel(callMethod).setStatementsGenerator(new AbstractStatementsGenerator() {
protected boolean generateStatements(AbstractMethodDeclaration methodDecl) {
- List<Statement> statements = new ArrayList<Statement>();
+
+ // into head of tryStats we generate local vars to be shared by case statements:
+ List<Statement> tryStats = new ArrayList<Statement>();
+ HashSet<String> baseArgs = new HashSet<String>();
+
SwitchStatement switchStat = new SwitchStatement();
switchStat.expression =
isReplace
? gen.arrayReference(gen.singleNameReference(CALLIN_ID), gen.singleNameReference(INDEX)) // switch(callinId[index]) { ...
: gen.singleNameReference(CALLIN_ID); // switch(callinId) { ...
+ // statements for the body of the switchStatement:
+ List<Statement> statements = new ArrayList<Statement>();
+
int callinIdCount = teamDecl.getTeamModel().getCallinIdCount();
// callinIds not handled here will be handled using a super-call.
boolean[] handledCallinIds = new boolean[callinIdCount];
@@ -363,6 +378,8 @@
{
if (callinDecl.ignoreFurtherInvestigation || RoleModel.isRoleWithBaseProblem(callinDecl.scope.referenceType()))
continue;
+ if (!callinDecl.hasParsedParamMappings) // during reconcile we may not be interested in this level of detail (e.g., of a role file)
+ continue;
gen.retargetFrom(callinDecl);
@@ -376,10 +393,6 @@
callinDecl.isReplaceCallin());
TypeBinding baseReturn = baseSpec.resolvedType();
- boolean mayUseResultArgument = callinDecl.callinModifier == TerminalTokens.TokenNameafter
- && callinDecl.mappings != null
- && baseReturn != TypeBinding.VOID;
-
boolean isStaticRoleMethod = callinDecl.getRoleMethod().isStatic();
ReferenceBinding roleType = callinDecl.scope.enclosingReceiverType();
MethodBinding roleMethodBinding = callinDecl.getRoleMethod();
@@ -389,8 +402,15 @@
&& roleType.isCompatibleWith(roleMethodBinding.declaringClass);
List<Statement> blockStatements = new ArrayList<Statement>();
-
- // -------------- base predicate check -------
+
+ // do we need to expose _OT$result as result?
+ if (callinDecl.callinModifier == TerminalTokens.TokenNameafter
+ && (callinDecl.mappings != null || callinDecl.predicate != null)
+ && baseReturn != TypeBinding.VOID)
+ blockStatements.add(gen.localVariable(RESULT, baseReturn, // BaseReturnType result = (BaseReturnType)_OT$result;
+ gen.createCastOrUnboxing(gen.singleNameReference(_OT_RESULT), baseReturn, true/*baseAccess*/)));
+
+ // -------------- base predicate check -------
boolean hasBasePredicate = false;
for (MethodSpec baseMethodSpec : callinDecl.baseMethodSpecs) {
char[] resultName = null;
@@ -409,11 +429,8 @@
}
Expression resetFlag =
CallinImplementor.setExecutingCallin(roleType.roleModel, blockStatements); // boolean _OT$oldIsExecutingCallin = _OT$setExecutingCallin(true);
-
- if (mayUseResultArgument)
- blockStatements.add(gen.localVariable(RESULT, baseReturn, // BaseReturnType result = (BaseReturnType)_OT$result;
- gen.createCastOrUnboxing(gen.singleNameReference(_OT_RESULT), baseReturn)));
- Expression receiver;
+
+ Expression receiver;
char[] roleVar = null;
if (!isStaticRoleMethod) {
if (needLiftedRoleVar) {
@@ -441,25 +458,30 @@
receiver = gen.singleNameReference(callinDecl.getRoleMethod().declaringClass.sourceName());
}
+ int baseArgOffset = 0;
+ if (baseSpec.isCallin()) baseArgOffset+=MethodSignatureEnhancer.ENHANCING_ARG_LEN;
+ if (baseSpec.isStatic() && baseSpec.getDeclaringClass().isRole()) baseArgOffset+=2;
// unpack arguments to be used by parameter mappings and base predicate:
// ArgTypeN argn = args[n]
if (callinDecl.mappings != null || (hasBasePredicate && baseSpec.arguments != null)) {
TypeBinding[] baseParams = baseSpec.resolvedParameters();
for (int i=0; i<baseSpec.arguments.length; i++) {
Argument baseArg = baseSpec.arguments[i];
- Expression rawArg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i);
+ Expression rawArg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i+baseArgOffset);
Expression init = rawArg;
if (!baseParams[i].isTypeVariable())
init = gen.createCastOrUnboxing(rawArg, baseParams[i], callinDecl.scope);
+ if (baseArgs.add(String.valueOf(baseArg.name)))
+ tryStats.add(i, gen.localVariable(baseArg.name,
+ gen.alienScopeTypeReference(baseArg.type, callinDecl.scope),
+ null));
if (hasBasePredicate) { // BaseType baseArg = castAndOrUnbox(arguments[n]);
// add to front so it is already available for the base predicate check:
- blockStatements.add(i, gen.localVariable(baseArg.name,
- AstClone.copyTypeReference(baseArg.type),
- init));
+ blockStatements.add(i, gen.assignment(gen.singleNameReference(baseArg.name),
+ init));
} else {
// otherwise give it a chance for expressions/types that depend on the role instance
- blockStatements.add(gen.localVariable(baseArg.name,
- gen.alienScopeTypeReference(baseArg.type, callinDecl.scope),
+ blockStatements.add(gen.assignment(gen.singleNameReference(baseArg.name),
new PotentialRoleReceiverExpression(
init,
roleVar,
@@ -492,7 +514,7 @@
}
}
if (callinDecl.mappings == null) {
- arg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i); // prepare: somePreparation(arguments[i])
+ arg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i+baseArgOffset); // prepare: somePreparation(arguments[i])
TypeBinding baseArgType = baseSpec.resolvedParameters()[i];
if (roleParam.isBaseType()) {
// this includes intermediate cast to boxed type:
@@ -504,14 +526,19 @@
CastExpression.RAW);
} else {
// Object -> MyBaseClass
+ ReferenceBinding baseclass = roleType.baseclass();
+ if (baseclass instanceof DependentTypeBinding && baseArgType instanceof ReferenceBinding)
+ baseArgType = RoleTypeCreator.maybeInstantiateFromPlayedBy(callinDecl.scope, (ReferenceBinding)baseArgType);
arg = gen.castExpression(arg,
gen.alienScopeTypeReference(
gen.typeReference(baseArgType),
callinDecl.scope),
CastExpression.DO_WRAP);
- // lift?(MyBaseClass)
- arg = gen.potentialLift(gen.thisReference(), arg, roleParam, isReplace/*reversible*/);
- canLiftingFail |= checkLiftingProblem(teamDecl, callinDecl, (ReferenceBinding)roleParam.leafComponentType());
+ if (!roleParam.leafComponentType().isBaseType()) {
+ // lift?(MyBaseClass)
+ arg = gen.potentialLift(gen.thisReference(), arg, roleParam, isReplace/*reversible*/);
+ canLiftingFail |= checkLiftingProblem(teamDecl, callinDecl, (ReferenceBinding)roleParam.leafComponentType());
+ }
}
} else {
arg = getArgument(callinDecl, // prepare: <mappedArg<n>>
@@ -551,7 +578,7 @@
continue;
// -- role side predicate:
- Expression[] predicateArgs = maybeAddResultReference(callinDecl, callArgs, _OT_RESULT, gen);
+ Expression[] predicateArgs = maybeAddResultReference(callinDecl, callArgs, RESULT, gen);
Statement rolePredicateCheck = predGen.createPredicateCheck( // if (!when(callArgs)) throw new LiftingVetoException();
callinDecl,
callinDecl.scope.referenceType(),
@@ -575,10 +602,15 @@
Statement[] messageSendStatements;
if (isReplace) {
Expression result = roleMethodCall;
- if (baseSpec.returnNeedsTranslation) {// FIXME(SH): per base method!
+ if (baseSpec.returnNeedsTranslation) {
// lowering:
TypeBinding[]/*role,base*/ returnTypes = getReturnTypes(callinDecl, 0);
- result = new Lowering().lowerExpression(methodDecl.scope, result, returnTypes[0], returnTypes[1], gen.thisReference(), true);
+ // who is responsible for lowering: the team or the current role?
+ Expression lowerReceiver = (isRoleOfCurrentRole(roleType, returnTypes[0]))
+ ? gen.singleNameReference(roleVar)
+ : gen.thisReference();
+ result = new Lowering().lowerExpression(methodDecl.scope, result, returnTypes[0], returnTypes[1],
+ lowerReceiver, true/*needNullCheck*/, true/*delayedResolve*/);
}
// possibly convert using result mapping
callinDecl.checkResultMapping();
@@ -624,10 +656,14 @@
gen.breakStatement() // break;
};
}
- blockStatements.add(gen.tryFinally(messageSendStatements, new Statement[]{resetFlag})); // try { roleMessageSend(); } finally { _OT$setExecutingCallin(_OT$oldIsExecutingCallin); }
+ // assemble:
+ // try { roleMessageSend(); }
+ // catch(Exception _OT$caughtException) { throw new SneakyException(_OT$caughtException); }
+ // finally { _OT$setExecutingCallin(_OT$oldIsExecutingCallin); }
+ blockStatements.add(protectRoleMethodCall(messageSendStatements, roleMethodBinding, resetFlag, gen));
statements.add(gen.block(blockStatements.toArray(new Statement[blockStatements.size()])));
// collectively report the problem(s)
- if (canLiftingFail)
+ if (canLiftingFail && callinDecl.rolesWithLiftingProblem != null)
for (Map.Entry<ReferenceBinding, Integer> entry : callinDecl.rolesWithLiftingProblem.entrySet())
callinDecl.scope.problemReporter().callinDespiteLiftingProblem(entry.getKey(), entry.getValue(), callinDecl);
}
@@ -709,10 +745,11 @@
gen.qualifiedTypeReference(IOTConstants.ORG_OBJECTTEAMS_LIFTING_VETO))
};
exceptionStatementss = new Statement[][]{{catchStatement1}};
- }
+ }
+ tryStats.add(switchStat);
methodDecl.statements = new Statement[] {
gen.tryCatch(
- new Statement[] {switchStat},
+ tryStats.toArray(new Statement[tryStats.size()]),
// expected exception is ignored, do nothing (before/after) or proceed to callNext (replace)
exceptionArguments,
exceptionStatementss)
@@ -781,11 +818,21 @@
caseBlockStats.add(gen.caseStatement(gen.intLiteral(baseSpec.getCallinId(aTeam)))); // case bseSpecCallinId:
int nRoleArgs = mapping.getRoleMethod().getSourceParamLength();
TypeBinding[] roleParams = mapping.getRoleMethod().getSourceParameters();
+ for (int i=0; i<roleParams.length; i++)
+ if (roleParams[i].isRole() && TeamModel.isTeamContainingRole(teamDecl.binding, (ReferenceBinding) roleParams[i]))
+ roleParams[i] = TeamModel.strengthenRoleType(teamDecl.binding, roleParams[i]);
+
List<Statement> repackingStats = new ArrayList<Statement>();
if (mapping.positions != null) {
int[] poss = mapping.positions;
nLabels = caseBlockStats.size();
+ int argOffset = 0; // some methods have their real arguments at an offset
+ MethodSpec baseSpec = mapping.baseMethodSpecs[0]; // TODO(SH): check all base methods??
+ if (baseSpec.isCallin())
+ argOffset += 6;
+ if (baseSpec.isStatic() && baseSpec.getDeclaringClass().isRole())
+ argOffset += 2;
for (int i=0; i<poss.length; i++)
// arguments[basepos] = baseCallArguments[i]
if (poss[i] > 0) {
@@ -795,45 +842,48 @@
// FIXME(SH): per basemethod:
TypeBinding baseSideParameter = mapping.baseMethodSpecs[0].resolvedParameters()[poss[i]-1];
Expression roleSideArgument = gen.arrayReference(gen.singleNameReference(BASE_CALL_ARGS), i);// ... baseCallArguments[i] ...
+ if (roleSideParameter != baseSideParameter)
+ roleSideArgument = gen.resolvedCastExpression(roleSideArgument, roleSideParameter, CastExpression.RAW);
if ( roleSideParameter.isRole()
&& ((ReferenceBinding)roleSideParameter).baseclass().isCompatibleWith(baseSideParameter))
- roleSideArgument = new Lowering().lowerExpression(mapping.scope,
- roleSideArgument,
- roleSideParameter,
- baseSideParameter,
- gen.thisReference(),
- true);
+ roleSideArgument = new PotentialLowerExpression(roleSideArgument, baseSideParameter, gen.thisReference());
repackingStats.add(gen.assignment(gen.arrayReference(gen.singleNameReference(ARGUMENTS), // arguments[p] = baseCallArguments[i];
- poss[i]-1), // 0 represents result
+ poss[i]-1+argOffset), // 0 represents result
roleSideArgument));
}
} else if (nRoleArgs > 0) {
for (int i=0; i<nRoleArgs; i++) {
Expression basecallArg = gen.arrayReference(gen.singleNameReference(BASE_CALL_ARGS), i);
if (mapping.baseMethodSpecs[0].argNeedsTranslation(i)) { // FIXME(SH): per basemethod!
- basecallArg = new Lowering().lowerExpression(mapping.scope,
- gen.castExpression(basecallArg,
+ basecallArg = new PotentialLowerExpression(gen.castExpression(basecallArg,
gen.typeReference(roleParams[i]),
CastExpression.RAW),
- roleParams[i],
- mapping.baseMethodSpecs[0].resolvedParameters()[i], // FIXME(SH): per basemethod!
- gen.qualifiedThisReference(teamDecl.binding),
- true);
+ mapping.baseMethodSpecs[0].resolvedParameters()[i], // FIXME(SH): per basemethod!
+ gen.qualifiedThisReference(teamDecl.binding));
}
repackingStats.add(gen.assignment(gen.arrayReference(gen.singleNameReference(ARGUMENTS), i), // arguments[i] = lower?(baseCallArguments[i])
basecallArg));
}
}
caseBlockStats.add(gen.ifStatement(gen.nullCheck(gen.singleNameReference(BASE_CALL_ARGS)), // if (baseCallArgs == null) {} { arguments[i] = ...; ... }
- null,
+ gen.emptyStatement(),
gen.block(repackingStats.toArray(new Statement[repackingStats.size()]))));
Expression result = gen.messageSend(gen.superReference(), OT_CALL_NEXT, superArgs); // return cast+lift?(super._OT$callNext(..));
if (mapping.baseMethodSpecs[0].returnNeedsTranslation) { // FIXME(SH): per basemethod!
// lifting:
TypeBinding[]/*role,base*/ returnTypes = getReturnTypes(mapping, 0);
+ // who is responsible for lifting: the team or the current role?
+ ReferenceBinding currentRole = mapping.scope.enclosingReceiverType();
+ Expression liftReceiver = (isRoleOfCurrentRole(currentRole, returnTypes[0]))
+ ? Lifting.liftCall(mapping.scope,
+ gen.thisReference(),
+ gen.castExpression(gen.singleNameReference(IOTConstants.BASE), gen.typeReference(currentRole.baseclass()), CastExpression.RAW),
+ currentRole.baseclass(), currentRole, false)
+ // TODO: might want to extend the signature of callNext to pass the current role to avoid this lifting?
+ : gen.thisReference();
result = Lifting.liftCall(mapping.scope,
- gen.thisReference(),
+ liftReceiver,
gen.castExpression(result,
gen.typeReference(returnTypes[1]),
CastExpression.RAW),
@@ -868,6 +918,22 @@
return new TypeBinding[]{roleReturn, baseReturn};
}
+ /** Convert custom exceptions into SneakyException as to bypass checking by the compiler. */
+ TryStatement protectRoleMethodCall(Statement[] statements, MethodBinding roleMethod, Statement finallyStat, AstGenerator gen) {
+ Argument catchArg = gen.argument(CATCH_ARG, gen.qualifiedTypeReference(TypeConstants.JAVA_LANG_EXCEPTION));
+ Statement[] catchStat = new Statement[] {
+ gen.throwStatement(gen.allocation(
+ gen.qualifiedTypeReference(IOTConstants.SNEAKY_EXCEPTION),
+ new Expression[] { gen.singleNameReference(CATCH_ARG) }
+ ))
+ };
+ return gen.tryStatement(
+ statements,
+ new Argument[] {catchArg},
+ new Statement[][] {catchStat},
+ new Statement[] {finallyStat});
+ }
+
private void generateCallOrigStatic(List<CallinMappingDeclaration> callinDecls, TeamModel aTeam) {
// public Object _OT$callOrigStatic(int callinId, int boundMethodId, Object[] args)
// this team method delegates to the corresponding _OT$callOrigStatic(int,Object[])
@@ -897,8 +963,9 @@
for (MethodSpec baseSpec : mapping.baseMethodSpecs) {
MethodBinding baseMethod = baseSpec.resolvedMethod;
if (baseMethod.isStatic()) {
- swStatements.add(gen.caseStatement(gen.intLiteral(baseSpec.getCallinId(aTeam)))); // case baseSpecCallinId:
- Expression result = gen.fakeMessageSend(gen.baseNameReference(baseMethod.declaringClass), // return BaseClass._OT$callOrigStatic(boundMethodId, args);
+ ReferenceBinding baseClass = mapping.scope.enclosingReceiverType().baseclass();
+ swStatements.add(gen.caseStatement(gen.intLiteral(baseSpec.getCallinId(aTeam)))); // case baseSpecCallinId:
+ Expression result = gen.fakeMessageSend(gen.baseTypeReference(baseClass), // return BaseClass._OT$callOrigStatic(boundMethodId, args);
OT_CALL_ORIG_STATIC,
passThroughArgs,
baseMethod.declaringClass,
@@ -927,4 +994,40 @@
}
return false;
}
+
+ /**
+ * the expression local$role$n.roleMethod(..) should not wrap its
+ * return type anchored to the generated team anchor _OT$role,
+ * because the method should actually be seen as being within
+ * the scope of this role already, although, physically it is part of
+ * the team.
+ *
+ * @param scope use the scope to determine if we are actually within
+ * a callin wrapper.
+ * @param receiver if this is _OT$role this is the role method call.
+ * @return true if the return type should not be wrapped further.
+ */
+ public static boolean avoidWrapRoleType(BlockScope scope, Expression receiver) {
+ MethodScope methodScope = scope.methodScope();
+ if (methodScope != null) { // CLOVER: never false in jacks suite
+ AbstractMethodDeclaration refMethod = methodScope.referenceMethod();
+ if ( refMethod != null
+ && refMethod.isMappingWrapper._callin())
+ {
+ if ( receiver instanceof SingleNameReference
+ && CharOperation.prefixEquals(LOCAL_ROLE.toCharArray(), ((SingleNameReference)receiver).token))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isRoleOfCurrentRole(ReferenceBinding currentRole, TypeBinding type) {
+ TypeBinding leafType = type.leafComponentType();
+ if (leafType.isRole()) {
+ return currentRole.erasure().isCompatibleWith(leafType.enclosingType().erasure());
+ }
+ return false;
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
index 2b87176..288baf5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
@@ -577,7 +577,7 @@
if (calloutDecl.baseMethodSpec.isStatic())
// we thought we should use an instance
// but callout-to-static is sent to the base *class*
- receiver = gen.baseNameReference(baseType.getRealClass());
+ receiver = gen.baseTypeReference(baseType);
switch (calloutDecl.baseMethodSpec.implementationStrategy) {
case DIRECT:
if (calloutDecl.isCalloutToField()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
index 77ad3d8..79eea38 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
@@ -64,7 +64,7 @@
if (baseSpec.resolvedType() == TypeBinding.VOID)
return messageSend;
else
- return gen.createCastOrUnboxing(messageSend, baseSpec.resolvedType());
+ return gen.createCastOrUnboxing(messageSend, baseSpec.resolvedType(), true/*baseAccess*/);
}
private static char[] ensureAccessor(Scope scope, ReferenceBinding baseType, boolean isStatic) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
index 5f3c2b7..5fb1691 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
@@ -76,13 +76,14 @@
public class TeamModel extends TypeModel {
// constants for bits in tagBits:
+ public static final int CopyRolesFromTSuperMASK = 0x0FF;
+ public static final int MaxTSuperRoles = 8; // so many bits allocated in CopyRolesFromTSuperMask
- // can lifting fail due to role abstractness?
- public static final int HasAbstractRelevantRole = ASTNode.Bit20;
-
- // details of completeTypeBindings:
- public static final int BeginCopyRoles = ASTNode.Bit21;
+ // details of completeTypeBindings:
+ public static final int BeginCopyRoles = ASTNode.Bit9;
+ // can lifting fail due to role abstractness?
+ public static final int HasAbstractRelevantRole = ASTNode.Bit10;
/** The Marker interface created for this Team (_TSuper__OT__TeamName); */
public TypeDeclaration markerInterface;
@@ -332,8 +333,12 @@
return false;
}
- public static void setTagBit(ReferenceBinding teamBinding, int tagBit) {
- teamBinding.getTeamModel().tagBits |= tagBit;
+ public static boolean setTagBit(ReferenceBinding teamBinding, int tagBit) {
+ TeamModel model = teamBinding.getTeamModel();
+ if ((model.tagBits & tagBit) != 0)
+ return false; // was already set
+ model.tagBits |= tagBit;
+ return true;
}
public static boolean hasTagBit(ReferenceBinding typeBinding, int tagBit) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
index 35ba3c8..9b4a640 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
@@ -78,6 +78,7 @@
import org.eclipse.jdt.internal.compiler.problem.IProblemRechecker;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.RoleClassLiteralAccess;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TypeContainerMethod;
@@ -185,10 +186,6 @@
* Also connect roles with OT-specific links.
*/
public static void copyRoles(SourceTypeBinding teamBinding) {
- if (TeamModel.hasTagBit(teamBinding, TeamModel.BeginCopyRoles))
- return;
- TeamModel.setTagBit(teamBinding, TeamModel.BeginCopyRoles);
-
TeamModel teamModel= teamBinding.getTeamModel();
ReferenceBinding superTeam= teamBinding.superclass;
if (superTeam == null) {
@@ -197,15 +194,24 @@
}
// super team:
- TSuperHelper.addMarkerInterface(teamModel, superTeam);
- copyRolesFromTeam(superTeam, teamModel, false/*isTsuperTeam*/);
+ if (TeamModel.setTagBit(teamBinding, TeamModel.BeginCopyRoles)) {
+ TSuperHelper.addMarkerInterface(teamModel, superTeam);
+ copyRolesFromTeam(superTeam, teamModel, false/*isTsuperTeam*/);
+ }
// tsuper teams:
if (teamBinding.isRole()) {
- RoleModel teamAsRole = teamBinding.roleModel;
- for (ReferenceBinding tsuperTeam: teamAsRole.getTSuperRoleBindings()) {
- TSuperHelper.addMarkerInterface(teamModel, tsuperTeam);
- copyRolesFromTeam(tsuperTeam, teamModel, true/*isTsuperTeam*/);
+ ReferenceBinding[] tSuperRoleBindings = teamBinding.roleModel.getTSuperRoleBindings();
+ int length = tSuperRoleBindings.length;
+ if (length > TeamModel.MaxTSuperRoles)
+ throw new InternalCompilerError("Too many tsuper roles in "+String.valueOf(teamBinding.readableName())); //$NON-NLS-1$
+ for (int i = 0; i < length; i++) {
+ ReferenceBinding tsuperTeam = tSuperRoleBindings[i];
+ int tagBits = (1<<i) & TeamModel.CopyRolesFromTSuperMASK;
+ if (TeamModel.setTagBit(teamBinding, tagBits)) {
+ TSuperHelper.addMarkerInterface(teamModel, tsuperTeam);
+ copyRolesFromTeam(tsuperTeam, teamModel, true/*isTsuperTeam*/);
+ }
}
}
@@ -686,7 +692,67 @@
subTeam.scope.compilationUnitScope().registerBinaryNested(subRole);
}
- public static ReferenceBinding copyLateRole(TypeDeclaration teamDecl, ReferenceBinding tsuperRole) {
+ /**
+ * If a requested member type was not found in a team binding try if a combination
+ * of role file loading and role copying resolves the issue.
+ */
+ public static ReferenceBinding checkCopyLateRoleFile(SourceTypeBinding teamBinding, char[] name) {
+ if (!TeamModel.hasTagBit(teamBinding, TeamModel.BeginCopyRoles))
+ return null;
+ ReferenceBinding ifcPart = null;
+ if (CharOperation.prefixEquals(IOTConstants.OT_DELIM_NAME, name)) {
+ char[] ifcName = CharOperation.subarray(name, IOTConstants.OT_DELIM_LEN, -1);
+ ifcPart = teamBinding.getMemberType(ifcName);
+ }
+ TypeDeclaration roleDecl = internalCheckCopyLateRoleFile(teamBinding, name);
+ if (roleDecl != null && ifcPart != null) {
+ ReferenceBinding superTeam = teamBinding.superclass;
+ if (!hasHiearchyCheckBegun(superTeam))
+ Dependencies.ensureBindingState(superTeam, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY);
+ TypeLevel.connectRoleClasses(superTeam, roleDecl);
+ }
+ if (roleDecl != null)
+ return roleDecl.binding;
+ return null;
+ }
+ private static boolean hasHiearchyCheckBegun(ReferenceBinding type) {
+ if ((type.tagBits & TagBits.BeginHierarchyCheck) != 0)
+ return true;
+ if (type.enclosingType() != null)
+ return hasHiearchyCheckBegun(type.enclosingType());
+ return false;
+ }
+
+ public static TypeDeclaration internalCheckCopyLateRoleFile(SourceTypeBinding teamBinding, char[] name) {
+ ReferenceBinding superTeam = (ReferenceBinding) teamBinding.superclass().original(); // FIXME(SH): tsuper teams
+ if ( superTeam != null
+ && superTeam.isTeam()
+ && !TypeAnalyzer.isOrgObjectteamsTeam(superTeam)
+ && !teamBinding._teamModel._isCopyingLateRole
+ && !OTNameUtils.isTSuperMarkerInterface(name))
+ {
+ ReferenceBinding tsuperRole = superTeam.getMemberType(name);
+ if ((tsuperRole == null ||
+ (!tsuperRole.isValidBinding() && tsuperRole.problemId() == ProblemReasons.NotFound))
+ && superTeam instanceof SourceTypeBinding)
+ {
+ TypeDeclaration tsuperDecl = internalCheckCopyLateRoleFile(((SourceTypeBinding)superTeam), name);
+ if (tsuperDecl != null)
+ tsuperRole = tsuperDecl.binding;
+ }
+ if ( tsuperRole != null && tsuperRole.isRole() && tsuperRole.isValidBinding()
+ && !tsuperRole.isLocalType())
+ {
+ if ((teamBinding.tagBits & TagBits.BeginHierarchyCheck) != 0)
+ return copyLateRole(teamBinding._teamModel.getAst(), tsuperRole);
+ else
+ return copyLateRolePart(teamBinding._teamModel.getAst(), tsuperRole);
+ }
+ }
+ return null;
+ }
+
+ public static TypeDeclaration copyLateRole(TypeDeclaration teamDecl, ReferenceBinding tsuperRole) {
TypeDeclaration roleType = null;
ReferenceBinding ifcPart = null;
char[] tsuperName = tsuperRole.internalName();
@@ -696,19 +762,18 @@
}
roleType = copyLateRolePart(teamDecl, tsuperRole);
if (ifcPart != null) {
- // FIXME(SH): improve catch up: connecting bindings etc.
- Dependencies.ensureBindingState(tsuperRole.enclosingType(), ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY);
+ ReferenceBinding superTeam = tsuperRole.enclosingType();
+ if ((superTeam.tagBits & TagBits.BeginHierarchyCheck) == 0)
+ Dependencies.ensureBindingState(superTeam, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY);
if (StateHelper.hasState(tsuperRole, ITranslationStates.STATE_LENV_CONNECT_TYPE_HIERARCHY)) {
RoleModel subRole = roleType.getRoleModel();
- TypeLevel.connectRoleClasses(tsuperRole.enclosingType(), roleType);
- // subRole.set = ifcPart;
- // ifcPart.roleModel._classPart = roleType.binding;
+ TypeLevel.connectRoleClasses(superTeam, roleType);
setRoleState(subRole, STATE_LENV_CONNECT_TYPE_HIERARCHY);
}
}
if (roleType == null) return null;
Dependencies.lateRolesCatchup(teamDecl.getTeamModel());
- return roleType.binding;
+ return roleType;
}
private static TypeDeclaration copyLateRolePart(TypeDeclaration teamDecl, ReferenceBinding tsuperRole) {
TypeDeclaration roleDecl = copyRole(tsuperRole, false, teamDecl, false);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
index 8b11272..5843a2f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
@@ -63,7 +63,7 @@
* @param superTeam
* @param roleDecl
*/
- static SupertypeObligation[] connectRoleClasses(
+ public static SupertypeObligation[] connectRoleClasses(
ReferenceBinding superTeam,
TypeDeclaration roleDecl)
{
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/MethodSignatureEnhancer.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/MethodSignatureEnhancer.java
index 2249e7a..1cb78c0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/MethodSignatureEnhancer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/MethodSignatureEnhancer.java
@@ -368,7 +368,7 @@
//{OTDyn: configurable:
CallinImplementorDyn.DYNAMIC_WEAVING
? (makeShort
- ? "IBoundBase, Team[], int, int[], int, Object[]"
+ ? "IBoundBase, ITeam[], int, int[], int, Object[]"
: "org.objectteams.IBoundBase, org.objectteams.ITeam[], int, int[] int, java.lang.Object[]))")
// SH}
// {OT/JamVM support:
@@ -379,7 +379,7 @@
// CH}
: (makeShort
? "ITeam[], int[], int, int, int, Object[]"
- : "org.objectteams.ITeam[], int[] int, int, int, java.lang.Object[]))");
+ : "org.objectteams.ITeam[], int[], int, int, int, java.lang.Object[]))");
if (typeString.startsWith(prefix)) {
types.delete(0, prefix.length());
if (types.length()> 0 && types.charAt(0) == ',')
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
index 8491934..16f5a7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
@@ -743,6 +743,47 @@
return messageSend;
}
+ // function type for the next method:
+ public static interface IRunInScope { void run(BlockScope scope); }
+
+ /**
+ * Create a message send that has a custom resolve method (see inside for details).
+ */
+ public MessageSend messageSendWithResolveHook(Expression receiver, char[] selector, Expression[] parameters, final IRunInScope hook) {
+ MessageSend messageSend = new MessageSend() {
+ @Override
+ public TypeBinding resolveType(BlockScope scope) {
+ // arguments always need resolving:
+ if (this.arguments != null) {
+ int length = this.arguments.length;
+ for (int i = 0; i < length; i++){
+ Expression argument = this.arguments[i];
+ if (argument.resolvedType == null)
+ argument.resolveType(scope);
+ }
+ }
+ // skip the receiver unless its again a hooked message send:
+ if (this.receiver.getClass() == this.getClass())
+ this.receiver.resolveType(scope);
+
+ // the main payload:
+ hook.run(scope);
+
+ this.actualReceiverType = this.binding.declaringClass;
+ return this.resolvedType;
+ }
+ };
+ messageSend.sourceStart = this.sourceStart;
+ messageSend.sourceEnd = this.sourceEnd;
+ messageSend.statementEnd = this.sourceEnd;
+ messageSend.nameSourcePosition = this.pos;
+ messageSend.receiver = receiver;
+ messageSend.selector = selector;
+ messageSend.arguments = parameters;
+ messageSend.constant = Constant.NotAConstant;
+ return messageSend;
+ }
+
public MessageSend messageSend(Expression receiver, char[] selector, Expression[] parameters, final TypeBinding resolvedReturn) {
MessageSend messageSend = new MessageSend() {
@Override
@@ -1067,6 +1108,30 @@
return stat;
}
+ /** Generate a full try-catch-finally statement. */
+ public TryStatement tryStatement(Statement[] tryStatements,
+ Argument[] exceptionArguments, Statement[][] catchStatementss,
+ Statement[] finallyStatements)
+ {
+ TryStatement stat = new TryStatement();
+ stat.sourceStart = this.sourceStart;
+ stat.sourceEnd = this.sourceEnd;
+ stat.tryBlock = block(tryStatements);
+ stat.catchArguments = exceptionArguments;
+ stat.catchBlocks = new Block[catchStatementss.length];
+ for(int i=0; i<catchStatementss.length; i++)
+ stat.catchBlocks[i] = block(catchStatementss[i]);
+ stat.finallyBlock = block(finallyStatements);
+ if (finallyStatements != null) {
+ int len = finallyStatements.length;
+ if (len > 0) {
+ stat.finallyBlock.sourceStart = finallyStatements[0].sourceStart;
+ stat.finallyBlock.sourceEnd = finallyStatements[len-1].sourceEnd;
+ }
+ }
+ return stat;
+ }
+
/**
* Create a lifting of an expression to an expectedType if expectedType is in deed
* a role type different from the type of expression (deferred decision).
@@ -1227,9 +1292,11 @@
selector,
null);
}
- public Expression createCastOrUnboxing(Expression expression, TypeBinding expectedType) {
+ public Expression createCastOrUnboxing(Expression expression, TypeBinding expectedType, boolean baseAccess) {
if (expectedType.isBaseType())
return createUnboxing(expression, (BaseTypeBinding)expectedType);
+ else if (baseAccess)
+ return castExpression(expression, baseclassReference(expectedType), CastExpression.RAW);
else
return castExpression(expression, typeReference(expectedType), CastExpression.RAW);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
index 059c0f3..d59c199 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
@@ -277,7 +277,9 @@
&& !(existingAnchor instanceof TThisBinding)
&& !existingAnchor.hasSameBestNameAs(variableBinding))
{
- return originalType; // cannot merge anchors -> original type cannot be improved.
+ variableBinding = TeamAnchor.maybeImproveAnchor(site, existingAnchor, anchorExpr);
+ if (variableBinding == null)
+ return originalType; // cannot merge anchors -> original type cannot be improved.
}
// delegate to the principal function:
TypeBinding[] typeArguments = refBinding.isParameterizedType() ? ((ParameterizedTypeBinding)refBinding).arguments : null;
@@ -387,9 +389,15 @@
else
returnType = roleReturn;
}
- if (CallinImplementor.avoidWrapRoleType(scope, send.receiver))
- // don't use synthetic _OT$role as additional anchor
- return returnType;
+ if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+ if (CallinImplementorDyn.avoidWrapRoleType(scope, send.receiver))
+ // don't use synthetic local$role$n as additional anchor
+ return returnType;
+ } else {
+ if (CallinImplementor.avoidWrapRoleType(scope, send.receiver))
+ // don't use synthetic _OT$role as additional anchor
+ return returnType;
+ }
}
} else {
if (send.arguments != null && send.arguments.length > 0)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 4590c6e..efbbe32 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -13,6 +13,8 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
*******************************************************************************/
package org.eclipse.jdt.core.dom;
@@ -3382,7 +3384,11 @@
}
Type type = convertType(localDeclaration.type);
int typeEnd = type.getStartPosition() + type.getLength() - 1;
- int rightEnd = Math.max(typeEnd, localDeclaration.declarationSourceEnd);
+ // https://bugs.eclipse.org/393719 - [compiler] inconsistent warnings on iteration variables
+ // compiler considers collectionExpression as within the declarationSourceEnd, DOM AST must use the shorter range to avoid overlap
+ int sourceEnd = ((localDeclaration.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsForeachElementVariable) != 0)
+ ? localDeclaration.sourceEnd : localDeclaration.declarationSourceEnd;
+ int rightEnd = Math.max(typeEnd, sourceEnd);
/*
* There is extra work to do to set the proper type positions
* See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
index 9bc685e..d9d8240 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
@@ -1061,6 +1061,16 @@
return removeEntry(STATIC_PREFIX + qualifiedName);
}
+//{ObjectTeams:
+ /**
+ * Remove a base-import, similar to {@link #removeImport(String)} and {@link #removeStaticImport(String)}.
+ * @since 3.9
+ */
+ public boolean removeImportBase(String qualifiedName) {
+ return removeEntry(BASE_PREFIX + qualifiedName);
+ }
+// SH}
+
private static String getRawName(ITypeBinding normalizedBinding) {
return normalizedBinding.getTypeDeclaration().getName();
}
@@ -1123,9 +1133,9 @@
if (BASE_PREFIX == curr.charAt(0))
computer.addBaseImport(curr.substring(1));
else
- computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0), /*isBase*/false);
+ computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0), /*isBase*/false, usedAstRoot, this.restoreExistingImports);
/* orig:
- computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0));
+ computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0), usedAstRoot, this.restoreExistingImports);
:giro */
// SH}
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java
index e9ef87d..6dcb85d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java
@@ -1,13 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM Corporation - initial API and implementation
- * Technical University Berlin - extended API and implementation
+ * IBM Corporation - initial API and implementation
+ * Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for Bug 378024 - Ordering of comments between imports not preserved
*******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite;
@@ -277,11 +278,13 @@
int nextOffsetLine= root.getLineNumber(nextOffset);
int extendedStart = root.getExtendedStartPosition(curr);
+ int extendedLength = root.getExtendedLength(curr);
if (extendedStart < this.replaceRange.getOffset()) {
// don't touch the first comments before the start of import declarations
+ extendedLength -= (currOffset - extendedStart);
extendedStart = currOffset;
}
- int extendedLength = root.getExtendedLength(curr);
+
// if next import is on a different line, modify the end position to the next line begin offset
int nextLineOffset = nextOffset; // offset at the start of next line. Next import may not start here
if (currEndLine < nextOffsetLine) {
@@ -322,9 +325,10 @@
if (currEndLine < nextOffsetLine) {
nextOffset= root.getPosition(nextOffsetLine, 0);
- currPackage= new PackageEntry(); // create a comment package entry for this
- this.packageEntries.add(currPackage);
- currPackage.add(new ImportDeclEntry(packName.length(), null, false, new Region(nextLineOffset, nextOffset - nextLineOffset)));
+ int length = nextOffset - nextLineOffset;
+ if (length > 2) { // valid comment has at least two chars
+ currPackage.add(new ImportDeclEntry(packName.length(), null, false, new Region(nextLineOffset, length)));
+ }
currOffset= nextOffset;
}
@@ -341,7 +345,7 @@
currPackage= new PackageEntry(packName, null, isStatic);
:giro */
if (currPackage == null || currPackage.compareTo(packName, isStatic, isBase) != 0) {
- currPackage= new PackageEntry(packName, null, isStatic, curr.isBase());
+ currPackage= new PackageEntry(packName, null, isStatic, isBase);
// SH}
this.packageEntries.add(currPackage);
}
@@ -588,6 +592,7 @@
}
String groupId= null;
int longestPrefix= -1;
+ PackageEntry matchingCommentEntry = null;
// find the matching group
for (int i= 0; i < this.packageEntries.size(); i++) {
PackageEntry curr= (PackageEntry) this.packageEntries.get(i);
@@ -600,8 +605,11 @@
String currGroup= curr.getGroupID();
if (currGroup != null && newName.startsWith(currGroup)) {
int prefixLen= currGroup.length();
- if (prefixLen == newName.length()) {
+ if (prefixLen == newName.length() && !curr.isComment()) {
return curr; // perfect fit, use entry
+ } else if (curr.isComment()) {
+ matchingCommentEntry = curr; // may be the only fit if no actual import of this group is already present
+ continue;
}
if ((newName.charAt(prefixLen) == '.' || prefixLen == 0) && prefixLen > longestPrefix) {
longestPrefix= prefixLen;
@@ -610,6 +618,9 @@
}
}
}
+ if (matchingCommentEntry != null) {
+ return matchingCommentEntry;
+ }
PackageEntry bestMatch= null;
PackageMatcher matcher= new PackageMatcher();
matcher.initialize(newName, ""); //$NON-NLS-1$
@@ -648,15 +659,83 @@
}
//{ObjectTeams: added param 'isBase':
- public void addImport(String fullTypeName, boolean isStatic, boolean isBase) {
+ public void addImport(String fullTypeName, boolean isStatic, boolean isBase, CompilationUnit root, boolean restoreExistingImports) {
String typeContainerName= getQualifier(fullTypeName, isStatic);
- ImportDeclEntry decl= new ImportDeclEntry(typeContainerName.length(), fullTypeName, isStatic, null);
+ ImportDeclEntry decl;
+ if (restoreExistingImports) {
+ decl = new ImportDeclEntry(typeContainerName.length(), fullTypeName, isStatic, null);
+ } else {
+ decl = addImportDeclEntry(typeContainerName, fullTypeName, isStatic, root);
+ }
if (isBase)
decl.setIsBase(isBase);
sortIn(typeContainerName, decl, isStatic, isBase);
}
// SH}
+ /**
+ * adds the import entry, but if its an existing import entry then preserves the comments surrounding the import
+ */
+ private ImportDeclEntry addImportDeclEntry(String containerName, String fullTypeName, boolean isStatic, CompilationUnit root) {
+ List/*ImportDeclaration*/ decls= root.imports();
+ if (decls.isEmpty() || this.preserveExistingCommentsRanges == null || this.preserveExistingCommentsRanges.length == 0) {
+ return new ImportDeclEntry(containerName.length(), fullTypeName, isStatic, null);
+ }
+ IRegion precedingCommentRange = null;
+ IRegion trailingCommentRange = null;
+ int prevOffset = this.replaceRange.getOffset(); // will store offset of the previous import's extended end
+ int numOfImports = decls.size();
+ for (int i= 0; i < numOfImports; i++) {
+ ImportDeclaration curr= (ImportDeclaration) decls.get(i);
+ int currOffset= curr.getStartPosition();
+ int currLength= curr.getLength();
+ int currExtendedStart = root.getExtendedStartPosition(curr);
+ int currExtendedLen = root.getExtendedLength(curr);
+ String name= getFullName(curr);
+ String packName= getQualifier(curr);
+ if (packName.equals(containerName) && (name.equals(fullTypeName) || name.endsWith("*"))) {//$NON-NLS-1$
+ int preserveCommentsLen = this.preserveExistingCommentsRanges.length;
+ for (int j = 0; j < preserveCommentsLen; j++) {
+ int offset = this.preserveExistingCommentsRanges[j].getOffset();
+ boolean wasRangeUsed = false;
+ int existingCommentLength = this.preserveExistingCommentsRanges[j].getLength();
+ if (offset == currExtendedStart) {
+ // comments belonging to this import's extended start
+ precedingCommentRange = new Region(offset, existingCommentLength);
+ wasRangeUsed = true;
+ } else if (offset < currExtendedStart && offset > prevOffset) {
+ // comment between two imports but not inside either's extended ranges
+ // to preserve the position of these comments add a dummy comment entry
+ PackageEntry commentEntry = new PackageEntry(); // create a comment package entry for this
+ commentEntry.setGroupID(packName); // the comment should belong to the current group
+ this.packageEntries.add(commentEntry);
+ commentEntry.add(new ImportDeclEntry(packName.length(), null, false, new Region(offset, existingCommentLength)));
+ wasRangeUsed = true;
+ } else if ((currExtendedStart + currExtendedLen) != (currOffset + currLength)){
+ if (offset == currOffset + currLength) {
+ // comment is in the extended end of the import
+ trailingCommentRange = new Region(offset, existingCommentLength);
+ wasRangeUsed = true;
+ } else if (offset > (currOffset + currLength)) {
+ break;
+ }
+ }
+ if (wasRangeUsed) {
+ // remove this comment from preserveExistingCommentsRanges array
+ IRegion[] tempRegions = new IRegion[--preserveCommentsLen];
+ System.arraycopy(this.preserveExistingCommentsRanges, 0, tempRegions, 0, j);
+ System.arraycopy(this.preserveExistingCommentsRanges, j+1, tempRegions, j, tempRegions.length - j);
+ this.preserveExistingCommentsRanges = tempRegions;
+ j--;
+ }
+ }
+ return new ImportDeclEntry(containerName.length(), fullTypeName, isStatic, null, precedingCommentRange, trailingCommentRange);
+ }
+ prevOffset = currExtendedStart + currExtendedLen - 1;
+ }
+ return new ImportDeclEntry(containerName.length(), fullTypeName, isStatic, null);
+ }
+
//{ObjectTeams: added isBase:
/* orig:
public boolean removeImport(String qualifiedName, boolean isStatic) {
@@ -843,16 +922,21 @@
continue;
}
- if (spacesBetweenGroups > 0) {
+ if (spacesBetweenGroups > 0 && lastPackage != null) {
// add a space between two different groups by looking at the two adjacent imports
- if (lastPackage != null && !pack.isComment() && !pack.isSameGroup(lastPackage)) {
- ImportDeclEntry last= lastPackage.getImportAt(lastPackage.getNumberOfImports() - 1);
- ImportDeclEntry first= pack.getImportAt(0);
- if (!lastPackage.isComment() && (last.isNew() || first.isNew())) {
- for (int k= spacesBetweenGroups; k > 0; k--) {
- stringsToInsert.add(lineDelim);
- }
+ if (!lastPackage.isComment() && !pack.isComment() && !pack.isSameGroup(lastPackage)) {
+ for (int k= spacesBetweenGroups; k > 0; k--) {
+ stringsToInsert.add(lineDelim);
}
+ } else if (lastPackage.isComment() && pack.isSameGroup(lastPackage)) {
+ // the last pack may be a dummy for a comment which doesn't belong to any extended range
+ stringsToInsert.add(lineDelim);
+//{ObjectTeams: space between regular imports and base import:
+ } else if (!lastPackage.isComment() && !pack.isComment() && pack.isBase() != lastPackage.isBase()) {
+ for (int k= spacesBetweenGroups; k > 0; k--) {
+ stringsToInsert.add(lineDelim);
+ }
+// SH}
}
}
lastPackage= pack;
@@ -861,24 +945,38 @@
int threshold= isStatic ? this.staticImportOnDemandThreshold : this.importOnDemandThreshold;
boolean doStarImport= pack.hasStarImport(threshold, onDemandConflicts);
+ boolean allImportsAddedToStar = false;
if (doStarImport && (pack.find("*") == null)) { //$NON-NLS-1$
String[] imports = getNewImportStrings(buffer, pack, isStatic, lineDelim);
for (int j = 0, max = imports.length; j < max; j++) {
stringsToInsert.add(imports[j]);
}
+ allImportsAddedToStar = true; // may still need to handle onDemandConflicts below
}
for (int k= 0; k < nImports; k++) {
ImportDeclEntry currDecl= pack.getImportAt(k);
IRegion region= currDecl.getSourceRange();
-
+ boolean isConflict = !currDecl.isComment() && onDemandConflicts != null && onDemandConflicts.contains(currDecl.getSimpleName());
+ boolean addRegularToStar = doStarImport && !currDecl.isOnDemand();
+
if (region == null) { // new entry
- if (!doStarImport || currDecl.isOnDemand() || (onDemandConflicts != null && onDemandConflicts.contains(currDecl.getSimpleName()))) {
+ if (!addRegularToStar || isConflict) {
+ IRegion rangeBefore = currDecl.getPrecedingCommentRange();
+ IRegion rangeAfter = currDecl.getTrailingCommentRange();
+ if (rangeBefore != null) {
+ stringsToInsert.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
+ }
+
+ String trailingComment = null;
+ if (rangeAfter != null) {
+ trailingComment = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
+ }
//{ObjectTeams: new 3. param:
- String str= getNewImportString(currDecl.getElementName(), isStatic, currDecl.isBase(), lineDelim);
+ String str= getNewImportString(currDecl.getElementName(), isStatic, currDecl.isBase(), trailingComment, lineDelim);
// SH}
stringsToInsert.add(str);
- } else if (doStarImport && !currDecl.isOnDemand()) {
+ } else if (addRegularToStar && !allImportsAddedToStar) {
String simpleName = currDecl.getTypeQualifiedName();
if (simpleName.indexOf('.') != -1) {
//{ObjectTeams: new 3. param:
@@ -889,7 +987,7 @@
}
}
}
- } else if (!doStarImport || currDecl.isOnDemand() || onDemandConflicts == null || onDemandConflicts.contains(currDecl.getSimpleName())) {
+ } else if (!addRegularToStar || isConflict) {
int offset= region.getOffset();
IRegion rangeBefore = currDecl.getPrecedingCommentRange();
if (rangeBefore != null && currPos > rangeBefore.getOffset()) {
@@ -913,7 +1011,7 @@
}
// SH}
currPos= offset + region.getLength();
- } else if (doStarImport && !currDecl.isOnDemand()) {
+ } else if (addRegularToStar && !allImportsAddedToStar && !currDecl.isComment()) {
String simpleName = currDecl.getTypeQualifiedName();
if (simpleName.indexOf('.') != -1) {
IRegion rangeBefore = currDecl.getPrecedingCommentRange();
@@ -942,7 +1040,7 @@
// insert back all existing imports comments since existing imports were not preserved
if (this.preserveExistingCommentsRanges != null) {
- for (int i = 0, max = this.preserveExistingCommentsRanges.length; i < max; i++) {
+ for (int i = 0, max = this.preserveExistingCommentsRanges.length; (i < max && this.preserveExistingCommentsRanges[i] != null); i++) {
IRegion region = this.preserveExistingCommentsRanges[i];
String text = buffer.getText(region.getOffset(), region.getLength());
// remove preceding whitespaces
@@ -1130,11 +1228,10 @@
List allImports = new ArrayList();
int nImports = packageEntry.getNumberOfImports();
StringBuffer allComments = null;
+ StringBuffer allCommentsLead = null;
for (int i= 0; i < nImports; i++) {
ImportDeclEntry curr= packageEntry.getImportAt(i);
- String simpleName = curr.getTypeQualifiedName();
- if (simpleName.indexOf('.') != -1) {
- // member type imports - we preserve it
+ if (curr.isComment()) {
IRegion rangeBefore = curr.getPrecedingCommentRange();
if (rangeBefore != null) {
allImports.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
@@ -1144,33 +1241,65 @@
if (rangeAfter != null) {
trailingComment = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
}
-//{ObjectTeams: added isBase(false) (2 occur)
- allImports.add(getNewImportString(curr.getElementName(), isStatic, false, trailingComment, lineDelim));
- } else if (!isStarImportAdded) {
- String starImportString= packageEntry.getName() + ".*"; //$NON-NLS-1$
- allImports.add(getNewImportString(starImportString, isStatic, false, lineDelim));
-// SH}
- isStarImportAdded = true;
- } else {
- // collect all comments
- IRegion rangeBefore = curr.getPrecedingCommentRange();
- if (rangeBefore != null) {
- if (allComments == null) {
- allComments = new StringBuffer();
- }
- allComments.append(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength())).append(lineDelim);
+ if (trailingComment != null) {
+ allImports.add(buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength()));
}
- IRegion rangeAfter = curr.getTrailingCommentRange();
- if (rangeAfter != null) {
- if (allComments == null) {
- allComments = new StringBuffer();
+ } else {
+ String simpleName = curr.getTypeQualifiedName();
+ if (simpleName.indexOf('.') != -1) {
+ // member type imports - we preserve it
+ IRegion rangeBefore = curr.getPrecedingCommentRange();
+ if (rangeBefore != null) {
+ allImports.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
}
- allComments.append(buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength())).append(lineDelim);
+ IRegion rangeAfter = curr.getTrailingCommentRange();
+ String trailingComment = null;
+ if (rangeAfter != null) {
+ trailingComment = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
+ }
+//{ObjectTeams: added isBase(false)
+ allImports.add(getNewImportString(curr.getElementName(), isStatic, false, trailingComment, lineDelim));
+// SH}
+ } else if (!isStarImportAdded) {
+ String starImportString= packageEntry.getName() + ".*"; //$NON-NLS-1$
+ // collect all comments
+ IRegion rangeBefore = curr.getPrecedingCommentRange();
+ if (rangeBefore != null) {
+ allImports.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
+ }
+ IRegion rangeAfter = curr.getTrailingCommentRange();
+ String trailComments = null;
+ if (rangeAfter != null) {
+ trailComments = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
+ }
+//{ObjectTeams: added isBase(false)
+ allImports.add(getNewImportString(starImportString, isStatic, false, trailComments, lineDelim));
+// SH}
+ isStarImportAdded = true;
+ } else {
+ // collect all comments
+ IRegion rangeBefore = curr.getPrecedingCommentRange();
+ if (rangeBefore != null) {
+ if (allCommentsLead == null) {
+ allCommentsLead = new StringBuffer();
+ }
+ allCommentsLead.append(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
+ }
+ IRegion rangeAfter = curr.getTrailingCommentRange();
+ if (rangeAfter != null) {
+ if (allComments == null) {
+ allComments = new StringBuffer();
+ }
+ allComments.append(buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength()));
+ }
}
}
}
+ if (allCommentsLead != null) {
+ allImports.add(0, String.valueOf(allCommentsLead));
+ }
if (allComments != null) {
- allImports.add(0, String.valueOf(allComments));
+ allImports.add(String.valueOf(allComments.append(lineDelim)));
}
return (String[]) allImports.toArray(new String[allImports.size()]);
}
@@ -1233,8 +1362,8 @@
private boolean isBase = false;
// SH}
private int containerNameLength;
- private IRegion precedingCommentRange;
- private IRegion trailingCommentRange;
+ IRegion precedingCommentRange;
+ IRegion trailingCommentRange;
public ImportDeclEntry(
int containerNameLength,
@@ -1534,14 +1663,19 @@
for (int i= 0; i < nImports; i++) {
ImportDeclEntry curr= getImportAt(i);
buf.append(" "); //$NON-NLS-1$
- if (curr.isStatic()) {
- buf.append("static "); //$NON-NLS-1$
- }
+ if (curr.isComment()) {
+ buf.append("comment"); //$NON-NLS-1$
+ } else {
//{ObjectTeams:
- else if (curr.isBase()) {
- buf.append("base "); //$NON-NLS-1$
- }
+ if (curr.isBase()) {
+ buf.append("base "); //$NON-NLS-1$
+ }
// SH}
+ if (curr.isStatic()) {
+ buf.append("static "); //$NON-NLS-1$
+ }
+ buf.append(curr.getTypeQualifiedName());
+ }
buf.append(curr.getTypeQualifiedName());
if (curr.isNew()) {
buf.append(" (new)"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
index 3797269..62b9372 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -154,35 +154,35 @@
boolean exists();
/**
- * Returns the first ancestor of this Java element that has the given type.
- * Returns <code>null</code> if no such an ancestor can be found.
+ * Returns this Java element or the first ancestor of this element that has the given type.
+ * Returns <code>null</code> if no such element can be found.
* This is a handle-only method.
*
* @param ancestorType the given type
- * @return the first ancestor of this Java element that has the given type, null if no such an ancestor can be found
+ * @return this Java element or the first ancestor of this element that has the given type, or <code>null</code> if no such element can be found
* @since 2.0
*/
IJavaElement getAncestor(int ancestorType);
/**
- * <p>Returns the Javadoc as an html source if this element has an attached javadoc,
- * null otherwise.</p>
- * <p>This should be used only for binary elements. Source elements will always return null.</p>
- * <p>The encoding used to read the javadoc is the one defined by the content type of the
- * file. If none is defined, then the project's encoding of this java element is used. If the project's
+ * <p>Returns the Javadoc as HTML source if this element has attached Javadoc,
+ * <code>null</code> otherwise.</p>
+ * <p>This should be used only for binary elements. Source elements will always return <code>null</code>.</p>
+ * <p>The encoding used to read the Javadoc is the one defined by the content type of the
+ * file. If none is defined, then the project's encoding of this Java element is used. If the project's
* encoding cannot be retrieved, then the platform encoding is used.</p>
- * <p>In case of the javadoc doesn't exist for this element, null is returned.</p>
+ * <p>In case the Javadoc doesn't exist for this element, <code>null</code> is returned.</p>
*
- * <p>The html is extracted from the attached javadoc and provided as is. No
+ * <p>The HTML is extracted from the attached Javadoc and provided as is. No
* transformation or validation is done.</p>
*
- * @param monitor the given progress monitor
+ * @param monitor the given progress monitor, can be <code>null</code>
* @exception JavaModelException if:<ul>
* <li>this element does not exist</li>
* <li>retrieving the attached javadoc fails (timed-out, invalid URL, ...)</li>
* <li>the format of the javadoc doesn't match expected standards (different anchors,...)</li>
* </ul>
- * @return the extracted javadoc from the attached javadoc, null if none
+ * @return the extracted javadoc from the attached javadoc, <code>null</code> if none
* @see IClasspathAttribute#JAVADOC_LOCATION_ATTRIBUTE_NAME
* @since 3.2
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index b15a906..63c7408 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -99,6 +99,8 @@
* COMPILER_PB_MISSING_ENUM_CASE_DESPITE_DEFAULT
* COMPILER_PB_SWITCH_MISSING_DEFAULT_CASE
* COMPILER_INHERIT_NULL_ANNOTATIONS
+ * COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED
+ * COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS
*******************************************************************************/
package org.eclipse.jdt.core;
@@ -1507,7 +1509,7 @@
* <p>If the annotation specified by this option is applied to a type in a method
* signature or variable declaration, this will be interpreted as a specification
* that <code>null</code> is a legal value in that position. Currently supported
- * positions are: method parameters, method return type and local variables.</p>
+ * positions are: method parameters, method return type, fields and local variables.</p>
* <p>If a value whose type
* is annotated with this annotation is dereferenced without checking for null,
* the compiler will trigger a diagnostic as further controlled by
@@ -1533,7 +1535,7 @@
* <p>If the annotation specified by this option is applied to a type in a method
* signature or variable declaration, this will be interpreted as a specification
* that <code>null</code> is <b>not</b> a legal value in that position. Currently
- * supported positions are: method parameters, method return type and local variables.</p>
+ * supported positions are: method parameters, method return type, fields and local variables.</p>
* <p>For values declared with this annotation, the compiler will never trigger a null
* reference diagnostic (as controlled by {@link #COMPILER_PB_POTENTIAL_NULL_REFERENCE}
* and {@link #COMPILER_PB_NULL_REFERENCE}), because the assumption is made that null
@@ -1557,8 +1559,8 @@
* <p>This option defines a fully qualified Java type name that the compiler may use
* to perform special null analysis.</p>
* <p>If the annotation is applied without an argument, all unannotated types in method signatures
- * within the annotated element will be treated as if they were specified with the non-null annotation
- * (see {@link #COMPILER_NONNULL_ANNOTATION_NAME}).</p>
+ * and field declarations within the annotated element will be treated as if they were specified
+ * with the non-null annotation (see {@link #COMPILER_NONNULL_ANNOTATION_NAME}).</p>
* <p>If the annotation is applied with the constant <code>false</code> as its argument
* all corresponding defaults at outer scopes will be canceled for the annotated element.</p>
* <p>This option only has an effect if the option {@link #COMPILER_ANNOTATION_NULL_ANALYSIS} is enabled.</p>
@@ -1609,6 +1611,9 @@
* for at least one of its parameters, tries to tighten that null contract by
* specifying a nonnull annotation for its corresponding parameter
* (prohibition of covariant parameters).</li>
+ * <li>A non-static field with a nonnull annotation is not definitely assigned at
+ * the end of each constructor.</li>
+ * <li>A static field with a nonnull annotation is not definitely assigned in static initializers.</li>
* </ol>
* In the above an expression is considered as <em>nullable</em> if
* either it is statically known to evaluate to the value <code>null</code>, or if it is
@@ -1705,6 +1710,20 @@
*/
public static final String COMPILER_PB_REDUNDANT_NULL_ANNOTATION = PLUGIN_ID + ".compiler.problem.redundantNullAnnotation"; //$NON-NLS-1$
/**
+ * Compiler option ID: Perform syntactic null analysis for fields.
+ * <p>When enabled, the compiler will detect certain syntactic constellations where a null
+ * related warning against a field reference would normally be raised but can be suppressed
+ * at low risk given that the same field reference was known to be non-null immediately before.</p>
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "disabled", "enabled" }</code></dd>
+ * <dt>Default:</dt><dd><code>"disabled"</code></dd>
+ * </dl>
+ * @since 3.9
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS = JavaCore.PLUGIN_ID+".compiler.problem.syntacticNullAnalysisForFields"; //$NON-NLS-1$
+ /**
* Compiler option ID: Inheritance of null annotations.
* <p>When enabled, the compiler will check for each method without any explicit null annotations:
* If it overrides a method which has null annotations, it will treat the
@@ -1725,6 +1744,32 @@
*/
public static final String COMPILER_INHERIT_NULL_ANNOTATIONS = JavaCore.PLUGIN_ID+".compiler.annotation.inheritNullAnnotations"; //$NON-NLS-1$
/**
+ * Compiler option ID: Reporting Dropped Nonnull Parameter Annotations.
+ * <p>When enabled, the compiler will issue an error or a warning against a parameter of
+ * a method that overrides an inherited method
+ * if all of the following hold:</p>
+ * <ul>
+ * <li>The overridden method declares the corresponding parameter as non-null (see {@link #COMPILER_NONNULL_ANNOTATION_NAME}).</li>
+ * <li>The parameter in the overriding method has no null annotation.</li>
+ * <li>The overriding method is not affected by a nullness default (see {@link #COMPILER_NONNULL_BY_DEFAULT_ANNOTATION_NAME}).</li>
+ * <li>Inheritance of null annotations is disabled (see {@link #COMPILER_INHERIT_NULL_ANNOTATIONS}).</li>
+ * </ul>
+ * <p>This particular situation bears the same inherent risk as any unannotated method parameter,
+ * because the compiler's null ananysis cannot decide wither <code>null</code> is or is not a legal value for this parameter.
+ * However, the annotation in the overridden method <em>suggests</em> that the parameter should also be annotated as non-null.
+ * If that is not intended or possible, it is recommended to annotate the parameter as nullable,
+ * in order to make this (legal) change of contract explicit.</p>
+ * <dl>
+ * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped"</code></dd>
+ * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
+ * <dt>Default:</dt><dd><code>"warning"</code></dd>
+ * </dl>
+ * @since 3.9
+ * @category CompilerOptionID
+ */
+ public static final String COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED = JavaCore.PLUGIN_ID+".compiler.problem.nonnullParameterAnnotationDropped"; //$NON-NLS-1$
+
+ /**
* Compiler option ID: Setting Source Compatibility Mode.
* <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
* reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
@@ -5600,5 +5645,4 @@
super.start(context);
JavaModelManager.getJavaModelManager().startup();
}
-
}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index 50cfb6b..5f42ba9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -370,11 +370,6 @@
if (status.isOK()) {
return super.getBuffer();
} else {
- // .class file not on classpath, create a new buffer to be nice (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=41444)
- Object info = ((ClassFile) getClassFile()).getBinaryTypeInfo((IFile) resource());
- IBuffer buffer = openBuffer(null, info);
- if (buffer != null && !(buffer instanceof NullBuffer))
- return buffer;
switch (status.getCode()) {
case IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH: // don't throw a JavaModelException to be able to open .class file outside the classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138507 )
case IJavaModelStatusConstants.INVALID_ELEMENT_TYPES: // don't throw a JavaModelException to be able to open .class file in proj==src case without source (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=221904 )
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 02ccb62..fc7e58e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -1487,6 +1487,7 @@
propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) ||
+ propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM) ||
propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE)) {
JavaModelManager manager = JavaModelManager.getJavaModelManager();
IJavaModel model = manager.getJavaModel();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index f96e87a..205bfef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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
@@ -1560,7 +1560,8 @@
propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE) ||
- propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL))
+ propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) ||
+ propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM))
{
manager.deltaState.addClasspathValidation(JavaProject.this);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
index 19890be..5408aef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 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,7 +27,6 @@
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
@@ -484,7 +483,7 @@
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
String contents = getURLContents(String.valueOf(pathBuffer));
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
- if (contents == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+ if (contents == null) return null;
contents = (new JavadocContents(contents)).getPackageDoc();
if (contents == null) contents = ""; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
index 124adaa..aacd3e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2013 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
@@ -704,6 +704,25 @@
return;
}
break;
+ case Scanner.WILDCARD:
+ // support the '-' in "Lpack/package-info;", see bug 398920
+ if (!CharOperation.endsWith(this.scanner.getTokenSource(), new char[] {'/', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '-'})) {
+ malformedKey();
+ return;
+ }
+
+ int start = this.scanner.start;
+ if (this.scanner.nextToken() == Scanner.TYPE) {
+ if (!CharOperation.equals(this.scanner.getTokenSource(), new char[] {'i', 'n', 'f', 'o'})) {
+ malformedKey();
+ return;
+ }
+ this.scanner.start = start;
+ this.keyStart = start-1;
+ consumeFullyQualifiedName(this.scanner.getTokenSource());
+ break;
+ }
+ break;
default:
malformedKey();
return;
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index a889303..3665462 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -21,7 +21,7 @@
</parent>
<groupId>eclipse.jdt.core</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
- <version>3.8.1-SNAPSHOT</version>
+ <version>3.9.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
index d410f72..b5c542e 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java
@@ -15,6 +15,7 @@
import java.io.InputStream;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
import org.eclipse.core.runtime.FileLocator;
@@ -37,7 +38,15 @@
return null;
}
if (localUrl.getProtocol().equals("file")) { //$NON-NLS-1$
- return new FileIndexLocation(url, new File(localUrl.getPath()));
+ File localFile = null;
+ try {
+ URI localFileURI = new URI(localUrl.toExternalForm());
+ localFile = new File(localFileURI);
+ }
+ catch(Exception ex) {
+ localFile = new File(localUrl.getPath());
+ }
+ return new FileIndexLocation(url, localFile);
}
return new JarIndexLocation(url, localUrl);
}
diff --git a/plugins/org.eclipse.objectteams.eclipse.monitor/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.eclipse.monitor/META-INF/MANIFEST.MF
index 67a14a0..f5c8512 100644
--- a/plugins/org.eclipse.objectteams.eclipse.monitor/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.eclipse.monitor/META-INF/MANIFEST.MF
@@ -8,7 +8,7 @@
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui;bundle-version="[3.7.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)"
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.eclipse.objectteams.eclipse.monitor.internal;x-internal:=true
diff --git a/plugins/org.eclipse.objectteams.otdt.apt/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.apt/META-INF/MANIFEST.MF
index fc0f243..26ac8eb 100644
--- a/plugins/org.eclipse.objectteams.otdt.apt/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.apt/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otdt.apt;singleton:=true
-Bundle-Version: 2.0.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Require-Bundle: org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+Require-Bundle: org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.osgi;bundle-version="[3.7.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)"
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF
index a85ab56..b27a348 100644
--- a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF
@@ -6,7 +6,7 @@
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.jdt.core;bundle-version="[3.9.0.v_OTDT_r220,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
org.eclipse.core.resources;bundle-version="[3.7.100,4.0.0)",
org.eclipse.pde.core;bundle-version="[3.7.0,4.0.0)",
diff --git a/plugins/org.eclipse.objectteams.otdt.debug.adaptor/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.debug.adaptor/META-INF/MANIFEST.MF
index 4451b4a..8f18bcc 100644
--- a/plugins/org.eclipse.objectteams.otdt.debug.adaptor/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.debug.adaptor/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otdt.debug.adaptor;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.objectteams.otdt;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt.debug;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt.debug.ui;bundle-version="[2.0.0,3.0.0)",
diff --git a/plugins/org.eclipse.objectteams.otdt.debug.adaptor/src/org/eclipse/objectteams/otdt/internal/debug/adaptor/launching/JDTLaunchingAdaptor.java b/plugins/org.eclipse.objectteams.otdt.debug.adaptor/src/org/eclipse/objectteams/otdt/internal/debug/adaptor/launching/JDTLaunchingAdaptor.java
index 4d06867..3fb5413 100644
--- a/plugins/org.eclipse.objectteams.otdt.debug.adaptor/src/org/eclipse/objectteams/otdt/internal/debug/adaptor/launching/JDTLaunchingAdaptor.java
+++ b/plugins/org.eclipse.objectteams.otdt.debug.adaptor/src/org/eclipse/objectteams/otdt/internal/debug/adaptor/launching/JDTLaunchingAdaptor.java
@@ -88,7 +88,7 @@
for (int i = 0; i < origEntries.length; i++)
{
IPath entryPath = origEntries[i].getPath();
- if (OTREContainer.BCEL_PATH.equals(entryPath))
+ if (OTREContainer.BYTECODE_LIBRARY_PATH.equals(entryPath))
hasBCEL = true;
else if (otreMinJarPath.equals(entryPath))
hasOTRE_min = true;
@@ -98,7 +98,7 @@
IRuntimeClasspathEntry entry;
if (!hasBCEL) {
- entry = JavaRuntime.newArchiveRuntimeClasspathEntry(OTREContainer.BCEL_PATH);
+ entry = JavaRuntime.newArchiveRuntimeClasspathEntry(OTREContainer.BYTECODE_LIBRARY_PATH);
result.add(entry);
}
diff --git a/plugins/org.eclipse.objectteams.otdt.debug/scripts/genIOOTBreakPoints.sh b/plugins/org.eclipse.objectteams.otdt.debug/scripts/genIOOTBreakPoints.sh
old mode 100644
new mode 100755
diff --git a/plugins/org.eclipse.objectteams.otdt.debug/src/org/eclipse/objectteams/otdt/debug/internal/breakpoints/IOOTBreakPoints.java b/plugins/org.eclipse.objectteams.otdt.debug/src/org/eclipse/objectteams/otdt/debug/internal/breakpoints/IOOTBreakPoints.java
index 0fe1beb..1bc582f 100644
--- a/plugins/org.eclipse.objectteams.otdt.debug/src/org/eclipse/objectteams/otdt/debug/internal/breakpoints/IOOTBreakPoints.java
+++ b/plugins/org.eclipse.objectteams.otdt.debug/src/org/eclipse/objectteams/otdt/debug/internal/breakpoints/IOOTBreakPoints.java
@@ -28,8 +28,8 @@
*/
public interface IOOTBreakPoints
{
- int LINE_TeamConstructor = 62;
- int LINE_ConfinedGetTeam = 93;
+ int LINE_TeamConstructor = 61;
+ int LINE_ConfinedGetTeam = 92;
int LINE_ActivateMethod = 164;
int LINE_DeactivateMethod = 195;
int LINE_ImplicitActivateMethod = 242;
diff --git a/plugins/org.eclipse.objectteams.otdt.jdt.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.jdt.ui/META-INF/MANIFEST.MF
index ae4360d..625bc95 100644
--- a/plugins/org.eclipse.objectteams.otdt.jdt.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.jdt.ui/META-INF/MANIFEST.MF
@@ -19,7 +19,7 @@
org.eclipse.ui.views;bundle-version="[3.6.0,4.0.0)",
org.eclipse.core.filesystem;bundle-version="[1.3.100,2.0.0)",
org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.objectteams.otdt.ui;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt;bundle-version="[2.0.0,3.0.0)"
Bundle-Vendor: %providerName
diff --git a/plugins/org.eclipse.objectteams.otdt.pde.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.pde.ui/META-INF/MANIFEST.MF
index 05a7b3b..0b438d2 100644
--- a/plugins/org.eclipse.objectteams.otdt.pde.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.pde.ui/META-INF/MANIFEST.MF
@@ -18,7 +18,7 @@
org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)",
org.eclipse.objectteams.otdt;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt.debug;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.objectteams.otdt.ui;bundle-version="[2.0.0,3.0.0)"
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
index 7aa2e02..002476c 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
@@ -13,7 +13,7 @@
org.eclipse.ui;bundle-version="[3.7.0,4.0.0)",
org.eclipse.ui.editors;bundle-version="[3.7.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.jdt.core.manipulation;bundle-version="[1.2.0,2.0.0)",
org.eclipse.ltk.ui.refactoring;bundle-version="[3.4.1,4.0.0)",
org.eclipse.objectteams.otdt;bundle-version="[2.0.0,3.0.0)",
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/RenameAdaptor.java b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/RenameAdaptor.java
index 0b15e3a..0a19d0b 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/RenameAdaptor.java
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/RenameAdaptor.java
@@ -1,7 +1,7 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2004, 2005, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2013 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
@@ -10,7 +10,6 @@
* 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
- * $Id: RenameAdaptor.java 23473 2010-02-05 19:46:08Z stephan $
*
* Please visit http://www.objectteams.org for updates and contact.
*
@@ -20,13 +19,17 @@
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.refactoring.adaptor;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
@@ -41,6 +44,10 @@
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclaration;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
+import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.jdt.internal.ui.JavaPlugin;
@@ -53,7 +60,9 @@
import org.eclipse.objectteams.otdt.internal.refactoring.corext.OTRefactoringCoreMessages;
import org.eclipse.objectteams.otdt.internal.refactoring.corext.rename.BaseCallFinder;
import org.eclipse.objectteams.otdt.internal.refactoring.util.RefactoringUtil;
+import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
import base org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
import base org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil;
@@ -61,6 +70,9 @@
import base org.eclipse.jdt.internal.corext.refactoring.rename.RenameVirtualMethodProcessor;
import base org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer;
import base org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil.ProblemNodeFinder;
+import base org.eclipse.jdt.internal.corext.refactoring.rename.RenamePackageProcessor.ImportsManager;
+import base org.eclipse.jdt.internal.corext.refactoring.rename.RenamePackageProcessor.PackageRenamer;
+import base org.eclipse.jdt.internal.corext.refactoring.rename.RenamePackageProcessor.ImportsManager.ImportChange;
/**
* @author stephan
@@ -308,9 +320,116 @@
return status;
}
return status;
- }
+ }
}
+ /** Add support for base imports: check if an import being updated is a base import and record those separately. */
+ protected class PackageRenamer playedBy PackageRenamer {
+
+ @SuppressWarnings("decapsulation")
+ ImportsManager getFImportsManager() -> get ImportsManager fImportsManager;
+
+ @SuppressWarnings("decapsulation")
+ updateImport <- replace updateImport;
+
+ @SuppressWarnings("basecall")
+ callin void updateImport(ICompilationUnit cu, IImportDeclaration importDeclaration, String updatedImport) throws JavaModelException {
+ if ((importDeclaration.getFlags() & ExtraCompilerModifiers.AccBase) != 0) {
+ final ImportsManager importsManager = getFImportsManager();
+ ImportChange<@importsManager> importChange= importsManager.getImportChange(cu);
+ importChange.removeBaseImport(importDeclaration.getElementName());
+ importChange.addBaseImport(updatedImport);
+
+ } else {
+ base.updateImport(cu, importDeclaration, updatedImport);
+ }
+ }
+ }
+
+ /** Add support for base imports: when performing the changes invoke choose the appropriate add- method in ImportRewrite. */
+ protected team class ImportsManager playedBy ImportsManager {
+
+ /** Extend existing record class by two more lists. */
+ @SuppressWarnings("decapsulation")
+ public class ImportChange playedBy ImportChange {
+ protected List<String> getStaticToRemove() -> get ArrayList<String> fStaticToRemove;
+ protected List<String> getToRemove() -> get ArrayList<String> fToRemove;
+ protected List<String[]> getStaticToAdd() -> get ArrayList<String[]> fStaticToAdd;
+ protected List<String> getToAdd() -> get ArrayList<String> fToAdd;
+
+ protected ArrayList<String> fBaseToRemove= new ArrayList<String>();
+ protected ArrayList<String> fBaseToAdd= new ArrayList<String>();
+
+ public void removeBaseImport(String elementName) {
+ fBaseToRemove.add(elementName);
+ }
+ public void addBaseImport(String updatedImport) {
+ fBaseToAdd.add(updatedImport);
+ }
+ }
+
+ @SuppressWarnings("decapsulation")
+ Iterator<ICompilationUnit> getCompilationUnits() -> get HashMap<ICompilationUnit, ImportChange> fImportChanges
+ with { result <- fImportChanges.keySet().iterator() }
+
+ protected ImportChange getImportChange(ICompilationUnit cu) -> ImportChange getImportChange(ICompilationUnit cu);
+
+ rewriteImports <- replace rewriteImports;
+
+ /* Copy from its base version. */
+ @SuppressWarnings("basecall")
+ callin void rewriteImports(TextChangeManager changeManager, IProgressMonitor pm) throws CoreException {
+//{ObjectTeams: separate iteration (over ICU) from fetching ImportChanges (needs lifting):
+ /* orig:
+ for (Iterator<Entry<ICompilationUnit, ImportChange>> iter= fImportChanges.entrySet().iterator(); iter.hasNext();) {
+ Entry<ICompilationUnit, ImportChange> entry= iter.next();
+ ICompilationUnit cu= entry.getKey();
+ ImportChange importChange= entry.getValue();
+ :giro */
+ for (Iterator<ICompilationUnit> iter= getCompilationUnits(); iter.hasNext();) {
+ ICompilationUnit cu= iter.next();
+ ImportChange importChange= getImportChange(cu);
+// SH}
+ ImportRewrite importRewrite= StubUtility.createImportRewrite(cu, true);
+ importRewrite.setFilterImplicitImports(false);
+ for (Iterator<String> iterator= importChange.getStaticToRemove().iterator(); iterator.hasNext();) {
+ importRewrite.removeStaticImport(iterator.next());
+ }
+ for (Iterator<String> iterator= importChange.getToRemove().iterator(); iterator.hasNext();) {
+ importRewrite.removeImport(iterator.next());
+ }
+//{ObectTeams: one more kind of imports to remove
+ for (Iterator<String> iterator= importChange.fBaseToRemove.iterator(); iterator.hasNext();) {
+ importRewrite.removeImportBase(iterator.next());
+ }
+// SH}
+ for (Iterator<String[]> iterator= importChange.getStaticToAdd().iterator(); iterator.hasNext();) {
+ String[] toAdd= iterator.next();
+ importRewrite.addStaticImport(toAdd[0], toAdd[1], true);
+ }
+ for (Iterator<String> iterator= importChange.getToAdd().iterator(); iterator.hasNext();) {
+ importRewrite.addImport(iterator.next());
+ }
+//{ObectTeams: one more kind of imports to add
+ for (Iterator<String> iterator= importChange.fBaseToAdd.iterator(); iterator.hasNext();) {
+ importRewrite.addImportBase(iterator.next());
+ }
+// SH}
+ if (importRewrite.hasRecordedChanges()) {
+ TextEdit importEdit= importRewrite.rewriteImports(pm);
+ String name= RefactoringCoreMessages.RenamePackageRefactoring_update_imports;
+ try {
+ TextChangeCompatibility.addTextEdit(changeManager.get(cu), name, importEdit);
+ } catch (MalformedTreeException e) {
+ JavaPlugin.logErrorMessage("MalformedTreeException while processing cu " + cu); //$NON-NLS-1$
+ throw e;
+ }
+ }
+ }
+ }
+ }
+
+
/**
* Find more occurrences, currently:
* - references to an argument with declared lifting via the fakedRoleVariable.
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
index 08af6bd..01c4170 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otdt.samples;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Activator: org.eclipse.objectteams.otdt.internal.samples.OTSamplesPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -21,7 +21,7 @@
org.eclipse.objectteams.otdt;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt.ui;bundle-version="[2.0.0,3.0.0)",
org.eclipse.objectteams.otdt.ui.help;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)"
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)"
Export-Package: org.eclipse.objectteams.otdt.internal.samples;x-internal:="true"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt.ui.help/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.ui.help/META-INF/MANIFEST.MF
index b4c1a35..375ea03 100644
--- a/plugins/org.eclipse.objectteams.otdt.ui.help/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.ui.help/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otdt.ui.help;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Activator: org.eclipse.objectteams.otdt.ui.help.OTHelpPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -22,7 +22,7 @@
org.eclipse.jdt.ui;bundle-version="[3.7.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.7.0.v_OTDT_r200,4.0.0)",
org.eclipse.objectteams.otdt.ui;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.objectteams.otdt.doc;bundle-version="2.1.0"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
index a8deefe..d401ddf 100644
--- a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
@@ -16,7 +16,7 @@
org.eclipse.jdt.launching;bundle-version="[3.6.100,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.7.100,4.0.0)",
org.eclipse.osgi;bundle-version="[3.8.0,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.1.0,3.0.0)",
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)",
org.eclipse.ui.ide;bundle-version="3.8.0"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt/about.ini b/plugins/org.eclipse.objectteams.otdt/about.ini
index 1b7a00b..5395c79 100644
--- a/plugins/org.eclipse.objectteams.otdt/about.ini
+++ b/plugins/org.eclipse.objectteams.otdt/about.ini
@@ -1,10 +1,10 @@
aboutText=Object Teams Development Tooling\n\
\n\
-Version: 2.2.0 M4\n\
+Version: 2.2.0 M5\n\
\n\
Part of the Eclipse Kepler Simultaneous Release\n\
\n\
-(c) Copyright TU Berlin, Fraunhofer FIRST and others, 2005, 2012\n\
+(c) Copyright TU Berlin, Fraunhofer FIRST and others, 2005, 2013\n\
Visit http://www.eclipse.org/objectteams
featureImage=OTDT_32x32.png
diff --git a/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTDTPlugin.java b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTDTPlugin.java
index 45c87cf..0ba2b62 100644
--- a/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTDTPlugin.java
+++ b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTDTPlugin.java
@@ -28,6 +28,8 @@
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.objectteams.otdt.core.compiler.CompilerVersion;
+import org.eclipse.objectteams.otequinox.TransformerPlugin;
import org.osgi.framework.BundleContext;
@@ -239,7 +241,16 @@
public void start(BundleContext context) throws Exception {
super.start(context);
try {
- OTREContainer.findBCEL(context);
+ String weavingProperty = System.getProperty("ot.weaving"); //$NON-NLS-1$
+ boolean useDynamicWeaving;
+ if (weavingProperty != null) {
+ useDynamicWeaving = "dynamic".equals(weavingProperty);
+ } else
+ useDynamicWeaving = TransformerPlugin.useDynamicWeaving();
+ CompilerVersion.setDynamicWeaving(useDynamicWeaving);
+ OTREContainer.findBytecodeLib(context, useDynamicWeaving);
+ if (useDynamicWeaving)
+ OTREContainer.OT_RUNTIME_PLUGIN = "org.eclipse.objectteams.otredyn"; //$NON-NLS-1$
} catch (RuntimeException re) {
this.getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, "Cannot initialize BCEL location", re)); //$NON-NLS-1$
}
diff --git a/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTREContainer.java b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTREContainer.java
index fee5479..102562e 100644
--- a/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTREContainer.java
+++ b/plugins/org.eclipse.objectteams.otdt/src/org/eclipse/objectteams/otdt/core/ext/OTREContainer.java
@@ -56,11 +56,11 @@
private static IPath OTRE_AGENT_JAR_PATH;
private static IPath OTEQUINOX_AGENT_JAR_PATH;
- public static IPath BCEL_PATH; // will be initialized in {@link findBCEL(BundleContext)}
+ public static IPath BYTECODE_LIBRARY_PATH; // will be initialized in {@link findBytecodeLib(BundleContext,boolean)}
// details of this container: name and hosting plugin:
private static final IPath OTRE_CONTAINER_PATH = new Path(OTRE_CONTAINER_NAME);
- private static final String OT_RUNTIME_PLUGIN = "org.eclipse.objectteams.runtime"; //$NON-NLS-1$
+ static String OT_RUNTIME_PLUGIN = "org.eclipse.objectteams.runtime"; //$NON-NLS-1$
// file names for the above OTRE_X_JAR_PATH constants:
private static final String OTRE_MIN_JAR_FILENAME = "otre_min.jar"; //$NON-NLS-1$
@@ -71,6 +71,9 @@
private static final String BCEL_BUNDLE_NAME = "org.apache.bcel"; //$NON-NLS-1$
private static final String BCEL_VERSION_RANGE = "[5.2.0,5.3.0)"; //$NON-NLS-1$
+ private static final String ASM_BUNDLE_NAME = "org.objectweb.asm"; //$NON-NLS-1$
+ private static final String ASM_VERSION_RANGE = "[3.3.1,4.0.0)"; //$NON-NLS-1$
+
private IClasspathEntry[] _cpEntries;
/**
@@ -206,16 +209,19 @@
null) );
}
- /** Fetch the location of the bcel bundle into BCEL_PATH. */
- static void findBCEL(BundleContext context) throws IOException {
+ /** Fetch the location of the bcel or asm bundle into BCEL_PATH. */
+ static void findBytecodeLib(BundleContext context, boolean useDynamicWeaving) throws IOException {
ServiceReference<PackageAdmin> ref= (ServiceReference<PackageAdmin>) context.getServiceReference(PackageAdmin.class);
if (ref == null)
throw new IllegalStateException("Cannot connect to PackageAdmin"); //$NON-NLS-1$
PackageAdmin packageAdmin = context.getService(ref);
- for (Bundle bundle : packageAdmin.getBundles(BCEL_BUNDLE_NAME, BCEL_VERSION_RANGE)) {
- BCEL_PATH = new Path(FileLocator.toFileURL(bundle.getEntry("/")).getFile()); //$NON-NLS-1$
+ String bundleName = useDynamicWeaving ? ASM_BUNDLE_NAME : BCEL_BUNDLE_NAME;
+ String bundleVersionRange = useDynamicWeaving ? ASM_VERSION_RANGE : BCEL_VERSION_RANGE;
+ for (Bundle bundle : packageAdmin.getBundles(bundleName, bundleVersionRange)) {
+ BYTECODE_LIBRARY_PATH = new Path(FileLocator.toFileURL(bundle.getEntry("/")).getFile()); //$NON-NLS-1$
return;
}
- throw new RuntimeException("bundle org.apache.bcel not found"); //$NON-NLS-1$
+ throw new RuntimeException("bytecode libarary not found, useDynamicWeaving="+useDynamicWeaving); //$NON-NLS-1$
}
+
}
diff --git a/plugins/org.eclipse.objectteams.otequinox.branding/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otequinox.branding/META-INF/MANIFEST.MF
index 747b850..de1184c 100644
--- a/plugins/org.eclipse.objectteams.otequinox.branding/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otequinox.branding/META-INF/MANIFEST.MF
@@ -2,13 +2,13 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.objectteams.otequinox.branding;singleton:=true
-Bundle-Version: 2.0.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
org.eclipse.ui.workbench;bundle-version="[3.7.0,4.0.0)",
org.eclipse.ui;bundle-version="[3.7.0,4.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.0.0,3.0.0)"
+ org.eclipse.objectteams.otequinox;bundle-version="[2.2.0,3.0.0)"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.objectteams.otequinox.branding.Activator
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/AspectPermission.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/AspectPermission.java
index b50bd80..64813d4 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/AspectPermission.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/AspectPermission.java
@@ -7,7 +7,6 @@
* 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
- * $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/HookConfigurator.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/HookConfigurator.java
index 99ea653..f7aefc4 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/HookConfigurator.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/HookConfigurator.java
@@ -10,7 +10,6 @@
* 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
- * $Id: HookConfigurator.java 23461 2010-02-04 22:10:39Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -37,7 +36,6 @@
* to contain the OTDT version number, too (for logging).
*
* @author stephan
- * @version $Id: HookConfigurator.java 23461 2010-02-04 22:10:39Z stephan $
*/
public class HookConfigurator implements org.eclipse.osgi.baseadaptor.HookConfigurator {
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IAspectRegistry.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IAspectRegistry.java
index a580f42..5d03a99 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IAspectRegistry.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IAspectRegistry.java
@@ -7,7 +7,6 @@
* 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
- * $Id: MasterTeamLoader.java 15426 2007-02-25 12:52:19Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IByteCodeAnalyzer.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IByteCodeAnalyzer.java
index 949ed95..cb9419f 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IByteCodeAnalyzer.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/hook/IByteCodeAnalyzer.java
@@ -7,7 +7,6 @@
* 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
- * $Id: IByteCodeAnalyzer.java 23461 2010-02-04 22:10:39Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/ByteCodeAnalyzer.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/ByteCodeAnalyzer.java
index 1db9f60..f5d8e2e 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/ByteCodeAnalyzer.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/ByteCodeAnalyzer.java
@@ -10,7 +10,6 @@
* 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
- * $Id: TransformerPlugin.java 15357 2007-02-18 17:01:36Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/Logger.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/Logger.java
index 42dba38..7ae983f 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/Logger.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/Logger.java
@@ -10,7 +10,6 @@
* 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
- * $Id: MasterTeamLoader.java 15426 2007-02-25 12:52:19Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/OTStorageHook.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/OTStorageHook.java
index e76f9c2..0d4d966 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/OTStorageHook.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/OTStorageHook.java
@@ -7,7 +7,6 @@
* 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
- * $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
index d27c18b..35f19c5 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
@@ -10,7 +10,6 @@
* 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
- * $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -105,7 +104,6 @@
* will throw an exception to avoid loading of any class from that bundle.
* </p>
* @author stephan
- * @version $Id$
*/
@SuppressWarnings("nls")
public class TransformerHook implements ClassLoadingHook, BundleWatcher, ClassLoaderDelegateHook, ClassLoadingStatsHook
diff --git a/plugins/org.eclipse.objectteams.otequinox/about.ini b/plugins/org.eclipse.objectteams.otequinox/about.ini
index 06091aa..d0c5125 100644
--- a/plugins/org.eclipse.objectteams.otequinox/about.ini
+++ b/plugins/org.eclipse.objectteams.otequinox/about.ini
@@ -1,10 +1,10 @@
aboutText=Object Teams -- Equinox integration (OT/Equinox)\n\
\n\
-Version: 2.2.0 M4\n\
+Version: 2.2.0 M5\n\
\n\
Part of the Eclipse Kepler Simultaneous Release\n\
\n\
-(c) Copyright Technical University Berlin and others, 2005, 2012\n\
+(c) Copyright Technical University Berlin and others, 2005, 2013\n\
Visit http://www.eclipse.org/objectteams\n\
\n\
Upon installation, OT/Equinox is enabled in your configuration/config.ini file.\n\
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/ActivationKind.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/ActivationKind.java
index 2beae77..932f579 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/ActivationKind.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/ActivationKind.java
@@ -7,7 +7,6 @@
* 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
- * $Id: ActivationKind.java 23461 2010-02-04 22:10:39Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/AspectBindingRequestAnswer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/AspectBindingRequestAnswer.java
index 98d769e..87b7c6e 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/AspectBindingRequestAnswer.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/AspectBindingRequestAnswer.java
@@ -7,7 +7,6 @@
* 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
- * $Id: AspectBindingRequestAnswer.java 23468 2010-02-04 22:34:27Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -22,7 +21,7 @@
* Answer for an aspect binding request. See extension point org.eclipse.objectteams.otequinox.aspectBindingNegotiators.
*
* @author stephan
- * @see 1.2.6
+ * @since 1.2.6
*/
public class AspectBindingRequestAnswer
{
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
index 59c643f..fada6ab 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
@@ -7,7 +7,6 @@
* 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
- * $Id: Constants.java 23461 2010-02-04 22:10:39Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -60,5 +59,4 @@
/** Simple name of the extension point org.eclipse.objectteams.otequinox.aspectBindingNegotiators. */
public static final String ASPECT_NEGOTIATOR_EXTPOINT_ID = "aspectBindingNegotiators";
-
}
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRequestNegotiator.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRequestNegotiator.java
index 353370e..3e16c0d 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRequestNegotiator.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRequestNegotiator.java
@@ -7,7 +7,6 @@
* 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
- * $Id: IAspectRequestNegotiator.java 23468 2010-02-04 22:34:27Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
index b222512..b4893f0 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
@@ -10,7 +10,6 @@
* 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
- * $Id: TransformerPlugin.java 23468 2010-02-04 22:34:27Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -63,7 +62,6 @@
* i.e., if this class is not found, no workspace location will be used.
*
* @author stephan
- * @version $Id: TransformerPlugin.java 23468 2010-02-04 22:34:27Z stephan $
*/
@SuppressWarnings("restriction") // accessing InternalPlatform
public class TransformerPlugin implements BundleActivator, IOTEquinoxService
@@ -72,7 +70,7 @@
static {
KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.jdt.ui");
KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.compiler.adaptor");
- KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.refactoring.adaptor");
+ KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.refactoring");
KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.pde.ui");
KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.samples");
}
@@ -151,7 +149,7 @@
public static TransformerPlugin getDefault() {
return instance;
}
-
+
/** public API: Do we know about any team that has not yet been initiaized as requested? */
public static boolean isWaitingForTeams() {
synchronized (instance.masterTeamLoaders) {
@@ -618,5 +616,9 @@
public IByteCodeAnalyzer getByteCodeAnalyzer() {
return new ASMByteCodeAnalyzer();
}
+
+ public static boolean useDynamicWeaving() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/ASMByteCodeAnalyzer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/ASMByteCodeAnalyzer.java
index 4544d37..f2906d3 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/ASMByteCodeAnalyzer.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/ASMByteCodeAnalyzer.java
@@ -1,24 +1,22 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2008 Technical University Berlin, Germany.
+ * Copyright 2008 Oliver Frank.
*
* 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
- * $Id: ASMByteCodeAnalyzer.java 23468 2010-02-04 22:34:27Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
- * Technical University Berlin - Initial API and implementation
+ * Oliver Frank - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otequinox.internal;
import java.io.IOException;
import java.io.InputStream;
-import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectBinding.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectBinding.java
index 7b1547a..c33deec 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectBinding.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectBinding.java
@@ -7,7 +7,6 @@
* 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
- * $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectPermissionManager.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectPermissionManager.java
index 38e425b..befb818 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectPermissionManager.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/internal/AspectPermissionManager.java
@@ -7,7 +7,6 @@
* 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
- * $Id: AspectPermissionManager.java 23468 2010-02-04 22:34:27Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -538,7 +537,7 @@
if (status >= TransformerPlugin.WARN_LEVEL)
this.log.log(Constants.TRANSFORMER_PLUGIN_ID, status, "OT/Equinox: "+msg);
}
-
+
List<Runnable> obligations = new ArrayList<Runnable>();
public void addBaseBundleObligations(final List<Object> teamInstances, final ArrayList<TeamClassRecord> teamClasses, final Bundle baseBundle) {
schedule(new Runnable() {
diff --git a/plugins/org.eclipse.objectteams.otredyn/.classpath b/plugins/org.eclipse.objectteams.otredyn/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.objectteams.otredyn/.gitignore b/plugins/org.eclipse.objectteams.otredyn/.gitignore
new file mode 100644
index 0000000..79e839a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.gitignore
@@ -0,0 +1,4 @@
+/otre.jar
+/otre_min.jar
+/otre_agent.jar
+/bin
diff --git a/plugins/org.eclipse.objectteams.otredyn/.project b/plugins/org.eclipse.objectteams.otredyn/.project
new file mode 100644
index 0000000..e0a35ad
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.objectteams.otredyn</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.objectteams.otredyn/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otredyn/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8871fec
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Fri Jul 15 18:22:12 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/plugins/org.eclipse.objectteams.otredyn/MANIFEST.MF b/plugins/org.eclipse.objectteams.otredyn/MANIFEST.MF
new file mode 100644
index 0000000..8ccd719
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Premain-Class: org.eclipse.objectteams.otredyn.transformer.jplis.otreAgent
+Can-Redefine-Classes: true
+
+
diff --git a/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..4732fce
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2