blob: a5b565efd32f4e49e1ee8ba3a00cd9182f692bc6 [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] 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;
/**
* <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(&quot;FooClass( field1=%s, field2=%s )&quot;, 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);
}
}