blob: 2e2e672872386cca524092fd0f670d9f8010b379 [file] [log] [blame]
/*******************************************************************************
* 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();
switch (nbChanges) {
case 0:
return null;
case 1:
return changes.get(0);
default:
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];
}
}