blob: d9bb91fbcd79966af3c2abaadf4daa701cd1633e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.internal.corext.refactoring.reorg;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dltk.core.IMember;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.ISourceManipulation;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.internal.corext.refactoring.Checks;
import org.eclipse.dltk.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.dltk.internal.corext.refactoring.changes.DeleteFileChange;
import org.eclipse.dltk.internal.corext.refactoring.changes.DeleteFolderChange;
import org.eclipse.dltk.internal.corext.refactoring.changes.DeleteFromBuildpathChange;
import org.eclipse.dltk.internal.corext.refactoring.changes.DeleteProjectFragmentChange;
import org.eclipse.dltk.internal.corext.refactoring.changes.DeleteSourceManipulationChange;
import org.eclipse.dltk.internal.corext.refactoring.changes.DynamicValidationStateChange;
import org.eclipse.dltk.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.NullChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.MultiTextEdit;
class DeleteChangeCreator {
private DeleteChangeCreator() {
// private
}
static Change createDeleteChange(TextChangeManager manager,
IResource[] resources, IModelElement[] modelElements,
String changeName) throws CoreException {
final DynamicValidationStateChange result = new DynamicValidationStateChange(
changeName) {
@Override
public Change perform(IProgressMonitor pm) throws CoreException {
super.perform(pm);
return null;
}
};
for (int i = 0; i < modelElements.length; i++) {
IModelElement element = modelElements[i];
if (!ReorgUtils.isInsideSourceModule(element))
result.add(createDeleteChange(element));
}
for (int i = 0; i < resources.length; i++) {
result.add(createDeleteChange(resources[i]));
}
Map grouped = ReorgUtils
.groupBySourceModule(getElementsSmallerThanCu(modelElements));
if (grouped.size() != 0) {
Assert.isNotNull(manager);
for (Iterator iter = grouped.keySet().iterator(); iter.hasNext();) {
ISourceModule cu = (ISourceModule) iter.next();
Change change = createDeleteChange(cu, (List) grouped.get(cu),
manager);
if (change != null) {
result.add(change);
}
}
}
return result;
}
private static Change createDeleteChange(IResource resource) {
Assert.isTrue(!(resource instanceof IWorkspaceRoot));// cannot be done
Assert.isTrue(!(resource instanceof IProject)); // project deletion is
// handled by the
// workbench
if (resource instanceof IFile)
return new DeleteFileChange((IFile) resource, true);
if (resource instanceof IFolder)
return new DeleteFolderChange((IFolder) resource, true);
Assert.isTrue(false);// there're no more kinds
return null;
}
/*
* List<IModelElement> modelElements
*/
private static Change createDeleteChange(ISourceModule cu,
List<IModelElement> modelElements, TextChangeManager manager)
throws CoreException {
// SourceModule cuNode= RefactoringASTParser.parseWithASTProvider(cu, false, null);
// SourceModuleRewrite rewriter= new SourceModuleRewrite(cu, cuNode);
Assert.isNotNull(cu);
Assert.isNotNull(modelElements);
Assert.isNotNull(manager);
TextFileChange textFileChange = null;
if (cu != null && cu.getResource() instanceof IFile) {
textFileChange = new TextFileChange(cu.getElementName(),
(IFile) cu.getResource());
MultiTextEdit fileChangeRootEdit = new MultiTextEdit();
textFileChange.setEdit(fileChangeRootEdit);
manager.manage(cu, textFileChange);
IModelElement[] elements = modelElements
.toArray(new IModelElement[modelElements.size()]);
for (int cnt = 0, max = elements.length; cnt < max; cnt++) {
ISourceRange sourceRange = null;
if (elements[cnt] instanceof IMember) {
IMember type = (IMember) elements[cnt];
sourceRange = type.getSourceRange();
}
if (sourceRange != null) {
DeleteEdit edit = new DeleteEdit(sourceRange.getOffset(),
sourceRange.getLength());
fileChangeRootEdit.addChild(edit);
if (cu.isWorkingCopy()) {
textFileChange.setSaveMode(TextFileChange.LEAVE_DIRTY);
}
}
}
}
// ASTNodeDeleteUtil.markAsDeleted(elements, rewriter, null);
// return addTextEditFromRewrite(manager, cu, rewriter.getASTRewrite());
return textFileChange;
}
// private static TextChange addTextEditFromRewrite(TextChangeManager manager, ISourceModule cu, ASTRewrite rewrite) throws CoreException {
// try {
// ITextFileBuffer buffer= RefactoringFileBuffers.acquire(cu);
// TextEdit resultingEdits= rewrite.rewriteAST(buffer.getDocument(), cu.getScriptProject().getOptions(true));
// TextChange textChange= manager.get(cu);
// if (textChange instanceof TextFileChange) {
// TextFileChange tfc= (TextFileChange) textChange;
// if (cu.isWorkingCopy())
// tfc.setSaveMode(TextFileChange.LEAVE_DIRTY);
// }
// String message= RefactoringCoreMessages.DeleteChangeCreator_1;
// TextChangeCompatibility.addTextEdit(textChange, message, resultingEdits);
// return textChange;
// } finally {
// RefactoringFileBuffers.release(cu);
// }
// }
// List<IModelElement>
private static List getElementsSmallerThanCu(
IModelElement[] modelElements) {
List result = new ArrayList();
for (int i = 0; i < modelElements.length; i++) {
IModelElement element = modelElements[i];
if (ReorgUtils.isInsideSourceModule(element))
result.add(element);
}
return result;
}
private static Change createDeleteChange(IModelElement modelElement) {
Assert.isTrue(!ReorgUtils.isInsideSourceModule(modelElement));
switch (modelElement.getElementType()) {
case IModelElement.PROJECT_FRAGMENT:
return createProjectFragmentDeleteChange(
(IProjectFragment) modelElement);
case IModelElement.SCRIPT_FOLDER:
return createSourceManipulationDeleteChange(
(IScriptFolder) modelElement);
case IModelElement.SOURCE_MODULE:
return createSourceManipulationDeleteChange(
(ISourceModule) modelElement);
case IModelElement.SCRIPT_MODEL: // cannot be done
Assert.isTrue(false);
return null;
case IModelElement.SCRIPT_PROJECT: // handled differently
Assert.isTrue(false);
return null;
case IModelElement.TYPE:
case IModelElement.FIELD:
case IModelElement.METHOD:
// case IModelElement.INITIALIZER:
// case IModelElement.PACKAGE_DECLARATION:
// case IModelElement.IMPORT_CONTAINER:
// case IModelElement.IMPORT_DECLARATION:
// Assert.isTrue(false);//not done here
default:
Assert.isTrue(false);// there's no more kinds
return new NullChange();
}
}
private static Change createSourceManipulationDeleteChange(
ISourceManipulation element) {
// XXX workaround for bug 31384, in case of linked ISourceManipulation
// delete the resource
if (element instanceof ISourceModule
|| element instanceof IScriptFolder) {
IResource resource;
if (element instanceof ISourceModule)
resource = ReorgUtils.getResource((ISourceModule) element);
else
resource = ((IScriptFolder) element).getResource();
if (resource != null && resource.isLinked())
return createDeleteChange(resource);
}
return new DeleteSourceManipulationChange(element, true);
}
private static Change createProjectFragmentDeleteChange(
IProjectFragment root) {
IResource resource = root.getResource();
if (resource != null && resource.isLinked()) {
// XXX using this code is a workaround for jcore bug 31998
// jcore cannot handle linked stuff
// normally, we should always create DeleteProjectFragmentChange
CompositeChange composite = new DynamicValidationStateChange(
RefactoringCoreMessages.DeleteRefactoring_delete_package_fragment_root);
composite.add(new DeleteFromBuildpathChange(root));
Assert.isTrue(!Checks.isBuildpathDelete(root));// checked in
// preconditions
composite.add(createDeleteChange(resource));
return composite;
}
Assert.isTrue(!root.isExternal());
// TODO remove the query argument
return new DeleteProjectFragmentChange(root, true, null);
}
}