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 - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070
Mateusz Matela - [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
/*******************************************************************************
* 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;
Implementation of AbstractToStringGenerator
that creates toString()
method by concatenating String
s
Generated methods look like this:
public String toString() {
return "FooClass( field1=" + field1 + ", field2=" + field2 + ", method1()=" + method1 + ")";
}
Since: 3.5
/**
* <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 "FooClass( field1=" + field1 + ", field2=" + field2 + ", method1()=" + method1 + ")";
* }
* </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);
}
}