Copyright (c) 2010, 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] finish toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=267710 Red Hat Inc. - moved to jdt.core.manipulation
/******************************************************************************* * Copyright (c) 2010, 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] finish toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=267710 * Red Hat Inc. - moved to jdt.core.manipulation *******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.text.edits.TextEdit; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.ASTMatcher; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationMessages; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2Core; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; import org.eclipse.jdt.internal.corext.util.JavaModelUtil;

A workspace runnable to add implementation for Object.toString()

Since:3.5
/** * <p> * A workspace runnable to add implementation for <code>{@link java.lang.Object#toString()}</code> * </p> * * @since 3.5 */
public class GenerateToStringOperation implements IWorkspaceRunnable {
The insertion point, or null
/** The insertion point, or <code>null</code> */
private IJavaElement fInsert; private CompilationUnitRewrite fRewrite; private ToStringGenerationContext fContext; private AbstractToStringGenerator fGenerator; private CompilationUnit fUnit; private boolean fApply= false; private boolean fSave= false; private TextEdit fEdit= null; private GenerateToStringOperation(IJavaElement insert, ToStringGenerationContext context, AbstractToStringGenerator generator, CompilationUnit unit, CompilationUnitRewrite rewrite, boolean apply, boolean save) { fInsert= insert; fContext= context; fRewrite= rewrite; fUnit= unit; fGenerator= generator; fApply= apply; fSave= save; } @Override public void run(IProgressMonitor monitor) throws CoreException { if (monitor == null) monitor= new NullProgressMonitor(); try { monitor.beginTask("", 1); //$NON-NLS-1$ monitor.setTaskName(CodeGenerationMessages.GenerateToStringOperation_description); AbstractTypeDeclaration declaration= (AbstractTypeDeclaration)ASTNodes.findDeclaration(fContext.getTypeBinding(), fRewrite.getRoot()); ListRewrite rewriter= fRewrite.getASTRewrite().getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); if (fContext.getTypeBinding() != null && rewriter != null) { MethodDeclaration toStringMethod= fGenerator.generateToStringMethod(); List<BodyDeclaration> list= declaration.bodyDeclarations(); BodyDeclaration replace= findMethodToReplace(list, toStringMethod); if (replace == null || ((Boolean)toStringMethod.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)).booleanValue()) insertMethod(toStringMethod, rewriter, replace); List<MethodDeclaration> helperMethods= fGenerator.generateHelperMethods(); for (Iterator<MethodDeclaration> iterator= helperMethods.iterator(); iterator.hasNext();) { MethodDeclaration method= iterator.next(); replace= findMethodToReplace(list, method); if (replace == null || ((Boolean)method.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)).booleanValue()) { insertMethod(method, rewriter, replace); } } fEdit= fRewrite.createChange(true).getEdit(); if (fApply) { JavaModelUtil.applyEdit((ICompilationUnit)fUnit.getJavaElement(), fEdit, fSave, monitor); } } } finally { monitor.done(); } }
Returns the resulting text edit.
Returns:the resulting edit
/** * Returns the resulting text edit. * * @return the resulting edit */
public final TextEdit getResultingEdit() { return fEdit; }
Returns:RefactoringStatus with eventual errors and warnings
/** * @return RefactoringStatus with eventual errors and warnings */
public RefactoringStatus checkConditions() { return fGenerator.checkConditions(); } protected void insertMethod(MethodDeclaration method, ListRewrite rewriter, BodyDeclaration replace) throws JavaModelException { if (replace != null) { rewriter.replace(replace, method, null); } else { ASTNode insertion= StubUtility2Core.getNodeToInsertBefore(rewriter, fInsert); if (insertion != null) rewriter.insertBefore(method, insertion, null); else rewriter.insertLast(method, null); } }
Determines if given method exists in a given list
Params:
  • list – list of method to search through
  • method – method to find
Returns:declaration of method from the list that has the same name and parameter types, or null if not found
/** * Determines if given method exists in a given list * * @param list list of method to search through * @param method method to find * @return declaration of method from the list that has the same name and parameter types, or * null if not found */
protected BodyDeclaration findMethodToReplace(final List<BodyDeclaration> list, MethodDeclaration method) { for (final Iterator<BodyDeclaration> iterator= list.iterator(); iterator.hasNext();) { final BodyDeclaration bodyDecl= iterator.next(); if (bodyDecl instanceof MethodDeclaration) { final MethodDeclaration method2= (MethodDeclaration)bodyDecl; if (method2.getName().getIdentifier().equals(method.getName().getIdentifier()) && method2.parameters().size() == method.parameters().size()) { Iterator<SingleVariableDeclaration> iterator1= method.parameters().iterator(); Iterator<SingleVariableDeclaration> iterator2= method2.parameters().iterator(); boolean ok= true; while (iterator1.hasNext()) { if (!iterator1.next().getType().subtreeMatch(new ASTMatcher(), iterator2.next().getType())) { ok= false; break; } } if (ok) return method2; } } } return null; } public ISchedulingRule getSchedulingRule() { return ResourcesPlugin.getWorkspace().getRoot(); } public static final int STRING_CONCATENATION= 0; public static final int STRING_BUILDER= 1; public static final int STRING_BUILDER_CHAINED= 2; public static final int STRING_FORMAT= 3; public static final int CUSTOM_BUILDER= 4; private final static String[] hardcoded_styles= { CodeGenerationMessages.GenerateToStringOperation_stringConcatenation_style_name, CodeGenerationMessages.GenerateToStringOperation_stringBuilder_style_name, CodeGenerationMessages.GenerateToStringOperation_StringBuilder_chained_style_name, CodeGenerationMessages.GenerateToStringOperation_string_format_style_name, CodeGenerationMessages.GenerateToStringOperation_customStringBuilder_style_name };
Returns:Array containing names of implemented code styles
/** * @return Array containing names of implemented code styles */
public static String[] getStyleNames() { return hardcoded_styles; }
Params:
  • toStringStyle – id number of the code style (its position in the array returned by getStyleNames()
Returns:a toString() generator implementing given code style
/** * * @param toStringStyle id number of the code style (its position in the array returned by * {@link #getStyleNames()} * @return a toString() generator implementing given code style */
private static AbstractToStringGenerator createToStringGenerator(int toStringStyle) { switch (toStringStyle) { case STRING_CONCATENATION: return new StringConcatenationGenerator(); case STRING_BUILDER: return new StringBuilderGenerator(); case STRING_BUILDER_CHAINED: return new StringBuilderChainGenerator(); case STRING_FORMAT: return new StringFormatGenerator(); case CUSTOM_BUILDER: return new CustomBuilderGenerator(); default: throw new IllegalArgumentException("Undefined toString() code style: " + toStringStyle); //$NON-NLS-1$ } }
Params:
  • toStringStyle – id number of the style (its position in the array returned by getStyleNames()
Returns:a template parser that should be used with given code style
/** * @param toStringStyle id number of the style (its position in the array returned by * {@link #getStyleNames()} * @return a template parser that should be used with given code style */
public static ToStringTemplateParser createTemplateParser(int toStringStyle) { return new ToStringTemplateParser(); }
Creates new GenerateToStringOperation, using settings.toStringStyle field to choose the right subclass.
Params:
  • typeBinding – binding for the type for which the toString() method will be created
  • selectedBindings – bindings for the typetype's members to be used in created method
  • unit – a compilation unit containing the type
  • elementPosition – at this position in the compilation unit created method will be added
  • settings – the settings for toString() generator
  • apply – true if the resulting edit should be applied, false otherwise
  • save – true if the changed compilation unit should be saved, false otherwise
Returns:a ready to use GenerateToStringOperation object
/** * Creates new <code>GenerateToStringOperation</code>, using <code>settings.toStringStyle</code> * field to choose the right subclass. * * @param typeBinding binding for the type for which the toString() method will be created * @param selectedBindings bindings for the typetype's members to be used in created method * @param unit a compilation unit containing the type * @param elementPosition at this position in the compilation unit created method will be added * @param settings the settings for toString() generator * @param apply <code>true</code> if the resulting edit should be applied, <code>false</code> otherwise * @param save <code>true</code> if the changed compilation unit should be saved, <code>false</code> otherwise * @return a ready to use <code>GenerateToStringOperation</code> object */
public static GenerateToStringOperation createOperation(ITypeBinding typeBinding, Object[] selectedBindings, CompilationUnit unit, IJavaElement elementPosition, ToStringGenerationSettingsCore settings, boolean apply, boolean save) { AbstractToStringGenerator generator= createToStringGenerator(settings.toStringStyle); ToStringTemplateParser parser= createTemplateParser(settings.toStringStyle); parser.parseTemplate(settings.stringFormatTemplate); CompilationUnitRewrite rewrite= new CompilationUnitRewrite((ICompilationUnit)unit.getTypeRoot(), unit); ToStringGenerationContext context= new ToStringGenerationContext(parser, selectedBindings, settings, typeBinding, rewrite); generator.setContext(context); return new GenerateToStringOperation(elementPosition, context, generator, unit, rewrite, apply, save); } }