Bug 203342 - AST of a NumberLiteral has wrong source code range
Summary: AST of a NumberLiteral has wrong source code range
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.4   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M2   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-09-13 14:36 EDT by Genady Beryozkin CLA
Modified: 2007-09-19 20:20 EDT (History)
2 users (show)

See Also:


Attachments
Proposed fix (2.83 KB, patch)
2007-09-14 10:50 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Genady Beryozkin CLA 2007-09-13 14:36:30 EDT
Build ID: 3.4 - I20070911-0833

For double literal "0x0.0000000000001P-1022", as in 

public static final double VAR = 0x0.0000000000001P-1022; 

the lenght of the AST NumberLiteral is set to 3.

After little debugging I found that it it initially set to the correct length of 23, and then set to 3 by the
ASTConverter.removeLeadingAndTrailingCommentsFromLiteral() method.
Comment 1 Olivier Thomann CLA 2007-09-13 14:56:35 EDT
I cannot reproduce with HEAD.
Are you sure that your project settings are 1.5 ?
Comment 2 Olivier Thomann CLA 2007-09-13 15:01:29 EDT
I tried this test case and the number literal positions look good.
======================================
public class X {
	public static final double VAR = 0x0.0000000000001P-1022;
}
======================================

I also tried with comments before and after the field, without more success.
Comment 3 Olivier Thomann CLA 2007-09-13 15:19:39 EDT
Added disabled test org.eclipse.jdt.core.tests.dom.ASTConverter15Test#_test0284.
Please provide a patch with a test case that fails.
Comment 4 Olivier Thomann CLA 2007-09-13 15:23:28 EDT
If I get a test case in time, this could potentially be fixed for 3.4M2.
Comment 5 Genady Beryozkin CLA 2007-09-13 15:31:38 EDT
ok, one moment. I'll try to reproduce it programmatically.
Comment 6 Genady Beryozkin CLA 2007-09-13 15:42:47 EDT
	private void testAST() {
		ASTParser parser = ASTParser.newParser(AST.JLS3);
		String code= "\r\n" + 
				"public class ThisClass {\r\n" + 
				"\r\n" + 
				"	public static final long VAL = 100L + \r\n" + 
				"			20L" + 
				"	public static final double XO = 0x0.0000000000001P-1022; \r\n" + 
				"}\r\n" + 
				"";
		parser.setSource(code.toCharArray());
		
		CompilationUnit u = (CompilationUnit) parser.createAST(null);
		ASTNode nd = ASTNodeSearchUtil.getAstNode(u, code.indexOf("0x0"), 23);
		System.out.println(nd.getLength());
	}
Comment 7 Genady Beryozkin CLA 2007-09-13 15:52:04 EDT
And without ASTNodeSearchUtil:

		ASTParser parser = ASTParser.newParser(AST.JLS3);
		String code= "\r\n" + 
				"public class ThisClass {\r\n" + 
				"\r\n" + 
				"	public static final long VAL = 100L + \r\n" + 
				"			20L" + 
				"	public static final double XO = 0x0.0000000000001P-1022; \r\n" + 
				"}\r\n" + 
				"";
		parser.setSource(code.toCharArray());
		
		CompilationUnit u = (CompilationUnit) parser.createAST(null);
		FieldDeclaration field = 
			(FieldDeclaration) ((org.eclipse.jdt.core.dom.AbstractTypeDeclaration) u.types().get(0)).bodyDeclarations().get(1);
		VariableDeclarationFragment fr = (VariableDeclarationFragment)field.fragments().get(0);
		Expression e = fr.getInitializer();
		System.out.println(e.getLength());


--
That prints 3 for me.
Comment 8 Olivier Thomann CLA 2007-09-13 19:08:02 EDT
Isn't this related to the missing ';' at the end of the first field declaration?
I'll investigate.
Comment 9 Genady Beryozkin CLA 2007-09-13 19:16:50 EDT
Missed the semicolon in the test case. 
But that doesn't change the result.
Comment 10 Olivier Thomann CLA 2007-09-13 19:28:44 EDT
The problem comes from the fact that the AST parser is not set to use 1.5 options.
If you add this code:
        Map options = new HashMap();
        options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_5);
        options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
        options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
        parser.setCompilerOptions(options);

it works as expected.

Note that with our code, you do have an error on the field you are looking at. The ASTParser is scanning the code using a 1.4 scanner which doesn't know how to read hexadecimal floating point literals.

Ok to close?
Comment 11 Genady Beryozkin CLA 2007-09-13 19:47:17 EDT
Ok, it works for me with the compiler options (isn't JLS3 enough?).

So now it is probably an enhancement request:
But if you manage to parse the source code, why do you need to forcefully
chop the source of the value? If there is an error, the user won't mind about getting the full initialization, right?

With the semicolon in place, I also tried to check compilation unit's messages and problems and both returned arrays were empty.
Comment 12 Olivier Thomann CLA 2007-09-13 19:54:23 EDT
With this code:
ASTParser parser = ASTParser.newParser(AST.JLS3);
	        String code= "\r\n" + 
	                        "public class ThisClass {\r\n" + 
	                        "\r\n" + 
	                        "       public static final long VAL = 100L +\r\n" + 
	                        "                       20L;" + 
	                        "       public static final double XO = 0x0.0000000000001P-1022; \r\n" + 
	                        "}\r\n" + 
	                        "";
	        parser.setSource(code.toCharArray());
/*	        Map options = new HashMap();
	        options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_5);
	        options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
	        options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
	        parser.setCompilerOptions(options);*/
	        CompilationUnit u = (CompilationUnit) parser.createAST(null);
	        System.out.println("" + u.getProblems().length + " problems");
	        FieldDeclaration field = 
	                (FieldDeclaration)
	((org.eclipse.jdt.core.dom.AbstractTypeDeclaration)
	u.types().get(0)).bodyDeclarations().get(1);
	        VariableDeclarationFragment fr =
	(VariableDeclarationFragment)field.fragments().get(0);
	        Expression e = fr.getInitializer();
	        System.out.println(e.getLength());

I do get a problem in the compilation problems array.
Also the javadoc of ASTParser.setCompilerOptions(Map) is pretty clear about the defaults.
JLS3 is more about the shape of the resulting tree.
Comment 13 Genady Beryozkin CLA 2007-09-14 03:40:06 EDT
I think I found the difference. If the workbench settings are Java6.0 and the default complience box is checked, I get the behavior I've described (and no errors).
If I uncheck the "use defaults" box it and set the source code level to 5.0 I get the correct behavior. If the default compliance level is 5.0, parsing works ok too. If the workbench compliance level is set to 1.4 I get the error which is also ok.
Comment 14 Olivier Thomann CLA 2007-09-14 09:52:01 EDT
(In reply to comment #13)
> I think I found the difference. If the workbench settings are Java6.0 and the
> default complience box is checked, I get the behavior I've described (and no
> errors).
This would be a bug. I'll try to reproduce.

> If I uncheck the "use defaults" box it and set the source code level to 5.0 I
> get the correct behavior. If the default compliance level is 5.0, parsing works
> ok too. If the workbench compliance level is set to 1.4 I get the error which
> is also ok.
So this seems to be acceptable.

Let me know if I misunderstood, but only the first case should be investigated. Right?
Comment 15 Olivier Thomann CLA 2007-09-14 09:54:35 EDT
Reproduced the first case.
I am investigating.
Comment 16 Genady Beryozkin CLA 2007-09-14 10:12:32 EDT
Yes, only the first case is problematic. In the real code (patch for bug 85382) I have a compilation unit which should carry the appropriate compiler options.

Maybe the documentation of ASTParser can be improved to stress that the compiler options affect the parsing. For example, the top level comment says 

<code>
ASTParser parser = ASTParser.newParser(AST.JLS3);  // handles JDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
</code>

and it can be understood that using JLS3 is enough to parse 5.0 syntax.

Another place where the need for compiler options could be documented is in the newParser() method.
Comment 17 Olivier Thomann CLA 2007-09-14 10:16:07 EDT
The problem comes from the inner scanner. It was not set to "scan" in 1.6 mode.
So it missed part of the floating point literal.
Fix is under testing.
Thanks for the test case and the time you spent on this issue.

You are right about the documentation. I'll see what I can do for this.
Comment 18 Olivier Thomann CLA 2007-09-14 10:42:38 EDT
I added this comment in the header of ASTParser:
This is especially important to use if the parsing/scanning of the source code requires a different version than the default of the workspace. For example, the workspace defaults are 1.4 and you want to create an AST for a source code that is using 1.5 constructs.

Hopefully this is clear enough now.

Tests are running. As soon as they passed, I'll release the fix.
Comment 19 Olivier Thomann CLA 2007-09-14 10:50:00 EDT
Created attachment 78435 [details]
Proposed fix
Comment 20 Olivier Thomann CLA 2007-09-14 15:39:42 EDT
Released for 3.4M2.
Regression test added in org.eclipse.jdt.core.tests.dom.ASTConverter16Test#test0001
Comment 21 Genady Beryozkin CLA 2007-09-14 16:02:31 EDT
Thanks for the quick fix!
Comment 22 Olivier Thomann CLA 2007-09-14 17:03:41 EDT
This was well deserved after all the help you provided.
If you could test the 3.4M2 warmup build to provide feedback on this one, it would be great.
Comment 23 David Audel CLA 2007-09-18 11:18:52 EDT
Verified for 3.4M2 using build I20070918-0010
Comment 24 Genady Beryozkin CLA 2007-09-19 20:20:37 EDT
Works for me too.