| /******************************************************************************* |
| * Copyright (c) 2000, 2007 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| |
| *******************************************************************************/ |
| package org.eclipse.dltk.core.tests.model; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelElementDelta; |
| import org.eclipse.dltk.core.IParent; |
| 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.IType; |
| import org.eclipse.dltk.core.ModelException; |
| |
| |
| abstract public class CopyMoveTests extends ModifyingResourceTests { |
| public CopyMoveTests(String TestProjectName, String name) { |
| super(TestProjectName, name); |
| } |
| |
| /** |
| * Attempts to copy the element with optional forcing. The operation should |
| * fail with the failure code. |
| */ |
| public void copyNegative(IModelElement element, IModelElement destination, |
| IModelElement sibling, String rename, boolean force, int failureCode) { |
| try { |
| ((ISourceManipulation) element).copy(destination, sibling, rename, |
| force, null); |
| } catch (ModelException jme) { |
| assertTrue("Code not correct for ModelException: " + jme, jme |
| .getStatus().getCode() == failureCode); |
| return; |
| } |
| assertTrue("The copy should have failed for: " + element, false); |
| return; |
| } |
| |
| /** |
| * Attempts to copy the elements with optional forcing. The operation should |
| * fail with the failure code. |
| */ |
| public void copyNegative(IModelElement[] elements, |
| IModelElement[] destinations, IModelElement[] siblings, |
| String[] renames, boolean force, int failureCode) { |
| try { |
| getScriptModel().copy(elements, destinations, siblings, renames, |
| force, null); |
| } catch (ModelException jme) { |
| assertTrue("Code not correct for ModelException: " + jme, jme |
| .getStatus().getCode() == failureCode); |
| return; |
| } |
| assertTrue("The move should have failed for for multiple elements: ", |
| false); |
| return; |
| } |
| |
| /** |
| * Copies the element to the container with optional rename and forcing. The |
| * operation should succeed, so any exceptions encountered are thrown. |
| */ |
| public IModelElement copyPositive(IModelElement element, |
| IModelElement container, IModelElement sibling, String rename, |
| boolean force) throws ModelException { |
| // if forcing, ensure that a name collision exists |
| if (force) { |
| IModelElement collision = generateHandle(element, rename, container); |
| assertTrue("Collision does not exist", collision.exists()); |
| } |
| |
| IModelElement copy; |
| try { |
| startDeltas(); |
| |
| // copy |
| ((ISourceManipulation) element).copy(container, sibling, rename, |
| force, null); |
| |
| // ensure the original element still exists |
| assertTrue("The original element must still exist", element |
| .exists()); |
| |
| // generate the new element handle |
| copy = generateHandle(element, rename, container); |
| assertTrue("Copy should exist", copy.exists()); |
| |
| // ensure correct position |
| if (element.getElementType() > IModelElement.SOURCE_MODULE) { |
| ensureCorrectPositioning((IParent) container, sibling, copy); |
| } else { |
| if (container.getElementType() == IModelElement.PROJECT_FRAGMENT) { |
| } else { |
| // ensure package name is correct |
| //TODO: Add package declaration checks. |
| } |
| } |
| // if (copy.getElementType() == IModelElement.IMPORT_DECLARATION) |
| // container = ((ISourceModule) container).getImportContainer(); |
| //TODO: Add import declarations check. |
| IModelElementDelta destDelta = getDeltaFor(container, true); |
| assertTrue("Destination container not changed", destDelta != null |
| && destDelta.getKind() == IModelElementDelta.CHANGED); |
| IModelElementDelta[] deltas = destDelta.getAddedChildren(); |
| assertTrue("Added children not correct for element copy", deltas[0] |
| .getElement().equals(copy)); |
| } finally { |
| stopDeltas(); |
| } |
| return copy; |
| } |
| |
| /** |
| * Generates a new handle to the original element in its new container. |
| */ |
| public IModelElement generateHandle(IModelElement original, String rename, |
| IModelElement container) { |
| String name = original.getElementName(); |
| if (rename != null) { |
| name = rename; |
| } |
| switch (container.getElementType()) { |
| case IModelElement.PROJECT_FRAGMENT: |
| switch (original.getElementType()) { |
| case IModelElement.SCRIPT_FOLDER: |
| return ((IProjectFragment) container) |
| .getScriptFolder(name); |
| default: |
| assertTrue("illegal child type", false); |
| break; |
| } |
| break; |
| case IModelElement.SCRIPT_FOLDER: |
| switch (original.getElementType()) { |
| case IModelElement.SOURCE_MODULE: |
| return ((IScriptFolder) container).getSourceModule(name); |
| default: |
| assertTrue("illegal child type", false); |
| break; |
| } |
| break; |
| case IModelElement.SOURCE_MODULE: |
| //TODO: Add import and package declarations check... |
| switch (original.getElementType()) { |
| // case IModelElement.IMPORT_DECLARATION: |
| // return ((ISourceModule) container).getImport(name); |
| // case IModelElement.PACKAGE_DECLARATION: |
| // return ((ISourceModule) container) |
| // .getPackageDeclaration(name); |
| case IModelElement.TYPE: |
| if (isMainType(original, container)) { |
| // the cu has been renamed as well |
| container = ((IScriptFolder) container.getParent()) |
| .getSourceModule(name + ".java"); |
| } |
| return ((ISourceModule) container).getType(name); |
| default: |
| assertTrue("illegal child type", false); |
| break; |
| } |
| break; |
| case IModelElement.TYPE: |
| switch (original.getElementType()) { |
| case IModelElement.METHOD: |
| if (name.equals(original.getParent().getElementName())) { |
| // method is a constructor |
| return ((IType) container).getMethod(container |
| .getElementName()); |
| } |
| return ((IType) container).getMethod(name); |
| case IModelElement.FIELD: |
| return ((IType) container).getField(name); |
| case IModelElement.TYPE: |
| return ((IType) container).getType(name); |
| // case IModelElement.INITIALIZER: |
| // // hack to return the first initializer |
| // return ((IType) container).getInitializer(1); |
| default: |
| assertTrue("illegal child type", false); |
| break; |
| } |
| break; |
| default: |
| assertTrue("unsupported container type", false); |
| break; |
| } |
| assertTrue("should not get here", false); |
| return null; |
| } |
| |
| /** |
| * Returns true if this element is the main type of its compilation unit. |
| */ |
| protected boolean isMainType(IModelElement element, IModelElement parent) { |
| if (parent instanceof ISourceModule) { |
| if (element instanceof IType) { |
| ISourceModule cu = (ISourceModule) parent; |
| String typeName = cu.getElementName(); |
| typeName = typeName.substring(0, typeName.length() - 5); |
| return element.getElementName().equals(typeName) |
| && element.getParent().equals(cu); |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Attempts to move the element with optional forcing. The operation should |
| * fail with the failure code. |
| */ |
| public void moveNegative(IModelElement element, IModelElement destination, |
| IModelElement sibling, String rename, boolean force, int failureCode) { |
| try { |
| ((ISourceManipulation) element).move(destination, sibling, rename, |
| force, null); |
| } catch (ModelException jme) { |
| assertTrue("Code not correct for ModelException: " + jme, jme |
| .getStatus().getCode() == failureCode); |
| return; |
| } |
| assertTrue("The move should have failed for: " + element, false); |
| return; |
| } |
| |
| /** |
| * Attempts to move the element with optional forcing. The operation should |
| * fail with the failure code. |
| */ |
| public void moveNegative(IModelElement[] elements, |
| IModelElement[] destinations, IModelElement[] siblings, |
| String[] renames, boolean force, int failureCode) { |
| try { |
| getScriptModel().move(elements, destinations, siblings, renames, |
| force, null); |
| } catch (ModelException jme) { |
| assertTrue("Code not correct for ModelException: " + jme, jme |
| .getStatus().getCode() == failureCode); |
| return; |
| } |
| assertTrue("The move should have failed for for multiple elements: ", |
| false); |
| return; |
| } |
| |
| /** |
| * Moves the element to the container with optional rename and forcing. The |
| * operation should succeed, so any exceptions encountered are thrown. |
| */ |
| public void movePositive(IModelElement element, IModelElement container, |
| IModelElement sibling, String rename, boolean force) |
| throws ModelException { |
| IModelElement[] siblings = new IModelElement[] { sibling }; |
| String[] renamings = new String[] { rename }; |
| if (sibling == null) { |
| siblings = null; |
| } |
| if (rename == null) { |
| renamings = null; |
| } |
| movePositive(new IModelElement[] { element }, |
| new IModelElement[] { container }, siblings, renamings, force); |
| } |
| |
| /** |
| * Moves the elements to the containers with optional renaming and forcing. |
| * The operation should succeed, so any exceptions encountered are thrown. |
| */ |
| public void movePositive(IModelElement[] elements, |
| IModelElement[] destinations, IModelElement[] siblings, |
| String[] names, boolean force) throws ModelException { |
| movePositive(elements, destinations, siblings, names, force, null); |
| } |
| |
| /** |
| * Moves the elements to the containers with optional renaming and forcing. |
| * The operation should succeed, so any exceptions encountered are thrown. |
| */ |
| public void movePositive(IModelElement[] elements, |
| IModelElement[] destinations, IModelElement[] siblings, |
| String[] names, boolean force, IProgressMonitor monitor) |
| throws ModelException { |
| // if forcing, ensure that a name collision exists |
| int i; |
| if (force) { |
| for (i = 0; i < elements.length; i++) { |
| IModelElement e = elements[i]; |
| IModelElement collision = null; |
| if (names == null) { |
| collision = generateHandle(e, null, destinations[i]); |
| } else { |
| collision = generateHandle(e, names[i], destinations[i]); |
| } |
| assertTrue("Collision does not exist", collision.exists()); |
| } |
| } |
| |
| try { |
| startDeltas(); |
| |
| // move |
| getScriptModel().move(elements, destinations, siblings, names, force, |
| monitor); |
| for (i = 0; i < elements.length; i++) { |
| IModelElement element = elements[i]; |
| IModelElement moved = null; |
| if (names == null) { |
| moved = generateHandle(element, null, destinations[i]); |
| } else { |
| moved = generateHandle(element, names[i], destinations[i]); |
| } |
| // ensure the original element no longer exists, unless moving |
| // within the same container |
| if (!destinations[i].equals(element.getParent())) { |
| if (element.getElementType() == IModelElement.SCRIPT_FOLDER) { |
| // moving a package fragment does not necessary mean |
| // that it no longer exists |
| // it could have members that are not part of the Script |
| // Model |
| try { |
| IResource[] members = ((IContainer) element |
| .getUnderlyingResource()).members(); |
| if (members.length == 0) { |
| assertTrue( |
| "The original element must not exist", |
| !element.exists()); |
| } |
| } catch (CoreException ce) { |
| throw new ModelException(ce); |
| } |
| } else { |
| assertTrue("The original element must not exist", |
| !element.exists()); |
| } |
| } |
| assertTrue("Moved element should exist", moved.exists()); |
| |
| // ensure correct position |
| if (element.getElementType() > IModelElement.SOURCE_MODULE) { |
| if (siblings != null && siblings.length > 0) { |
| ensureCorrectPositioning((IParent) moved.getParent(), |
| siblings[i], moved); |
| } |
| } else { |
| IModelElement container = destinations[i]; |
| if (container.getElementType() == IModelElement.PROJECT_FRAGMENT) { |
| } else { // ensure package name is correct |
| |
| //TODO: Add import declarations checking. |
| } |
| } |
| IModelElementDelta destDelta = null; |
| if (isMainType(element, destinations[i]) && names != null |
| && names[i] != null) { // moved/renamed main type to |
| // same cu |
| destDelta = getDeltaFor(moved.getParent()); |
| assertTrue( |
| "Renamed compilation unit as result of main type not added", |
| destDelta != null |
| && destDelta.getKind() == IModelElementDelta.ADDED); |
| assertTrue("flag should be F_MOVED_FROM", (destDelta |
| .getFlags() & IModelElementDelta.F_MOVED_FROM) > 0); |
| assertTrue("moved from handle should be original", |
| destDelta.getMovedFromElement().equals( |
| element.getParent())); |
| } else { |
| destDelta = getDeltaFor(destinations[i], true); |
| assertTrue( |
| "Destination container not changed", |
| destDelta != null |
| && destDelta.getKind() == IModelElementDelta.CHANGED); |
| IModelElementDelta[] deltas = destDelta.getAddedChildren(); |
| assertTrue("Added children not correct for element copy", |
| deltas[i].getElement().equals(moved)); |
| assertTrue("should be K_ADDED", |
| deltas[i].getKind() == IModelElementDelta.ADDED); |
| IModelElementDelta sourceDelta = getDeltaFor(element, false); |
| assertTrue("should be K_REMOVED", |
| sourceDelta.getKind() == IModelElementDelta.REMOVED); |
| } |
| } |
| } finally { |
| stopDeltas(); |
| } |
| } |
| } |