blob: ab7703f952d42ae5497cac8c7cf2ab280b646d7e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
* Rabea Gransberger <rgransberger@gmx.de> - [quick fix] Fix several visibility issues - https://bugs.eclipse.org/394692
*******************************************************************************/
package org.eclipse.jdt.internal.corext.util;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.TypeDeclaration;
/**
* Java element flags from a Java language model point of view.
* <p>
* {@link IMember#getFlags()} (and hence {@link Flags}) only take explicitly declared flags
* from source into account.
* This class also considers the implicit properties as defined in the Java Language Specification.
* </p>
* <p>
* <code>JdtFlags</code> is the right choice for most analysis tasks and for presentation in the UI.
* </p>
*/
// @see JDTUIHelperClasses
public class JdtFlags {
private JdtFlags(){
}
public static final String VISIBILITY_STRING_PRIVATE= "private"; //$NON-NLS-1$
public static final String VISIBILITY_STRING_PACKAGE= ""; //$NON-NLS-1$
public static final String VISIBILITY_STRING_PROTECTED= "protected"; //$NON-NLS-1$
public static final String VISIBILITY_STRING_PUBLIC= "public"; //$NON-NLS-1$
public static final int VISIBILITY_CODE_INVALID= -1;
public static boolean isDefaultMethod(IMethodBinding method) {
return Modifier.isDefault(method.getModifiers());
}
public static boolean isDefaultMethod(IMethod method) throws JavaModelException {
return Flags.isDefaultMethod(method.getFlags());
}
public static boolean isAbstract(IMember member) throws JavaModelException{
int flags= member.getFlags();
if (!member.isBinary() && isInterfaceOrAnnotationMethod(member)) {
return !Flags.isPrivate(flags) && !Flags.isStatic(flags) && !Flags.isDefaultMethod(flags);
}
return Flags.isAbstract(flags);
}
public static boolean isAbstract(IMethodBinding member) {
return Modifier.isAbstract(member.getModifiers());
}
public static boolean isStatic(BodyDeclaration bodyDeclaration) {
if (isNestedInterfaceOrAnnotation(bodyDeclaration))
return true;
int nodeType= bodyDeclaration.getNodeType();
if (!(nodeType == ASTNode.METHOD_DECLARATION || nodeType == ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION) &&
isInterfaceOrAnnotationMember(bodyDeclaration))
return true;
if (bodyDeclaration instanceof EnumConstantDeclaration)
return true;
if (bodyDeclaration instanceof EnumDeclaration && bodyDeclaration.getParent() instanceof AbstractTypeDeclaration)
return true;
return Modifier.isStatic(bodyDeclaration.getModifiers());
}
public static boolean isStatic(IMember member) throws JavaModelException {
if (isNestedInterfaceOrAnnotation(member))
return true;
if (member.getElementType() != IJavaElement.METHOD
&& isInterfaceOrAnnotationMember(member))
return true;
if (isEnum(member) && (member.getElementType() == IJavaElement.FIELD || member.getDeclaringType() != null))
return true;
return Flags.isStatic(member.getFlags());
}
public static boolean isStatic(IMethodBinding methodBinding){
return Modifier.isStatic(methodBinding.getModifiers());
}
public static boolean isDeprecated(IMember member) throws JavaModelException{
return Flags.isDeprecated(member.getFlags());
}
public static boolean isFinal(IMember member) throws JavaModelException{
if (isInterfaceOrAnnotationField(member))
return true;
if (isAnonymousType(member))
return true;
if (isEnumConstant(member) || isEnumTypeFinal(member))
return true;
return Flags.isFinal(member.getFlags());
}
private static boolean isEnumTypeFinal(IMember member) throws JavaModelException {
if (!(isEnum(member) && member.getElementType() == IJavaElement.TYPE))
return false;
// An enum type is implicitly final unless it contains at least one enum constant that has a class body.
IJavaElement[] children= member.getChildren();
for (IJavaElement child : children) {
if (isEnumConstant((IMember) child) && ((IField) child).getChildren().length != 0) {
return false;
}
}
return true;
}
public static boolean isNative(IMember member) throws JavaModelException{
return Flags.isNative(member.getFlags());
}
public static boolean isPackageVisible(IMember member) throws JavaModelException{
return (! isPrivate(member) && ! isProtected(member) && ! isPublic(member));
}
public static boolean isPackageVisible(BodyDeclaration bodyDeclaration) {
return (! isPrivate(bodyDeclaration) && ! isProtected(bodyDeclaration) && ! isPublic(bodyDeclaration));
}
public static boolean isPackageVisible(IBinding binding) {
return (! isPrivate(binding) && ! isProtected(binding) && ! isPublic(binding));
}
public static boolean isPrivate(IMember member) throws JavaModelException{
return Flags.isPrivate(member.getFlags());
}
public static boolean isPrivate(BodyDeclaration bodyDeclaration) {
return Modifier.isPrivate(bodyDeclaration.getModifiers());
}
public static boolean isPrivate(IBinding binding) {
return Modifier.isPrivate(binding.getModifiers());
}
public static boolean isProtected(IMember member) throws JavaModelException{
return Flags.isProtected(member.getFlags());
}
public static boolean isProtected(BodyDeclaration bodyDeclaration) {
return Modifier.isProtected(bodyDeclaration.getModifiers());
}
public static boolean isProtected(IBinding binding) {
return Modifier.isProtected(binding.getModifiers());
}
public static boolean isPublic(IMember member) throws JavaModelException{
if (isInterfaceOrAnnotationMember(member))
return true;
if (isEnumConstant(member))
return true;
return Flags.isPublic(member.getFlags());
}
public static boolean isPublic(IBinding binding) {
if (isInterfaceOrAnnotationMember(binding))
return true;
return Modifier.isPublic(binding.getModifiers());
}
public static boolean isPublic(BodyDeclaration bodyDeclaration) {
if (isInterfaceOrAnnotationMember(bodyDeclaration))
return true;
return Modifier.isPublic(bodyDeclaration.getModifiers());
}
public static boolean isStatic(IVariableBinding variableBinding){
if (isInterfaceOrAnnotationMember(variableBinding))
return true;
return Modifier.isStatic(variableBinding.getModifiers());
}
public static boolean isSynchronized(IMember member) throws JavaModelException{
return Flags.isSynchronized(member.getFlags());
}
public static boolean isSynthetic(IMember member) throws JavaModelException{
return Flags.isSynthetic(member.getFlags());
}
public static boolean isAnnotation(IMember member) throws JavaModelException{
return Flags.isAnnotation(member.getFlags());
}
public static boolean isEnum(IMember member) throws JavaModelException{
return Flags.isEnum(member.getFlags());
}
public static boolean isVarargs(IMethod method) throws JavaModelException{
return Flags.isVarargs(method.getFlags());
}
public static boolean isTransient(IMember member) throws JavaModelException{
return Flags.isTransient(member.getFlags());
}
public static boolean isVolatile(IMember member) throws JavaModelException{
return Flags.isVolatile(member.getFlags());
}
private static boolean isInterfaceOrAnnotationMethod(IMember member) throws JavaModelException {
return member.getElementType() == IJavaElement.METHOD && isInterfaceOrAnnotationMember(member);
}
private static boolean isInterfaceOrAnnotationField(IMember member) throws JavaModelException {
return member.getElementType() == IJavaElement.FIELD && isInterfaceOrAnnotationMember(member);
}
private static boolean isInterfaceOrAnnotationMember(IMember member) throws JavaModelException {
return member.getDeclaringType() != null && JavaModelUtil.isInterfaceOrAnnotation(member.getDeclaringType());
}
private static boolean isInterfaceOrAnnotationMember(IBinding binding) {
ITypeBinding declaringType= null;
if (binding instanceof IVariableBinding) {
declaringType= ((IVariableBinding) binding).getDeclaringClass();
} else if (binding instanceof IMethodBinding) {
declaringType= ((IMethodBinding) binding).getDeclaringClass();
} else if (binding instanceof ITypeBinding) {
declaringType= ((ITypeBinding) binding).getDeclaringClass();
}
return declaringType != null && (declaringType.isInterface() || declaringType.isAnnotation());
}
private static boolean isInterfaceOrAnnotationMember(BodyDeclaration bodyDeclaration) {
return isInterfaceOrAnnotation(bodyDeclaration.getParent());
}
private static boolean isInterfaceOrAnnotation(ASTNode node) {
boolean isInterface= (node instanceof TypeDeclaration) && ((TypeDeclaration) node).isInterface();
boolean isAnnotation= node instanceof AnnotationTypeDeclaration;
return isInterface || isAnnotation;
}
private static boolean isNestedInterfaceOrAnnotation(BodyDeclaration bodyDeclaration) {
return bodyDeclaration.getParent() instanceof AbstractTypeDeclaration && isInterfaceOrAnnotation(bodyDeclaration);
}
private static boolean isNestedInterfaceOrAnnotation(IMember member) throws JavaModelException{
return member.getElementType() == IJavaElement.TYPE &&
member.getDeclaringType() != null &&
JavaModelUtil.isInterfaceOrAnnotation((IType)member);
}
private static boolean isEnumConstant(IMember member) throws JavaModelException {
return member.getElementType() == IJavaElement.FIELD && isEnum(member);
}
private static boolean isAnonymousType(IMember member) throws JavaModelException {
return member.getElementType() == IJavaElement.TYPE &&
((IType)member).isAnonymous();
}
public static int getVisibilityCode(IMember member) throws JavaModelException {
if (isPublic(member))
return Modifier.PUBLIC;
else if (isProtected(member))
return Modifier.PROTECTED;
else if (isPackageVisible(member))
return Modifier.NONE;
else if (isPrivate(member))
return Modifier.PRIVATE;
Assert.isTrue(false);
return VISIBILITY_CODE_INVALID;
}
public static int getVisibilityCode(BodyDeclaration bodyDeclaration) {
if (isPublic(bodyDeclaration))
return Modifier.PUBLIC;
else if (isProtected(bodyDeclaration))
return Modifier.PROTECTED;
else if (isPackageVisible(bodyDeclaration))
return Modifier.NONE;
else if (isPrivate(bodyDeclaration))
return Modifier.PRIVATE;
Assert.isTrue(false);
return VISIBILITY_CODE_INVALID;
}
public static int getVisibilityCode(IBinding binding) {
if (isPublic(binding))
return Modifier.PUBLIC;
else if (isProtected(binding))
return Modifier.PROTECTED;
else if (isPackageVisible(binding))
return Modifier.NONE;
else if (isPrivate(binding))
return Modifier.PRIVATE;
Assert.isTrue(false);
return VISIBILITY_CODE_INVALID;
}
public static String getVisibilityString(int visibilityCode){
if (Modifier.isPublic(visibilityCode))
return VISIBILITY_STRING_PUBLIC;
if (Modifier.isProtected(visibilityCode))
return VISIBILITY_STRING_PROTECTED;
if (Modifier.isPrivate(visibilityCode))
return VISIBILITY_STRING_PRIVATE;
return VISIBILITY_STRING_PACKAGE;
}
public static int getVisibilityCode(String visibilityString) {
Assert.isNotNull(visibilityString);
if (null != visibilityString)
switch (visibilityString) {
case VISIBILITY_STRING_PACKAGE:
return 0;
case VISIBILITY_STRING_PRIVATE:
return Modifier.PRIVATE;
case VISIBILITY_STRING_PROTECTED:
return Modifier.PROTECTED;
case VISIBILITY_STRING_PUBLIC:
return Modifier.PUBLIC;
default:
break;
}
return VISIBILITY_CODE_INVALID;
}
public static void assertVisibility(int visibility){
Assert.isTrue( visibility == Modifier.PUBLIC ||
visibility == Modifier.PROTECTED ||
visibility == Modifier.NONE ||
visibility == Modifier.PRIVATE);
}
/**
* Compares two visibilities.
*
* @param newVisibility the 'new' visibility
* @param oldVisibility the 'old' visibility
* @return <code>true</code> iff the 'new' visibility is strictly higher than the old visibility
*
* @see Modifier#PUBLIC
* @see Modifier#PROTECTED
* @see Modifier#NONE
* @see Modifier#PRIVATE
*/
public static boolean isHigherVisibility(int newVisibility, int oldVisibility){
assertVisibility(oldVisibility);
assertVisibility(newVisibility);
switch (oldVisibility) {
case Modifier.PRIVATE :
return newVisibility == Modifier.NONE
|| newVisibility == Modifier.PUBLIC
|| newVisibility == Modifier.PROTECTED;
case Modifier.NONE :
return newVisibility == Modifier.PUBLIC
|| newVisibility == Modifier.PROTECTED;
case Modifier.PROTECTED :
return newVisibility == Modifier.PUBLIC;
case Modifier.PUBLIC :
return false;
default:
Assert.isTrue(false);
return false;
}
}
public static int getLowerVisibility(int visibility1, int visibility2) {
if (isHigherVisibility(visibility1, visibility2))
return visibility2;
else
return visibility1;
}
/**
* Gets the higher visibility of the given parameters.
*
* @param visibility1 First visibility value to compare. Valid inputs are the {@link Modifier} visibility constants.
* @param visibility2 Second visibility value to compare. Valid inputs are the {@link Modifier} visibility constants.
* @return The parameter value with the higher visibility.
* @since 3.9
*/
public static int getHigherVisibility(int visibility1, int visibility2) {
if (isHigherVisibility(visibility1, visibility2))
return visibility1;
else
return visibility2;
}
public static int clearAccessModifiers(int flags) {
return clearFlag(Modifier.PROTECTED | Modifier.PUBLIC | Modifier.PRIVATE, flags);
}
public static int clearFlag(int flag, int flags){
return flags & ~ flag;
}
}