Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eclipse 2024-03 reports unclosed closeable for whitelisted StreamEx #2199

Merged
merged 3 commits into from Mar 26, 2024

Conversation

stephan-herrmann
Copy link
Contributor

tests #2191

@stephan-herrmann
Copy link
Contributor Author

Mmmhhh,

testStreamEx_GH2919 - 1.8 14 ms Passed
testStreamEx_GH2919 - 11 11 ms Passed
testStreamEx_GH2919 - 17 11 ms Passed
testStreamEx_GH2919 - 21 13 ms Passed
testStreamEx_GH2919 - 22 14 ms Passed

@szarnekow do you see any difference between my test and your use case?

@szarnekow
Copy link
Contributor

@stephan-herrmann, thank you for investigating.

The error reproduces for me with this stub:

package one.util.streamex;

import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.BaseStream;
import java.util.stream.Stream;

public abstract class StreamEx<T> extends AbstractStreamEx<T, StreamEx<T>> {
	public static <T> StreamEx<T> of(T element) {
        return null;
    }
	public <R> StreamEx<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
        return null;
    }
}

abstract class AbstractStreamEx<T, S extends AbstractStreamEx<T, S>> extends
BaseStreamEx<T, Stream<T>, Spliterator<T>, S> implements Stream<T>, Iterable<T> {
	@Override
	public Spliterator<T> spliterator() {
		return null;
	}
}
abstract class BaseStreamEx<T, S extends BaseStream<T, S>, SPLTR extends Spliterator<T>, B extends BaseStreamEx<T, S, SPLTR, B>>
implements BaseStream<T, S> {
}

The test case can subsequently be simplified to

import one.util.streamex.StreamEx;
class Issue2191 {
	void whoot(Object obj) {
		// Potential resource leak: '<unassigned Closeable value>' may not be closed
		StreamEx.of(obj).toString();
	}

and

package one.util.streamex;

import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.Stream;

public abstract class StreamEx<T> extends Base<T> {
	public static <T> StreamEx<T> of(T element) {
		return null;
	}
}

abstract class Base<T> implements Stream<T> {
}

If we make the case a tiny bit more interesting:

package one.util.streamex;

import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.Stream;

public abstract class StreamEx<T> extends Base<T> {
	public static <T> StreamEx<T> of(T element) {
		return null;
	}

	public static <T> StreamEx<T> of(Spliterator<? extends T> spliterator) {
		return null;
	}

	@Override
	public <R> StreamEx<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
		return null;
	}

	public StreamEx<T> append(Stream<? extends T> other) {
		return null;
	}
}

abstract class Base<T> implements Stream<T> {
}

another warning pops up

import java.util.Spliterator;

import one.util.streamex.StreamEx;

class Issue2191 {
	Object puzzling(Object obj) {
		// Potential resource leak: '<unassigned Closeable value>' may not be closed
		return StreamEx.of(obj)
		.flatMap(container -> 
			// Resource leak: '<unassigned Closeable value>' is never closed
			StreamEx
				.of((Spliterator<Object>)null)
				.append(
						// Mandatory close of resource '<unassigned Closeable value>' has not been shown
						StreamEx.of((Spliterator<Object>)null)));
	}
}

The compiler settings I used:

Screenshot 2024-03-22 at 09 32 34

issue2191.zip

@stephan-herrmann
Copy link
Contributor Author

-	public abstract class StreamEx<T> implements Stream<T> {
+	public abstract class StreamEx<T> extends AbstractStreamEx<T, StreamEx<T>> {

Guess what: this innocent diff revealed a real blooper in our existing whitelist detection:

  • we have separate methods for detecting white listed interfaces vs classes
  • these methods are invoked when superclass or superInterfaces are resolved respectively
  • the methods, however, don't even look at a superclass or interface, but at the current type.

For source types the solution is simple: invoke the appropriate variant during connectTypeHierarch() (after super type resolving may have set BitAutoCloseable).

For binary types and parameterized types I didn't (yet) change the wiring into superclass() and superInterfaces(). The effect is that white list detection may happen twice (once from each method), but since the method is fast, and double invocation should not cause any harm, I'm leaving it at that for now.

@stephan-herrmann
Copy link
Contributor Author

Test failure is #2187

@stephan-herrmann stephan-herrmann merged commit 19e8e90 into eclipse-jdt:master Mar 26, 2024
8 of 9 checks passed
@stephan-herrmann stephan-herrmann deleted the issue2191 branch March 26, 2024 17:58
@szarnekow
Copy link
Contributor

@stephan-herrmann I installed the Eclipse batch compiler for Java from this update site: https://download.eclipse.org/eclipse/updates/4.32-I-builds/I20240403-0940/plugins/

I still see the same errors for usages of StreamEx. Should that build contain the fix?

@szarnekow
Copy link
Contributor

Ah, it seems I've to install the Eclipse Java Development Tools instead.

@stephan-herrmann
Copy link
Contributor Author

@stephan-herrmann I installed the Eclipse batch compiler for Java from this update site: https://download.eclipse.org/eclipse/updates/4.32-I-builds/I20240403-0940/plugins/

How can you use a plugins directory as an update site? For me that shows "No software site found at ..."

Ah, it seems I've to install the Eclipse Java Development Tools instead.

Did that help?

@szarnekow
Copy link
Contributor

@stephan-herrmann Yes, this helped.

Note that I used the wrong link (plugins subdir), I tried installing the batch compiler alone from the update site, but had to choose the correct feature. My bad. Everything's gucci now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants