Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 415860

Summary: [1.8][compiler] EclipseCompiler should not hard code compliance level
Product: [Eclipse Project] JDT Reporter: Jay Arthanareeswaran <jarthana>
Component: CoreAssignee: Jay Arthanareeswaran <jarthana>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: anchakrk, markus.kell.r, Olivier_Thomann, sasikanth.bharadwaj, srikanth_sankaran, stephan.herrmann
Version: 4.3   
Target Milestone: BETA J9   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Bug Depends on:    
Bug Blocks: 414627    
Attachments:
Description Flags
Testcase
none
Patch for the fix
none
Patch for the fix
none
Patch accommodating review comments. none

Description Jay Arthanareeswaran CLA 2013-08-26 07:51:01 EDT
We have the following code in EclipseCompiler.java, which is our implementation of JavaCompiler:

  eclipseCompiler2.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
  eclipseCompiler2.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
  eclipseCompiler2.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);

There has to be a way clients, at least, JDT core tests that use this, can pass a different compliance level than this.

This is affecting the new tests I am planning to add as part of bug 414627.
Comment 1 Jay Arthanareeswaran CLA 2013-08-27 00:22:38 EDT
I also see this EclipseCompiler.java. Looks like this needs to be updated too. But wasn't touched for Java 7.


// Eclipse compiler supports all possible versions from version 0 to
		// version 6
		// we don't care about the order
EnumSet<SourceVersion> enumSet = EnumSet.range(SourceVersion.RELEASE_0, SourceVersion.RELEASE_6);

Olivier, can you throw some light on this, esp. the piece of code I shared in comment #0 ? Is it okay to set the compliance and source level to 1.8?
Comment 2 Srikanth Sankaran CLA 2013-08-27 01:39:09 EDT
(In reply to comment #0)
> We have the following code in EclipseCompiler.java, which is our
> implementation of JavaCompiler:
> 
>   eclipseCompiler2.options.put(CompilerOptions.OPTION_Compliance,
> CompilerOptions.VERSION_1_6);
>   eclipseCompiler2.options.put(CompilerOptions.OPTION_Source,
> CompilerOptions.VERSION_1_6);
>   eclipseCompiler2.options.put(CompilerOptions.OPTION_TargetPlatform,
> CompilerOptions.VERSION_1_6);
> 
> There has to be a way clients, at least, JDT core tests that use this, can
> pass a different compliance level than this.

Via org.eclipse.jdt.internal.compiler.tool.EclipseCompiler.run(InputStream, OutputStream, OutputStream, String...) ?
Comment 3 Olivier Thomann CLA 2013-08-27 09:07:31 EDT
If I remember well, this is related to the fact that this compiler had to be able to consume 1.6 annotation processors. As is it had to be at least 1.6 compliant. Any value above 1.6 should work.
Comment 4 Srikanth Sankaran CLA 2013-08-27 19:20:40 EDT
(In reply to comment #3)
> If I remember well, this is related to the fact that this compiler had to be
> able to consume 1.6 annotation processors. As is it had to be at least 1.6
> compliant. Any value above 1.6 should work.

I agree. Jay, we can fix this beginning Java 8 - since it is not material to
Java 7
Comment 5 Srikanth Sankaran CLA 2013-08-30 00:59:08 EDT
Jay, Anirban is looking for compiler items, assign this to him ?
Comment 6 Jay Arthanareeswaran CLA 2013-08-30 01:07:00 EDT
Anirban, please take this forward. This should take only couple of hours including testing. Let me know if you need any information on testing the fix.
Comment 7 Jay Arthanareeswaran CLA 2013-08-30 05:20:47 EDT
As Anirban just found out, SourceVersion.RELEASE_8 is available only in JDK 8 and to access the same, we need JDK 8 in the build path. I am not sure if there's another way.
Comment 8 Srikanth Sankaran CLA 2013-08-30 05:33:51 EDT
We should not hardcode again: See javax.lang.model.SourceVersion.latest() and javax.lang.model.SourceVersion.latestSupported()
Comment 9 Jay Arthanareeswaran CLA 2013-08-30 06:08:48 EDT
Created attachment 235027 [details]
Testcase

Patch that can be used as a test case. When this patch is applied on BETA_JAVA and org.eclipse.jdt.compiler.apt.tests.AllTests is run with b100, there should be just one failure. But now you would see an additional failure, which should go away when the fix is in place.
Comment 10 Jay Arthanareeswaran CLA 2013-08-30 08:23:55 EDT
(In reply to comment #9)
> Created attachment 235027 [details]
> Testcase
> 
> Patch that can be used as a test case. When this patch is applied on
> BETA_JAVA and org.eclipse.jdt.compiler.apt.tests.AllTests is run with b100,
> there should be just one failure. But now you would see an additional
> failure, which should go away when the fix is in place.

Forgot to mention this:
Whenever you make changes to the test files or the test APT processors in compiler.apt.tests, you must recreate a certain jar by running compiler.apt.tests\apttestprocessors.jardesc.
Comment 11 ANIRBAN CHAKRABORTY CLA 2013-08-30 16:56:33 EDT
Created attachment 235055 [details]
Patch for the fix

Hello,
Jay uploaded the testcase in the previous patch.
This patch represents the code change.
Thanks
Anirban
Comment 12 ANIRBAN CHAKRABORTY CLA 2013-09-01 14:41:23 EDT
Created attachment 235063 [details]
Patch for the fix

Hello,
Patch with dynamic assignment of latest supported source version.
Thanks
Anirban
Comment 13 Jay Arthanareeswaran CLA 2013-09-02 05:32:45 EDT
(In reply to ANIRBAN CHAKRABORTY from comment #12)
> Created attachment 235063 [details]
> Patch for the fix

Anirban, since you are not hard-coding the latest supported version, I think the move from JavaSE1.6 to JavaSE1.8 to the compiler.tool project is not necessary. Can you please remove that classpath change from the patch? Also please include the test case in the same patch.
Comment 14 Srikanth Sankaran CLA 2013-09-02 10:11:59 EDT
I thought I added this comment earlier, but it seems to be missing:

Please update the comment:

 		// Eclipse compiler supports all possible versions from version 0 to
 		// version 6
 		// we don't care about the order

that exists one line before the place which is changed by the patch, TIA.
Comment 15 ANIRBAN CHAKRABORTY CLA 2013-09-03 18:03:53 EDT
Created attachment 235124 [details]
Patch accommodating review comments.

Patch accommodating review comments.
Comment 17 Markus Keller CLA 2013-09-05 14:24:17 EDT
This change broke org.eclipse.jdt.compiler.tool.tests.AllTests.

You also have to update the bundle version in MANIFEST.MF and pom.xml to 1.0.300 (for both the production and the test bundle), and you should add the 1.8/8/8.0 to the static initializer in org.eclipse.jdt.internal.compiler.tool.Options


(In reply to Srikanth Sankaran from comment #8)
> We should not hardcode again: See javax.lang.model.SourceVersion.latest()
> and javax.lang.model.SourceVersion.latestSupported()

I don't think that change was correct. Doesn't that mean a org.eclipse.jdt.compiler.tool.jar compiled today will include 1.9 when it is run with a 1.9 EE? And it would say it's not able to compile 1.8 source code if it's running on a 1.7 EE.

The org.eclipse.jdt.compiler.tool bundle should stay at BREE 1.6, and the EclipseCompiler should use other means to find the latest supported releases > 6. The EnumSet.range(..) is also a bit scary, since it assumes the order of enum constants is immutable. JLS7 13.4.26 explicitly allows reordering of constants, so I wouldn't say it's safe to rely on the declaration order.

We should use explicit references to SourceVersion.RELEASE_0-6 and use SourceVersion.valueOf("RELEASE_7") etc. for later versions (catch the IAE if we're running on a 1.6 EE).
Comment 18 Jay Arthanareeswaran CLA 2013-09-06 00:52:21 EDT
(In reply to Markus Keller from comment #17)
> The EnumSet.range(..) is also a bit scary, since it assumes the order
> of enum constants is immutable. JLS7 13.4.26 explicitly allows reordering of
> constants, so I wouldn't say it's safe to rely on the declaration order.


The EnumSet's javadoc has this:

"The iterator returned by the iterator method traverses the elements in their natural order (the order in which the enum constants are declared). "

This combined with the unmodifiable collection should be good enough, isn't it?
Comment 19 Jay Arthanareeswaran CLA 2013-09-06 01:14:31 EDT
Looks like the following code has problem too:

eclipseCompiler2.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);

We need something like this:

		String compilerVersion = null;
		try {
			SourceVersion.valueOf("RELEASE_8"); //$NON-NLS-1$
			compilerVersion = CompilerOptions.VERSION_1_8;
			
		} catch (IllegalArgumentException iae) {
			compilerVersion = CompilerOptions.VERSION_1_6;
		}
		eclipseCompiler2.options.put(CompilerOptions.OPTION_Compliance, compilerVersion);
		....

But even that's not going to be enough because some of the tests are hard-coding the JDK level, like this:

assertEquals("Wrong value", ClassFileConstants.JDK1_6, reader.getVersion());
Comment 20 Jay Arthanareeswaran CLA 2013-09-06 01:32:44 EDT
(In reply to Srikanth Sankaran from comment #2)
> > There has to be a way clients, at least, JDT core tests that use this, can
> > pass a different compliance level than this.
> 
> Via org.eclipse.jdt.internal.compiler.tool.EclipseCompiler.run(InputStream,
> OutputStream, OutputStream, String...) ?

Looks like the tests are not passing the compliance level at all and relying on the EclipseCompiler to set it to 1_6. And as I mentioned in comment #19, the always expect the code to be compiled at 1.6 :(
Comment 21 Jay Arthanareeswaran CLA 2013-09-06 06:21:44 EDT
I have reverted the changes made by commit b40a58ab0876d24632a275ef1be808b26bd863a5 to avoid the failures. I figured we can force the compliance level from the tests directly (even though we are not doing it at the moment and relying on EclipseCompiler to hard-code 1.6). We will run into this problem pretty soon when we have to add annotation processors with 1.8 support.
Comment 22 Markus Keller CLA 2013-09-06 06:55:18 EDT
(In reply to Jayaprakash Arthanareeswaran from comment #18)
If you assume that the order of declarations in the SourceVersion enum won't change, then everything is safe. But my point is that nothing prevents the maintainers of that class from changing the declaration order (neither a Javadoc contract nor binary compatibility rules). Therefore, EnumSet.range(..) is unsafe, unless the order of declarations is guaranteed to be stable.

Like the Oracle Java 7 JRE could "legally" change the order in Class#getDeclaredMethods(), this could also apply here (without breaking any rules). Or they could add RELEASE_7_JIGSAW between RELEASE_7 and RELEASE_8, and if we use a range, we would wrongly include it.
Comment 23 Srikanth Sankaran CLA 2013-09-29 12:59:02 EDT
Jay, what do you recommend as the way forward ?
Comment 24 Jay Arthanareeswaran CLA 2013-09-30 01:07:36 EDT
Earlier, I thought there is no way for our tests to override the 1.6 level that is set as default. But I figured there is a way the tests can override this by just adding "-1.8" to the options before invoking the compiler.

So, I guess we don't need do anything here, at least for the time being.
Comment 25 Jay Arthanareeswaran CLA 2017-08-07 02:51:18 EDT
It is about time we reopen and fix this. Looks like Javac has moved ahead with the default compliance to the latest but we (ECJ through JSR 199) are still stuck at 1.6.
Comment 26 Jay Arthanareeswaran CLA 2017-08-08 03:11:07 EDT
Resolved via:

http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA9&id=6af4a0a291a362228d60748995c15e8fd3464cbc

At the moment, the latest supported is still at 1.8, as we have no reliable way of supporting the constant 9 without moving ourselves to compliance 9. But the hard coding of the latest compliance level has been fixed along with the affected tests.