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

JDK API leaks despite source/target compatibility settings #620

Closed
mjshashank opened this issue Apr 11, 2018 · 8 comments
Closed

JDK API leaks despite source/target compatibility settings #620

mjshashank opened this issue Apr 11, 2018 · 8 comments
Assignees
Labels
Milestone

Comments

@mjshashank
Copy link

Does this Language Server support completions for Java 7 by any chance? If so, should the home key value change in the JavaConfiguration in the initializationOptions for initialize params suffice or is something else to be done as well?

@gorkem
Copy link
Contributor

gorkem commented Apr 12, 2018

java_home only effects the VM used to run the server and it needs to be Java 8 minimum. You can set the Java compatibility level for a project on the maven pom.xml or build.gradle file which will cause the language server to set correct compilation and code assist level.

@mjshashank
Copy link
Author

mjshashank commented Apr 13, 2018

I have a gradle.build file with the following contents in an otherwise empty project root

apply plugin: 'java'

version = 0.1.0
sourceCompatibility = 1.7

Then when I create a .java file with the following contents:

import java.util.HashMap;
import java.util.Map;

// Program to Increment a Map value in Java 8
class MapUtils
{
	public static<K> void increment(Map<K,Integer> map, K key) {
		Integer count = map.

It still provides me with getOrDefault(Object key, Integer defaultValue) : Integer at the line Integer count = map. as a valid completion which shouldn't be the case since it is a Java8 function.

Am I doing something wrong here?

@fbricon
Copy link
Contributor

fbricon commented Apr 13, 2018

Ok so this one is a bit tricky.

By default, JDT, regardless of the compilation options you provide, always leaks the JDK classes/methods of the JDK used to compile your project (but the same happens with a CLI build).

Now, if you were on a Mac AND Java 7 was installed in /Library/Java/JavaVirtualMachines, then jdt.ls would automatically pick it up and use it to provide compilation, content assist for your project, regardless of the Java version the server is started with. That'd solve your issue.

One possible fix for jdt.ls would probably be to expose some preferences to set some specific JDKs used for compilation.

possible workaround:
Because this issue also happens with pure javac from CLI, in Java 9 was introduced the release flag, which prevents API leaking when targeting a previous compilation level.

If jdt.ls is started with Java 9 (or higher), and is used to compile your projects, then there's a way to enable that release flag.
In your project's .settings/org.eclipse.jdt.core.prefs, add this line:

org.eclipse.jdt.core.compiler.release=enabled

Unfortunately, JDT would still leak Java 9 APIs during autocompletion (that's an upstream issue), but at least you'd get a compilation error as soon as the file is saved.

@fbricon fbricon added the bug label Apr 13, 2018
@fbricon fbricon changed the title Support for Java7 completions? JDK API leaks despite source/target compatibility settings Apr 13, 2018
@fbricon fbricon removed the question label Apr 13, 2018
@mjshashank
Copy link
Author

Okay, that clears up things, I'll look into the workaround. Thank you so much.

@fbricon
Copy link
Contributor

fbricon commented Apr 26, 2018

For Maven-based projects, this change in m2e will help.

For Gradle projects, one solution would be to make Gradle generate the project's .settings/org.eclipse.jdt.core.prefs so it contains

org.eclipse.jdt.core.compiler.release=enabled

Maybe Buildship can do it automatically? cc @donat

@fbricon
Copy link
Contributor

fbricon commented Jun 13, 2018

The more I think about it, the more I think we should probably set org.eclipse.jdt.core.compiler.release=enabled by default. This will ensure all JDK versions >= 9 won't leak their APIs when compiling against lower Java targets. The setting will be ignored when using JDK < 9.
I can't find any reason not to do it. @gorkem @tsmaeder WDYT?

@gorkem
Copy link
Contributor

gorkem commented Jun 13, 2018

Why is it even a setting if it does not have any side-effects

@fbricon
Copy link
Contributor

fbricon commented Jun 13, 2018

¯\(ツ)

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

No branches or pull requests

3 participants