From ddc93548229df592d9b95daaf061f992533dc82d Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sun, 24 Mar 2024 14:39:27 +0100 Subject: [PATCH] + resolve confusion about superclass/interface vs. current type --- .../compiler/lookup/BinaryTypeBinding.java | 4 +-- .../internal/compiler/lookup/ClassScope.java | 9 ++---- .../lookup/ParameterizedTypeBinding.java | 4 +-- .../compiler/lookup/ReferenceBinding.java | 27 +++++++++-------- .../regression/ResourceLeakTests.java | 30 ++++++++++++++----- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 87806b36676..d2c917ee2c7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -2477,7 +2477,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.environment.globalOptions); + this.typeBits |= applyCloseableWhitelists(this.environment.globalOptions); detectCircularHierarchy(); return this.superclass; } @@ -2566,7 +2566,7 @@ public ReferenceBinding[] superInterfaces() { } this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! - this.typeBits |= applyCloseableInterfaceWhitelists(this.environment.globalOptions); + this.typeBits |= applyCloseableWhitelists(this.environment.globalOptions); } this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces; return this.superInterfaces; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java index 70ab28d56e5..4c770913cf1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java @@ -1202,9 +1202,6 @@ private boolean connectSuperclass() { // only want to reach here when no errors are reported sourceType.setSuperClass(superclass); 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(this.compilerOptions()); return true; } } @@ -1458,9 +1455,6 @@ private boolean connectSuperInterfaces() { } // only want to reach here when no errors are reported sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits); - // further analysis against white lists for the unlikely case we are compiling java.util.stream.Stream: - if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) - sourceType.typeBits |= sourceType.applyCloseableInterfaceWhitelists(compilerOptions()); interfaceBindings[count++] = superInterface; } // hold onto all correctly resolved superinterfaces @@ -1479,6 +1473,9 @@ void connectTypeHierarchy() { environment().typesBeingConnected.add(sourceType); boolean noProblems = connectSuperclass(); noProblems &= connectSuperInterfaces(); + if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) { + sourceType.typeBits |= sourceType.applyCloseableWhitelists(compilerOptions()); + } environment().typesBeingConnected.remove(sourceType); sourceType.tagBits |= TagBits.EndHierarchyCheck; // connectPermittedTypes(); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 7ecbcad0d3b..166ec1560f3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -1516,7 +1516,7 @@ public ReferenceBinding superclass() { 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.environment.globalOptions); + this.typeBits |= applyCloseableWhitelists(this.environment.globalOptions); } return this.superclass; } @@ -1534,7 +1534,7 @@ public ReferenceBinding[] superInterfaces() { for (int i = this.superInterfaces.length; --i >= 0;) { this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! - this.typeBits |= applyCloseableInterfaceWhitelists(this.environment.globalOptions); + this.typeBits |= applyCloseableWhitelists(this.environment.globalOptions); } } } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 4fac878d543..d8a07a0ae42 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -2167,6 +2167,16 @@ protected int applyCloseableClassWhitelists(CompilerOptions options) { } } } + for (int i=0; i<3; i++) { + if (!CharOperation.equals(this.compoundName[i], TypeConstants.ONE_UTIL_STREAMEX[i])) { + return 0; + } + } + for (char[] streamName : TypeConstants.RESOURCE_FREE_CLOSEABLE_STREAMEX) { + if (CharOperation.equals(this.compoundName[3], streamName)) { + return TypeIds.BitResourceFreeCloseable; + } + } break; } int l = TypeConstants.OTHER_WRAPPER_CLOSEABLES.length; @@ -2199,7 +2209,11 @@ protected boolean hasMethodWithNumArgs(char[] selector, int numArgs) { } return false; } - +protected int applyCloseableWhitelists(CompilerOptions options) { + return isInterface() + ? applyCloseableInterfaceWhitelists(options) + : applyCloseableClassWhitelists(options); +} /* * 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). @@ -2218,17 +2232,6 @@ protected int applyCloseableInterfaceWhitelists(CompilerOptions options) { return TypeIds.BitResourceFreeCloseable; } } - } else { - for (int i=0; i<3; i++) { - if (!CharOperation.equals(this.compoundName[i], TypeConstants.ONE_UTIL_STREAMEX[i])) { - return 0; - } - } - for (char[] streamName : TypeConstants.RESOURCE_FREE_CLOSEABLE_STREAMEX) { - if (CharOperation.equals(this.compoundName[3], streamName)) { - return TypeIds.BitResourceFreeCloseable; - } - } } break; } 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 d9df255066d..0406c8b4cef 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 @@ -54,14 +54,28 @@ public class ResourceLeakTests extends AbstractRegressionTest { // one.util.streamex.StreamEx stub private static final String STREAMEX_JAVA = "one/util/streamex/StreamEx.java"; -private static final String STREAMEX_CONTENT = "package one.util.streamex;\n" + - "import java.util.stream.*;\n" + - "import java.util.function.*;\n" + - "public abstract class StreamEx implements Stream {\n" + - " public static StreamEx create() { return null; }\n" + - " public static StreamEx of(T element) { return null; }\n" + - " @Override public StreamEx flatMap(Function> mapper) { return null; }\n" + // from AbstractStreamEx - "}\n"; +private static final String STREAMEX_CONTENT = + """ + package one.util.streamex; + import java.util.Spliterator; + import java.util.stream.*; + import java.util.function.*; + public abstract class StreamEx extends AbstractStreamEx> { + public static StreamEx create() { return null; } + public static StreamEx of(T element) { return null; } + @Override public StreamEx flatMap(Function> mapper) { return null; } + } + abstract class AbstractStreamEx> extends + BaseStreamEx, Spliterator, S> implements Stream, Iterable { + @Override + public Spliterator spliterator() { + return null; + } + } + abstract class BaseStreamEx, SPLTR extends Spliterator, B extends BaseStreamEx> + implements BaseStream { + } + """; static { // TESTS_NAMES = new String[] { "testBug463320" };