/******************************************************************************* * Copyright (c) 2005, 2007 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.NonEclipseImplementationException; import org.eclipse.jdt.apt.core.internal.declaration.DeclarationImpl; import org.eclipse.jdt.apt.core.internal.declaration.EclipseDeclarationImpl; import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject; 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; if( ! ((EclipseDeclarationImpl)sub).isBindingBased() || ! ((EclipseDeclarationImpl)sup).isBindingBased() ) 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 EclipseMirrorObject ){ if( memberDecl instanceof DeclarationImpl ) return ((DeclarationImpl)memberDecl).getDeclarationBinding(); else return null; } throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$ " Found " + memberDecl.getClass().getName()); //$NON-NLS-1$ } 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; } }