| /******************************************************************************* |
| * Copyright (c) 2005 BEA Systems, Inc. |
| * 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 |
| * |
| * Contributors: |
| * tyeung@bea.com - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.apt.core.internal.util; |
| |
| import org.eclipse.jdt.apt.core.internal.EclipseMirrorImpl; |
| import org.eclipse.jdt.apt.core.internal.NonEclipseImplementationException; |
| import org.eclipse.jdt.apt.core.internal.declaration.DeclarationImpl; |
| import org.eclipse.jdt.apt.core.internal.declaration.MemberDeclarationImpl; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.IPackageBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.Modifier; |
| |
| import com.sun.mirror.declaration.MemberDeclaration; |
| import com.sun.mirror.declaration.MethodDeclaration; |
| import com.sun.mirror.util.Declarations; |
| |
| public class DeclarationsUtil implements Declarations |
| { |
| public boolean hides(MemberDeclaration sub, MemberDeclaration sup) { |
| |
| // A declaration cannot hide itself |
| if (sub == sup || sub.equals(sup)) |
| return false; |
| |
| MemberDeclarationImpl subImpl = (MemberDeclarationImpl)sub; |
| MemberDeclarationImpl supImpl = (MemberDeclarationImpl)sup; |
| |
| IBinding subBinding = subImpl.getDeclarationBinding(); |
| IBinding supBinding = supImpl.getDeclarationBinding(); |
| |
| |
| // Hiding can only take place between declarations of the same kind and name, |
| // and types, variables and methods |
| int subKind = subBinding.getKind(); |
| int supKind = supBinding.getKind(); |
| if (subKind != supKind || subKind == IBinding.PACKAGE) |
| return false; |
| if (!subBinding.getName().equals(supBinding.getName())) |
| return false; |
| |
| // Methods must be both static and the sub a subsignature of the sup |
| if (subKind == IBinding.METHOD) { |
| boolean allowed = false; |
| int modifiers = subBinding.getModifiers(); |
| if ((modifiers & Modifier.STATIC) == Modifier.STATIC) { |
| IMethodBinding methodBinding = (IMethodBinding)subBinding; |
| if (methodBinding.isSubsignature((IMethodBinding)supBinding)) { |
| allowed = true; |
| } |
| } |
| if (!allowed) |
| return false; |
| } |
| |
| // sub's enclosing class must be a subclass of sup's |
| ITypeBinding subClass = getDeclaringClass(subBinding); |
| ITypeBinding supClass = getDeclaringClass(supBinding); |
| if (subClass == null || supClass == null) |
| return false; |
| if (!subClass.isSubTypeCompatible(supClass)) |
| return false; |
| |
| // sup must be visible from sub |
| if (!isVisibleForHiding(supClass, supClass, supBinding.getModifiers())) |
| return false; |
| |
| return true; |
| } |
| |
| /** |
| * Is a method, field, type visible from the viewer? |
| * That is, do accessibility rules allow it? (public, protected, etc.)<P> |
| * |
| * Note that we make an assumption about protected here since |
| * its use in hides() already determines that the declaringTarget |
| * must be a subclass of the declaringViewer. |
| */ |
| private static boolean isVisibleForHiding( |
| final ITypeBinding declaringTarget, |
| final ITypeBinding declaringViewer, |
| final int modifiers) { |
| |
| // Public is always visible |
| if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC) |
| return true; |
| if ((modifiers & Modifier.PRIVATE) == Modifier.PRIVATE) { |
| // Must be the same class |
| if (declaringTarget.equals(declaringViewer)) |
| return true; |
| else |
| return false; |
| } |
| if ((modifiers & Modifier.PROTECTED) == Modifier.PROTECTED) { |
| // We've already checked for subclassing |
| return true; |
| } |
| // Package-friendly (no accessibility modifier) |
| // Classes must be in the same package |
| IPackageBinding targetPackage = declaringTarget.getPackage(); |
| IPackageBinding viewerPackage = declaringViewer.getPackage(); |
| return targetPackage.equals(viewerPackage); |
| } |
| |
| public boolean overrides(MethodDeclaration sub, MethodDeclaration sup) { |
| final IMethodBinding subBinding = (IMethodBinding)getBinding(sub); |
| final IMethodBinding supBinding = (IMethodBinding)getBinding(sup); |
| if(subBinding == null || supBinding == null) return false; |
| return subBinding.overrides(supBinding); |
| } |
| |
| private static IBinding getBinding(MemberDeclaration memberDecl) |
| throws NonEclipseImplementationException |
| { |
| if( memberDecl == null ) return null; |
| if( memberDecl instanceof EclipseMirrorImpl ){ |
| return ((DeclarationImpl)memberDecl).getDeclarationBinding(); |
| } |
| throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + |
| " Found " + memberDecl.getClass().getName()); |
| } |
| |
| private static ITypeBinding getDeclaringClass(IBinding binding) { |
| int kind = binding.getKind(); |
| if (kind == IBinding.TYPE) |
| return ((ITypeBinding)binding).getDeclaringClass(); |
| if (kind == IBinding.METHOD) |
| return ((IMethodBinding)binding).getDeclaringClass(); |
| if (kind == IBinding.VARIABLE) |
| return ((IVariableBinding)binding).getDeclaringClass(); |
| |
| // Package binding -- no declaring class |
| return null; |
| } |
| } |