Tue, 11 Aug 2009 01:13:14 +0100
6521805: Regression: JDK5/JDK6 javac allows write access to outer class reference
Summary: javac should warn/complain about identifiers with the same name as synthetic symbol
Reviewed-by: jjg
1 /*
2 * Copyright 1997-2006 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 */
26 package com.sun.tools.javadoc;
28 import com.sun.javadoc.*;
30 import com.sun.tools.javac.code.*;
31 import com.sun.tools.javac.code.Symbol.*;
32 import com.sun.tools.javac.code.Type;
33 import com.sun.tools.javac.code.TypeTags;
34 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
35 import com.sun.tools.javac.util.Position;
37 import java.lang.reflect.Modifier;
39 /**
40 * Represents a method of a java class.
41 *
42 * @since 1.2
43 * @author Robert Field
44 * @author Neal Gafter (rewrite)
45 */
47 public class MethodDocImpl
48 extends ExecutableMemberDocImpl implements MethodDoc {
50 /**
51 * constructor.
52 */
53 public MethodDocImpl(DocEnv env, MethodSymbol sym) {
54 super(env, sym);
55 }
57 /**
58 * constructor.
59 */
60 public MethodDocImpl(DocEnv env, MethodSymbol sym,
61 String docComment, JCMethodDecl tree, Position.LineMap lineMap) {
62 super(env, sym, docComment, tree, lineMap);
63 }
65 /**
66 * Return true if it is a method, which it is.
67 * Note: constructors are not methods.
68 * This method is overridden by AnnotationTypeElementDocImpl.
69 *
70 * @return true
71 */
72 public boolean isMethod() {
73 return true;
74 }
76 /**
77 * Return true if this method is abstract
78 */
79 public boolean isAbstract() {
80 //### This is dubious, but old 'javadoc' apparently does it.
81 //### I regard this as a bug and an obstacle to treating the
82 //### doclet API as a proper compile-time reflection facility.
83 //### (maddox 09/26/2000)
84 if (containingClass().isInterface()) {
85 //### Don't force creation of ClassDocImpl for super here.
86 // Abstract modifier is implicit. Strip/canonicalize it.
87 return false;
88 }
89 return Modifier.isAbstract(getModifiers());
90 }
92 /**
93 * Get return type.
94 *
95 * @return the return type of this method, null if it
96 * is a constructor.
97 */
98 public com.sun.javadoc.Type returnType() {
99 return TypeMaker.getType(env, sym.type.getReturnType(), false);
100 }
102 /**
103 * Return the class that originally defined the method that
104 * is overridden by the current definition, or null if no
105 * such class exists.
106 *
107 * @return a ClassDocImpl representing the superclass that
108 * originally defined this method, null if this method does
109 * not override a definition in a superclass.
110 */
111 public ClassDoc overriddenClass() {
112 com.sun.javadoc.Type t = overriddenType();
113 return (t != null) ? t.asClassDoc() : null;
114 }
116 /**
117 * Return the type containing the method that this method overrides.
118 * It may be a <code>ClassDoc</code> or a <code>ParameterizedType</code>.
119 */
120 public com.sun.javadoc.Type overriddenType() {
122 if ((sym.flags() & Flags.STATIC) != 0) {
123 return null;
124 }
126 ClassSymbol origin = (ClassSymbol)sym.owner;
127 for (Type t = env.types.supertype(origin.type);
128 t.tag == TypeTags.CLASS;
129 t = env.types.supertype(t)) {
130 ClassSymbol c = (ClassSymbol)t.tsym;
131 for (Scope.Entry e = c.members().lookup(sym.name); e.scope != null; e = e.next()) {
132 if (sym.overrides(e.sym, origin, env.types, true)) {
133 return TypeMaker.getType(env, t);
134 }
135 }
136 }
137 return null;
138 }
140 /**
141 * Return the method that this method overrides.
142 *
143 * @return a MethodDoc representing a method definition
144 * in a superclass this method overrides, null if
145 * this method does not override.
146 */
147 public MethodDoc overriddenMethod() {
149 // Real overriding only. Static members are simply hidden.
150 // Likewise for constructors, but the MethodSymbol.overrides
151 // method takes this into account.
152 if ((sym.flags() & Flags.STATIC) != 0) {
153 return null;
154 }
156 // Derived from com.sun.tools.javac.comp.Check.checkOverride .
158 ClassSymbol origin = (ClassSymbol)sym.owner;
159 for (Type t = env.types.supertype(origin.type);
160 t.tag == TypeTags.CLASS;
161 t = env.types.supertype(t)) {
162 ClassSymbol c = (ClassSymbol)t.tsym;
163 for (Scope.Entry e = c.members().lookup(sym.name); e.scope != null; e = e.next()) {
164 if (sym.overrides(e.sym, origin, env.types, true)) {
165 return env.getMethodDoc((MethodSymbol)e.sym);
166 }
167 }
168 }
169 return null;
170 }
172 /**
173 * Tests whether this method overrides another.
174 * The overridden method may be one declared in a superclass or
175 * a superinterface (unlike {@link #overriddenMethod()}).
176 *
177 * <p> When a non-abstract method overrides an abstract one, it is
178 * also said to <i>implement</i> the other.
179 *
180 * @param meth the other method to examine
181 * @return <tt>true</tt> if this method overrides the other
182 */
183 public boolean overrides(MethodDoc meth) {
184 MethodSymbol overridee = ((MethodDocImpl) meth).sym;
185 ClassSymbol origin = (ClassSymbol) sym.owner;
187 return sym.name == overridee.name &&
189 // not reflexive as per JLS
190 sym != overridee &&
192 // we don't care if overridee is static, though that wouldn't
193 // compile
194 !sym.isStatic() &&
196 // sym, whose declaring type is the origin, must be
197 // in a subtype of overridee's type
198 env.types.asSuper(origin.type, overridee.owner) != null &&
200 // check access and signatures; don't check return types
201 sym.overrides(overridee, origin, env.types, false);
202 }
205 public String name() {
206 return sym.name.toString();
207 }
209 public String qualifiedName() {
210 return sym.enclClass().getQualifiedName() + "." + sym.name;
211 }
213 /**
214 * Returns a string representation of this method. Includes the
215 * qualified signature, the qualified method name, and any type
216 * parameters. Type parameters follow the class name, as they do
217 * in the syntax for invoking methods with explicit type parameters.
218 */
219 public String toString() {
220 return sym.enclClass().getQualifiedName() +
221 "." + typeParametersString() + name() + signature();
222 }
223 }