blob: 36fa6924ae8caa749d9a49cc35a647d3bcd8f9b5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2019 Mateusz Matela and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Mateusz Matela <mateusz.matela@gmail.com> - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070
* Mateusz Matela <mateusz.matela@gmail.com> - [toString] Wrong code generated with String concatenation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=275360
* Red Hat Inc. - moved to jdt.core.manipulation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.InfixExpression.Operator;
/**
* <p>
* Implementation of <code>AbstractToStringGenerator</code> that creates <code>toString()</code>
* method by concatenating <code>String</code>s
* </p>
* <p>
* Generated methods look like this:
*
* <pre>
* public String toString() {
* return &quot;FooClass( field1=&quot; + field1 + &quot;, field2=&quot; + field2 + &quot;, method1()=&quot; + method1 + &quot;)&quot;;
* }
* </pre>
*
* </p>
*
* @since 3.5
*/
public class StringConcatenationGenerator extends AbstractToStringGenerator {
private class SumExpressionBuilder {
private Expression expression;
private StringBuffer buffer;
public SumExpressionBuilder(Expression expression) {
this.expression= expression;
buffer= new StringBuffer();
}
public Expression getExpression() {
flushBuffer();
return expression;
}
private void flushBuffer() {
if (buffer.length() > 0) {
StringLiteral bufferedStringLiteral= fAst.newStringLiteral();
bufferedStringLiteral.setLiteralValue(buffer.toString());
buffer.setLength(0);
expression= createSumExpression(expression, bufferedStringLiteral);
}
}
public void addString(String string) {
buffer.append(string);
}
public void addExpression(Expression exp) {
flushBuffer();
expression= createSumExpression(expression, exp);
}
}
private SumExpressionBuilder toStringExpressionBuilder;
@Override
protected void initialize() {
super.initialize();
toStringExpressionBuilder= new SumExpressionBuilder(null);
}
@Override
protected void complete() throws CoreException {
super.complete();
ReturnStatement returnStatement= fAst.newReturnStatement();
returnStatement.setExpression(toStringExpressionBuilder.getExpression());
toStringMethod.getBody().statements().add(returnStatement);
}
@Override
protected void addElement(Object element) {
addElement(element, toStringExpressionBuilder);
}
private void addElement(Object element, SumExpressionBuilder builder) {
if (element instanceof String) {
builder.addString((String)element);
}
if (element instanceof Expression) {
Expression expr= (Expression)element;
if (expr instanceof ConditionalExpression) {
ParenthesizedExpression expr2= fAst.newParenthesizedExpression();
expr2.setExpression(expr);
expr= expr2;
}
builder.addExpression(expr);
}
}
@Override
protected void addMember(Object member, boolean addSeparator) {
boolean[] interfaces= implementsInterfaces(getMemberType(member).getErasure(), new String[] { "java.util.Collection", "java.util.Map" }); //$NON-NLS-1$ //$NON-NLS-2$
if (getContext().isLimitItems() && getContext().isSkipNulls() && (interfaces[0] || interfaces[1] || getMemberType(member).isArray())) {
addMemberCheckNull(member, addSeparator);
} else {
super.addMember(member, addSeparator);
}
}
@Override
protected void addMemberCheckNull(Object member, boolean addSeparator) {
ConditionalExpression cExpression= fAst.newConditionalExpression();
// member != null ?
InfixExpression infExpression= fAst.newInfixExpression();
infExpression.setLeftOperand(createMemberAccessExpression(member, true, true));
infExpression.setRightOperand(fAst.newNullLiteral());
infExpression.setOperator(Operator.NOT_EQUALS);
cExpression.setExpression(infExpression);
SumExpressionBuilder builder= new SumExpressionBuilder(null);
String[] arrayString= getContext().getTemplateParser().getBody();
for (int i= 0; i < arrayString.length; i++) {
addElement(processElement(arrayString[i], member), builder);
}
if (addSeparator)
addElement(getContext().getTemplateParser().getSeparator(), builder);
cExpression.setThenExpression(builder.getExpression());
StringLiteral literal= fAst.newStringLiteral();
literal.setLiteralValue(getContext().isSkipNulls() ? "" : "null"); //$NON-NLS-1$ //$NON-NLS-2$
cExpression.setElseExpression(literal);
ParenthesizedExpression pExpression= fAst.newParenthesizedExpression();
pExpression.setExpression(cExpression);
toStringExpressionBuilder.addExpression(pExpression);
}
private Expression createSumExpression(Expression left, Expression right) {
if (right == null)
return left;
if (left == null)
return right;
return createInfixExpression(left, Operator.PLUS, right);
}
}