Copyright (c) 2019 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 Microsoft Corporation - based this file on RefactoringAvailabilityTester
/******************************************************************************* * Copyright (c) 2019 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 * Microsoft Corporation - based this file on RefactoringAvailabilityTester *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ILocalVariable; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.SourceRange; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.NodeFinder; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.jdt.core.dom.SuperMethodInvocation; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.internal.corext.util.JdtFlags;
Helper class to detect whether a certain refactoring can be enabled on a selection.

This class has been introduced to decouple actions from the refactoring code, in order not to eagerly load refactoring classes during action initialization.

Since:1.12
/** * 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> * * @since 1.12 */
public final class RefactoringAvailabilityTesterCore { public static boolean isMoveStaticMembersAvailable(final IMember[] members) throws JavaModelException { if (members == null) return false; if (members.length == 0) return false; if (!isMoveStaticAvailable(members)) return false; if (!isCommonDeclaringType(members)) return false; return true; } public static boolean isMoveStaticAvailable(final IMember[] members) throws JavaModelException { for (int index= 0; index < members.length; index++) { if (!isMoveStaticAvailable(members[index])) return false; } return true; } public static boolean isMoveStaticAvailable(final IMember member) throws JavaModelException { if (!member.exists()) return false; final int type= member.getElementType(); if (type != IJavaElement.METHOD && type != IJavaElement.FIELD && type != IJavaElement.TYPE) return false; if (JdtFlags.isEnum(member) && type != IJavaElement.TYPE) return false; final IType declaring= member.getDeclaringType(); if (declaring == null) return false; if (!Checks.isAvailable(member)) return false; if (type == IJavaElement.METHOD && declaring.isInterface()) { boolean is18OrHigher= JavaModelUtil.is18OrHigher(member.getJavaProject()); if (!is18OrHigher || !Flags.isStatic(member.getFlags())) return false; } if (type == IJavaElement.METHOD && !JdtFlags.isStatic(member)) return false; if (type == IJavaElement.METHOD && ((IMethod) member).isConstructor()) return false; if (type == IJavaElement.TYPE && !JdtFlags.isStatic(member)) return false; if (!declaring.isInterface() && !JdtFlags.isStatic(member)) return false; return true; } public static boolean isCommonDeclaringType(final IMember[] members) { if (members.length == 0) return false; final IType type= members[0].getDeclaringType(); if (type == null) return false; for (int index= 0; index < members.length; index++) { if (!type.equals(members[index].getDeclaringType())) return false; } return true; } public static boolean isDelegateCreationAvailable(final IField field) throws JavaModelException { return field.exists() && (Flags.isStatic(field.getFlags()) && Flags.isFinal(field.getFlags()) /* * && * hasInitializer(field) */); } public static boolean isInlineTempAvailable(final ILocalVariable variable) throws JavaModelException { return Checks.isAvailable(variable); } public static boolean isInlineConstantAvailable(final IField field) throws JavaModelException { return Checks.isAvailable(field) && JdtFlags.isStatic(field) && JdtFlags.isFinal(field) && !JdtFlags.isEnum(field); } public static boolean isInlineMethodAvailable(IMethod method) throws JavaModelException { if (method == null) return false; if (!method.exists()) return false; if (!method.isStructureKnown()) return false; if (!method.isBinary()) return true; if (method.isConstructor()) return false; return SourceRange.isAvailable(method.getNameRange()); } public static ASTNode getInlineableMethodNode(ITypeRoot typeRoot, CompilationUnit root, int offset, int length) { ASTNode node= null; try { node= getInlineableMethodNode(NodeFinder.perform(root, offset, length, typeRoot), typeRoot); } catch(JavaModelException e) { // Do nothing } if (node != null) return node; return getInlineableMethodNode(NodeFinder.perform(root, offset, length), typeRoot); } private static ASTNode getInlineableMethodNode(ASTNode node, IJavaElement unit) { if (node == null) return null; switch (node.getNodeType()) { case ASTNode.SIMPLE_NAME: StructuralPropertyDescriptor locationInParent= node.getLocationInParent(); if (locationInParent == MethodDeclaration.NAME_PROPERTY) { return node.getParent(); } else if (locationInParent == MethodInvocation.NAME_PROPERTY || locationInParent == SuperMethodInvocation.NAME_PROPERTY) { return unit instanceof ICompilationUnit ? node.getParent() : null; // don't start on invocations in binary } return null; case ASTNode.EXPRESSION_STATEMENT: node= ((ExpressionStatement)node).getExpression(); } switch (node.getNodeType()) { case ASTNode.METHOD_DECLARATION: return node; case ASTNode.METHOD_INVOCATION: case ASTNode.SUPER_METHOD_INVOCATION: case ASTNode.CONSTRUCTOR_INVOCATION: return unit instanceof ICompilationUnit ? node : null; // don't start on invocations in binary } return null; } }