Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Arthanareeswaran2020-01-14 04:50:35 +0000
committerJay Arthanareeswaran2020-01-14 04:50:35 +0000
commitd04c2a1e0ff1279fd935640e680c6a597ce7ba9c (patch)
treeaa600a58f17311e071c7f932dd9f2d8db8e8ca11
parent7981c10bd3535ec152649aa02ae20bf17561669e (diff)
parent67a3ce361d29320458a1d8de160c15d48f4f6d32 (diff)
downloadeclipse.jdt.core-d04c2a1e0ff1279fd935640e680c6a597ce7ba9c.tar.gz
eclipse.jdt.core-d04c2a1e0ff1279fd935640e680c6a597ce7ba9c.tar.xz
eclipse.jdt.core-d04c2a1e0ff1279fd935640e680c6a597ce7ba9c.zip
Merge remote-tracking branch 'origin/master' into BETA_JAVA14Y20200114-0045
# Conflicts: # org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java # org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java # org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java Change-Id: I8e3bcb243de66196f358b6fb655a1f219fb07662
-rw-r--r--org.eclipse.jdt.compiler.apt/pom.xml13
-rw-r--r--org.eclipse.jdt.compiler.tool/pom.xml13
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java4
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java171
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java717
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java31
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java56
-rw-r--r--org.eclipse.jdt.core.tests.model/JCL/jclMin1.8.jarbin13995 -> 14382 bytes
-rw-r--r--org.eclipse.jdt.core.tests.model/JCL/jclMin1.8src.zipbin10189 -> 11104 bytes
-rw-r--r--org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.core.tests.model/pom.xml2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java38
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java38
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java44
-rw-r--r--org.eclipse.jdt.core/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java112
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java23
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties5
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java2
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java43
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java4
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java6
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java15
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java2
-rw-r--r--org.eclipse.jdt.core/pom.xml8
46 files changed, 1390 insertions, 154 deletions
diff --git a/org.eclipse.jdt.compiler.apt/pom.xml b/org.eclipse.jdt.compiler.apt/pom.xml
index 95fb78f28e..d2162c34d7 100644
--- a/org.eclipse.jdt.compiler.apt/pom.xml
+++ b/org.eclipse.jdt.compiler.apt/pom.xml
@@ -120,16 +120,23 @@
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<target>
+ <path id="ecj.id">
+ <fileset dir="${basedir}/../org.eclipse.jdt.core/target/">
+ <include name="org.eclipse.jdt.core-*-SNAPSHOT-batch-compiler.jar"/>
+ </fileset>
+ </path>
+
+ <property name="ecj.file" refid="ecj.id"/>
<exec dir="${basedir}/../org.eclipse.jdt.core/target/" executable="curl">
<arg value="--output"/>
- <arg value="org.eclipse.jdt.core-3.20.0-SNAPSHOT-batch-compiler.jar"/>
+ <arg value="${ecj.file}"/>
<arg value="--form"/>
- <arg value="file=@org.eclipse.jdt.core-3.20.0-SNAPSHOT-batch-compiler.jar"/>
+ <arg value="file=@${ecj.file}"/>
<arg value="--silent"/>
<arg value="--show-error"/>
<arg value="--fail"/>
<arg value="http://build.eclipse.org:31338/sign"/>
- </exec>
+ </exec>
</target>
</configuration>
<goals>
diff --git a/org.eclipse.jdt.compiler.tool/pom.xml b/org.eclipse.jdt.compiler.tool/pom.xml
index 9e591bec92..540f97ec3d 100644
--- a/org.eclipse.jdt.compiler.tool/pom.xml
+++ b/org.eclipse.jdt.compiler.tool/pom.xml
@@ -121,16 +121,23 @@
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<target>
+ <path id="ecj.id">
+ <fileset dir="${basedir}/../org.eclipse.jdt.core/target/">
+ <include name="org.eclipse.jdt.core-*-SNAPSHOT-batch-compiler.jar"/>
+ </fileset>
+ </path>
+
+ <property name="ecj.file" refid="ecj.id"/>
<exec dir="${basedir}/../org.eclipse.jdt.core/target/" executable="curl">
<arg value="--output"/>
- <arg value="org.eclipse.jdt.core-3.20.0-SNAPSHOT-batch-compiler.jar"/>
+ <arg value="${ecj.file}"/>
<arg value="--form"/>
- <arg value="file=@org.eclipse.jdt.core-3.20.0-SNAPSHOT-batch-compiler.jar"/>
+ <arg value="file=@${ecj.file}"/>
<arg value="--silent"/>
<arg value="--show-error"/>
<arg value="--fail"/>
<arg value="http://build.eclipse.org:31338/sign"/>
- </exec>
+ </exec>
</target>
</configuration>
<goals>
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 614b7b5881..9abf62c1fa 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
@@ -632,6 +632,7 @@ public void test011_problem_categories() {
expectedProblemAttributes.put("InheritedIncompatibleReturnType", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("InheritedMethodHidesEnclosingName", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("InheritedMethodReducesVisibility", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("InheritedParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("InheritedTypeHidesEnclosingName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("InitializerMustCompleteNormally", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("InstanceFieldDuringConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -814,6 +815,7 @@ public void test011_problem_categories() {
expectedProblemAttributes.put("MissingEnumDefaultCase", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("MissingNonNullByDefaultAnnotationOnPackage", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("MissingNonNullByDefaultAnnotationOnType", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+ expectedProblemAttributes.put("MissingNullAnnotationImplicitlyUsed", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("MissingRequiresTransitiveForTypeInAPI", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1640,6 +1642,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("InheritedIncompatibleReturnType", SKIP);
expectedProblemAttributes.put("InheritedMethodHidesEnclosingName", SKIP);
expectedProblemAttributes.put("InheritedMethodReducesVisibility", SKIP);
+ expectedProblemAttributes.put("InheritedParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED));
expectedProblemAttributes.put("InheritedTypeHidesEnclosingName", SKIP);
expectedProblemAttributes.put("InitializerMustCompleteNormally", SKIP);
expectedProblemAttributes.put("InstanceFieldDuringConstructorInvocation", SKIP);
@@ -1825,6 +1828,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("MissingEnumDefaultCase", new ProblemAttributes(JavaCore.COMPILER_PB_SWITCH_MISSING_DEFAULT_CASE));
expectedProblemAttributes.put("MissingNonNullByDefaultAnnotationOnPackage", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION));
expectedProblemAttributes.put("MissingNonNullByDefaultAnnotationOnType", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION));
+ expectedProblemAttributes.put("MissingNullAnnotationImplicitlyUsed", SKIP);
expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
expectedProblemAttributes.put("MissingRequiresTransitiveForTypeInAPI", new ProblemAttributes(JavaCore.COMPILER_PB_API_LEAKS));
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 1f7126921c..8dd1976b59 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
@@ -1290,44 +1290,44 @@ public void test_parameter_specification_inheritance_014() {
"----------\n" +
"1. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString1(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString2(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"3. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString5(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"4. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString3(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n"
: // at 1.8 we show null type annotations in the message:
"----------\n" +
"1. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method @Nullable String getString1(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method String getString2(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"3. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString5(@NonNull String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n" +
"4. ERROR in p1\\Y.java (at line 2)\n" +
" public class Y extends X implements IY {\n" +
- " ^\n" +
+ " ^\n" +
"The method getString3(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
"----------\n"));
}
@@ -1415,8 +1415,8 @@ public void test_parameter_specification_inheritance_017() {
"----------\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 specifies this parameter as @NonNull\n" +
+ " ^\n" +
+ "Parameter 1 of method foo(String) lacks a @NonNull annotation as specified in type IX\n" +
"----------\n");
}
@@ -6127,24 +6127,24 @@ public void testBug388281_06() {
"----------\n" +
"1. ERROR in ctest\\C.java (at line 2)\n" +
" public class C extends c.C2 implements i2.I2A {\n" +
- " ^\n" +
+ " ^^^^\n" +
"The method m2(Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in ctest\\C.java (at line 2)\n" +
" public class C extends c.C2 implements i2.I2A {\n" +
- " ^\n" +
+ " ^^^^\n" +
"The method m1(Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" +
"----------\n"
: // at 1.8 we show null type annotations:
"----------\n" +
"1. ERROR in ctest\\C.java (at line 2)\n" +
" public class C extends c.C2 implements i2.I2A {\n" +
- " ^\n" +
+ " ^^^^\n" +
"The method m2(@NonNull Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in ctest\\C.java (at line 2)\n" +
" public class C extends c.C2 implements i2.I2A {\n" +
- " ^\n" +
+ " ^^^^\n" +
"The method m1(@NonNull Object) from C2 cannot implement the corresponding method from I2A due to incompatible nullness constraints\n" +
"----------\n"),
libs,
@@ -9142,24 +9142,24 @@ public void testBug502214() {
"----------\n" +
"1. ERROR in test\\X.java (at line 22)\n" +
" class Y extends A implements I {\n" +
- " ^\n" +
+ " ^\n" +
"The method m2() from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in test\\X.java (at line 22)\n" +
" class Y extends A implements I {\n" +
- " ^\n" +
+ " ^\n" +
"The method m1(Object) from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" +
"----------\n"
:
"----------\n" +
"1. ERROR in test\\X.java (at line 22)\n" +
" class Y extends A implements I {\n" +
- " ^\n" +
+ " ^\n" +
"The method @Nullable String m2() from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" +
"----------\n" +
"2. ERROR in test\\X.java (at line 22)\n" +
" class Y extends A implements I {\n" +
- " ^\n" +
+ " ^\n" +
"The method m1(Object) from A cannot implement the corresponding method from I due to incompatible nullness constraints\n" +
"----------\n"
)
@@ -10930,4 +10930,139 @@ public void testBug481931_binary() {
runner.javacTestOptions = Excuse.EclipseWarningConfiguredAsError;
runner.runNegativeTest();
}
+public void testBug459397() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "NonNullBug.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "public class NonNullBug {\n" +
+ " public static final String PACKid_$metamodel$ = null;\n" +
+ " public static final String PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_SimpleRDBMS = null;\n" +
+ " public static final String PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_UMLtoRDBMS = null;\n" +
+ " public static final String PACKid_http_c_s_s_www_eclipse_org_s_qvt_s_examples_s_0_1_s_simpleUML = null;\n" +
+ " public static final String CLSSid_Association = null;\n" +
+ " public static final String CLSSid_AssociationToForeignKey = null;\n" +
+ " public static final String CLSSid_Attribute = null;\n" +
+ " public static final String CLSSid_AttributeToColumn = null;\n" +
+ " public static final String CLSSid_Class = null;\n" +
+ " public static final String CLSSid_ClassToTable = null;\n" +
+ " public static final String CLSSid_Class_0 = null;\n" +
+ " public static final String CLSSid_Classifier = null;\n" +
+ " public static final String CLSSid_Column = null;\n" +
+ " public static final String CLSSid_ForeignKey = null;\n" +
+ " public static final String CLSSid_FromAttribute = null;\n" +
+ " public static final String CLSSid_Key = null;\n" +
+ " public static final String CLSSid_NonLeafAttribute = null;\n" +
+ " public static final String CLSSid_Package = null;\n" +
+ " public static final String CLSSid_PackageElement = null;\n" +
+ " public static final String CLSSid_PackageToSchema = null;\n" +
+ " public static final String CLSSid_PrimitiveDataType = null;\n" +
+ " public static final String CLSSid_PrimitiveToName = null;\n" +
+ " public static final String CLSSid_Schema = null;\n" +
+ " public static final String CLSSid_Table = null;\n" +
+ " public static final String STR_2 = \"2\";\n" +
+ " public static final String STR_BOOLEAN = \"BOOLEAN\";\n" +
+ " public static final String STR_Boolean = \"Boolean\";\n" +
+ " public static final String STR_Integer = \"Integer\";\n" +
+ " public static final String STR_NUMBER = \"NUMBER\";\n" +
+ " public static final String STR_String = \"String\";\n" +
+ " public static final String STR_VARCHAR = \"VARCHAR\";\n" +
+ " public static final String STR__ = \"_\";\n" +
+ " public static final String STR__pk = \"_pk\";\n" +
+ " public static final String STR__tid = \"_tid\";\n" +
+ " public static final String STR_base = \"base\";\n" +
+ " public static final String STR_persistent = \"persistent\";\n" +
+ " public static final String STR_primary = \"primary\";\n" +
+ " public static final String BAG_CLSSid_AttributeToColumn = null;\n" +
+ " public static final String BAG_CLSSid_FromAttribute = null;\n" +
+ " public static final String ORD_CLSSid_AssociationToForeignKey = null;\n" +
+ " public static final String ORD_CLSSid_Attribute = null;\n" +
+ " public static final String ORD_CLSSid_Column = null;\n" +
+ " public static final String ORD_CLSSid_ForeignKey = null;\n" +
+ " public static final String ORD_CLSSid_Key = null;\n" +
+ " public static final String ORD_CLSSid_PackageElement = null;\n" +
+ " public static final String SET_CLSSid_Association = null;\n" +
+ " public static final String SET_CLSSid_Attribute = null;\n" +
+ " public static final String SET_CLSSid_AttributeToColumn = null;\n" +
+ " public static final String SET_CLSSid_Class = null;\n" +
+ " public static final String SET_CLSSid_ClassToTable = null;\n" +
+ " public static final String SET_CLSSid_FromAttribute = null;\n" +
+ " public static final String SET_CLSSid_NonLeafAttribute = null;\n" +
+ " public static final String SET_CLSSid_Package = null;\n" +
+ " public static final String SET_CLSSid_PrimitiveToName = null;\n" +
+ "\n" +
+ " protected final String OPPOSITE_OF_ClassToTable_table = null;\n" +
+ " protected final String OPPOSITE_OF_ClassToTable_umlClass = null;\n" +
+ " protected final String OPPOSITE_OF_FromAttribute_attribute = null;\n" +
+ " protected final String OPPOSITE_OF_PrimitiveToName_primitive = null;\n" +
+ "\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " private static final String[] classIndex2classId = new String[] {};\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " private final static int[][] classIndex2allClassIndexes = new int[][] {};\n" +
+ "\n" +
+ " protected String x(final @NonNull Exception a, final @NonNull String p_4, final @Nullable String p2s_9) throws Exception {\n" +
+ " final @Nullable Throwable destination = a.getCause();\n" +
+ " final @Nullable Throwable dc = a.getCause();\n" +
+ " if (dc == null) {\n" +
+ " throw new Exception();\n" +
+ " }\n" +
+ " try {\n" +
+ " if (dc instanceof Exception) {\n" +
+ " throw (Exception) dc;\n" +
+ " }\n" +
+ " boolean eq_2 = (destination != null) ? destination.equals(dc) : (dc == null);\n" +
+ " } catch (Exception e) {\n" +
+ " }\n" +
+ " boolean ne = (destination != null) ? !destination.equals(dc) : (dc != null);\n" +
+ " return dc.toString();\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in NonNullBug.java (at line 80)\n" +
+ " boolean eq_2 = (destination != null) ? destination.equals(dc) : (dc == null);\n" +
+ " ^^\n" +
+ "Null comparison always yields false: The variable dc cannot be null at this location\n" +
+ "----------\n" +
+ "2. ERROR in NonNullBug.java (at line 83)\n" +
+ " boolean ne = (destination != null) ? !destination.equals(dc) : (dc != null);\n" +
+ " ^^\n" +
+ "Redundant null check: The variable dc cannot be null at this location\n" +
+ "----------\n");
+}
+public void testBug466477() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "SuperI.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "\n" +
+ "public interface SuperI {\n" +
+ " void testNN(@NonNull String s);\n" +
+ " void testNu(@Nullable String s);\n" +
+ "}\n",
+ "Base.java",
+ "public class Base {\n" +
+ " public void testNN(String s) { }\n" +
+ " public void testNu(String s) { }\n" +
+ "}\n",
+ "Custom.java",
+ "public class Custom extends Base implements SuperI {\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in Custom.java (at line 1)\n" +
+ " public class Custom extends Base implements SuperI {\n" +
+ " ^^^^\n" +
+ "The method testNu(String) from Base cannot implement the corresponding method from SuperI due to incompatible nullness constraints\n" +
+ "----------\n" +
+ "2. WARNING in Custom.java (at line 1)\n" +
+ " public class Custom extends Base implements SuperI {\n" +
+ " ^^^^\n" +
+ "Parameter 1 of method testNN(String) lacks a @NonNull annotation as specified in type SuperI\n" +
+ "----------\n");
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
index da9bb3dce9..47ba9ccd6b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
@@ -57,7 +57,7 @@ private static final String APACHE_DBUTILS_CONTENT = "package org.apache.commons
"}\n";
static {
-// TESTS_NAMES = new String[] { "testBug542707_002" };
+// TESTS_NAMES = new String[] { "testBug463320" };
// TESTS_NUMBERS = new int[] { 50 };
// TESTS_RANGE = new int[] { 11, -1 };
}
@@ -3092,7 +3092,12 @@ public void testBug368709a() {
"}\n"
},
"----------\n" +
- "1. ERROR in X.java (at line 18)\n" +
+ "1. ERROR in X.java (at line 15)\n" +
+ " return wc.open(getObjectId(), type).openStream();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 18)\n" +
" return new ObjectStream.Filter(type, size, in);\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Potential resource leak: \'in\' may not be closed at this location\n" +
@@ -4219,13 +4224,13 @@ public void testBug395977() {
null);
}
-// Bug 395977 - Resource leak warning behavior possibly incorrect for anonymous inner class
-// variant with named local class - don't accept as a secure resource wrapper
+//Bug 395977 - Resource leak warning behavior possibly incorrect for anonymous inner class
+//variant with named local class - accept as a secure resource wrapper since no close method
public void testBug395977_1() {
Map options = getCompilerOptions();
options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
- runLeakTest(
+ runConformTest(
new String[] {
"WriterTest.java",
"import java.io.*;\n" +
@@ -4275,8 +4280,68 @@ public void testBug395977_1() {
" }\n" +
"}"
},
+ "",
+ options);
+}
+//Bug 395977 - Resource leak warning behavior possibly incorrect for anonymous inner class
+//variant with named local class - don't accept as a secure resource wrapper since close() method exist
+public void testBug395977_1a() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "WriterTest.java",
+ "import java.io.*;\n" +
+ "\n" +
+ "public class WriterTest implements Runnable\n" +
+ "{\n" +
+ " private BufferedWriter m_Writer;\n" +
+ " \n" +
+ " public void run()\n" +
+ " {\n" +
+ " try\n" +
+ " {\n" +
+ " initializeWriter();\n" +
+ " \n" +
+ " m_Writer.write(\"string\");\n" +
+ " m_Writer.newLine();\n" +
+ " \n" +
+ " closeWriter();\n" +
+ " }\n" +
+ " catch (IOException ioe)\n" +
+ " {\n" +
+ " ioe.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ " \n" +
+ " private void initializeWriter()\n" +
+ " throws UnsupportedEncodingException, FileNotFoundException\n" +
+ " {\n" +
+ " class MyBufferedWriter extends BufferedWriter\n" +
+ " {\n" +
+ " MyBufferedWriter(OutputStreamWriter writer) { super(writer); }\n" +
+ " /**\n" +
+ " * Writes an LF character on all platforms, to avoid constantly flipping the line terminator style.\n" +
+ " */\n" +
+ " public void newLine() throws IOException\n" +
+ " {\n" +
+ " write('\\n');\n" +
+ " }\n" +
+ " public void close() {}\n" +
+ " };" +
+ " m_Writer = new MyBufferedWriter(new OutputStreamWriter(new FileOutputStream(\"file\"), \"UTF-8\"));\n" +
+ " }\n" +
+ " \n" +
+ " private void closeWriter()\n" +
+ " throws IOException\n" +
+ " {\n" +
+ " m_Writer.close();\n" +
+ " }\n" +
+ "}"
+ },
"----------\n" +
- "1. ERROR in WriterTest.java (at line 37)\n" +
+ "1. ERROR in WriterTest.java (at line 38)\n" +
" }; m_Writer = new MyBufferedWriter(new OutputStreamWriter(new FileOutputStream(\"file\"), \"UTF-8\"));\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
@@ -5363,7 +5428,8 @@ public void testBug473317() {
if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // using diamond
Map<String, String> compilerOptions = getCompilerOptions();
compilerOptions.put(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION, JavaCore.IGNORE);
- runLeakTest(
+ Runner runner = new Runner();
+ runner.testFiles =
new String[] {
"AutoCloseableEnhancedForTest.java",
"import java.util.Iterator;\n" +
@@ -5427,7 +5493,8 @@ public void testBug473317() {
" }\n" +
" }\n" +
"}\n"
- },
+ };
+ runner.expectedCompilerLog =
"----------\n" +
"1. WARNING in AutoCloseableEnhancedForTest.java (at line 44)\n" +
" for (Object value : new MyIterable<>())\n" +
@@ -5438,8 +5505,9 @@ public void testBug473317() {
" MyIterable<Object> iterable = new MyIterable<>();\n" +
" ^^^^^^^^\n" +
"Resource leak: \'iterable\' is never closed\n" +
- "----------\n",
- compilerOptions);
+ "----------\n";
+ runner.customOptions = compilerOptions;
+ runner.runWarningTest(); // javac warns about exception thrown from close() method
}
public void testBug541705() {
if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // uses diamond
@@ -5707,4 +5775,633 @@ public void testBug486506() {
"----------\n",
options);
}
+public void testBug463320() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "Try17.java",
+ "import java.util.zip.*;\n" +
+ "import java.io.*;\n" +
+ "public class Try17 {\n" +
+ " void potential() throws IOException {\n" +
+ " String name= getZipFile().getName();\n" +
+ " System.out.println(name);\n" +
+ " }\n" +
+ " void definite() throws IOException {\n" +
+ " String name= new ZipFile(\"bla.jar\").getName();\n" +
+ " System.out.println(name);\n" +
+ " }\n" +
+ " void withLocal() throws IOException {\n" +
+ " ZipFile zipFile = getZipFile();\n" +
+ " String name= zipFile.getName();\n" +
+ " System.out.println(name);\n" +
+ " }\n" +
+ "\n" +
+ " ZipFile getZipFile() throws IOException {\n" +
+ " return new ZipFile(\"bla.jar\");\n" +
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in Try17.java (at line 5)\n" +
+ " String name= getZipFile().getName();\n" +
+ " ^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in Try17.java (at line 9)\n" +
+ " String name= new ZipFile(\"bla.jar\").getName();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in Try17.java (at line 13)\n" +
+ " ZipFile zipFile = getZipFile();\n" +
+ " ^^^^^^^\n" +
+ "Potential resource leak: \'zipFile\' may not be closed\n" +
+ "----------\n",
+ options);
+}
+public void testBug463320_comment8() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // required version of java.nio.file.*
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "Try17.java",
+ "import java.io.*;\n" +
+ "import java.nio.file.*;\n" +
+ "import java.net.*;\n" +
+ "public class Try17 {\n" +
+ " public InputStream openInputStream(URI uri) {\n" +
+ " try {\n" +
+ " System.out.println(FileSystems.getFileSystem(uri));\n" +
+ " return Files.newInputStream(Paths.get(uri));\n" +
+ " } catch (FileSystemNotFoundException e) {\n" +
+ " throw new IllegalArgumentException(e);\n" +
+ " } catch (IOException e) {\n" +
+ " throw new IllegalStateException(e);\n" +
+ " }\n" +
+ " }\n" +
+ " public InputStream delegateGet(URI uri) {\n" +
+ " return openInputStream(uri);\n" + // no problem here!
+ " }\n" +
+ "}"
+ },
+ "----------\n" +
+ "1. ERROR in Try17.java (at line 7)\n" +
+ " System.out.println(FileSystems.getFileSystem(uri));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value from line 7>\' may not be closed\n" +
+ "----------\n",
+ options);
+}
+public void testBug558574() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses varargs signatures
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.io.*;\n" +
+ "public class X {\n" +
+ " void m1() throws FileNotFoundException {\n" +
+ " PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(\"/tmp/out\")));\n" +
+ " pw.printf(\"%d\", 42).close();\n" +
+ " }\n" +
+ " void m2(PrintWriter pw) throws FileNotFoundException {\n" +
+ " pw.printf(\"%d\", 42).append(\"end\").close();\n" +
+ " }\n" +
+ " void m3() throws FileNotFoundException {\n" +
+ " new PrintWriter(new OutputStreamWriter(new FileOutputStream(\"/tmp/out\")))\n" +
+ " .format(\"%d\", 42)\n" +
+ " .append(\"end\")\n" +
+ " .close();\n" +
+ " }\n" +
+ " void m4(PrintWriter pw) throws FileNotFoundException {\n" +
+ " pw.printf(\"%d\", 42).append(\"end\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ "",
+ options);
+}
+public void testBug463320_comment19() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+
+ runConformTest(
+ new String[] {
+ "Try17.java",
+ "import java.util.zip.*;\n" +
+ "import java.io.*;\n" +
+ "public class Try17 {\n" +
+ " void withLocal() throws IOException {\n" +
+ " ZipFile zipFile = null;\n" +
+ " if (zipFile != null)" +
+ " zipFile = getZipFile();\n" + // not reachable
+ " String name= zipFile.getName();\n" +
+ " System.out.println(name);\n" +
+ " }\n" +
+ "\n" +
+ " ZipFile getZipFile() throws IOException {\n" +
+ " return new ZipFile(\"bla.jar\");\n" +
+ " }\n" +
+ "}"
+ },
+ options);
+}
+public void testBug552521() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // uses try-with-resources
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
+ runLeakTest(
+ new String[] {
+ "EclipseBug552521getChannel.java",
+ "import java.io.File;\n" +
+ "import java.io.FileInputStream;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.nio.channels.FileChannel;\n" +
+ "\n" +
+ "public class EclipseBug552521getChannel {\n" +
+ "\n" +
+ " @SuppressWarnings(\"unused\")\n" +
+ " public void copyFile(final File srcFile, final File dstFile) throws Exception {\n" +
+ " /*\n" +
+ " * TODO Eclipse Setting: Window/Preferences/Java/Compiler/Errors-Warnings/\n" +
+ " * Resource not managed via try-with-resource = Ignore (default)\n" +
+ " */\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 17
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO Warning ok\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ "\n" +
+ " if (srcFile.isFile()) { // \"if\" (resolved at runtime) -> Warning suppressed\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 28
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME Warning missing!\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " } else { // \"else\" (resolved at runtime) -> Warning suppressed\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 38
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME Warning missing!\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " if (true) { // Dummy \"if\" (= constant true) -> Warning\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 50
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO Warning ok\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " } else { // Dummy \"else\" (= constant false) -> Warning suppressed\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 60
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME Warning missing!\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " if (false) { // Dummy \"if\" (= constant false) -> Warning suppressed\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 72
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME Warning missing!\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " } else { // Dummy \"else\" (= constant true) -> Warning\n" +
+ " try (\n" +
+ " final FileInputStream srcStream = new FileInputStream (srcFile);\n" +
+ " final FileChannel srcChannel = srcStream.getChannel();\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" + // line 82
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO Warning ok\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " }\n" +
+ " /*\n" +
+ " * Following test-case differs from all the above as follows:\n" +
+ " * FileInputStream is unassigned, instead of FileOutputStream\n" +
+ " */\n" +
+ " try (\n" +
+ " final FileChannel srcChannel = new FileInputStream (srcFile) .getChannel();\n" + // line 94
+ " // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO Warning ok\n" +
+ " final FileOutputStream dstStream = new FileOutputStream(srcFile);\n" +
+ " final FileChannel dstChannel = dstStream.getChannel();\n" +
+ " )\n" +
+ " {\n" +
+ " srcChannel.transferTo(0, srcChannel.size(), dstChannel);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in EclipseBug552521getChannel.java (at line 17)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "2. ERROR in EclipseBug552521getChannel.java (at line 28)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "3. ERROR in EclipseBug552521getChannel.java (at line 38)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "4. ERROR in EclipseBug552521getChannel.java (at line 50)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "5. ERROR in EclipseBug552521getChannel.java (at line 60)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "6. ERROR in EclipseBug552521getChannel.java (at line 72)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "7. ERROR in EclipseBug552521getChannel.java (at line 82)\n" +
+ " final FileChannel dstChannel = new FileOutputStream(dstFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n" +
+ "8. ERROR in EclipseBug552521getChannel.java (at line 94)\n" +
+ " final FileChannel srcChannel = new FileInputStream (srcFile) .getChannel();\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Resource leak: \'<unassigned Closeable value>\' is never closed\n" +
+ "----------\n",
+ options);
+}
+public void testBug552521_comment14() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses foreach
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "X.java",
+ "import java.io.*;\n" +
+ "import java.util.*;\n" +
+ "public class X {\n" +
+ " List<String> process(InputStream is) throws IOException {\n" +
+ " is.close();\n" +
+ " return Collections.emptyList();\n" +
+ " }\n" +
+ " void test(String fileName) throws IOException {\n" +
+ " for (String string : process(new FileInputStream(fileName))) {\n" +
+ " System.out.println(string);\n" +
+ " }\n" +
+ " }\n" +
+ " void test2(String fileName) throws IOException {\n" +
+ " for (String string : process(new FileInputStream(fileName)))\n" +
+ " System.out.println(string);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " for (String string : process(new FileInputStream(fileName))) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " for (String string : process(new FileInputStream(fileName)))\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n",
+ options);
+}
+public void testBug552521_comment14b() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses foreach
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "X.java",
+ "import java.io.*;\n" +
+ "public class X {\n" +
+ " boolean check(InputStream is) throws IOException {\n" +
+ " is.close();\n" +
+ " return true;\n" +
+ " }\n" +
+ " void test1(String fileName) throws IOException {\n" +
+ " while (check(new FileInputStream(fileName)))\n" +
+ " System.out.println(\"while\");\n" +
+ " }\n" +
+ " void test2(String fileName) throws IOException {\n" +
+ " do {\n" +
+ " System.out.println(\"while\");\n" +
+ " } while (check(new FileInputStream(fileName)));\n" +
+ " }\n" +
+ " void test3(String fileName) throws IOException {\n" +
+ " for (int i=0;check(new FileInputStream(fileName));i++)\n" +
+ " System.out.println(i);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " while (check(new FileInputStream(fileName)))\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " } while (check(new FileInputStream(fileName)));\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 17)\n" +
+ " for (int i=0;check(new FileInputStream(fileName));i++)\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Potential resource leak: \'<unassigned Closeable value>\' may not be closed\n" +
+ "----------\n",
+ options);
+}
+public void testBug519740() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // uses try-with-resources
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runConformTest(
+ new String[] {
+ "Snippet.java",
+ "class Snippet {\n" +
+ " static void foo() throws Exception {\n" +
+ " try (java.util.Scanner scanner = new java.util.Scanner(new java.io.FileInputStream(\"abc\"))) {\n" +
+ " while (scanner.hasNext()) \n" +
+ " if (scanner.hasNextInt())\n" +
+ " throw new RuntimeException(); /* Potential resource leak: 'scanner' may not be closed at this location */\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ options);
+}
+public void testBug552441() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // uses try-with-resources
+
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+
+ runConformTest(
+ new String[] {
+ "Test.java",
+ "import java.io.BufferedOutputStream;\n" +
+ "import java.io.FileOutputStream;\n" +
+ "import java.io.IOException;\n" +
+ "import java.io.OutputStream;\n" +
+ "import java.util.concurrent.atomic.AtomicLong;\n" +
+ "\n" +
+ "public class Test {\n" +
+ " public static class CountingBufferedOutputStream extends BufferedOutputStream {\n" +
+ " private final AtomicLong bytesWritten;\n" +
+ "\n" +
+ " public CountingBufferedOutputStream(OutputStream out, AtomicLong bytesWritten) throws IOException {\n" +
+ " super(out);\n" +
+ " this.bytesWritten = bytesWritten;\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public void write(byte[] b) throws IOException {\n" +
+ " super.write(b);\n" +
+ " bytesWritten.addAndGet(b.length);\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public void write(byte[] b, int off, int len) throws IOException {\n" +
+ " super.write(b, off, len);\n" +
+ " bytesWritten.addAndGet(len);\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public synchronized void write(int b) throws IOException {\n" +
+ " super.write(b);\n" +
+ " bytesWritten.incrementAndGet();\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public static void test(String[] args) throws IOException {\n" +
+ " AtomicLong uncompressedBytesOut = new AtomicLong();\n" +
+ " int val = 0;\n" +
+ " try (CountingBufferedOutputStream out = new CountingBufferedOutputStream(\n" +
+ " new FileOutputStream(\"outputfile\"), uncompressedBytesOut)) {\n" +
+ "\n" +
+ " for (int i = 0; i < 1; i++) {\n" +
+ " if (val > 2) {\n" +
+ " throw new RuntimeException(\"X\");\n" +
+ " }\n" +
+ " }\n" +
+ " if (val > 2) {\n" +
+ " throw new RuntimeException(\"Y\");\n" +
+ " }\n" +
+ " throw new RuntimeException(\"Z\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ },
+ options);
+}
+public void testBug400523() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+
+ runConformTest(
+ new String[] {
+ "LeakWarning.java",
+ "import java.sql.Connection;\n" +
+ "import java.sql.PreparedStatement;\n" +
+ "import java.sql.ResultSet;\n" +
+ "import java.sql.SQLException;\n" +
+ "\n" +
+ "public class LeakWarning {\n" +
+ " String value = null;\n" +
+ " \n" +
+ " public void setValue(Connection conn)\n" +
+ " { \n" +
+ " PreparedStatement stmt = null;\n" +
+ " ResultSet rs = null;\n" +
+ " try { \n" +
+ " stmt = conn.prepareStatement(\"SELECT 'value'\"); /* marked as potential resource leak */\n" +
+ " rs = stmt.executeQuery(); /* marked as potential resource leak */\n" +
+ " if (rs.next()) value = rs.getString(1);\n" +
+ " } catch(SQLException e) {\n" +
+ " }\n" +
+ " finally {\n" +
+ " if (null != rs) try { rs.close(); } catch (SQLException e) {} finally { rs = null; }\n" +
+ " if (null != stmt) try { stmt.close(); } catch (SQLException e) {} finally { stmt = null; }\n" +
+ " }\n" +
+ " }\n" +
+ " \n" +
+ " public void setValueReturn(Connection conn)\n" +
+ " { \n" +
+ " PreparedStatement stmt = null;\n" +
+ " ResultSet rs = null;\n" +
+ " try { \n" +
+ " stmt = conn.prepareStatement(\"SELECT 'value'\");\n" +
+ " rs = stmt.executeQuery();\n" +
+ " if (rs.next()) value = rs.getString(1);\n" +
+ " } catch(SQLException e) {\n" +
+ " }\n" +
+ " finally {\n" +
+ " if (null != rs) try { rs.close(); } catch (SQLException e) {} finally { rs = null; }\n" +
+ " if (null != stmt) try { stmt.close(); } catch (SQLException e) {} finally { stmt = null; }\n" +
+ " }\n" +
+ " return; /* no warning now */\n" +
+ " }\n" +
+ "}\n"
+ },
+ options);
+}
+public void testBug527761() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "class BAOSWrapper extends java.io.ByteArrayOutputStream {}\n" +
+ "public class X {\n" +
+ " public static void warningCauser() {\n" +
+ " BAOSWrapper baos = new BAOSWrapper();\n" +
+ " //WARNING HAS BEEN CAUSED\n" +
+ " baos.write(0);\n" +
+ " }\n" +
+ "}\n"
+ },
+ options);
+}
+public void testBug527761_otherClose() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses generics
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ String xSource =
+ "public class X {\n" +
+ " public static void warningCauser() {\n" +
+ " BAOSWrapper<String> baos = new BAOSWrapper<String>();\n" +
+ " //WARNING HAS BEEN CAUSED\n" +
+ " baos.write(0);\n" +
+ " }\n" +
+ "}\n";
+ runConformTest(
+ new String[] {
+ "BAOSWrapper.java",
+ "class BAOSWrapper<T> extends java.io.ByteArrayOutputStream {\n" +
+ " public void close(java.util.List<?> l) {}\n" + // not relevant, param challenges treatment of unresolved types
+ "}\n",
+ "X.java",
+ xSource
+ },
+ options);
+ // consume BAOSWrapper from .class:
+ runConformTest(false,
+ new String[] { "X.java", xSource },
+ "", "", "", null);
+}
+public void testBug527761_neg() {
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ runLeakTest(
+ new String[] {
+ "X.java",
+ "class BAOSWrapper extends java.io.ByteArrayOutputStream {\n" +
+ " public void close() {}\n" + // indicates that resource could be relevant
+ "}\n" +
+ "public class X {\n" +
+ " public static void warningCauser() {\n" +
+ " BAOSWrapper baos = new BAOSWrapper();\n" +
+ " //WARNING HAS BEEN CAUSED\n" +
+ " baos.write(0);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " BAOSWrapper baos = new BAOSWrapper();\n" +
+ " ^^^^\n" +
+ "Resource leak: \'baos\' is never closed\n" +
+ "----------\n",
+ options);
+}
+// regression caused by Bug 527761
+public void testBug558759() {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses generics
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
+ String ySource =
+ "public class Y {\n" +
+ " class YInner extends X<I> {}\n" +
+ "}\n";
+ runConformTest(
+ new String[] {
+ "I.java",
+ "import java.io.Closeable;\n" +
+ "public interface I extends Closeable {\n" +
+ " interface Location {}\n" +
+ " void m(Location l);\n" +
+ "}\n",
+ "X0.java",
+ "public abstract class X0<T extends I> implements I {\n" +
+ " public void close() {}\n" +
+ "}\n",
+ "X.java",
+ "public class X<T extends I> extends X0<T> implements I {\n" +
+ " public void m(Location l) {}\n" +
+ "}\n",
+ "Y.java",
+ ySource
+ },
+ options);
+ runConformTest(false,
+ new String[] { "Y.java", ySource },
+ "", "", "", null);
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
index ce9e6cf0d0..ed924e0d97 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
@@ -8830,4 +8830,35 @@ public class StackMapAttributeTest extends AbstractRegressionTest {
},
"SUCCESS");
}
+ public void test558844() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " \n" +
+ " public static void main( String[] args ) {\n" +
+ " System.out.println(new X().getText());\n" +
+ " }\n" +
+ "\n" +
+ " public String getText() {\n" +
+ " Long lValue1 = getValue1();\n" +
+ " Long lValue2 = getValue2();\n" +
+ " return ( isValue1() ? \"\" : ( lValue1 == null ? \"\" : lValue1.toString() ) + \"-\" ) + ( lValue2 == null ? \"\" : lValue2.toString() );\n" +
+ " }\n" +
+ "\n" +
+ " private Long getValue1() {\n" +
+ " return Long.valueOf( 1 );\n" +
+ " }\n" +
+ "\n" +
+ " private Long getValue2() {\n" +
+ " return Long.valueOf( 1 );\n" +
+ " }\n" +
+ "\n" +
+ " private boolean isValue1() {\n" +
+ " return false;\n" +
+ " }\n" +
+ "}",
+ },
+ "1-1");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
index 9e79e516f9..5575b3a39f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
@@ -25,6 +25,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -88,6 +89,13 @@ public class StandAloneASTParserTest extends AbstractRegressionTest {
parser.setUnitName(unitName);
return parser.createAST(null);
}
+ protected File createFile(File dir, String fileName, String contents) throws IOException {
+ File file = new File(dir, fileName);
+ try (Writer writer = new BufferedWriter(new FileWriter(file))) {
+ writer.write(contents);
+ }
+ return file;
+ }
public void testBug529654_001() {
String contents =
"module m {\n" +
@@ -1829,4 +1837,52 @@ public class StandAloneASTParserTest extends AbstractRegressionTest {
YieldStatement yieldStatement = (YieldStatement) ((Block)se.statements().get(1)).statements().get(0);
assertNotNull("Expression null", yieldStatement.getExpression());
}
+ public void testBug558517() throws IOException {
+ File f1 = null, f2 = null, packDir = null;
+ try {
+ File rootDir = new File(System.getProperty("java.io.tmpdir"));
+ packDir = new File(rootDir, "P/src/x");
+ packDir.mkdirs();
+
+ String fileName1 = "EnsureImpl$1.java";
+ String fileName2 = "C9947f.java";
+ f1 = createFile(
+ packDir, fileName1,
+ "package x;\n" +
+ "\n" +
+ "class EnsureImpl$1 {\n" +
+ "}\n");
+ f2 = createFile(
+ packDir, fileName2,
+ "package x;\n" +
+ "public final class C9947f {\n" +
+ " public C9947f() {\n" +
+ " try {\n" +
+ " new x.EnsureImpl$1();\n" +
+ " } catch (Throwable unused) {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n");
+ ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
+ parser.setResolveBindings(true);
+ Map<String, String> options = new HashMap<>();
+ JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
+ parser.setCompilerOptions(options );
+ parser.setEnvironment(null,
+ new String[] { rootDir + "/P/src" },
+ null,
+ true);
+ parser.createASTs(new String[] { packDir + "/" + fileName1, packDir + "/" + fileName2 },
+ null,
+ new String[] { "Lx/C9947f;" },
+ new FileASTRequestor() {
+ },
+ null);
+ // just ensure the above doesn't throw NPE
+ } finally {
+ f1.delete();
+ f2.delete();
+ packDir.delete();
+ }
+ }
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8.jar b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8.jar
index d7e520134e..074df0519a 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8.jar
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8src.zip b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8src.zip
index aed574c89d..1aa9c7b3ea 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8src.zip
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.8src.zip
Binary files differ
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 9e50a9da1a..851e327040 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 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.10.1000.qualifier
+Bundle-Version: 3.10.1100.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index f61b3ef5d4..9ef8306803 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core.tests.model</artifactId>
- <version>3.10.1000-SNAPSHOT</version>
+ <version>3.10.1100-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 3296f5a78f..26bab5ad44 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -1745,8 +1745,8 @@ public void testBug252556a() {
"public class Test {\n" +
"\n" +
"int foo() {\n" +
- " return 0;\n" +
- " }\n" +
+ " return 0;\n" +
+ "}\n" +
"void bar(){}\n" +
"}\n"
);
@@ -1765,8 +1765,8 @@ public void testBug252556b() {
"public class Test {\n" +
"\n" +
"int foo() {\n" +
- " return 0;\n" +
- " }\n" +
+ " return 0;\n" +
+ "}\n" +
"void bar(){}\n" +
"}\n"
);
@@ -13055,4 +13055,34 @@ public void testBug220713() {
" }\n" +
"}");
}
+/**
+ * https://bugs.eclipse.org/558421 [formatter] Generate getter/setter creates unnecessary blank line
+ */
+public void testBug() {
+ this.formatterPrefs.blank_lines_after_last_class_body_declaration = 1;
+ String source =
+ "public int getA() {\n" +
+ " return a;\n" +
+ "}";
+ formatSource(source, source, CodeFormatter.K_CLASS_BODY_DECLARATIONS);
+}
+/**
+ * https://bugs.eclipse.org/250656 - [formatter] Formatting selection destroys correct indentation
+ */
+public void testBug250656() {
+ this.formatterPrefs.page_width = 50;
+ formatSource(
+ "class C {\n" +
+ " void f() {\n" +
+ " doSomething(aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbb\n" +
+ "[# + ccccccccccccccccccc);#]\n" +
+ " }\n" +
+ "}",
+ "class C {\n" +
+ " void f() {\n" +
+ " doSomething(aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbb\n" +
+ " + ccccccccccccccccccc);\n" +
+ " }\n" +
+ "}");
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
index c913cd2812..1c6de96d1b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
@@ -1002,9 +1002,9 @@ public void testBug232768_Javadoc03() throws JavaModelException {
"public class C {\n" +
" \n" +
" /**\n" +
- " * a b c d .\n" +
- " */\n" +
- " void m1 ( ) {\n" +
+ " * a b c d .\n" +
+ " */\n" +
+ " void m1 ( ) {\n" +
" \n" +
" } \n" +
"\n" +
@@ -1099,8 +1099,8 @@ public void testBug232768_Javadoc06() throws JavaModelException {
" public class C{ \n" +
" \n" +
" /**\n" +
- " * a b c d .\n" +
- " */\n" +
+ " * a b c d .\n" +
+ " */\n" +
" void m1 ( ) {\n" +
" \n" +
" } \n" +
@@ -1195,9 +1195,9 @@ public void testBug232768_Block03() throws JavaModelException {
"public class D {\n" +
" \n" +
" /*\n" +
- " * a b c d .\n" +
- " */\n" +
- " void m2 ( ) {\n" +
+ " * a b c d .\n" +
+ " */\n" +
+ " void m2 ( ) {\n" +
" \n" +
" } \n" +
"\n" +
@@ -1292,8 +1292,8 @@ public void testBug232768_Block06() throws JavaModelException {
" public class D{ \n" +
" \n" +
" /*\n" +
- " * a b c d .\n" +
- " */\n" +
+ " * a b c d .\n" +
+ " */\n" +
" void m2 ( ) {\n" +
" \n" +
" } \n" +
@@ -1362,9 +1362,9 @@ public void testBug232768_Line03() throws JavaModelException {
"\n" +
" void m3() { // this is a bug\n" +
"\n" +
- " }\n" +
+ " }\n" +
"\n" +
- "}"
+ " }"
);
}
public void testBug232768_Line04() throws JavaModelException {
@@ -1449,7 +1449,7 @@ public void testBug232768_Line07() throws JavaModelException {
" \n" +
"\n" +
" void m3() { \n" +
- " // this is a bug\n" +
+ " // this is a bug\n" +
"\n" +
" }\n" +
" \n" +
@@ -1567,11 +1567,11 @@ public void testBug233011() throws JavaModelException {
"\n" +
"public class E01 {\n" +
" /**\n" +
- " * Javadoc comment\n" +
- " */\n" +
+ " * Javadoc comment\n" +
+ " */\n" +
" /*\n" +
- " * block comment\n" +
- " */\n" +
+ " * block comment\n" +
+ " */\n" +
" // single line comment\n" +
"}"
);
@@ -6042,7 +6042,7 @@ public void testBug280255() throws JavaModelException {
" {\n" +
"\n" +
"\n" +
- " return;\n" +
+ " return;\n" +
" }\n" +
" }\n" +
" }\n" +
@@ -6072,7 +6072,7 @@ public void testBug280255b() throws JavaModelException {
" {\r\n" +
"\r\n" +
"\r\n" +
- " return;\r\n" +
+ " return;\r\n" +
" }\r\n" +
" }\r\n" +
" }\r\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
index b36337b3a0..0cf01c8e5e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2019 GK Software AG and others.
+ * Copyright (c) 2011, 2020 GK Software AG and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1094,4 +1094,46 @@ public class NullAnnotationModelTests extends ReconcilerTests {
IAnnotationBinding[] annotations = typeBinding.getAnnotations();
assertEquals(0, annotations.length);
}
+ public void testBug479389() throws CoreException, IOException {
+ IJavaProject project = null;
+ try {
+ project = createJavaProject("Bug479389", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "1.8");
+ project.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+
+ createFolder("Bug479389/src/nullAnalysis");
+ String testSource =
+ "package nullAnalysis;\n" +
+ "interface MyList<T> {\n" +
+ " public Stream<T> stream();\n" +
+ "}\n" +
+ "interface Stream<T> {\n" +
+ " T[] toArray(IntFunction<T[]> supplier);" +
+ "}\n" +
+ "interface IntFunction<T> {\n" +
+ " T apply(int i);\n" +
+ "}\n" +
+ "public class X {\n" +
+ "\n" +
+ " public String[] method(MyList<String> in) {\n" +
+ " return in.stream().toArray(String[]::new);\n" +
+ " }\n" +
+ "}\n";
+ String testSourcePath = "Bug479389/src/nullAnalysis/X.java";
+ createFile(testSourcePath, testSource);
+ char[] testSourceChars = testSource.toCharArray();
+ this.problemRequestor.initialize(testSourceChars);
+
+ getCompilationUnit(testSourcePath).getWorkingCopy(this.wcOwner, null);
+ assertProblems(
+ "Unexpected problems",
+ "----------\n" +
+ "1. ERROR in /Bug479389/src/nullAnalysis/X.java (at line 13)\n" +
+ " return in.stream().toArray(String[]::new);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Annotation type \'org.eclipse.jdt.annotation.NonNull\' cannot be found on the build path, which is implicitly needed for null analysis\n" +
+ "----------\n" );
+ } finally {
+ deleteProject(project);
+ }
+ }
}
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 594a60d7c3..257ec2f2fd 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true
-Bundle-Version: 3.20.100.qualifier
+Bundle-Version: 3.21.0.qualifier
Bundle-Activator: org.eclipse.jdt.core.JavaCore
Bundle-Vendor: %providerName
Bundle-Localization: plugin
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 1d1cf6752d..c65fb61253 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1837,6 +1837,8 @@ void setSourceStart(int sourceStart);
int RedundantNullCheckOnConstNonNullField = Internal + 944;
/** @since 3.20 */
int ConstNonNullFieldComparisonYieldsFalse = Internal + 945;
+ /** @since 3.21 */
+ int InheritedParameterLackingNonNullAnnotation = MethodRelated + 946;
/** @since 3.10 */
int ArrayReferencePotentialNullReference = Internal + 951;
@@ -1900,6 +1902,8 @@ void setSourceStart(int sourceStart);
int NonNullTypeVariableFromLegacyMethod = TypeRelated + 980;
/** @since 3.12 */
int NonNullMethodTypeVariableFromLegacyMethod = TypeRelated + 981;
+ /** @since 3.21 */
+ int MissingNullAnnotationImplicitlyUsed = Internal + 982;
// Java 8 work
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index ca9627ba32..71de6cf5eb 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
@@ -6058,7 +6058,7 @@ public class ClassFile implements TypeConstants, TypeIds {
private TypeBinding getNewTypeBinding(char[] typeConstantPoolName, Scope scope) {
char[] typeName = typeConstantPoolName;
- if (isLikelyLocalTypeName(typeName)) {
+ if (this.innerClassesBindings != null && isLikelyLocalTypeName(typeName)) {
// find local type in innerClassesBindings:
Set<TypeBinding> innerTypeBindings = this.innerClassesBindings.keySet();
for (TypeBinding binding : innerTypeBindings) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
index 5736ac48a4..cd4d6c53ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
@@ -81,6 +81,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
private static final int REPORTED_DEFINITIVE_LEAK = 64;
// a local declarations that acts as the element variable of a foreach loop (should never suggest to use t-w-r):
private static final int FOREACH_ELEMENT_VAR = 128;
+ public MessageSend acquisition;
public static boolean TEST_372319 = false; // see https://bugs.eclipse.org/372319
@@ -215,7 +216,10 @@ public class FakedTrackingVariable extends LocalDeclaration {
} else if (expression instanceof AllocationExpression) {
// return any preliminary tracking variable from analyseCloseableAllocation
return ((AllocationExpression) expression).closeTracker;
- }
+ } else if (expression instanceof MessageSend) {
+ // return any preliminary tracking variable from analyseCloseableAcquisition
+ return ((MessageSend) expression).closeTracker;
+ }
return null;
}
@@ -231,7 +235,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
* @param rhs the rhs of the assignment resp. the initialization of the local variable declaration.
* <strong>Precondition:</strong> client has already checked that the resolved type of this expression is either a closeable type or NULL.
*/
- public static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs, FlowInfo flowInfo) {
+ public static FakedTrackingVariable preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs, FlowInfo flowInfo) {
FakedTrackingVariable closeTracker = null;
if (containsAllocation(rhs)) {
closeTracker = local.closeTracker;
@@ -247,7 +251,18 @@ public class FakedTrackingVariable extends LocalDeclaration {
closeTracker.currentAssignment = location;
preConnectTrackerAcrossAssignment(location, local, flowInfo, closeTracker, rhs);
}
+ } else if (rhs instanceof MessageSend) {
+ closeTracker = local.closeTracker;
+ if (closeTracker != null) {
+ handleReassignment(flowInfo, closeTracker, location);
+ }
+ if (rhs.resolvedType != TypeBinding.NULL) { // not NULL means valid closeable as per method precondition
+ closeTracker = new FakedTrackingVariable(local, location, flowInfo, null, FlowInfo.UNKNOWN);
+ closeTracker.currentAssignment = location;
+ ((MessageSend) rhs).closeTracker = closeTracker;
+ }
}
+ return closeTracker;
}
private static boolean containsAllocation(SwitchExpression location) {
@@ -302,7 +317,9 @@ public class FakedTrackingVariable extends LocalDeclaration {
allocationExpression.closeTracker = closeTracker;
if (allocationExpression.arguments != null && allocationExpression.arguments.length > 0) {
// also push into nested allocations, see https://bugs.eclipse.org/368709
- preConnectTrackerAcrossAssignment(location, local, allocationExpression.arguments[0], flowInfo);
+ FakedTrackingVariable inner = preConnectTrackerAcrossAssignment(location, local, allocationExpression.arguments[0], flowInfo);
+ if (inner != closeTracker && closeTracker.innerTracker == null)
+ closeTracker.innerTracker = inner;
}
}
@@ -382,6 +399,56 @@ public class FakedTrackingVariable extends LocalDeclaration {
}
}
+ /**
+ * Check if a message send acquires a closeable from its receiver, see:
+ * Bug 463320 - [compiler][resource] potential "resource leak" problem disappears when local variable inlined
+ */
+ public static FlowInfo analyseCloseableAcquisition(BlockScope scope, FlowInfo flowInfo, MessageSend acquisition) {
+ if (isFluentMethod(acquisition.binding)) {
+ // share the existing close tracker of the receiver (if any):
+ acquisition.closeTracker = findCloseTracker(scope, flowInfo, acquisition.receiver);
+ return flowInfo;
+ }
+ // client has checked that the resolvedType is an AutoCloseable, hence the following cast is safe:
+ if (((ReferenceBinding)acquisition.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
+ // remove unnecessary attempts (closeable is not relevant)
+ if (acquisition.closeTracker != null) {
+ acquisition.closeTracker.withdraw();
+ acquisition.closeTracker = null;
+ }
+ return flowInfo;
+ } else { // regular resource
+ FakedTrackingVariable tracker = acquisition.closeTracker;
+ if (tracker != null) {
+ // pre-connected tracker means: directly assigning the acquisition to a local, forget special treatment:
+ tracker.withdraw();
+ acquisition.closeTracker = null;
+ return flowInfo;
+ } else {
+ tracker = new FakedTrackingVariable(scope, acquisition, flowInfo, FlowInfo.UNKNOWN); // no local available, closeable is unassigned
+ acquisition.closeTracker = tracker;
+ }
+ tracker.acquisition = acquisition;
+ FlowInfo outsideInfo = flowInfo.copy();
+ outsideInfo.markAsDefinitelyNonNull(tracker.binding);
+ flowInfo.markAsDefinitelyNull(tracker.binding);
+ return FlowInfo.conditional(outsideInfo, flowInfo);
+ }
+ }
+
+ private static boolean isFluentMethod(MethodBinding binding) {
+ if (binding.isStatic())
+ return false;
+ ReferenceBinding declaringClass = binding.declaringClass;
+ if (declaringClass.equals(binding.returnType)) {
+ for (char[][] compoundName : TypeConstants.FLUENT_RESOURCE_CLASSES) {
+ if (CharOperation.equals(compoundName, declaringClass.compoundName))
+ return true;
+ }
+ }
+ return false;
+ }
+
private static FakedTrackingVariable pickMoreUnsafe(FakedTrackingVariable tracker1, FakedTrackingVariable tracker2, BlockScope scope, FlowInfo info) {
// whichever of the two trackers has stronger indication to be leaking will be returned,
// the other one will be removed from the scope (considered to be merged into the former).
@@ -404,18 +471,22 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (presetTracker != null && presetTracker.originalBinding != null) {
// the current assignment forgets a previous resource in the LHS, may cause a leak
// report now because handleResourceAssignment can't distinguish this from a self-wrap situation
- int closeStatus = flowInfo.nullStatus(presetTracker.binding);
- if (closeStatus != FlowInfo.NON_NULL // old resource was not closed
- && closeStatus != FlowInfo.UNKNOWN // old resource had some flow information
- && !flowInfo.isDefinitelyNull(presetTracker.originalBinding) // old resource was not null
- && !(presetTracker.currentAssignment instanceof LocalDeclaration)) // forgetting old val in local decl is syntactically impossible
- allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus);
+ handleReassignment(flowInfo, presetTracker, presetTracker.currentAssignment);
} else {
allocation.closeTracker = new FakedTrackingVariable(scope, allocation, flowInfo, FlowInfo.UNKNOWN); // no local available, closeable is unassigned
}
flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding);
}
+ private static void handleReassignment(FlowInfo flowInfo, FakedTrackingVariable existingTracker, ASTNode location) {
+ int closeStatus = flowInfo.nullStatus(existingTracker.binding);
+ if (closeStatus != FlowInfo.NON_NULL // old resource was not closed
+ && closeStatus != FlowInfo.UNKNOWN // old resource had some flow information
+ && !flowInfo.isDefinitelyNull(existingTracker.originalBinding) // old resource was not null
+ && !(location instanceof LocalDeclaration)) // forgetting old val in local decl is syntactically impossible
+ existingTracker.recordErrorLocation(location, closeStatus);
+ }
+
/** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */
private static FakedTrackingVariable findCloseTracker(BlockScope scope, FlowInfo flowInfo, Expression arg)
{
@@ -438,6 +509,8 @@ public class FakedTrackingVariable extends LocalDeclaration {
} else if (arg instanceof AllocationExpression) {
// nested allocation
return ((AllocationExpression)arg).closeTracker;
+ } else if (arg instanceof MessageSend) {
+ return ((MessageSend) arg).closeTracker;
}
return null; // not a tracked expression
}
@@ -482,7 +555,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
rhsTrackVar.globalClosingState &= ~(SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR);
}
} else {
- if (rhs instanceof AllocationExpression || rhs instanceof ConditionalExpression || rhs instanceof SwitchExpression) {
+ if (rhs instanceof AllocationExpression || rhs instanceof ConditionalExpression || rhs instanceof SwitchExpression || rhs instanceof MessageSend) {
if (rhsTrackVar == disconnectedTracker)
return; // b.: self wrapper: res = new Wrap(res); -> done!
if (local.closeTracker == rhsTrackVar
@@ -645,6 +718,12 @@ public class FakedTrackingVariable extends LocalDeclaration {
tracker.withdraw();
((AllocationExpression) expression).closeTracker = null;
}
+ } else if (expression instanceof MessageSend) {
+ FakedTrackingVariable tracker = ((MessageSend) expression).closeTracker;
+ if (tracker != null && tracker.originalBinding == null) {
+ tracker.withdraw();
+ ((MessageSend) expression).closeTracker = null;
+ }
} else {
// assignment passing a local into a field?
LocalVariableBinding local = expression.localVariableBinding();
@@ -714,8 +793,13 @@ public class FakedTrackingVariable extends LocalDeclaration {
if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
return FlowInfo.POTENTIALLY_NULL; // non-null + doubt = pot null
return FlowInfo.NON_NULL;
- } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
+ } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) {
return FlowInfo.POTENTIALLY_NULL;
+ } else if (status == FlowInfo.UNKNOWN) {
+ // if unassigned resource (not having an originalBinding) is not withdrawn it is unclosed:
+ if (this.originalBinding == null)
+ return FlowInfo.NULL;
+ }
return status;
}
@@ -775,7 +859,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (owned) {
return infoResourceIsClosed; // don't let downstream signal any problems on this flow
} else {
- return FlowInfo.conditional(flowInfo, infoResourceIsClosed); // only report potential problems on this flow
+ return FlowInfo.conditional(flowInfo, infoResourceIsClosed).unconditionalCopy(); // only report potential problems on this flow
}
}
return flowInfo;
@@ -1003,6 +1087,10 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (isPotentialProblem) {
if ((this.globalClosingState & (REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK)) != 0)
return 0;
+// if ((this.globalClosingState & (ACQUIRED_FROM_OUTSIDE)) != 0
+// && location instanceof ReturnStatement
+// && ((ReturnStatement) location).expression == this.acquisition)
+// return 0; // directly returning a resource acquired from a message send: don't assume responsibility
problemReporter.potentiallyUnclosedCloseable(this, location);
} else {
if ((this.globalClosingState & (REPORTED_DEFINITIVE_LEAK)) != 0)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index ebf647586c..8f96fa7288 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -237,6 +237,7 @@ public class ForStatement extends Statement {
}
}
this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+ this.scope.checkUnclosedCloseables(mergedInfo, loopingContext, null, null);
return mergedInfo;
}
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 fe438b0220..07167e6b9c 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
@@ -131,11 +131,10 @@ public class ForeachStatement extends Statement {
if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy();
- if (this.action instanceof Block) {
- FakedTrackingVariable.markForeachElementVar(this.elementVariable);
- // action.analyseCode() missed the following check due to identical scopes of ForeachStatement and Block:
- this.scope.checkUnclosedCloseables(actionInfo, loopingContext, null, null);
- }
+ FakedTrackingVariable.markForeachElementVar(this.elementVariable);
+ // action.analyseCode() missed the following check due to identical scopes of ForeachStatement and action:
+ FlowInfo actionNullInfo = condInfo.copy().addNullInfoFrom(actionInfo); // previously action did not see nullinfo from condInfo
+ this.scope.checkUnclosedCloseables(actionNullInfo, loopingContext, null, null);
}
// code generation can be optimized when no need to continue in the loop
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 975c54713f..c93bc8a098 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
@@ -143,6 +143,7 @@ public class MessageSend extends Expression implements IPolyExpression, Invocati
public TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
public boolean argumentsHaveErrors = false;
+ public FakedTrackingVariable closeTracker;
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
@@ -242,6 +243,10 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// checkExceptionHandlers; consider protecting there instead of here;
// NullReferenceTest#test0510
}
+ // after having analysed exceptions above start tracking newly allocated resource:
+ if (analyseResources && FakedTrackingVariable.isAnyCloseable(this.resolvedType))
+ flowInfo = FakedTrackingVariable.analyseCloseableAcquisition(currentScope, flowInfo, this);
+
manageSyntheticAccessIfNecessary(currentScope, flowInfo);
// account for pot. exceptions thrown by method execution
flowContext.recordAbruptExit();
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 803240ddb7..42b9d2600a 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
@@ -6059,12 +6059,12 @@ public void multianewarray(
this.bCodeStream[this.classFileOffset++] = (byte) dimensions;
}
-// We didn't call it new, because there is a conflit with the new keyword
+// We didn't call it new, because there is a conflict with the new keyword
public void new_(TypeBinding typeBinding) {
this.new_(null, typeBinding);
}
-// We didn't call it new, because there is a conflit with the new keyword
+// We didn't call it new, because there is a conflict with the new keyword
public void new_(TypeReference typeReference, TypeBinding typeBinding) {
this.countLabels = 0;
this.stackDepth++;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java
index c2ef996a6c..a0fc8e25b3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrame.java
@@ -129,7 +129,7 @@ public class StackMapFrame {
return result;
}
- private VerificationTypeInfo getCachedValue(Map<VerificationTypeInfo, VerificationTypeInfo> cache, VerificationTypeInfo value) {
+ private static VerificationTypeInfo getCachedValue(Map<VerificationTypeInfo, VerificationTypeInfo> cache, VerificationTypeInfo value) {
VerificationTypeInfo cachedValue = value;
if (value != null) {
if (value.tag == VerificationTypeInfo.ITEM_UNINITIALIZED || value.tag == VerificationTypeInfo.ITEM_UNINITIALIZED_THIS) {
@@ -393,7 +393,7 @@ public class StackMapFrame {
return 0;
}
- private boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) {
+ private static boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) {
if (info == null) {
return info2 == null;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.java
index d3afd5ba1b..7f3be5a786 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/VerificationTypeInfo.java
@@ -195,14 +195,16 @@ public class VerificationTypeInfo {
public boolean equals(Object obj) {
if (obj instanceof VerificationTypeInfo) {
VerificationTypeInfo info1 = (VerificationTypeInfo) obj;
- return info1.tag == this.tag && CharOperation.equals(info1.constantPoolName(), constantPoolName());
+ return info1.tag == this.tag
+ && info1.offset == this.offset
+ && CharOperation.equals(info1.constantPoolName(), constantPoolName());
}
return false;
}
@Override
public int hashCode() {
- return this.tag + this.id + this.binding.constantPoolName().length;
+ return this.tag + this.offset + CharOperation.hashCode(constantPoolName());
}
public char[] constantPoolName() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index be247dbcdc..d0ff19b8d8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1930,11 +1930,9 @@ public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
}
// refine null bits requirements
if (!otherHasNulls) {
- if (resetLimit < mergeLimit) {
- resetLimit = mergeLimit;
- }
copyLimit = 0; // no need to carry inexisting nulls
mergeLimit = 0;
+ resetLimit = 0;
}
if (!thisHadNulls) {
resetLimit = 0; // no need to reset anything
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
index 9a0cdac9a8..8802c9d527 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
@@ -101,7 +101,7 @@ public static AnnotationBinding[] addStandardAnnotations(AnnotationBinding[] rec
}
private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] compoundName, ModuleBinding module, LookupEnvironment env) {
- ReferenceBinding type = env.getResolvedType(compoundName, module, null);
+ ReferenceBinding type = env.getResolvedType(compoundName, module, null, false);
// since this is a member type name using '$' the return binding is a
// problem reference binding with reason ProblemReasons.InternalNameProvided
if (!type.isValidBinding()) {
@@ -111,7 +111,7 @@ private static AnnotationBinding buildMarkerAnnotationForMemberType(char[][] com
}
private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, ModuleBinding module, LookupEnvironment env) {
- ReferenceBinding type = env.getResolvedType(compoundName, module, null);
+ ReferenceBinding type = env.getResolvedType(compoundName, module, null, false);
return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS);
}
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 03e6df4e54..96b41b2330 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
@@ -2098,7 +2098,7 @@ public ReferenceBinding superclass() {
}
this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()!
- this.typeBits |= applyCloseableClassWhitelists();
+ this.typeBits |= applyCloseableClassWhitelists(this.environment.globalOptions);
detectCircularHierarchy();
return this.superclass;
}
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 bf4ea57df6..a21beb4742 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
@@ -1167,8 +1167,19 @@ public void correlateTrackingVarsIfElse(FlowInfo thenFlowInfo, FlowInfo elseFlow
int trackVarCount = this.trackingVariables.size();
for (int i=0; i<trackVarCount; i++) {
FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
- if (trackingVar.originalBinding == null)
+ if (trackingVar.originalBinding == null) {
+ // avoid problem weakened to 'potential' if unassigned resource exists only in one branch:
+ boolean hasNullInfoInThen = thenFlowInfo.hasNullInfoFor(trackingVar.binding);
+ boolean hasNullInfoInElse = elseFlowInfo.hasNullInfoFor(trackingVar.binding);
+ if (hasNullInfoInThen && !hasNullInfoInElse) {
+ int nullStatus = thenFlowInfo.nullStatus(trackingVar.binding);
+ elseFlowInfo.markNullStatus(trackingVar.binding, nullStatus);
+ } else if (!hasNullInfoInThen && hasNullInfoInElse) {
+ int nullStatus = elseFlowInfo.nullStatus(trackingVar.binding);
+ thenFlowInfo.markNullStatus(trackingVar.binding, nullStatus);
+ }
continue;
+ }
if ( thenFlowInfo.isDefinitelyNonNull(trackingVar.binding) // closed in then branch
&& elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding)) // null in else branch
{
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 20937e3244..a4359d4f43 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
@@ -1019,7 +1019,7 @@ public class ClassScope extends Scope {
sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits);
// further analysis against white lists for the unlikely case we are compiling java.io.*:
if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
- sourceType.typeBits |= sourceType.applyCloseableClassWhitelists();
+ sourceType.typeBits |= sourceType.applyCloseableClassWhitelists(this.compilerOptions());
return true;
}
}
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 97e45e5d3b..f41bdba3a1 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -687,7 +687,7 @@ ImportBinding[] getDefaultImports() {
problemReporter().isClassPathCorrect(
TypeConstants.JAVA_LANG_OBJECT,
this.referenceContext,
- this.environment.missingClassFileLocation);
+ this.environment.missingClassFileLocation, false);
BinaryTypeBinding missingObject = this.environment.createMissingType(null, TypeConstants.JAVA_LANG_OBJECT);
importBinding = missingObject.fPackage;
}
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 95594bd7bb..8161215460 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2018 GK Software AG, IBM Corporation and others.
+ * Copyright (c) 2012, 2020 GK Software SE, IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -25,6 +25,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
/**
@@ -436,10 +437,13 @@ public class ImplicitNullAnnotationVerifier {
if (TypeBinding.equalsEquals(inheritedMethod.declaringClass, one.declaringClass) && getParameterNonNullness(one, i, useTypeAnnotations) != Boolean.TRUE)
continue parameterLoop;
}
- scope.problemReporter().parameterLackingNonnullAnnotation(
- currentArgument,
- inheritedMethod.declaringClass,
- annotationName);
+ if (currentArgument != null) {
+ scope.problemReporter().parameterLackingNonnullAnnotation(currentArgument, inheritedMethod.declaringClass, annotationName);
+ } else {
+ TypeDeclaration type = scope.classScope().referenceContext;
+ ASTNode location = type.superclass != null ? type.superclass : type;
+ scope.problemReporter().inheritedParameterLackingNonnullAnnotation(currentMethod, i+1, inheritedMethod.declaringClass, location, annotationName);
+ }
continue;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 071252f1e2..31bebbc4fb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1515,7 +1515,7 @@ public AnnotationBinding getNonNullAnnotation() {
if (this.root != this) {
return this.nonNullAnnotation = this.root.getNonNullAnnotation();
}
- ReferenceBinding nonNull = getResolvedType(this.globalOptions.nonNullAnnotationName, null);
+ ReferenceBinding nonNull = getResolvedType(this.globalOptions.nonNullAnnotationName, this.UnNamedModule, null, true);
return this.nonNullAnnotation = this.typeSystem.getAnnotationType(nonNull, true);
}
@@ -1623,11 +1623,11 @@ PackageBinding getPackage0(char[] name) {
* Fail with a classpath error if the type cannot be found.
*/
public ReferenceBinding getResolvedType(char[][] compoundName, Scope scope) {
- return getResolvedType(compoundName, scope == null ? this.UnNamedModule : scope.module(), scope);
+ return getResolvedType(compoundName, scope == null ? this.UnNamedModule : scope.module(), scope, false);
}
-public ReferenceBinding getResolvedType(char[][] compoundName, ModuleBinding moduleBinding, Scope scope) {
+public ReferenceBinding getResolvedType(char[][] compoundName, ModuleBinding moduleBinding, Scope scope, boolean implicitAnnotationUse) {
if (this.module != moduleBinding)
- return moduleBinding.environment.getResolvedType(compoundName, moduleBinding, scope);
+ return moduleBinding.environment.getResolvedType(compoundName, moduleBinding, scope, implicitAnnotationUse);
ReferenceBinding type = getType(compoundName, moduleBinding);
if (type != null) return type;
@@ -1636,11 +1636,11 @@ public ReferenceBinding getResolvedType(char[][] compoundName, ModuleBinding mod
this.problemReporter.isClassPathCorrect(
compoundName,
scope == null ? this.root.unitBeingCompleted : scope.referenceCompilationUnit(),
- this.missingClassFileLocation);
+ this.missingClassFileLocation, implicitAnnotationUse);
return createMissingType(null, compoundName);
}
public ReferenceBinding getResolvedJavaBaseType(char[][] compoundName, Scope scope) {
- return getResolvedType(compoundName, javaBaseModule(), scope);
+ return getResolvedType(compoundName, javaBaseModule(), scope, false);
}
/* Answer the top level package named name.
@@ -1757,7 +1757,7 @@ private ReferenceBinding getTypeFromCompoundName(char[][] compoundName, boolean
* misconfiguration now that did not also exist in some equivalent form while producing the class files which encode
* these missing types. So no need to bark again. Note that wasMissingType == true signals a type referenced in a .class
* file which could not be found when the binary was produced. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=364450 */
- this.problemReporter.isClassPathCorrect(compoundName, this.root.unitBeingCompleted, this.missingClassFileLocation);
+ this.problemReporter.isClassPathCorrect(compoundName, this.root.unitBeingCompleted, this.missingClassFileLocation, false);
}
// create a proxy for the missing BinaryType
binding = createMissingType(null, compoundName);
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 09aca3df68..cc10f62567 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
@@ -1430,7 +1430,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
this.superclass = (ReferenceBinding) Scope.substitute(this, genericSuperclass);
this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()!
- this.typeBits |= applyCloseableClassWhitelists();
+ this.typeBits |= applyCloseableClassWhitelists(this.environment.globalOptions);
}
return this.superclass;
}
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 f9aa45340a..12446b0c1c 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
@@ -2068,7 +2068,7 @@ public FieldBinding[] unResolvedFields() {
* If a type - known to be a Closeable - is mentioned in one of our white lists
* answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable).
*/
-protected int applyCloseableClassWhitelists() {
+protected int applyCloseableClassWhitelists(CompilerOptions options) {
switch (this.compoundName.length) {
case 3:
if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) {
@@ -2106,10 +2106,27 @@ protected int applyCloseableClassWhitelists() {
for (int i = 0; i < l; i++) {
if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i]))
return TypeIds.BitWrapperCloseable;
- }
+ }
+ if (options.analyseResourceLeaks) {
+ ReferenceBinding mySuper = this.superclass();
+ if (mySuper != null && mySuper.id != TypeIds.T_JavaLangObject) {
+ if (hasMethodWithNumArgs(TypeConstants.CLOSE, 0))
+ return 0; // close methods indicates: class may need more closing than super
+ return mySuper.applyCloseableClassWhitelists(options);
+ }
+ }
return 0;
}
+protected boolean hasMethodWithNumArgs(char[] selector, int numArgs) {
+ for (MethodBinding methodBinding : unResolvedMethods()) {
+ if (CharOperation.equals(methodBinding.selector, TypeConstants.CLOSE)
+ && methodBinding.parameters.length == numArgs) {
+ return true;
+ }
+ }
+ return false;
+}
/*
* If a type - known to be a Closeable - is mentioned in one of our white lists
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 657fef8264..1ccd6b5eb6 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
@@ -2369,6 +2369,27 @@ boolean hasNonNullDefaultFor(int location, int sourceStart) {
}
@Override
+protected boolean hasMethodWithNumArgs(char[] selector, int numArgs) {
+ if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
+ return super.hasMethodWithNumArgs(selector, numArgs);
+ // otherwise don't trigger unResolvedMethods() which would actually resolve!
+ if (this.scope != null) {
+ for (AbstractMethodDeclaration method : this.scope.referenceContext.methods) {
+ if (CharOperation.equals(method.selector, TypeConstants.CLOSE)) {
+ if (numArgs == 0) {
+ if (method.arguments == null)
+ return true;
+ } else {
+ if (method.arguments != null && method.arguments.length == numArgs)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+@Override
public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
if (!isPrototype())
return this.prototype.retrieveAnnotationHolder(binding, forceInitialization);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index e95c3461da..34dc674f0d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -47,6 +47,7 @@ public interface TypeConstants {
char[] JAVAX = "javax".toCharArray(); //$NON-NLS-1$
char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
char[] IO = "io".toCharArray(); //$NON-NLS-1$
+ char[] NIO = "nio".toCharArray(); //$NON-NLS-1$
char[] UTIL = "util".toCharArray(); //$NON-NLS-1$
char[] ZIP = "zip".toCharArray(); //$NON-NLS-1$
char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$
@@ -322,7 +323,27 @@ public interface TypeConstants {
"LongStream".toCharArray(), //$NON-NLS-1$
"IntStream".toCharArray() //$NON-NLS-1$
};
-
+
+ // closeable classes containing one or more 'fluent' methods (returning 'this'):
+ char[] CHANNELS = "channels".toCharArray(); //$NON-NLS-1$
+ char[][][] FLUENT_RESOURCE_CLASSES = {
+ new char[][] {JAVA, IO, "CharArrayWriter".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, IO, "Console".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, IO, "PrintStream".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, IO, "PrintWriter".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, IO, "StringWriter".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, IO, "Writer".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "AsynchronousFileChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "AsynchronousServerSocketChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "FileChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "NetworkChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "SeekableByteChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "SelectableChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "Selector".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, NIO, CHANNELS, "ServerSocketChannel".toCharArray() }, //$NON-NLS-1$
+ new char[][] {JAVA, UTIL, "Formatter".toCharArray() } //$NON-NLS-1$
+ };
+
// different assertion utilities:
char[] ASSERT_CLASS = "Assert".toCharArray(); //$NON-NLS-1$
char[][] ORG_ECLIPSE_CORE_RUNTIME_ASSERT = new char[][] { ORG, ECLIPSE, CORE, RUNTIME, ASSERT_CLASS };
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index fd4246da7d..9e4703051d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -123,7 +123,7 @@ ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericTo
environment.problemReporter.isClassPathCorrect(
this.compoundName,
environment.root.unitBeingCompleted,
- environment.missingClassFileLocation);
+ environment.missingClassFileLocation, false);
}
// create a proxy for the missing BinaryType
targetType = environment.createMissingType(null, this.compoundName);
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 3e2d5f223c..a467ed33e0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -483,6 +483,7 @@ public static int getIrritant(int problemID) {
return CompilerOptions.NonNullTypeVariableFromLegacyInvocation;
case IProblem.ParameterLackingNonNullAnnotation:
+ case IProblem.InheritedParameterLackingNonNullAnnotation:
return CompilerOptions.NonnullParameterAnnotationDropped;
case IProblem.RequiredNonNullButProvidedPotentialNull:
@@ -817,6 +818,7 @@ public static int getProblemCategory(int severity, int problemID) {
case IProblem.IsClassPathCorrect :
case IProblem.CorruptedSignature :
case IProblem.UndefinedModuleAddReads :
+ case IProblem.MissingNullAnnotationImplicitlyUsed :
return CategorizedProblem.CAT_BUILDPATH;
case IProblem.ProblemNotAnalysed :
return CategorizedProblem.CAT_UNNECESSARY_CODE;
@@ -5037,7 +5039,7 @@ public void illegalTypeAnnotationsInStaticMemberAccess(Annotation first, Annotat
first.sourceStart,
last.sourceEnd);
}
-public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl, Object location) {
+public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl, Object location, boolean implicitAnnotationUse) {
// ProblemReporter is not designed to be reentrant. Just in case, we discovered a build path problem while we are already
// in the midst of reporting some other problem, save and restore reference context thereby mimicking a stack.
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=442755.
@@ -5058,7 +5060,7 @@ public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclar
}
try {
this.handle(
- IProblem.IsClassPathCorrect,
+ implicitAnnotationUse ? IProblem.MissingNullAnnotationImplicitlyUsed : IProblem.IsClassPathCorrect,
arguments,
arguments,
start,
@@ -9895,7 +9897,8 @@ public void redundantSpecificationOfTypeArguments(ASTNode location, TypeBinding[
}
public void potentiallyUnclosedCloseable(FakedTrackingVariable trackVar, ASTNode location) {
String[] args = { trackVar.nameForReporting(location, this.referenceContext) };
- if (location == null) {
+ if (location == null || trackVar.acquisition != null) {
+ // if acquisition is set, the problem is not location specific
this.handle(
IProblem.PotentiallyUnclosedCloseable,
args,
@@ -10095,20 +10098,26 @@ public void parameterLackingNullableAnnotation(Argument argument, ReferenceBindi
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);
+ argument.type.sourceStart,
+ argument.type.sourceEnd);
+}
+public void inheritedParameterLackingNonnullAnnotation(MethodBinding currentMethod, int paramRank, ReferenceBinding specificationType,
+ ASTNode location, char[][] annotationName) {
+ this.handle(IProblem.InheritedParameterLackingNonNullAnnotation,
+ new String[] {
+ String.valueOf(paramRank), new String(currentMethod.readableName()),
+ new String(specificationType.readableName()), CharOperation.toString(annotationName)
+ },
+ new String[] {
+ String.valueOf(paramRank), new String(currentMethod.shortReadableName()),
+ new String(specificationType.shortReadableName()), new String(annotationName[annotationName.length-1])
+ },
+ location.sourceStart, location.sourceEnd
+ );
}
public void illegalParameterRedefinition(Argument argument, ReferenceBinding declaringClass, TypeBinding inheritedParameter) {
int sourceStart = argument.type.sourceStart;
@@ -10266,8 +10275,14 @@ public void expressionPotentialNullReference(ASTNode location) {
public void cannotImplementIncompatibleNullness(ReferenceContext context, MethodBinding currentMethod, MethodBinding inheritedMethod, boolean showReturn) {
int sourceStart = 0, sourceEnd = 0;
if (context instanceof TypeDeclaration) {
- sourceStart = ((TypeDeclaration) context).sourceStart;
- sourceEnd = ((TypeDeclaration) context).sourceEnd;
+ TypeDeclaration type = (TypeDeclaration) context;
+ if (type.superclass != null) {
+ sourceStart = type.superclass.sourceStart;
+ sourceEnd = type.superclass.sourceEnd;
+ } else {
+ sourceStart = type.sourceStart;
+ sourceEnd = type.sourceEnd;
+ }
}
String[] problemArguments = {
showReturn
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 5090c70970..98f799307e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2019 IBM Corporation and others.
+# Copyright (c) 2000, 2020 IBM Corporation and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
@@ -822,6 +822,7 @@
943 = Nullness default is redundant with a default specified for the enclosing module {0}
944 = Redundant null check: The field {0} is a nonnull constant
945 = Null comparison always yields false: The field {0} is a nonnull constant
+946 = Parameter {0} of method {1} lacks a @{3} annotation as specified in type {2}
951 = Potential null pointer access: array element may be null
@@ -855,7 +856,7 @@
979 = Null type safety: required ''@{0}'' but this expression has type ''{1}'', a free type variable that may represent a ''@{2}'' type
980 = Unsafe interpretation of method return type as ''@{0}'' based on the receiver type ''{1}''. Type ''{2}'' doesn''t seem to be designed with null type annotations in mind
981 = Unsafe interpretation of method return type as ''@{0}'' based on substitution ''{1}={2}''. Declaring type ''{3}'' doesn''t seem to be designed with null type annotations in mind
-
+982 = Annotation type ''{0}'' cannot be found on the build path, which is implicitly needed for null analysis
# Java 8
1001 = Syntax error, modifiers and annotations are not allowed for the lambda parameter {0} as its type is elided
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index 6862c2aad7..b26baced89 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -420,7 +420,7 @@ public class DefaultCodeFormatter extends CodeFormatter {
private void prepareLineBreaks() {
LineBreaksPreparator breaksPreparator = new LineBreaksPreparator(this.tokenManager, this.workingOptions);
this.astRoot.accept(breaksPreparator);
- breaksPreparator.finishUp();
+ breaksPreparator.finishUp(this.formatRegions);
this.astRoot.accept(new OneLineEnforcer(this.tokenManager, this.workingOptions));
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
index f9026bc18a..82c7c2da9e 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
@@ -88,6 +88,7 @@ import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions.Alignment;
import org.eclipse.jdt.internal.formatter.Token.WrapMode;
import org.eclipse.jdt.internal.formatter.Token.WrapPolicy;
+import org.eclipse.jface.text.IRegion;
public class LineBreaksPreparator extends ASTVisitor {
final private TokenManager tm;
@@ -156,8 +157,8 @@ public class LineBreaksPreparator extends ASTVisitor {
public boolean visit(TypeDeclaration node) {
handleBodyDeclarations(node.bodyDeclarations());
- if (node.getName().getStartPosition() == -1)
- return true; // this is a fake type created by parsing in class body mode
+ if (this.tm.isFake(node))
+ return true;
breakLineBefore(node);
@@ -192,9 +193,11 @@ public class LineBreaksPreparator extends ASTVisitor {
previous = bodyDeclaration;
}
if (previous != null) {
- Token lastToken = this.tm.lastTokenIn(previous.getParent(), -1);
- if (lastToken.tokenType == TokenNameRBRACE) // otherwise it's a fake type
+ ASTNode parent = previous.getParent();
+ if (!(parent instanceof TypeDeclaration && this.tm.isFake((TypeDeclaration) parent))) {
+ Token lastToken = this.tm.lastTokenIn(parent, -1);
putBlankLinesBefore(lastToken, this.options.blank_lines_after_last_class_body_declaration);
+ }
}
}
@@ -799,13 +802,35 @@ public class LineBreaksPreparator extends ASTVisitor {
this.tm.get(lastIndex + 1).unindent();
}
- public void finishUp() {
+ public void finishUp(List<IRegion> regions) {
// the visits only noted where indents increase and decrease,
- // now prepare actual indent values
- int currentIndent = this.options.initial_indentation_level;
+ // now prepare actual indent values, preserving indents outside formatting regions
+ int currentIndent = this.options.initial_indentation_level * this.options.indentation_size;
+ Token previous = null;
for (Token token : this.tm) {
- currentIndent += token.getIndent();
- token.setIndent(currentIndent * this.options.indentation_size);
+ if (isFixedLineStart(token, previous, regions)) {
+ currentIndent = this.tm.findSourcePositionInLine(token.originalStart);
+ } else {
+ currentIndent = Math.max(currentIndent + token.getIndent() * this.options.indentation_size, 0);
+ }
+ token.setIndent(currentIndent);
+ previous = token;
}
}
+
+ private boolean isFixedLineStart(Token token, Token previous, List<IRegion> regions) {
+ if (previous == null && this.options.initial_indentation_level >0)
+ return false; // must be handling ast rewrite
+ if (previous != null && this.tm.countLineBreaksBetween(previous, token) == 0)
+ return false;
+ int lineStart = token.originalStart;
+ char c;
+ while (lineStart > 0 && (c = this.tm.charAt(lineStart - 1)) != '\r' && c != '\n')
+ lineStart--;
+ for (IRegion r : regions) {
+ if (token.originalStart >= r.getOffset() && lineStart <= r.getOffset() + r.getLength())
+ return false;
+ }
+ return true;
+ }
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
index ed85e6593b..174eb37562 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
@@ -172,8 +172,8 @@ public class SpacePreparator extends ASTVisitor {
@Override
public boolean visit(TypeDeclaration node) {
- if (node.getName().getStartPosition() == -1)
- return true; // this is a fake type created by parsing in class body mode
+ if (this.tm.isFake(node))
+ return true;
handleToken(node.getName(), TokenNameIdentifier, true, false);
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
index 071f28286c..9a066adcab 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
@@ -29,6 +29,7 @@ import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression.Operator;
import org.eclipse.jdt.internal.formatter.Token.WrapMode;
import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor;
@@ -412,6 +413,11 @@ public class TokenManager implements Iterable<Token> {
return false;
}
+ public boolean isFake(TypeDeclaration node) {
+ // might be a fake type created by parsing in class body mode
+ return node.getName().getStartPosition() == -1;
+ }
+
public void addNLSAlignIndex(int index, int align) {
if (this.tokenIndexToNLSAlign == null)
this.tokenIndexToNLSAlign = new HashMap<Integer, Integer>();
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
index d3b453f58e..aa844603d6 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
@@ -35,6 +35,7 @@ import org.eclipse.jdt.internal.formatter.Token.WrapMode;
import org.eclipse.jdt.internal.formatter.Token.WrapPolicy;
import org.eclipse.jdt.internal.formatter.TokenManager;
import org.eclipse.jdt.internal.formatter.TokenTraverser;
+import org.eclipse.jface.text.IRegion;
public class WrapExecutor {
@@ -148,7 +149,7 @@ public class WrapExecutor {
if (token.hasNLSTag())
this.isNLSTagInLine = true;
- if (token.isWrappable()) {
+ if (token.isWrappable() && isInsideFormatRegion(token)) {
WrapPolicy wrapPolicy = token.getWrapPolicy();
if (wrapPolicy.wrapMode == WrapMode.TOP_PRIORITY && getLineBreaksBefore() == 0
&& index > this.currentTopPriorityGroupEnd) {
@@ -408,12 +409,14 @@ public class WrapExecutor {
final TokenManager tm;
final DefaultCodeFormatterOptions options;
+ final List<IRegion> regions;
private final WrapInfo wrapInfoTemp = new WrapInfo();
- public WrapExecutor(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
+ public WrapExecutor(TokenManager tokenManager, DefaultCodeFormatterOptions options, List<IRegion> regions) {
this.tm = tokenManager;
this.options = options;
+ this.regions = regions;
this.lineAnalyzer = new LineAnalyzer(tokenManager, options);
}
@@ -542,7 +545,8 @@ public class WrapExecutor {
if (!token.isWrappable()
|| (activeTopPriorityWrap >= 0 && i != activeTopPriorityWrap)
|| policiesTried.contains(wrapPolicy)
- || wrapPolicy.structureDepth >= depthLimit)
+ || wrapPolicy.structureDepth >= depthLimit
+ || !isInsideFormatRegion(token))
continue;
policiesTried.add(wrapPolicy);
@@ -674,6 +678,11 @@ public class WrapExecutor {
return result;
}
+ boolean isInsideFormatRegion(Token token) {
+ int pos = token.originalStart;
+ return this.regions.stream().anyMatch(r -> pos >= r.getOffset() && pos < r.getOffset() + r.getLength());
+ }
+
int getWrapIndent(Token token) {
WrapPolicy policy = token.getWrapPolicy();
if (policy == null)
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index b07e6bae1e..a67b5e0074 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -1286,7 +1286,7 @@ public class WrapPreparator extends ASTVisitor {
public void finishUp(ASTNode astRoot, List<IRegion> regions) {
preserveExistingLineBreaks();
applyBreaksOutsideRegions(regions);
- new WrapExecutor(this.tm, this.options).executeWraps();
+ new WrapExecutor(this.tm, this.options, regions).executeWraps();
this.aligner.alignComments();
wrapComments();
fixEnumConstantIndents(astRoot);
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index 7180de1a4c..a57fe11eed 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2019 Eclipse Foundation and others.
+ Copyright (c) 2012, 2020 Eclipse Foundation and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Distribution License v1.0
which accompanies this distribution, and is available at
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
- <version>3.20.100-SNAPSHOT</version>
+ <version>3.21.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<properties>
@@ -34,14 +34,14 @@
<execution>
<phase>prepare-package</phase>
<configuration>
- <tasks>
+ <target>
<replace token="bundle_qualifier," value="${buildQualifier}," dir="${project.build.directory}/classes">
<include name="org/eclipse/jdt/internal/compiler/batch/messages.properties"/>
</replace>
<replace token="bundle_version" value="${unqualifiedVersion}" dir="${project.build.directory}/classes">
<include name="org/eclipse/jdt/internal/compiler/batch/messages.properties"/>
</replace>
- </tasks>
+ </target>
</configuration>
<goals>
<goal>run</goal>

Back to the top