Bug 105192

Summary: NaiveASTFlattener incorrectly renders a for statement with multiple initializers or multiple updaters
Product: [Eclipse Project] JDT Reporter: David Cok <david.cok>
Component: CoreAssignee: Olivier Thomann <Olivier_Thomann>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: 3.1   
Target Milestone: 3.2 M1   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description David Cok CLA 2005-07-26 13:37:11 EDT
The following code:

String input = "class T { void m() { for (i=0, j=0; i<10; i++, j++) ; }}";
    org.eclipse.jdt.core.dom.ASTParser p = 
org.eclipse.jdt.core.dom.ASTParser.newParser(org.eclipse.jdt.core.dom.AST.JLS3);
    p.setSource(input.toCharArray());
    org.eclipse.jdt.core.dom.ASTNode a = p.createAST(null);
    System.out.println("input = " + input);
    System.out.println("output = " + a.toString());

produces

input = class T { void m() { for (i=0, j=0; i<10; i++, j++) ; }}
output = class T {
  void m(){
    for (i=0j=0; i < 10; i++j++)     ;
  }
}

Note the lack of commas (and a bit of space) in the rendering of the for 
statement.

The problem is in  org.eclipse.jdt.core.dom.NaiveASTFlattener:

	public boolean visit(ForStatement node) {
		printIndent();
		this.buffer.append("for (");//$NON-NLS-1$
		for (Iterator it = node.initializers().iterator(); it.hasNext
(); ) {
			Expression e = (Expression) it.next();
			e.accept(this);
		}
		this.buffer.append("; ");//$NON-NLS-1$
		if (node.getExpression() != null) {
			node.getExpression().accept(this);
		}
		this.buffer.append("; ");//$NON-NLS-1$
		for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
			Expression e = (Expression) it.next();
			e.accept(this);
		}
		this.buffer.append(") ");//$NON-NLS-1$
		node.getBody().accept(this);
		return false;
	}

The loops for initializers and updaters need correcting, something like

	public boolean visit(ForStatement node) {
		printIndent();
		this.buffer.append("for (");//$NON-NLS-1$
		for (Iterator it = node.initializers().iterator(); it.hasNext
(); ) {
			Expression e = (Expression) it.next();
			e.accept(this);
                        if (it.hasNext()) buffer.append(", ");
		}
		this.buffer.append("; ");//$NON-NLS-1$
		if (node.getExpression() != null) {
			node.getExpression().accept(this);
		}
		this.buffer.append("; ");//$NON-NLS-1$
		for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
			Expression e = (Expression) it.next();
			e.accept(this);
                        if (it.hasNext()) buffer.append(", ");
		}
		this.buffer.append(") ");//$NON-NLS-1$
		node.getBody().accept(this);
		return false;
	}
Comment 1 Olivier Thomann CLA 2005-07-27 09:07:54 EDT
Fixed and released in HEAD.
Regression test added in
org.eclipse.jdt.core.tests.dom.ASTConverterTestAST3_2.test0614.

Note that this is for debug purpose only. You should not use the result of
toString() on a ASTNode to serialize your DOM compilation unit. To do that, you
should use the rewrite infrastructure.
Comment 2 Jerome Lanneluc CLA 2005-08-09 06:32:18 EDT
Verified with I20050808-2000 that the rendering contains the semi-colons. It
still contains extra spaces, but as Olivier said the toString() is for debugging
purpose only.