Bug 418924: [dom ast] ASTRewrite should allow removing left and right operands of infix expression
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
index 8d2bf21..1f54e1e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
@@ -12,7 +12,6 @@
 import java.util.List;
 
 import junit.framework.Test;
-import junit.framework.TestSuite;
 
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IPackageFragment;
@@ -74,12 +73,6 @@
 		return new Suite(THIS);
 	}
 
-	public static Test setUpTest(Test someTest) {
-		TestSuite suite= new Suite("one test");
-		suite.addTest(someTest);
-		return suite;
-	}
-
 	public static Test suite() {
 		return allTests();
 	}
@@ -1034,6 +1027,88 @@
 
 	}
 
+	public void testInfixExpression2() throws Exception {
+		IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class E {\n");
+		buf.append("    public void foo() {\n");
+		buf.append("        i= 0 + 2;\n");
+		buf.append("        j= 1 + 0;\n");
+		buf.append("        k= 0 + 2 + 3 + 4 + 5;\n");
+		buf.append("        l= 1 + 0 + 3 + 4 + 5;\n");
+		buf.append("        m= 0 + 0 + 0 + 4 + 5;\n");
+		buf.append("    }\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("E.java", buf.toString(), false, null);
+	
+		CompilationUnit astRoot= createAST(cu);
+		ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
+	
+		assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0);
+		TypeDeclaration type= findTypeDeclaration(astRoot, "E");
+		MethodDeclaration methodDecl= findMethodDeclaration(type, "foo");
+		Block block= methodDecl.getBody();
+		List statements= block.statements();
+		{ // remove left side
+			ExpressionStatement stmt= (ExpressionStatement) statements.get(0);
+			Assignment assignment= (Assignment) stmt.getExpression();
+			InfixExpression expr= (InfixExpression) assignment.getRightHandSide();
+	
+			rewrite.remove(expr.getLeftOperand(), null);
+		}
+	
+		{ // remove right side
+			ExpressionStatement stmt= (ExpressionStatement) statements.get(1);
+			Assignment assignment= (Assignment) stmt.getExpression();
+			InfixExpression expr= (InfixExpression) assignment.getRightHandSide();
+	
+			rewrite.remove(expr.getRightOperand(), null);
+		}
+	
+		{ // remove left side (with extended operands)
+			ExpressionStatement stmt= (ExpressionStatement) statements.get(2);
+			Assignment assignment= (Assignment) stmt.getExpression();
+			InfixExpression expr= (InfixExpression) assignment.getRightHandSide();
+	
+			rewrite.remove(expr.getLeftOperand(), null);
+		}
+	
+		{ // remove right side (with extended operands)
+			ExpressionStatement stmt= (ExpressionStatement) statements.get(3);
+			Assignment assignment= (Assignment) stmt.getExpression();
+			InfixExpression expr= (InfixExpression) assignment.getRightHandSide();
+			
+			rewrite.remove(expr.getRightOperand(), null);
+		}
+		
+		{ // remove left, right, and extended operand
+			ExpressionStatement stmt= (ExpressionStatement) statements.get(4);
+			Assignment assignment= (Assignment) stmt.getExpression();
+			InfixExpression expr= (InfixExpression) assignment.getRightHandSide();
+			
+			rewrite.remove(expr.getLeftOperand(), null);
+			rewrite.remove(expr.getRightOperand(), null);
+			rewrite.remove((ASTNode) expr.extendedOperands().get(0), null);
+		}
+		
+		String preview= evaluateRewrite(cu, rewrite);
+	
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class E {\n");
+		buf.append("    public void foo() {\n");
+		buf.append("        i= 2;\n");
+		buf.append("        j= 1;\n");
+		buf.append("        k= 2 + 3 + 4 + 5;\n");
+		buf.append("        l= 1 + 3 + 4 + 5;\n");
+		buf.append("        m= 4 + 5;\n");
+		buf.append("    }\n");
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	
+	}
+
 	/** @deprecated using deprecated code */
 	public void testInstanceofExpression() throws Exception {
 		IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index bc30774..983e5f3 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -2466,15 +2466,43 @@
 			return doVisitUnchangedChildren(node);
 		}
 
-		int pos= rewriteRequiredNode(node, InfixExpression.LEFT_OPERAND_PROPERTY);
+		Expression right= node.getRightOperand();
+		int pos;
+		
+		RewriteEvent leftEvent= getEvent(node, InfixExpression.LEFT_OPERAND_PROPERTY);
+		boolean removeLeft = leftEvent != null && leftEvent.getChangeKind() == RewriteEvent.REMOVED;
+		RewriteEvent rightEvent= getEvent(node, InfixExpression.RIGHT_OPERAND_PROPERTY);
+		boolean removeRight = rightEvent != null && rightEvent.getChangeKind() == RewriteEvent.REMOVED;
+		
+		if (removeLeft) {
+			Expression left= node.getLeftOperand();
+			int leftStart= getExtendedOffset(left);
+			pos= getExtendedOffset(right);
+			TextEditGroup editGroup= getEditGroup(leftEvent);
+			doTextRemoveAndVisit(leftStart, pos - leftStart, left, editGroup);
+		} else {
+			pos = rewriteRequiredNode(node, InfixExpression.LEFT_OPERAND_PROPERTY);
+		}
 
 		boolean needsNewOperation= isChanged(node, InfixExpression.OPERATOR_PROPERTY);
 		String operation= getNewValue(node, InfixExpression.OPERATOR_PROPERTY).toString();
-		if (needsNewOperation) {
+		if (needsNewOperation && !removeLeft && !removeRight) {
 			replaceOperation(pos, operation, getEditGroup(node, InfixExpression.OPERATOR_PROPERTY));
 		}
 
-		pos= rewriteRequiredNode(node, InfixExpression.RIGHT_OPERAND_PROPERTY);
+		if (removeRight) {
+			int end;
+			if (removeLeft && node.extendedOperands().size() > 0) {
+				end= getExtendedOffset((Expression) node.extendedOperands().get(0));
+			} else {
+				end= getExtendedEnd(right);
+			}
+			TextEditGroup editGroup= getEditGroup(rightEvent);
+			doTextRemoveAndVisit(pos, end - pos, right, editGroup);
+			pos= end;
+		} else {
+			pos= rewriteRequiredNode(node, InfixExpression.RIGHT_OPERAND_PROPERTY);
+		}
 
 		RewriteEvent event= getEvent(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
 		String prefixString= ' ' + operation + ' ';