1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package com.sun.tools.apt.mirror.util; 27 28 29 import com.sun.mirror.declaration.*; 30 import com.sun.mirror.util.Declarations; 31 import com.sun.tools.apt.mirror.declaration.DeclarationImpl; 32 import com.sun.tools.apt.mirror.declaration.MethodDeclarationImpl; 33 import com.sun.tools.apt.mirror.util.DeclarationsImpl; 34 import com.sun.tools.apt.mirror.AptEnv; 35 import com.sun.tools.javac.code.*; 36 import com.sun.tools.javac.code.Symbol.*; 37 import com.sun.tools.javac.util.Context; 38 39 import static com.sun.tools.javac.code.Kinds.*; 40 41 42 /** 43 * Implementation of Declarations utility methods for annotation processors 44 */ 45 46 public class DeclarationsImpl implements Declarations { 47 48 private final AptEnv env; 49 50 51 private static final Context.Key<Declarations> declarationsKey = 52 new Context.Key<Declarations>(); 53 54 public static Declarations instance(Context context) { 55 Declarations instance = context.get(declarationsKey); 56 if (instance == null) { 57 instance = new DeclarationsImpl(context); 58 } 59 return instance; 60 } 61 62 private DeclarationsImpl(Context context) { 63 context.put(declarationsKey, this); 64 env = AptEnv.instance(context); 65 } 66 67 68 /** 69 * {@inheritDoc} 70 * See JLS 2 sections 8.3 and 8.4.6. 71 */ 72 public boolean hides(MemberDeclaration sub, MemberDeclaration sup) { 73 Symbol hider = ((DeclarationImpl) sub).sym; 74 Symbol hidee = ((DeclarationImpl) sup).sym; 75 76 // Fields only hide fields; methods only methods; types only types. 77 // Names must match. Nothing hides itself (just try it). 78 if (hider == hidee || 79 hider.kind != hidee.kind || 80 hider.name != hidee.name) { 81 return false; 82 } 83 84 // Only static methods can hide other methods. 85 // Methods only hide methods with matching signatures. 86 if (hider.kind == MTH) { 87 if ((hider.flags() & Flags.STATIC) == 0 || 88 !env.jctypes.isSubSignature(hider.type, hidee.type)) { 89 return false; 90 } 91 } 92 93 // Hider must be in a subclass of hidee's class. 94 // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible 95 // in M1's class, then M1 and M2 both hide M3. 96 ClassSymbol hiderClass = hider.owner.enclClass(); 97 ClassSymbol hideeClass = hidee.owner.enclClass(); 98 if (hiderClass == null || hideeClass == null || 99 !hiderClass.isSubClass(hideeClass, env.jctypes)) { 100 return false; 101 } 102 103 // Hidee must be accessible in hider's class. 104 // The method isInheritedIn is poorly named: it checks only access. 105 return hidee.isInheritedIn(hiderClass, env.jctypes); 106 } 107 108 /** 109 * {@inheritDoc} 110 * See JLS 2 section 8.4.6.1. 111 */ 112 public boolean overrides(MethodDeclaration sub, MethodDeclaration sup) { 113 MethodSymbol overrider = ((MethodDeclarationImpl) sub).sym; 114 MethodSymbol overridee = ((MethodDeclarationImpl) sup).sym; 115 ClassSymbol origin = (ClassSymbol) overrider.owner; 116 117 return overrider.name == overridee.name && 118 119 // not reflexive as per JLS 120 overrider != overridee && 121 122 // we don't care if overridee is static, though that wouldn't 123 // compile 124 !overrider.isStatic() && 125 126 // overrider, whose declaring type is the origin, must be 127 // in a subtype of overridee's type 128 env.jctypes.asSuper(origin.type, overridee.owner) != null && 129 130 // check access and signatures; don't check return types 131 overrider.overrides(overridee, origin, env.jctypes, false); 132 } 133 }