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    }