001 /*
002 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.apt.mirror.util;
027
028
029 import com.sun.mirror.declaration.*;
030 import com.sun.mirror.util.Declarations;
031 import com.sun.tools.apt.mirror.declaration.DeclarationImpl;
032 import com.sun.tools.apt.mirror.declaration.MethodDeclarationImpl;
033 import com.sun.tools.apt.mirror.util.DeclarationsImpl;
034 import com.sun.tools.apt.mirror.AptEnv;
035 import com.sun.tools.javac.code.*;
036 import com.sun.tools.javac.code.Symbol.*;
037 import com.sun.tools.javac.util.Context;
038
039 import static com.sun.tools.javac.code.Kinds.*;
040
041
042 /**
043 * Implementation of Declarations utility methods for annotation processors
044 */
045
046 public class DeclarationsImpl implements Declarations {
047
048 private final AptEnv env;
049
050
051 private static final Context.Key<Declarations> declarationsKey =
052 new Context.Key<Declarations>();
053
054 public static Declarations instance(Context context) {
055 Declarations instance = context.get(declarationsKey);
056 if (instance == null) {
057 instance = new DeclarationsImpl(context);
058 }
059 return instance;
060 }
061
062 private DeclarationsImpl(Context context) {
063 context.put(declarationsKey, this);
064 env = AptEnv.instance(context);
065 }
066
067
068 /**
069 * {@inheritDoc}
070 * See JLS 2 sections 8.3 and 8.4.6.
071 */
072 public boolean hides(MemberDeclaration sub, MemberDeclaration sup) {
073 Symbol hider = ((DeclarationImpl) sub).sym;
074 Symbol hidee = ((DeclarationImpl) sup).sym;
075
076 // Fields only hide fields; methods only methods; types only types.
077 // Names must match. Nothing hides itself (just try it).
078 if (hider == hidee ||
079 hider.kind != hidee.kind ||
080 hider.name != hidee.name) {
081 return false;
082 }
083
084 // Only static methods can hide other methods.
085 // Methods only hide methods with matching signatures.
086 if (hider.kind == MTH) {
087 if ((hider.flags() & Flags.STATIC) == 0 ||
088 !env.jctypes.isSubSignature(hider.type, hidee.type)) {
089 return false;
090 }
091 }
092
093 // Hider must be in a subclass of hidee's class.
094 // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible
095 // in M1's class, then M1 and M2 both hide M3.
096 ClassSymbol hiderClass = hider.owner.enclClass();
097 ClassSymbol hideeClass = hidee.owner.enclClass();
098 if (hiderClass == null || hideeClass == null ||
099 !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 }