| /******************************************************************************* |
| * Copyright (c) 2000, 2012 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.core.refactoring; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.CompositeChange; |
| |
| /** |
| * |
| * provides methods to create refactoring changes |
| */ |
| public class JDTDebugRefactoringUtil { |
| |
| /** |
| * Take a list of Changes, and return a unique Change, a CompositeChange, or null. |
| */ |
| public static Change createChangeFromList(List<Change> changes, String changeLabel) { |
| int nbChanges= changes.size(); |
| if (nbChanges == 0) { |
| return null; |
| } |
| else if (nbChanges == 1) { |
| return changes.get(0); |
| } |
| else { |
| return new CompositeChange(changeLabel, changes.toArray(new Change[changes.size()])); |
| } |
| } |
| |
| /** |
| * Returns the new container name for the given project and launch configuration |
| * @param javaProject the java to get the new container name for |
| * @param launchConfiguration the associated launch configuration |
| * @return the new container name |
| * @since 3.2 |
| */ |
| protected static String computeNewContainerName(ILaunchConfiguration launchConfiguration) { |
| IFile file = launchConfiguration.getFile(); |
| if (file != null) { |
| return file.getParent().getProjectRelativePath().toString(); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns a change for the given launch configuration if the launch configuration needs to |
| * be updated for this IType change. It specifically looks to see if the main type of the launch configuration |
| * is an inner type of the given IType. |
| * @param config the launch configuration |
| * @param type the type to check for |
| * @param newfqname the new fully qualified name |
| * @param pname the new project name |
| * @return the <code>Change</code> for this outer type |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| protected static Change createChangesForOuterTypeChange(ILaunchConfiguration config, IType type, String newfqname, String pname) throws CoreException { |
| IType[] innerTypes = type.getTypes(); |
| if(innerTypes.length == 0) { |
| return null; |
| } |
| Change change = null; |
| String mtname = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); |
| for (int i= 0; i < innerTypes.length; i++) { |
| String newTypeName = newfqname + '$' + innerTypes[i].getElementName(); |
| // if it matches, check the type |
| if (innerTypes[i].getFullyQualifiedName().equals(mtname)) { |
| return new LaunchConfigurationProjectMainTypeChange(config, newTypeName, pname); |
| } |
| // if it's not the type, check the inner types |
| change = createChangesForOuterTypeChange(config, innerTypes[i], newTypeName, pname); |
| } |
| return change; |
| } |
| |
| /** |
| * Provides a public mechanism for creating the <code>Change</code> for moving a package |
| * @param packageFragment the fragment to move |
| * @param destination the destination to move it to |
| * @return the <code>Change</code> for moving the package |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| public static Change createChangesForPackageMove(IPackageFragment pfragment, IPackageFragmentRoot destination) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(pfragment.getJavaProject().getElementName()); |
| String mtname = null; |
| for (int i= 0; i < configs.length; i++) { |
| mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); |
| if(mtname != null) { |
| if(mtname.lastIndexOf(pfragment.getElementName()) > -1) { |
| changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], null, destination.getJavaProject().getElementName())); |
| } |
| } |
| } |
| return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); |
| } |
| |
| /** |
| * Provides a public mechanism for creating the <code>Change</code> for renaming a package |
| * @param packageFragment the fragment to rename |
| * @param newName the new name for the fragment |
| * @return the Change for the renaming |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| public static Change createChangesForPackageRename(IPackageFragment pfragment, String newname) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(pfragment.getJavaProject().getElementName()); |
| String mtname; |
| for (int i= 0; i < configs.length; i++) { |
| mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); |
| if(mtname != null) { |
| String pkname = ""; //$NON-NLS-1$ |
| int index = mtname.lastIndexOf('.'); |
| if(index > 0) { |
| pkname = mtname.substring(0, index); |
| } |
| if (pfragment.getElementName().equals(pkname)) { |
| String ntname = newname + '.' + mtname.substring(index + 1); |
| changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], ntname, null)); |
| } |
| } |
| else { |
| changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], null, null)); |
| } |
| } |
| return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); |
| } |
| |
| /** |
| * Provides a public mechanism for creating the <code>Change</code> for renaming a project |
| * @param javaProject the project to rename |
| * @param newProjectName the new name for the project |
| * @return the Change for the project rename |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| public static Change createChangesForProjectRename(IJavaProject project, String newname) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(project.getElementName()); |
| LaunchConfigurationProjectMainTypeChange change = null; |
| for (int i= 0; i < configs.length; i++) { |
| change = new LaunchConfigurationProjectMainTypeChange(configs[i], null, newname); |
| String newcname = computeNewContainerName(configs[i]); |
| if (newcname != null) { |
| change.setNewContainerName(newcname); |
| } |
| changes.add(change); |
| } |
| return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); |
| } |
| |
| /** |
| * Creates a <code>Change</code> for a type change |
| * @param type the type that is changing |
| * @param newfqname the new fully qualified name |
| * @param pname the project name |
| * @return the <code>Change</code> for changing the specified type |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| protected static Change createChangesForTypeChange(IType type, String newfqname, String pname) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| String typename = type.getFullyQualifiedName(); |
| ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(type.getJavaProject().getElementName()); |
| String mtname; |
| for (int i= 0; i < configs.length; i++) { |
| mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); |
| if (typename.equals(mtname)) { |
| changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], newfqname, pname)); |
| } |
| else { |
| Change change = createChangesForOuterTypeChange(configs[i], type, newfqname, pname); |
| if (change != null) { |
| changes.add(change); |
| } |
| } |
| } |
| return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); |
| } |
| |
| /** |
| * Provides a public mechanism for creating the <code>Change</code> for moving a type |
| * @param type the type being moved |
| * @param destination the destination to move the type to |
| * @return the <code>Change</code> for the type move |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| public static Change createChangesForTypeMove(IType type, IJavaElement destination) throws CoreException { |
| IJavaProject pdestination = destination.getJavaProject(); |
| String newpname = null; |
| if (!type.getJavaProject().equals(pdestination)) { |
| newpname = pdestination.getElementName(); |
| } |
| String newfqname = type.getElementName(); |
| if (destination instanceof IType) { |
| newfqname = ((IType)destination).getFullyQualifiedName() + '$' + type.getElementName(); |
| } |
| else if (destination instanceof IPackageFragment) { |
| if (!((IPackageFragment) destination).isDefaultPackage()) { |
| newfqname = destination.getElementName() + '.' + type.getElementName(); |
| } |
| } |
| return createChangesForTypeChange(type, newfqname, newpname); |
| } |
| |
| /** |
| * Provides a public mechanism for creating the <code>Change</code> for renaming a type |
| * @param type the type to rename |
| * @param newname the new name for the type |
| * @return the <code>Change</code> for the type rename |
| * @throws CoreException |
| * @since 3.2 |
| */ |
| public static Change createChangesForTypeRename(IType type, String newname) throws CoreException { |
| IType dtype = type.getDeclaringType(); |
| String newfqname = newname; |
| if (dtype == null) { |
| IPackageFragment packageFragment = type.getPackageFragment(); |
| if (!packageFragment.isDefaultPackage()) { |
| newfqname = packageFragment.getElementName() + '.' + newname; |
| } |
| } |
| else { |
| newfqname = dtype.getFullyQualifiedName() + '$' + newname; |
| } |
| return createChangesForTypeChange(type, newfqname, null); |
| } |
| |
| /** |
| * Returns a listing of configurations that have a specific project name attribute in them |
| * @param pname the project attribute to compare against |
| * @return the list of java type launch configurations that have the specified project attribute |
| * @since 3.2 |
| */ |
| protected static ILaunchConfiguration[] getJavaTypeLaunchConfigurations(String pname) { |
| try { |
| ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(); |
| ArrayList<ILaunchConfiguration> list = new ArrayList<>(); |
| String attrib; |
| for(int i = 0; i < configs.length; i++) { |
| attrib = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null); |
| if(attrib != null) { |
| if(attrib.equals(pname)) { |
| list.add(configs[i]); |
| } |
| } |
| } |
| return list.toArray(new ILaunchConfiguration[list.size()]); |
| } |
| catch(CoreException e) {JDIDebugPlugin.log(e);} |
| return new ILaunchConfiguration[0]; |
| } |
| |
| } |