| /******************************************************************************* |
| * Copyright (c) 2005, 2018 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.internal.corext.refactoring; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.dltk.core.IField; |
| import org.eclipse.dltk.core.IMethod; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IProjectFragment; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.IScriptModel; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.ScriptModelUtil; |
| import org.eclipse.dltk.internal.corext.refactoring.reorg.ReorgPolicyFactory; |
| import org.eclipse.dltk.internal.corext.refactoring.reorg.ReorgUtils; |
| import org.eclipse.dltk.internal.ui.editor.ModelTextSelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| |
| /** |
| * Helper class to detect whether a certain refactoring can be enabled on a |
| * selection. |
| * <p> |
| * This class has been introduced to decouple actions from the refactoring code, |
| * in order not to eagerly load refactoring classes during action |
| * initialization. |
| * </p> |
| * |
| * |
| */ |
| public final class RefactoringAvailabilityTester { |
| |
| public static IType getDeclaringType(IModelElement element) { |
| if (element == null) |
| return null; |
| if (!(element instanceof IType)) |
| element = element.getAncestor(IModelElement.TYPE); |
| return (IType) element; |
| } |
| |
| public static IModelElement[] getScriptElements(final Object[] elements) { |
| List<IModelElement> result = new ArrayList<>(); |
| for (int index = 0; index < elements.length; index++) { |
| if (elements[index] instanceof IModelElement) |
| result.add((IModelElement) elements[index]); |
| } |
| return result.toArray(new IModelElement[result.size()]); |
| } |
| |
| public static IResource[] getResources(final Object[] elements) { |
| List<IResource> result = new ArrayList<>(); |
| for (int index = 0; index < elements.length; index++) { |
| if (elements[index] instanceof IResource) |
| result.add((IResource) elements[index]); |
| } |
| return result.toArray(new IResource[result.size()]); |
| } |
| |
| public static boolean isRenameElementAvailable(IModelElement element) |
| throws CoreException { |
| switch (element.getElementType()) { |
| case IModelElement.SCRIPT_PROJECT: |
| return isRenameAvailable((IScriptProject) element); |
| case IModelElement.PROJECT_FRAGMENT: |
| return isRenameAvailable((IProjectFragment) element); |
| case IModelElement.SOURCE_MODULE: |
| return isRenameAvailable((ISourceModule) element); |
| case IModelElement.TYPE: |
| return isRenameAvailable((IType) element); |
| case IModelElement.METHOD: |
| final IMethod method = (IMethod) element; |
| if (method.isConstructor()) { |
| return isRenameAvailable(method.getDeclaringType()); |
| } |
| return isRenameAvailable(method); |
| case IModelElement.FIELD: |
| final IField field = (IField) element; |
| return isRenameFieldAvailable(field); |
| } |
| return false; |
| } |
| |
| public static boolean isRenameAvailable(final ISourceModule unit) { |
| if (unit == null) |
| return false; |
| if (!unit.exists()) |
| return false; |
| if (!ScriptModelUtil.isPrimary(unit)) |
| return false; |
| if (unit.isReadOnly()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IScriptProject project) |
| throws ModelException { |
| if (project == null) |
| return false; |
| if (!Checks.isAvailable(project)) |
| return false; |
| if (!project.isConsistent()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IMethod method) |
| throws CoreException { |
| if (method == null) |
| return false; |
| if (!Checks.isAvailable(method)) |
| return false; |
| if (method.isConstructor()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IScriptFolder fragment) |
| throws ModelException { |
| if (fragment == null) |
| return false; |
| if (!Checks.isAvailable(fragment)) |
| return false; |
| if (fragment.isRootFolder()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IProjectFragment root) |
| throws ModelException { |
| if (root == null) |
| return false; |
| if (!Checks.isAvailable(root)) |
| return false; |
| if (root.isArchive()) |
| return false; |
| if (root.isExternal()) |
| return false; |
| if (!root.isConsistent()) |
| return false; |
| if (root.getResource() instanceof IProject) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IResource resource) { |
| if (resource == null) |
| return false; |
| if (!resource.exists()) |
| return false; |
| if (!resource.isAccessible()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameAvailable(final IType type) |
| throws ModelException { |
| if (type == null) |
| return false; |
| if (!Checks.isAvailable(type)) |
| return false; |
| return true; |
| } |
| |
| public static boolean isRenameFieldAvailable(final IField field) |
| throws ModelException { |
| return Checks.isAvailable(field); |
| } |
| |
| public static boolean isReplaceInvocationsAvailable(IMethod method) |
| throws ModelException { |
| if (method == null) |
| return false; |
| if (!method.exists()) |
| return false; |
| if (method.isConstructor()) |
| return false; |
| return true; |
| } |
| |
| public static boolean isDeleteAvailable(final IModelElement element) |
| throws ModelException { |
| if (!element.exists()) |
| return false; |
| if (element instanceof IScriptModel |
| || element instanceof IScriptProject) |
| return false; |
| if (element.getParent() != null && element.getParent().isReadOnly()) |
| return false; |
| if (element instanceof IProjectFragment) { |
| IProjectFragment root = (IProjectFragment) element; |
| if (root.isExternal() || Checks.isBuildpathDelete(root)) // TODO |
| // rename |
| // isClasspathDelete |
| return false; |
| } |
| if (element.getResource() == null |
| && !RefactoringAvailabilityTester.isWorkingCopyElement(element)) |
| return false; |
| // if (element instanceof IMember && ((IMember) element).isBinary()) |
| // return false; |
| if (ReorgUtils.isDeletedFromEditor(element)) |
| return false; |
| return true; |
| } |
| |
| public static boolean isDeleteAvailable(final IResource resource) { |
| if (!resource.exists() || resource.isPhantom()) |
| return false; |
| if (resource.getType() == IResource.ROOT |
| || resource.getType() == IResource.PROJECT) |
| return false; |
| return true; |
| } |
| |
| public static boolean isDeleteAvailable( |
| final IStructuredSelection selection) throws ModelException { |
| if (!selection.isEmpty()) |
| return isDeleteAvailable(selection.toArray()); |
| return false; |
| } |
| |
| public static boolean isDeleteAvailable(final Object[] objects) |
| throws ModelException { |
| if (objects.length != 0) { |
| final IResource[] resources = RefactoringAvailabilityTester |
| .getResources(objects); |
| final IModelElement[] elements = RefactoringAvailabilityTester |
| .getScriptElements(objects); |
| if (objects.length != resources.length + elements.length) |
| return false; |
| for (int index = 0; index < resources.length; index++) { |
| if (!isDeleteAvailable(resources[index])) |
| return false; |
| } |
| for (int index = 0; index < elements.length; index++) { |
| if (!isDeleteAvailable(elements[index])) |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| public static boolean isWorkingCopyElement(final IModelElement element) { |
| if (element instanceof ISourceModule) |
| return ((ISourceModule) element).isWorkingCopy(); |
| if (ReorgUtils.isInsideSourceModule(element)) |
| return ReorgUtils.getSourceModule(element).isWorkingCopy(); |
| return false; |
| } |
| |
| private RefactoringAvailabilityTester() { |
| // Not for instantiation |
| } |
| |
| public static boolean isMoveAvailable(final IResource[] resources, |
| final IModelElement[] elements) throws ModelException { |
| if (elements != null) { |
| for (int index = 0; index < elements.length; index++) { |
| IModelElement element = elements[index]; |
| if ((element instanceof IType)) { |
| return false; |
| } |
| // if ((element instanceof IPackageDeclaration)) |
| // return false; |
| if (element instanceof IField) {// && DLTKFlags.isEnum((IMember) |
| // element)) |
| return false; |
| } |
| } |
| } |
| return ReorgPolicyFactory.createMovePolicy(resources, elements) |
| .canEnable(); |
| } |
| |
| public static boolean isMoveAvailable(final ModelTextSelection selection) |
| throws ModelException { |
| final IModelElement element = selection.resolveEnclosingElement(); |
| if (element == null) |
| return false; |
| return isMoveAvailable(new IResource[0], |
| new IModelElement[] { element }); |
| } |
| } |