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] toString wizard generates wrong code - https://bugs.eclipse.org/bugs/show_bug.cgi?id=270462
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] toString wizard generates wrong code - https://bugs.eclipse.org/bugs/show_bug.cgi?id=270462
* Red Hat Inc. - moved to jdt.core.manipulation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.StringLiteral;
Implementation of AbstractToStringGenerator
that creates toString()
method using String.format()
. This style ignores skip null values option.
Generated methods look like this:
public String toString() {
return String.format("FooClass( field1=%s, field2=%s )", field1, field2);
}
Since: 3.5
/**
* <p>
* Implementation of <code>AbstractToStringGenerator</code> that creates <code>toString()</code>
* method using <code>String.format()</code>. This style ignores <i>skip null values</i> option.
* <p>
* Generated methods look like this:
*
* <pre>
* public String toString() {
* return String.format("FooClass( field1=%s, field2=%s )", field1, field2);
* }
* </pre>
*
* </p>
*
* @since 3.5
*/
public class StringFormatGenerator extends AbstractToStringGenerator {
private List<Expression> arguments;
private StringBuffer buffer;
@Override
protected void initialize() {
super.initialize();
arguments= new ArrayList<>();
buffer= new StringBuffer();
}
@Override
protected void complete() throws CoreException {
super.complete();
ReturnStatement rStatement= fAst.newReturnStatement();
String formatClass;
if (getContext().is50orHigher())
formatClass= "java.lang.String"; //$NON-NLS-1$
else
formatClass= "java.text.MessageFormat"; //$NON-NLS-1$
MethodInvocation formatInvocation= createMethodInvocation(addImport(formatClass), "format", null); //$NON-NLS-1$
StringLiteral literal= fAst.newStringLiteral();
literal.setLiteralValue(buffer.toString());
formatInvocation.arguments().add(literal);
if (getContext().is50orHigher()) {
formatInvocation.arguments().addAll(arguments);
} else {
ArrayCreation arrayCreation= fAst.newArrayCreation();
arrayCreation.setType(fAst.newArrayType(fAst.newSimpleType(addImport("java.lang.Object")))); //$NON-NLS-1$
ArrayInitializer initializer= fAst.newArrayInitializer();
arrayCreation.setInitializer(initializer);
initializer.expressions().addAll(arguments);
formatInvocation.arguments().add(arrayCreation);
}
rStatement.setExpression(formatInvocation);
toStringMethod.getBody().statements().add(rStatement);
}
@Override
protected Object processElement(String templateElement, Object member) {
if (templateElement == ToStringTemplateParser.MEMBER_VALUE_VARIABLE) {
return createMemberAccessExpression(member, false, false);
}
return super.processElement(templateElement, member);
}
@Override
protected void addElement(Object element) {
if (element instanceof String) {
buffer.append((String)element);
}
if (element instanceof Expression) {
arguments.add((Expression) element);
if (getContext().is50orHigher()) {
buffer.append("%s"); //$NON-NLS-1$
} else {
buffer.append("{" + (arguments.size() - 1) + "}"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
@Override
protected Expression createMemberAccessExpression(Object member, boolean ignoreArraysCollections, boolean ignoreNulls) {
ITypeBinding type= getMemberType(member);
if (!getContext().is50orHigher() && type.isPrimitive()) {
String nonPrimitiveType= null;
String typeName= type.getName();
if (typeName.equals("byte"))nonPrimitiveType= "java.lang.Byte"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("short"))nonPrimitiveType= "java.lang.Short"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("char"))nonPrimitiveType= "java.lang.Character"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("int"))nonPrimitiveType= "java.lang.Integer"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("long"))nonPrimitiveType= "java.lang.Long"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("float"))nonPrimitiveType= "java.lang.Float"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("double"))nonPrimitiveType= "java.lang.Double"; //$NON-NLS-1$ //$NON-NLS-2$
if (typeName.equals("boolean"))nonPrimitiveType= "java.lang.Boolean"; //$NON-NLS-1$ //$NON-NLS-2$
ClassInstanceCreation classInstance= fAst.newClassInstanceCreation();
classInstance.setType(fAst.newSimpleType(addImport(nonPrimitiveType)));
classInstance.arguments().add(super.createMemberAccessExpression(member, true, true));
return classInstance;
}
return super.createMemberAccessExpression(member, ignoreArraysCollections, ignoreNulls);
}
}