History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/java/ClassDefinition.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/java/ClassDefinition.java+2085−0
@@ -0,0 +1,2085 @@
1+/*
2+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. 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. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.*;
29+import java.io.OutputStream;
30+import java.io.PrintStream;
31+import sun.tools.tree.Context;
32+import sun.tools.tree.Vset;
33+import sun.tools.tree.Expression;
34+import sun.tools.tree.LocalMember;
35+import sun.tools.tree.UplevelReference;
36+
37+/**
38+ * This class is a Java class definition
39+ *
40+ * WARNING: The contents of this source file are not part of any
41+ * supported API. Code that depends on them does so at its own risk:
42+ * they are subject to change or removal without notice.
43+ */
44+public
45+class ClassDefinition implements Constants {
46+
47+ protected Object source;
48+ protected long where;
49+ protected int modifiers;
50+ protected Identifier localName; // for local classes
51+ protected ClassDeclaration declaration;
52+ protected IdentifierToken superClassId;
53+ protected IdentifierToken interfaceIds[];
54+ protected ClassDeclaration superClass;
55+ protected ClassDeclaration interfaces[];
56+ protected ClassDefinition outerClass;
57+ protected MemberDefinition outerMember;
58+ protected MemberDefinition innerClassMember; // field for me in outerClass
59+ protected MemberDefinition firstMember;
60+ protected MemberDefinition lastMember;
61+ protected boolean resolved;
62+ protected String documentation;
63+ protected boolean error;
64+ protected boolean nestError;
65+ protected UplevelReference references;
66+ protected boolean referencesFrozen;
67+ private Hashtable fieldHash = new Hashtable(31);
68+ private int abstr;
69+
70+ // Table of local and anonymous classes whose internal names are constructed
71+ // using the current class as a prefix. This is part of a fix for
72+ // bugid 4054523 and 4030421. See also 'Environment.getClassDefinition'
73+ // and 'BatchEnvironment.makeClassDefinition'. Allocated on demand.
74+ private Hashtable localClasses = null;
75+ private final int LOCAL_CLASSES_SIZE = 31;
76+
77+ // The immediately surrounding context in which the class appears.
78+ // Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.
79+ // Null for classes that are not local or inside a local class.
80+ // At present, this field exists only for the benefit of 'resolveName' as part
81+ // of the fix for 4095716.
82+ protected Context classContext;
83+
84+ // The saved class context is now also used in 'SourceClass.getAccessMember'.
85+ // Provide read-only access via this method. Part of fix for 4098093.
86+ public Context getClassContext() {
87+ return classContext;
88+ }
89+
90+
91+ /**
92+ * Constructor
93+ */
94+ protected ClassDefinition(Object source, long where, ClassDeclaration declaration,
95+ int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {
96+ this.source = source;
97+ this.where = where;
98+ this.declaration = declaration;
99+ this.modifiers = modifiers;
100+ this.superClassId = superClass;
101+ this.interfaceIds = interfaces;
102+ }
103+
104+ /**
105+ * Get the source of the class
106+ */
107+ public final Object getSource() {
108+ return source;
109+ }
110+
111+ /**
112+ * Check if there were any errors in this class.
113+ */
114+ public final boolean getError() {
115+ return error;
116+ }
117+
118+ /**
119+ * Mark this class to be erroneous.
120+ */
121+ public final void setError() {
122+ this.error = true;
123+ setNestError();
124+ }
125+
126+ /**
127+ * Check if there were any errors in our class nest.
128+ */
129+ public final boolean getNestError() {
130+ // Check to see if our error value is set, or if any of our
131+ // outer classes' error values are set. This will work in
132+ // conjunction with setError(), which sets the error value
133+ // of its outer class, to yield true is any of our nest
134+ // siblings has an error. This addresses bug 4111488: either
135+ // code should be generated for all classes in a nest, or
136+ // none of them.
137+ return nestError || ((outerClass != null) ? outerClass.getNestError() : false);
138+ }
139+
140+ /**
141+ * Mark this class, and all siblings in its class nest, to be
142+ * erroneous.
143+ */
144+ public final void setNestError() {
145+ this.nestError = true;
146+ if (outerClass != null) {
147+ // If we have an outer class, set it to be erroneous as well.
148+ // This will work in conjunction with getError(), which checks
149+ // the error value of its outer class, to set the whole class
150+ // nest to be erroneous. This address bug 4111488: either
151+ // code should be generated for all classes in a nest, or
152+ // none of them.
153+ outerClass.setNestError();
154+ }
155+ }
156+
157+ /**
158+ * Get the position in the input
159+ */
160+ public final long getWhere() {
161+ return where;
162+ }
163+
164+ /**
165+ * Get the class declaration
166+ */
167+ public final ClassDeclaration getClassDeclaration() {
168+ return declaration;
169+ }
170+
171+ /**
172+ * Get the class' modifiers
173+ */
174+ public final int getModifiers() {
175+ return modifiers;
176+ }
177+ public final void subModifiers(int mod) {
178+ modifiers &= ~mod;
179+ }
180+ public final void addModifiers(int mod) {
181+ modifiers |= mod;
182+ }
183+
184+ // *** DEBUG ***
185+ protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);
186+
187+ /**
188+ * Get the class' super class
189+ */
190+ public final ClassDeclaration getSuperClass() {
191+ /*---
192+ if (superClass == null && superClassId != null)
193+ throw new CompilerError("getSuperClass "+superClassId);
194+ // There are obscure cases where null is the right answer,
195+ // in order to enable some error reporting later on.
196+ // For example: class T extends T.N { class N { } }
197+ ---*/
198+
199+ // *** DEBUG ***
200+ // This method should not be called if the superclass has not been resolved.
201+ if (!supersCheckStarted) throw new CompilerError("unresolved super");
202+
203+ return superClass;
204+ }
205+
206+ /**
207+ * Get the super class, and resolve names now if necessary.
208+ *
209+ * It is only possible to resolve names at this point if we are
210+ * a source class. The provision of this method at this level
211+ * in the class hierarchy is dubious, but see 'getInnerClass' below.
212+ * All other calls to 'getSuperClass(env)' appear in 'SourceClass'.
213+ * NOTE: An older definition of this method has been moved to
214+ * 'SourceClass', where it overrides this one.
215+ *
216+ * @see #resolveTypeStructure
217+ */
218+
219+ public ClassDeclaration getSuperClass(Environment env) {
220+ return getSuperClass();
221+ }
222+
223+ /**
224+ * Get the class' interfaces
225+ */
226+ public final ClassDeclaration getInterfaces()[] {
227+ if (interfaces == null) throw new CompilerError("getInterfaces");
228+ return interfaces;
229+ }
230+
231+ /**
232+ * Get the class' enclosing class (or null if not inner)
233+ */
234+ public final ClassDefinition getOuterClass() {
235+ return outerClass;
236+ }
237+
238+ /**
239+ * Set the class' enclosing class. Must be done at most once.
240+ */
241+ protected final void setOuterClass(ClassDefinition outerClass) {
242+ if (this.outerClass != null) throw new CompilerError("setOuterClass");
243+ this.outerClass = outerClass;
244+ }
245+
246+ /**
247+ * Set the class' enclosing current instance pointer.
248+ * Must be done at most once.
249+ */
250+ protected final void setOuterMember(MemberDefinition outerMember) {
251+
252+ if (isStatic() || !isInnerClass()) throw new CompilerError("setOuterField");
253+ if (this.outerMember != null) throw new CompilerError("setOuterField");
254+ this.outerMember = outerMember;
255+ }
256+
257+ /**
258+ * Tell if the class is inner.
259+ * This predicate also returns true for top-level nested types.
260+ * To test for a true inner class as seen by the programmer,
261+ * use <tt>!isTopLevel()</tt>.
262+ */
263+ public final boolean isInnerClass() {
264+ return outerClass != null;
265+ }
266+
267+ /**
268+ * Tell if the class is a member of another class.
269+ * This is false for package members and for block-local classes.
270+ */
271+ public final boolean isMember() {
272+ return outerClass != null && !isLocal();
273+ }
274+
275+ /**
276+ * Tell if the class is "top-level", which is either a package member,
277+ * or a static member of another top-level class.
278+ */
279+ public final boolean isTopLevel() {
280+ return outerClass == null || isStatic() || isInterface();
281+ }
282+
283+ /**
284+ * Tell if the class is local or inside a local class,
285+ * which means it cannot be mentioned outside of its file.
286+ */
287+
288+ // The comment above is true only because M_LOCAL is set
289+ // whenever M_ANONYMOUS is. I think it is risky to assume that
290+ // isAnonymous(x) => isLocal(x).
291+
292+ public final boolean isInsideLocal() {
293+ return isLocal() ||
294+ (outerClass != null && outerClass.isInsideLocal());
295+ }
296+
297+ /**
298+ * Tell if the class is local or or anonymous class, or inside
299+ * such a class, which means it cannot be mentioned outside of
300+ * its file.
301+ */
302+ public final boolean isInsideLocalOrAnonymous() {
303+ return isLocal() || isAnonymous () ||
304+ (outerClass != null && outerClass.isInsideLocalOrAnonymous());
305+ }
306+
307+ /**
308+ * Return a simple identifier for this class (idNull if anonymous).
309+ */
310+ public Identifier getLocalName() {
311+ if (localName != null) {
312+ return localName;
313+ }
314+ // This is also the name of the innerClassMember, if any:
315+ return getName().getFlatName().getName();
316+ }
317+
318+ /**
319+ * Set the local name of a class. Must be a local class.
320+ */
321+ public void setLocalName(Identifier name) {
322+ if (isLocal()) {
323+ localName = name;
324+ }
325+ }
326+
327+ /**
328+ * If inner, get the field for this class in the enclosing class
329+ */
330+ public final MemberDefinition getInnerClassMember() {
331+ if (outerClass == null)
332+ return null;
333+ if (innerClassMember == null) {
334+ // We must find the field in the outer class.
335+ Identifier nm = getName().getFlatName().getName();
336+ for (MemberDefinition field = outerClass.getFirstMatch(nm);
337+ field != null; field = field.getNextMatch()) {
338+ if (field.isInnerClass()) {
339+ innerClassMember = field;
340+ break;
341+ }
342+ }
343+ if (innerClassMember == null)
344+ throw new CompilerError("getInnerClassField");
345+ }
346+ return innerClassMember;
347+ }
348+
349+ /**
350+ * If inner, return an innermost uplevel self pointer, if any exists.
351+ * Otherwise, return null.
352+ */
353+ public final MemberDefinition findOuterMember() {
354+ return outerMember;
355+ }
356+
357+ /**
358+ * See if this is a (nested) static class.
359+ */
360+ public final boolean isStatic() {
361+ return (modifiers & ACC_STATIC) != 0;
362+ }
363+
364+ /**
365+ * Get the class' top-level enclosing class
366+ */
367+ public final ClassDefinition getTopClass() {
368+ ClassDefinition p, q;
369+ for (p = this; (q = p.outerClass) != null; p = q)
370+ ;
371+ return p;
372+ }
373+
374+ /**
375+ * Get the class' first field or first match
376+ */
377+ public final MemberDefinition getFirstMember() {
378+ return firstMember;
379+ }
380+ public final MemberDefinition getFirstMatch(Identifier name) {
381+ return (MemberDefinition)fieldHash.get(name);
382+ }
383+
384+ /**
385+ * Get the class' name
386+ */
387+ public final Identifier getName() {
388+ return declaration.getName();
389+ }
390+
391+ /**
392+ * Get the class' type
393+ */
394+ public final Type getType() {
395+ return declaration.getType();
396+ }
397+
398+ /**
399+ * Get the class' documentation
400+ */
401+ public String getDocumentation() {
402+ return documentation;
403+ }
404+
405+ /**
406+ * Return true if the given documentation string contains a deprecation
407+ * paragraph. This is true if the string contains the tag @deprecated
408+ * is the first word in a line.
409+ */
410+ public static boolean containsDeprecated(String documentation) {
411+ if (documentation == null) {
412+ return false;
413+ }
414+ doScan:
415+ for (int scan = 0;
416+ (scan = documentation.indexOf(paraDeprecated, scan)) >= 0;
417+ scan += paraDeprecated.length()) {
418+ // make sure there is only whitespace between this word
419+ // and the beginning of the line
420+ for (int beg = scan-1; beg >= 0; beg--) {
421+ char ch = documentation.charAt(beg);
422+ if (ch == '\n' || ch == '\r') {
423+ break; // OK
424+ }
425+ if (!Character.isSpace(ch)) {
426+ continue doScan;
427+ }
428+ }
429+ // make sure the char after the word is space or end of line
430+ int end = scan+paraDeprecated.length();
431+ if (end < documentation.length()) {
432+ char ch = documentation.charAt(end);
433+ if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {
434+ continue doScan;
435+ }
436+ }
437+ return true;
438+ }
439+ return false;
440+ }
441+
442+ public final boolean inSamePackage(ClassDeclaration c) {
443+ // find out if the class stored in c is defined in the same
444+ // package as the current class.
445+ return inSamePackage(c.getName().getQualifier());
446+ }
447+
448+ public final boolean inSamePackage(ClassDefinition c) {
449+ // find out if the class stored in c is defined in the same
450+ // package as the current class.
451+ return inSamePackage(c.getName().getQualifier());
452+ }
453+
454+ public final boolean inSamePackage(Identifier packageName) {
455+ return (getName().getQualifier().equals(packageName));
456+ }
457+
458+ /**
459+ * Checks
460+ */
461+ public final boolean isInterface() {
462+ return (getModifiers() & M_INTERFACE) != 0;
463+ }
464+ public final boolean isClass() {
465+ return (getModifiers() & M_INTERFACE) == 0;
466+ }
467+ public final boolean isPublic() {
468+ return (getModifiers() & M_PUBLIC) != 0;
469+ }
470+ public final boolean isPrivate() {
471+ return (getModifiers() & M_PRIVATE) != 0;
472+ }
473+ public final boolean isProtected() {
474+ return (getModifiers() & M_PROTECTED) != 0;
475+ }
476+ public final boolean isPackagePrivate() {
477+ return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;
478+ }
479+ public final boolean isFinal() {
480+ return (getModifiers() & M_FINAL) != 0;
481+ }
482+ public final boolean isAbstract() {
483+ return (getModifiers() & M_ABSTRACT) != 0;
484+ }
485+ public final boolean isSynthetic() {
486+ return (getModifiers() & M_SYNTHETIC) != 0;
487+ }
488+ public final boolean isDeprecated() {
489+ return (getModifiers() & M_DEPRECATED) != 0;
490+ }
491+ public final boolean isAnonymous() {
492+ return (getModifiers() & M_ANONYMOUS) != 0;
493+ }
494+ public final boolean isLocal() {
495+ return (getModifiers() & M_LOCAL) != 0;
496+ }
497+ public final boolean hasConstructor() {
498+ return getFirstMatch(idInit) != null;
499+ }
500+
501+
502+ /**
503+ * Check to see if a class must be abstract. This method replaces
504+ * isAbstract(env)
505+ */
506+ public final boolean mustBeAbstract(Environment env) {
507+ // If it is declared abstract, return true.
508+ // (Fix for 4110534.)
509+ if (isAbstract()) {
510+ return true;
511+ }
512+
513+ // Check to see if the class should have been declared to be
514+ // abstract.
515+
516+ // We make sure that the inherited method collection has been
517+ // performed.
518+ collectInheritedMethods(env);
519+
520+ // We check for any abstract methods inherited or declared
521+ // by this class.
522+ Iterator methods = getMethods();
523+ while (methods.hasNext()) {
524+ MemberDefinition method = (MemberDefinition) methods.next();
525+
526+ if (method.isAbstract()) {
527+ return true;
528+ }
529+ }
530+
531+ // We check for hidden "permanently abstract" methods in
532+ // our superclasses.
533+ return getPermanentlyAbstractMethods().hasNext();
534+ }
535+
536+ /**
537+ * Check if this is a super class of another class
538+ */
539+ public boolean superClassOf(Environment env, ClassDeclaration otherClass)
540+ throws ClassNotFound {
541+ while (otherClass != null) {
542+ if (getClassDeclaration().equals(otherClass)) {
543+ return true;
544+ }
545+ otherClass = otherClass.getClassDefinition(env).getSuperClass();
546+ }
547+ return false;
548+ }
549+
550+ /**
551+ * Check if this is an enclosing class of another class
552+ */
553+ public boolean enclosingClassOf(ClassDefinition otherClass) {
554+ while ((otherClass = otherClass.getOuterClass()) != null) {
555+ if (this == otherClass) {
556+ return true;
557+ }
558+ }
559+ return false;
560+ }
561+
562+ /**
563+ * Check if this is a sub class of another class
564+ */
565+ public boolean subClassOf(Environment env, ClassDeclaration otherClass) throws ClassNotFound {
566+ ClassDeclaration c = getClassDeclaration();
567+ while (c != null) {
568+ if (c.equals(otherClass)) {
569+ return true;
570+ }
571+ c = c.getClassDefinition(env).getSuperClass();
572+ }
573+ return false;
574+ }
575+
576+ /**
577+ * Check if this class is implemented by another class
578+ */
579+ public boolean implementedBy(Environment env, ClassDeclaration c) throws ClassNotFound {
580+ for (; c != null ; c = c.getClassDefinition(env).getSuperClass()) {
581+ if (getClassDeclaration().equals(c)) {
582+ return true;
583+ }
584+ ClassDeclaration intf[] = c.getClassDefinition(env).getInterfaces();
585+ for (int i = 0 ; i < intf.length ; i++) {
586+ if (implementedBy(env, intf[i])) {
587+ return true;
588+ }
589+ }
590+ }
591+ return false;
592+ }
593+
594+ /**
595+ * Check to see if a class which implements interface `this' could
596+ * possibly implement the interface `intDef'. Note that the only
597+ * way that this can fail is if `this' and `intDef' have methods
598+ * which are of the same signature and different return types. This
599+ * method is used by Environment.explicitCast() to determine if a
600+ * cast between two interfaces is legal.
601+ *
602+ * This method should only be called on a class after it has been
603+ * basicCheck()'ed.
604+ */
605+ public boolean couldImplement(ClassDefinition intDef) {
606+ // Check to see if we could have done the necessary checks.
607+ if (!doInheritanceChecks) {
608+ throw new CompilerError("couldImplement: no checks");
609+ }
610+
611+ // This method should only be called for interfaces.
612+ if (!isInterface() || !intDef.isInterface()) {
613+ throw new CompilerError("couldImplement: not interface");
614+ }
615+
616+ // Make sure we are not called before we have collected our
617+ // inheritance information.
618+ if (allMethods == null) {
619+ throw new CompilerError("couldImplement: called early");
620+ }
621+
622+ // Get the other classes' methods. getMethods() in
623+ // general can return methods which are not visible to the
624+ // current package. We need to make sure that these do not
625+ // prevent this class from being implemented.
626+ Iterator otherMethods = intDef.getMethods();
627+
628+ while (otherMethods.hasNext()) {
629+ // Get one of the methods from intDef...
630+ MemberDefinition method =
631+ (MemberDefinition) otherMethods.next();
632+
633+ Identifier name = method.getName();
634+ Type type = method.getType();
635+
636+ // See if we implement a method of the same signature...
637+ MemberDefinition myMethod = allMethods.lookupSig(name, type);
638+
639+ //System.out.println("Comparing\n\t" + myMethod +
640+ // "\nand\n\t" + method);
641+
642+ if (myMethod != null) {
643+ // We do. Make sure the methods have the same return type.
644+ if (!myMethod.sameReturnType(method)) {
645+ return false;
646+ }
647+ }
648+ }
649+
650+ return true;
651+ }
652+
653+ /**
654+ * Check if another class can be accessed from the 'extends' or 'implements'
655+ * clause of this class.
656+ */
657+ public boolean extendsCanAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
658+
659+ // Names in the 'extends' or 'implements' clause of an inner class
660+ // are checked as if they appeared in the body of the surrounding class.
661+ if (outerClass != null) {
662+ return outerClass.canAccess(env, c);
663+ }
664+
665+ // We are a package member.
666+
667+ ClassDefinition cdef = c.getClassDefinition(env);
668+
669+ if (cdef.isLocal()) {
670+ // No locals should be in scope in the 'extends' or
671+ // 'implements' clause of a package member.
672+ throw new CompilerError("top local");
673+ }
674+
675+ if (cdef.isInnerClass()) {
676+ MemberDefinition f = cdef.getInnerClassMember();
677+
678+ // Access to public member is always allowed.
679+ if (f.isPublic()) {
680+ return true;
681+ }
682+
683+ // Private access is ok only from the same class nest. This can
684+ // happen only if the class represented by 'this' encloses the inner
685+ // class represented by 'f'.
686+ if (f.isPrivate()) {
687+ return getClassDeclaration().equals(f.getTopClass().getClassDeclaration());
688+ }
689+
690+ // Protected or default access -- allow access if in same package.
691+ return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
692+ }
693+
694+ // Access to public member is always allowed.
695+ if (cdef.isPublic()) {
696+ return true;
697+ }
698+
699+ // Default access -- allow access if in same package.
700+ return getName().getQualifier().equals(c.getName().getQualifier());
701+ }
702+
703+ /**
704+ * Check if another class can be accessed from within the body of this class.
705+ */
706+ public boolean canAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
707+ ClassDefinition cdef = c.getClassDefinition(env);
708+
709+ if (cdef.isLocal()) {
710+ // if it's in scope, it's accessible
711+ return true;
712+ }
713+
714+ if (cdef.isInnerClass()) {
715+ return canAccess(env, cdef.getInnerClassMember());
716+ }
717+
718+ // Public access is always ok
719+ if (cdef.isPublic()) {
720+ return true;
721+ }
722+
723+ // It must be in the same package
724+ return getName().getQualifier().equals(c.getName().getQualifier());
725+ }
726+
727+ /**
728+ * Check if a field can be accessed from a class
729+ */
730+
731+ public boolean canAccess(Environment env, MemberDefinition f)
732+ throws ClassNotFound {
733+
734+ // Public access is always ok
735+ if (f.isPublic()) {
736+ return true;
737+ }
738+ // Protected access is ok from a subclass
739+ if (f.isProtected() && subClassOf(env, f.getClassDeclaration())) {
740+ return true;
741+ }
742+ // Private access is ok only from the same class nest
743+ if (f.isPrivate()) {
744+ return getTopClass().getClassDeclaration()
745+ .equals(f.getTopClass().getClassDeclaration());
746+ }
747+ // It must be in the same package
748+ return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
749+ }
750+
751+ /**
752+ * Check if a class is entitled to inline access to a class from
753+ * another class.
754+ */
755+ public boolean permitInlinedAccess(Environment env, ClassDeclaration c)
756+ throws ClassNotFound {
757+
758+ return (env.opt() && c.equals(declaration)) ||
759+ (env.opt_interclass() && canAccess(env, c));
760+ }
761+
762+ /**
763+ * Check if a class is entitled to inline access to a method from
764+ * another class.
765+ */
766+ public boolean permitInlinedAccess(Environment env, MemberDefinition f)
767+ throws ClassNotFound {
768+ return (env.opt()
769+ && (f.clazz.getClassDeclaration().equals(declaration))) ||
770+ (env.opt_interclass() && canAccess(env, f));
771+ }
772+
773+ /**
774+ * We know the the field is marked protected (and not public) and that
775+ * the field is visible (as per canAccess). Can we access the field as
776+ * <accessor>.<field>, where <accessor> has the type <accessorType>?
777+ *
778+ * Protected fields can only be accessed when the accessorType is a
779+ * subclass of the current class
780+ */
781+ public boolean protectedAccess(Environment env, MemberDefinition f,
782+ Type accessorType)
783+ throws ClassNotFound
784+ {
785+
786+ return
787+ // static protected fields are accessible
788+ f.isStatic()
789+ || // allow array.clone()
790+ (accessorType.isType(TC_ARRAY) && (f.getName() == idClone)
791+ && (f.getType().getArgumentTypes().length == 0))
792+ || // <accessorType> is a subtype of the current class
793+ (accessorType.isType(TC_CLASS)
794+ && env.getClassDefinition(accessorType.getClassName())
795+ .subClassOf(env, getClassDeclaration()))
796+ || // we are accessing the field from a friendly class (same package)
797+ (getName().getQualifier()
798+ .equals(f.getClassDeclaration().getName().getQualifier()));
799+ }
800+
801+
802+ /**
803+ * Find or create an access method for a private member,
804+ * or return null if this is not possible.
805+ */
806+ public MemberDefinition getAccessMember(Environment env, Context ctx,
807+ MemberDefinition field, boolean isSuper) {
808+ throw new CompilerError("binary getAccessMember");
809+ }
810+
811+ /**
812+ * Find or create an update method for a private member,
813+ * or return null if this is not possible.
814+ */
815+ public MemberDefinition getUpdateMember(Environment env, Context ctx,
816+ MemberDefinition field, boolean isSuper) {
817+ throw new CompilerError("binary getUpdateMember");
818+ }
819+
820+ /**
821+ * Get a field from this class. Report ambiguous fields.
822+ * If no accessible field is found, this method may return an
823+ * inaccessible field to allow a useful error message.
824+ *
825+ * getVariable now takes the source class `source' as an argument.
826+ * This allows getVariable to check whether a field is inaccessible
827+ * before it signals that a field is ambiguous. The compiler used to
828+ * signal an ambiguity even when one of the fields involved was not
829+ * accessible. (bug 4053724)
830+ */
831+ public MemberDefinition getVariable(Environment env,
832+ Identifier nm,
833+ ClassDefinition source)
834+ throws AmbiguousMember, ClassNotFound {
835+
836+ return getVariable0(env, nm, source, true, true);
837+ }
838+
839+ /*
840+ * private fields are never inherited. package-private fields are
841+ * not inherited across package boundaries. To capture this, we
842+ * take two booleans as parameters: showPrivate indicates whether
843+ * we have passed a class boundary, and showPackage indicates whether
844+ * we have crossed a package boundary.
845+ */
846+ private MemberDefinition getVariable0(Environment env,
847+ Identifier nm,
848+ ClassDefinition source,
849+ boolean showPrivate,
850+ boolean showPackage)
851+ throws AmbiguousMember, ClassNotFound {
852+
853+ // Check to see if this field is defined in the current class
854+ for (MemberDefinition member = getFirstMatch(nm);
855+ member != null;
856+ member = member.getNextMatch()) {
857+ if (member.isVariable()) {
858+ if ((showPrivate || !member.isPrivate()) &&
859+ (showPackage || !member.isPackagePrivate())) {
860+ // It is defined in this class.
861+ return member;
862+ } else {
863+ // Even though this definition is not inherited,
864+ // it hides all definitions in supertypes.
865+ return null;
866+ }
867+ }
868+ }
869+
870+ // Find the field in our superclass.
871+ ClassDeclaration sup = getSuperClass();
872+ MemberDefinition field = null;
873+ if (sup != null) {
874+ field =
875+ sup.getClassDefinition(env)
876+ .getVariable0(env, nm, source,
877+ false,
878+ showPackage && inSamePackage(sup));
879+ }
880+
881+ // Find the field in our superinterfaces.
882+ for (int i = 0 ; i < interfaces.length ; i++) {
883+ // Try to look up the field in an interface. Since interfaces
884+ // only have public fields, the values of the two boolean
885+ // arguments are not important.
886+ MemberDefinition field2 =
887+ interfaces[i].getClassDefinition(env)
888+ .getVariable0(env, nm, source, true, true);
889+
890+ if (field2 != null) {
891+ // If we have two different, accessible fields, then
892+ // we've found an ambiguity.
893+ if (field != null &&
894+ source.canAccess(env, field) &&
895+ field2 != field) {
896+
897+ throw new AmbiguousMember(field2, field);
898+ }
899+ field = field2;
900+ }
901+ }
902+ return field;
903+ }
904+
905+ /**
906+ * Tells whether to report a deprecation error for this class.
907+ */
908+ public boolean reportDeprecated(Environment env) {
909+ return (isDeprecated()
910+ || (outerClass != null && outerClass.reportDeprecated(env)));
911+ }
912+
913+ /**
914+ * Note that this class is being used somehow by <tt>ref</tt>.
915+ * Report deprecation errors, etc.
916+ */
917+ public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
918+ // (Have this deal with canAccess() checks, too?)
919+ if (reportDeprecated(env)) {
920+ env.error(where, "warn.class.is.deprecated", this);
921+ }
922+ }
923+
924+ /**
925+ * Get an inner class.
926+ * Look in supers but not outers.
927+ * (This is used directly to resolve expressions like "site.K", and
928+ * inside a loop to resolve lone names like "K" or the "K" in "K.L".)
929+ *
930+ * Called from 'Context' and 'FieldExpression' as well as this class.
931+ *
932+ * @see FieldExpression.checkCommon
933+ * @see resolveName
934+ */
935+ public MemberDefinition getInnerClass(Environment env, Identifier nm)
936+ throws ClassNotFound {
937+ // Note: AmbiguousClass will not be thrown unless and until
938+ // inner classes can be defined inside interfaces.
939+
940+ // Check if it is defined in the current class
941+ for (MemberDefinition field = getFirstMatch(nm);
942+ field != null ; field = field.getNextMatch()) {
943+ if (field.isInnerClass()) {
944+ if (field.getInnerClass().isLocal()) {
945+ continue; // ignore this name; it is internally generated
946+ }
947+ return field;
948+ }
949+ }
950+
951+ // Get it from the super class
952+ // It is likely that 'getSuperClass()' could be made to work here
953+ // but we would have to assure somehow that 'resolveTypeStructure'
954+ // has been called on the current class nest. Since we can get
955+ // here from 'resolveName', which is called from 'resolveSupers',
956+ // it is possible that the first attempt to resolve the superclass
957+ // will originate here, instead of in the call to 'getSuperClass'
958+ // in 'checkSupers'. See 'resolveTypeStructure', in which a call
959+ // to 'resolveSupers' precedes the call to 'checkSupers'. Why is
960+ // name resolution done twice, first in 'resolveName'?
961+ // NOTE: 'SourceMember.resolveTypeStructure' may initiate type
962+ // structure resolution for an inner class. Normally, this
963+ // occurs during the resolution of the outer class, but fields
964+ // added after the resolution of their containing class will
965+ // be resolved late -- see 'addMember(env,field)' below.
966+ // This should only happen for synthetic members, which should
967+ // never be an inner class.
968+ ClassDeclaration sup = getSuperClass(env);
969+ if (sup != null)
970+ return sup.getClassDefinition(env).getInnerClass(env, nm);
971+
972+ return null;
973+ }
974+
975+ /**
976+ * Lookup a method. This code implements the method lookup
977+ * mechanism specified in JLS 15.11.2.
978+ *
979+ * This mechanism cannot be used to lookup synthetic methods.
980+ */
981+ private MemberDefinition matchMethod(Environment env,
982+ ClassDefinition accessor,
983+ Identifier methodName,
984+ Type[] argumentTypes,
985+ boolean isAnonConstCall,
986+ Identifier accessPackage)
987+ throws AmbiguousMember, ClassNotFound {
988+
989+ if (allMethods == null || !allMethods.isFrozen()) {
990+ // This may be too restrictive.
991+ throw new CompilerError("matchMethod called early");
992+ // collectInheritedMethods(env);
993+ }
994+
995+ // A tentative maximally specific method.
996+ MemberDefinition tentative = null;
997+
998+ // A list of other methods which may be maximally specific too.
999+ List candidateList = null;
1000+
1001+ // Get all the methods inherited by this class which
1002+ // have the name `methodName'.
1003+ Iterator methods = allMethods.lookupName(methodName);
1004+
1005+ while (methods.hasNext()) {
1006+ MemberDefinition method = (MemberDefinition)methods.next();
1007+
1008+ // See if this method is applicable.
1009+ if (!env.isApplicable(method, argumentTypes)) {
1010+ continue;
1011+ }
1012+
1013+ // See if this method is accessible.
1014+ if (accessor != null) {
1015+ if (!accessor.canAccess(env, method)) {
1016+ continue;
1017+ }
1018+ } else if (isAnonConstCall) {
1019+ if (method.isPrivate() ||
1020+ (method.isPackagePrivate() &&
1021+ accessPackage != null &&
1022+ !inSamePackage(accessPackage))) {
1023+ // For anonymous constructor accesses, we
1024+ // haven't yet built an accessing class.
1025+ // We disallow anonymous classes from seeing
1026+ // private/package-private inaccessible
1027+ // constructors in their superclass.
1028+ continue;
1029+ }
1030+ } else {
1031+ // If accessor is null, we assume that the access
1032+ // is allowed. Query: is this option used?
1033+ }
1034+
1035+ if (tentative == null) {
1036+ // `method' becomes our tentative maximally specific match.
1037+ tentative = method;
1038+ } else {
1039+ if (env.isMoreSpecific(method, tentative)) {
1040+ // We have found a method which is a strictly better
1041+ // match than `tentative'. Replace it.
1042+ tentative = method;
1043+ } else {
1044+ // If this method could possibly be another
1045+ // maximally specific method, add it to our
1046+ // list of other candidates.
1047+ if (!env.isMoreSpecific(tentative,method)) {
1048+ if (candidateList == null) {
1049+ candidateList = new ArrayList();
1050+ }
1051+ candidateList.add(method);
1052+ }
1053+ }
1054+ }
1055+ }
1056+
1057+ if (tentative != null && candidateList != null) {
1058+ // Find out if our `tentative' match is a uniquely
1059+ // maximally specific.
1060+ Iterator candidates = candidateList.iterator();
1061+ while (candidates.hasNext()) {
1062+ MemberDefinition method = (MemberDefinition)candidates.next();
1063+ if (!env.isMoreSpecific(tentative, method)) {
1064+ throw new AmbiguousMember(tentative, method);
1065+ }
1066+ }
1067+ }
1068+
1069+ return tentative;
1070+ }
1071+
1072+ /**
1073+ * Lookup a method. This code implements the method lookup
1074+ * mechanism specified in JLS 15.11.2.
1075+ *
1076+ * This mechanism cannot be used to lookup synthetic methods.
1077+ */
1078+ public MemberDefinition matchMethod(Environment env,
1079+ ClassDefinition accessor,
1080+ Identifier methodName,
1081+ Type[] argumentTypes)
1082+ throws AmbiguousMember, ClassNotFound {
1083+
1084+ return matchMethod(env, accessor, methodName,
1085+ argumentTypes, false, null);
1086+ }
1087+
1088+ /**
1089+ * Lookup a method. This code implements the method lookup
1090+ * mechanism specified in JLS 15.11.2.
1091+ *
1092+ * This mechanism cannot be used to lookup synthetic methods.
1093+ */
1094+ public MemberDefinition matchMethod(Environment env,
1095+ ClassDefinition accessor,
1096+ Identifier methodName)
1097+ throws AmbiguousMember, ClassNotFound {
1098+
1099+ return matchMethod(env, accessor, methodName,
1100+ Type.noArgs, false, null);
1101+ }
1102+
1103+ /**
1104+ * A version of matchMethod to be used only for constructors
1105+ * when we cannot pass in a sourceClass argument. We just assert
1106+ * our package name.
1107+ *
1108+ * This is used only for anonymous classes, where we have to look up
1109+ * a (potentially) protected constructor with no valid sourceClass
1110+ * parameter available.
1111+ */
1112+ public MemberDefinition matchAnonConstructor(Environment env,
1113+ Identifier accessPackage,
1114+ Type argumentTypes[])
1115+ throws AmbiguousMember, ClassNotFound {
1116+
1117+ return matchMethod(env, null, idInit, argumentTypes,
1118+ true, accessPackage);
1119+ }
1120+
1121+ /**
1122+ * Find a method, ie: exact match in this class or any of the super
1123+ * classes.
1124+ *
1125+ * Only called by javadoc. For now I am holding off rewriting this
1126+ * code to rely on collectInheritedMethods(), as that code has
1127+ * not gotten along with javadoc in the past.
1128+ */
1129+ public MemberDefinition findMethod(Environment env, Identifier nm, Type t)
1130+ throws ClassNotFound {
1131+ // look in the current class
1132+ MemberDefinition f;
1133+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1134+ // Note that non-method types return false for equalArguments().
1135+ if (f.getType().equalArguments(t)) {
1136+ return f;
1137+ }
1138+ }
1139+
1140+ // constructors are not inherited
1141+ if (nm.equals(idInit)) {
1142+ return null;
1143+ }
1144+
1145+ // look in the super class
1146+ ClassDeclaration sup = getSuperClass();
1147+ if (sup == null)
1148+ return null;
1149+
1150+ return sup.getClassDefinition(env).findMethod(env, nm, t);
1151+ }
1152+
1153+ // We create a stub for this. Source classes do more work.
1154+ protected void basicCheck(Environment env) throws ClassNotFound {
1155+ // Do the outer class first.
1156+ if (outerClass != null)
1157+ outerClass.basicCheck(env);
1158+ }
1159+
1160+ /**
1161+ * Check this class.
1162+ */
1163+ public void check(Environment env) throws ClassNotFound {
1164+ }
1165+
1166+ public Vset checkLocalClass(Environment env, Context ctx,
1167+ Vset vset, ClassDefinition sup,
1168+ Expression args[], Type argTypes[]
1169+ ) throws ClassNotFound {
1170+ throw new CompilerError("checkLocalClass");
1171+ }
1172+
1173+ //---------------------------------------------------------------
1174+ // The non-synthetic methods defined in this class or in any
1175+ // of its parents (class or interface). This member is used
1176+ // to cache work done in collectInheritedMethods for use by
1177+ // getMethods() and matchMethod(). It should be accessed by
1178+ // no other method without forethought.
1179+ MethodSet allMethods = null;
1180+
1181+ // One of our superclasses may contain an abstract method which
1182+ // we are unable to ever implement. This happens when there is
1183+ // a package-private abstract method in our parent and we are in
1184+ // a different package than our parent. In these cases, we
1185+ // keep a list of the "permanently abstract" or "unimplementable"
1186+ // methods so that we can correctly detect that this class is
1187+ // indeed abstract and so that we can give somewhat comprehensible
1188+ // error messages.
1189+ private List permanentlyAbstractMethods = new ArrayList();
1190+
1191+ /**
1192+ * This method returns an Iterator of all abstract methods
1193+ * in our superclasses which we are unable to implement.
1194+ */
1195+ protected Iterator getPermanentlyAbstractMethods() {
1196+ // This method can only be called after collectInheritedMethods.
1197+ if (allMethods == null) {
1198+ throw new CompilerError("isPermanentlyAbstract() called early");
1199+ }
1200+
1201+ return permanentlyAbstractMethods.iterator();
1202+ }
1203+
1204+ /**
1205+ * A flag used by turnOffInheritanceChecks() to indicate if
1206+ * inheritance checks are on or off.
1207+ */
1208+ protected static boolean doInheritanceChecks = true;
1209+
1210+ /**
1211+ * This is a workaround to allow javadoc to turn off certain
1212+ * inheritance/override checks which interfere with javadoc
1213+ * badly. In the future it might be good to eliminate the
1214+ * shared sources of javadoc and javac to avoid the need for this
1215+ * sort of workaround.
1216+ */
1217+ public static void turnOffInheritanceChecks() {
1218+ doInheritanceChecks = false;
1219+ }
1220+
1221+ /**
1222+ * Add all of the methods declared in or above `parent' to
1223+ * `allMethods', the set of methods in the current class.
1224+ * `myMethods' is the set of all methods declared in this
1225+ * class, and `mirandaMethods' is a repository for Miranda methods.
1226+ * If mirandaMethods is null, no mirandaMethods will be
1227+ * generated.
1228+ *
1229+ * For a definition of Miranda methods, see the comment above the
1230+ * method addMirandaMethods() which occurs later in this file.
1231+ */
1232+ private void collectOneClass(Environment env,
1233+ ClassDeclaration parent,
1234+ MethodSet myMethods,
1235+ MethodSet allMethods,
1236+ MethodSet mirandaMethods) {
1237+
1238+ // System.out.println("Inheriting methods from " + parent);
1239+
1240+ try {
1241+ ClassDefinition pClass = parent.getClassDefinition(env);
1242+ Iterator methods = pClass.getMethods(env);
1243+ while (methods.hasNext()) {
1244+ MemberDefinition method =
1245+ (MemberDefinition) methods.next();
1246+
1247+ // Private methods are not inherited.
1248+ //
1249+ // Constructors are not inherited.
1250+ //
1251+ // Any non-abstract methods in an interface come
1252+ // from java.lang.Object. This means that they
1253+ // should have already been added to allMethods
1254+ // when we walked our superclass lineage.
1255+ if (method.isPrivate() ||
1256+ method.isConstructor() ||
1257+ (pClass.isInterface() && !method.isAbstract())) {
1258+
1259+ continue;
1260+ }
1261+
1262+ // Get the components of the methods' signature.
1263+ Identifier name = method.getName();
1264+ Type type = method.getType();
1265+
1266+ // Check for a method of the same signature which
1267+ // was locally declared.
1268+ MemberDefinition override =
1269+ myMethods.lookupSig(name, type);
1270+
1271+ // Is this method inaccessible due to package-private
1272+ // visibility?
1273+ if (method.isPackagePrivate() &&
1274+ !inSamePackage(method.getClassDeclaration())) {
1275+
1276+ if (override != null && this instanceof
1277+ sun.tools.javac.SourceClass) {
1278+ // We give a warning when a class shadows an
1279+ // inaccessible package-private method from
1280+ // its superclass. This warning is meant
1281+ // to prevent people from relying on overriding
1282+ // when it does not happen. This warning should
1283+ // probably be removed to be consistent with the
1284+ // general "no warnings" policy of this
1285+ // compiler.
1286+ //
1287+ // The `instanceof' above is a hack so that only
1288+ // SourceClass generates this warning, not a
1289+ // BinaryClass, for example.
1290+ env.error(method.getWhere(),
1291+ "warn.no.override.access",
1292+ override,
1293+ override.getClassDeclaration(),
1294+ method.getClassDeclaration());
1295+ }
1296+
1297+ // If our superclass has a package-private abstract
1298+ // method that we have no access to, then we add
1299+ // this method to our list of permanently abstract
1300+ // methods. The idea is, since we cannot override
1301+ // the method, we can never make this class
1302+ // non-abstract.
1303+ if (method.isAbstract()) {
1304+ permanentlyAbstractMethods.add(method);
1305+ }
1306+
1307+ // `method' is inaccessible. We do not inherit it.
1308+ continue;
1309+ }
1310+
1311+ if (override != null) {
1312+ // `method' and `override' have the same signature.
1313+ // We are required to check that `override' is a
1314+ // legal override of `method'
1315+
1316+ //System.out.println ("About to check override of " +
1317+ // method);
1318+
1319+ override.checkOverride(env, method);
1320+ } else {
1321+ // In the absence of a definition in the class
1322+ // itself, we check to see if this definition
1323+ // can be successfully merged with any other
1324+ // inherited definitions.
1325+
1326+ // Have we added a member of the same signature
1327+ // to `allMethods' already?
1328+ MemberDefinition formerMethod =
1329+ allMethods.lookupSig(name, type);
1330+
1331+ // If the previous definition is nonexistent or
1332+ // ignorable, replace it.
1333+ if (formerMethod == null) {
1334+ //System.out.println("Added " + method + " to " +
1335+ // this);
1336+
1337+ if (mirandaMethods != null &&
1338+ pClass.isInterface() && !isInterface()) {
1339+ // Whenever a class inherits a method
1340+ // from an interface, that method is
1341+ // one of our "miranda" methods. Early
1342+ // VMs require that these methods be
1343+ // added as true members to the class
1344+ // to enable method lookup to work in the
1345+ // VM.
1346+ method =
1347+ new sun.tools.javac.SourceMember(method,this,
1348+ env);
1349+ mirandaMethods.add(method);
1350+
1351+ //System.out.println("Added " + method +
1352+ // " to " + this + " as a Miranda");
1353+ }
1354+
1355+ // There is no previous inherited definition.
1356+ // Add `method' to `allMethods'.
1357+ allMethods.add(method);
1358+ } else if (isInterface() &&
1359+ !formerMethod.isAbstract() &&
1360+ method.isAbstract()) {
1361+ // If we are in an interface and we have inherited
1362+ // both an abstract method and a non-abstract method
1363+ // then we know that the non-abstract method is
1364+ // a placeholder from Object put in for type checking
1365+ // and the abstract method was already checked to
1366+ // be proper by our superinterface.
1367+ allMethods.replace(method);
1368+
1369+ } else {
1370+ // Okay, `formerMethod' and `method' both have the
1371+ // same signature. See if they are compatible.
1372+
1373+ //System.out.println ("About to check meet of " +
1374+ // method);
1375+
1376+ if (!formerMethod.checkMeet(env,
1377+ method,
1378+ this.getClassDeclaration())) {
1379+ // The methods are incompatible. Skip to
1380+ // next method.
1381+ continue;
1382+ }
1383+
1384+ if (formerMethod.couldOverride(env, method)) {
1385+ // Do nothing. The current definition
1386+ // is specific enough.
1387+
1388+ //System.out.println("trivial meet of " +
1389+ // method);
1390+ continue;
1391+ }
1392+
1393+ if (method.couldOverride(env, formerMethod)) {
1394+ // `method' is more specific than
1395+ // `formerMethod'. replace `formerMethod'.
1396+
1397+ //System.out.println("new def of " + method);
1398+ if (mirandaMethods != null &&
1399+ pClass.isInterface() && !isInterface()) {
1400+ // Whenever a class inherits a method
1401+ // from an interface, that method is
1402+ // one of our "miranda" methods. Early
1403+ // VMs require that these methods be
1404+ // added as true members to the class
1405+ // to enable method lookup to work in the
1406+ // VM.
1407+ method =
1408+ new sun.tools.javac.SourceMember(method,
1409+ this,env);
1410+
1411+ mirandaMethods.replace(method);
1412+
1413+ //System.out.println("Added " + method +
1414+ // " to " + this + " as a Miranda");
1415+ }
1416+
1417+ allMethods.replace(method);
1418+
1419+ continue;
1420+ }
1421+
1422+ // Neither method is more specific than the other.
1423+ // Oh well. We need to construct a nontrivial
1424+ // meet of the two methods.
1425+ //
1426+ // This is not yet implemented, so we give
1427+ // a message with a helpful workaround.
1428+ env.error(this.where,
1429+ "nontrivial.meet", method,
1430+ formerMethod.getClassDefinition(),
1431+ method.getClassDeclaration()
1432+ );
1433+ }
1434+ }
1435+ }
1436+ } catch (ClassNotFound ee) {
1437+ env.error(getWhere(), "class.not.found", ee.name, this);
1438+ }
1439+ }
1440+
1441+ /**
1442+ * <p>Collect all methods defined in this class or inherited from
1443+ * any of our superclasses or interfaces. Look for any
1444+ * incompatible definitions.
1445+ *
1446+ * <p>This function is also responsible for collecting the
1447+ * <em>Miranda</em> methods for a class. For a definition of
1448+ * Miranda methods, see the comment in addMirandaMethods()
1449+ * below.
1450+ */
1451+ protected void collectInheritedMethods(Environment env) {
1452+ // The methods defined in this class.
1453+ MethodSet myMethods;
1454+ MethodSet mirandaMethods;
1455+
1456+ //System.out.println("Called collectInheritedMethods() for " +
1457+ // this);
1458+
1459+ if (allMethods != null) {
1460+ if (allMethods.isFrozen()) {
1461+ // We have already done the collection. No need to
1462+ // do it again.
1463+ return;
1464+ } else {
1465+ // We have run into a circular need to collect our methods.
1466+ // This should not happen at this stage.
1467+ throw new CompilerError("collectInheritedMethods()");
1468+ }
1469+ }
1470+
1471+ myMethods = new MethodSet();
1472+ allMethods = new MethodSet();
1473+
1474+ // For testing, do not generate miranda methods.
1475+ if (env.version12()) {
1476+ mirandaMethods = null;
1477+ } else {
1478+ mirandaMethods = new MethodSet();
1479+ }
1480+
1481+ // Any methods defined in the current class get added
1482+ // to both the myMethods and the allMethods MethodSets.
1483+
1484+ for (MemberDefinition member = getFirstMember();
1485+ member != null;
1486+ member = member.nextMember) {
1487+
1488+ // We only collect methods. Initializers are not relevant.
1489+ if (member.isMethod() &&
1490+ !member.isInitializer()) {
1491+
1492+ //System.out.println("Declared in " + this + ", " + member);
1493+
1494+ ////////////////////////////////////////////////////////////
1495+ // PCJ 2003-07-30 modified the following code because with
1496+ // the covariant return type feature of the 1.5 compiler,
1497+ // there might be multiple methods with the same signature
1498+ // but different return types, and MethodSet doesn't
1499+ // support that. We use a new utility method that attempts
1500+ // to ensure that the appropriate method winds up in the
1501+ // MethodSet. See 4892308.
1502+ ////////////////////////////////////////////////////////////
1503+ // myMethods.add(member);
1504+ // allMethods.add(member);
1505+ ////////////////////////////////////////////////////////////
1506+ methodSetAdd(env, myMethods, member);
1507+ methodSetAdd(env, allMethods, member);
1508+ ////////////////////////////////////////////////////////////
1509+ }
1510+ }
1511+
1512+ // We're ready to start adding inherited methods. First add
1513+ // the methods from our superclass.
1514+
1515+ //System.out.println("About to start superclasses for " + this);
1516+
1517+ ClassDeclaration scDecl = getSuperClass(env);
1518+ if (scDecl != null) {
1519+ collectOneClass(env, scDecl,
1520+ myMethods, allMethods, mirandaMethods);
1521+
1522+ // Make sure that we add all unimplementable methods from our
1523+ // superclass to our list of unimplementable methods.
1524+ ClassDefinition sc = scDecl.getClassDefinition();
1525+ Iterator supIter = sc.getPermanentlyAbstractMethods();
1526+ while (supIter.hasNext()) {
1527+ permanentlyAbstractMethods.add(supIter.next());
1528+ }
1529+ }
1530+
1531+ // Now we inherit all of the methods from our interfaces.
1532+
1533+ //System.out.println("About to start interfaces for " + this);
1534+
1535+ for (int i = 0; i < interfaces.length; i++) {
1536+ collectOneClass(env, interfaces[i],
1537+ myMethods, allMethods, mirandaMethods);
1538+ }
1539+ allMethods.freeze();
1540+
1541+ // Now we have collected all of our methods from our superclasses
1542+ // and interfaces into our `allMethods' member. Good. As a last
1543+ // task, we add our collected miranda methods to this class.
1544+ //
1545+ // If we do not add the mirandas to the class explicitly, there
1546+ // will be no code generated for them.
1547+ if (mirandaMethods != null && mirandaMethods.size() > 0) {
1548+ addMirandaMethods(env, mirandaMethods.iterator());
1549+ }
1550+ }
1551+
1552+ ////////////////////////////////////////////////////////////
1553+ // PCJ 2003-07-30 added this utility method to insulate
1554+ // MethodSet additions from the covariant return type
1555+ // feature of the 1.5 compiler. When there are multiple
1556+ // methods with the same signature and different return
1557+ // types to be added, we try to ensure that the one with
1558+ // the most specific return type winds up in the MethodSet.
1559+ // This logic was not put into MethodSet itself because it
1560+ // requires access to an Environment for type relationship
1561+ // checking. No error checking is performed here, but that
1562+ // should be OK because this code is only still used by
1563+ // rmic. See 4892308.
1564+ ////////////////////////////////////////////////////////////
1565+ private static void methodSetAdd(Environment env,
1566+ MethodSet methodSet,
1567+ MemberDefinition newMethod)
1568+ {
1569+ MemberDefinition oldMethod = methodSet.lookupSig(newMethod.getName(),
1570+ newMethod.getType());
1571+ if (oldMethod != null) {
1572+ Type oldReturnType = oldMethod.getType().getReturnType();
1573+ Type newReturnType = newMethod.getType().getReturnType();
1574+ try {
1575+ if (env.isMoreSpecific(newReturnType, oldReturnType)) {
1576+ methodSet.replace(newMethod);
1577+ }
1578+ } catch (ClassNotFound ignore) {
1579+ }
1580+ } else {
1581+ methodSet.add(newMethod);
1582+ }
1583+ }
1584+ ////////////////////////////////////////////////////////////
1585+
1586+ /**
1587+ * Get an Iterator of all methods which could be accessed in an
1588+ * instance of this class.
1589+ */
1590+ public Iterator getMethods(Environment env) {
1591+ if (allMethods == null) {
1592+ collectInheritedMethods(env);
1593+ }
1594+ return getMethods();
1595+ }
1596+
1597+ /**
1598+ * Get an Iterator of all methods which could be accessed in an
1599+ * instance of this class. Throw a compiler error if we haven't
1600+ * generated this information yet.
1601+ */
1602+ public Iterator getMethods() {
1603+ if (allMethods == null) {
1604+ throw new CompilerError("getMethods: too early");
1605+ }
1606+ return allMethods.iterator();
1607+ }
1608+
1609+ // In early VM's there was a bug -- the VM didn't walk the interfaces
1610+ // of a class looking for a method, they only walked the superclass
1611+ // chain. This meant that abstract methods defined only in interfaces
1612+ // were not being found. To fix this bug, a counter-bug was introduced
1613+ // in the compiler -- the so-called Miranda methods. If a class
1614+ // does not provide a definition for an abstract method in one of
1615+ // its interfaces then the compiler inserts one in the class artificially.
1616+ // That way the VM didn't have to bother looking at the interfaces.
1617+ //
1618+ // This is a problem. Miranda methods are not part of the specification.
1619+ // But they continue to be inserted so that old VM's can run new code.
1620+ // Someday, when the old VM's are gone, perhaps classes can be compiled
1621+ // without Miranda methods. Towards this end, the compiler has a
1622+ // flag, -nomiranda, which can turn off the creation of these methods.
1623+ // Eventually that behavior should become the default.
1624+ //
1625+ // Why are they called Miranda methods? Well the sentence "If the
1626+ // class is not able to provide a method, then one will be provided
1627+ // by the compiler" is very similar to the sentence "If you cannot
1628+ // afford an attorney, one will be provided by the court," -- one
1629+ // of the so-called "Miranda" rights in the United States.
1630+
1631+ /**
1632+ * Add a list of methods to this class as miranda methods. This
1633+ * gets overridden with a meaningful implementation in SourceClass.
1634+ * BinaryClass should not need to do anything -- it should already
1635+ * have its miranda methods and, if it doesn't, then that doesn't
1636+ * affect our compilation.
1637+ */
1638+ protected void addMirandaMethods(Environment env,
1639+ Iterator mirandas) {
1640+ // do nothing.
1641+ }
1642+
1643+ //---------------------------------------------------------------
1644+
1645+ public void inlineLocalClass(Environment env) {
1646+ }
1647+
1648+ /**
1649+ * We create a stub for this. Source classes do more work.
1650+ * Some calls from 'SourceClass.checkSupers' execute this method.
1651+ * @see sun.tools.javac.SourceClass#resolveTypeStructure
1652+ */
1653+
1654+ public void resolveTypeStructure(Environment env) {
1655+ }
1656+
1657+ /**
1658+ * Look up an inner class name, from somewhere inside this class.
1659+ * Since supers and outers are in scope, search them too.
1660+ * <p>
1661+ * If no inner class is found, env.resolveName() is then called,
1662+ * to interpret the ambient package and import directives.
1663+ * <p>
1664+ * This routine operates on a "best-efforts" basis. If
1665+ * at some point a class is not found, the partially-resolved
1666+ * identifier is returned. Eventually, someone else has to
1667+ * try to get the ClassDefinition and diagnose the ClassNotFound.
1668+ * <p>
1669+ * resolveName() looks at surrounding scopes, and hence
1670+ * pulling in both inherited and uplevel types. By contrast,
1671+ * resolveInnerClass() is intended only for interpreting
1672+ * explicitly qualified names, and so look only at inherited
1673+ * types. Also, resolveName() looks for package prefixes,
1674+ * which appear similar to "very uplevel" outer classes.
1675+ * <p>
1676+ * A similar (but more complex) name-lookup process happens
1677+ * when field and identifier expressions denoting qualified names
1678+ * are type-checked. The added complexity comes from the fact
1679+ * that variables may occur in such names, and take precedence
1680+ * over class and package names.
1681+ * <p>
1682+ * In the expression type-checker, resolveInnerClass() is paralleled
1683+ * by code in FieldExpression.checkAmbigName(), which also calls
1684+ * ClassDefinition.getInnerClass() to interpret names of the form
1685+ * "OuterClass.Inner" (and also outerObject.Inner). The checking
1686+ * of an identifier expression that fails to be a variable is referred
1687+ * directly to resolveName().
1688+ */
1689+ public Identifier resolveName(Environment env, Identifier name) {
1690+ if (tracing) env.dtEvent("ClassDefinition.resolveName: " + name);
1691+ // This logic is pretty much exactly parallel to that of
1692+ // Environment.resolveName().
1693+ if (name.isQualified()) {
1694+ // Try to resolve the first identifier component,
1695+ // because inner class names take precedence over
1696+ // package prefixes. (Cf. Environment.resolveName.)
1697+ Identifier rhead = resolveName(env, name.getHead());
1698+
1699+ if (rhead.hasAmbigPrefix()) {
1700+ // The first identifier component refers to an
1701+ // ambiguous class. Limp on. We throw away the
1702+ // rest of the classname as it is irrelevant.
1703+ // (part of solution for 4059855).
1704+ return rhead;
1705+ }
1706+
1707+ if (!env.classExists(rhead)) {
1708+ return env.resolvePackageQualifiedName(name);
1709+ }
1710+ try {
1711+ return env.getClassDefinition(rhead).
1712+ resolveInnerClass(env, name.getTail());
1713+ } catch (ClassNotFound ee) {
1714+ // return partially-resolved name someone else can fail on
1715+ return Identifier.lookupInner(rhead, name.getTail());
1716+ }
1717+ }
1718+
1719+ // This method used to fail to look for local classes, thus a
1720+ // reference to a local class within, e.g., the type of a member
1721+ // declaration, would fail to resolve if the immediately enclosing
1722+ // context was an inner class. The code added below is ugly, but
1723+ // it works, and is lifted from existing code in 'Context.resolveName'
1724+ // and 'Context.getClassCommon'. See the comments there about the design.
1725+ // Fixes 4095716.
1726+
1727+ int ls = -2;
1728+ LocalMember lf = null;
1729+ if (classContext != null) {
1730+ lf = classContext.getLocalClass(name);
1731+ if (lf != null) {
1732+ ls = lf.getScopeNumber();
1733+ }
1734+ }
1735+
1736+ // Look for an unqualified name in enclosing scopes.
1737+ for (ClassDefinition c = this; c != null; c = c.outerClass) {
1738+ try {
1739+ MemberDefinition f = c.getInnerClass(env, name);
1740+ if (f != null &&
1741+ (lf == null || classContext.getScopeNumber(c) > ls)) {
1742+ // An uplevel member was found, and was nested more deeply than
1743+ // any enclosing local of the same name.
1744+ return f.getInnerClass().getName();
1745+ }
1746+ } catch (ClassNotFound ee) {
1747+ // a missing superclass, or something catastrophic
1748+ }
1749+ }
1750+
1751+ // No uplevel member found, so use the enclosing local if one was found.
1752+ if (lf != null) {
1753+ return lf.getInnerClass().getName();
1754+ }
1755+
1756+ // look in imports, etc.
1757+ return env.resolveName(name);
1758+ }
1759+
1760+ /**
1761+ * Interpret a qualified class name, which may have further subcomponents..
1762+ * Follow inheritance links, as in:
1763+ * class C { class N { } } class D extends C { } ... new D.N() ...
1764+ * Ignore outer scopes and packages.
1765+ * @see resolveName
1766+ */
1767+ public Identifier resolveInnerClass(Environment env, Identifier nm) {
1768+ if (nm.isInner()) throw new CompilerError("inner");
1769+ if (nm.isQualified()) {
1770+ Identifier rhead = resolveInnerClass(env, nm.getHead());
1771+ try {
1772+ return env.getClassDefinition(rhead).
1773+ resolveInnerClass(env, nm.getTail());
1774+ } catch (ClassNotFound ee) {
1775+ // return partially-resolved name someone else can fail on
1776+ return Identifier.lookupInner(rhead, nm.getTail());
1777+ }
1778+ } else {
1779+ try {
1780+ MemberDefinition f = getInnerClass(env, nm);
1781+ if (f != null) {
1782+ return f.getInnerClass().getName();
1783+ }
1784+ } catch (ClassNotFound ee) {
1785+ // a missing superclass, or something catastrophic
1786+ }
1787+ // Fake a good name for a diagnostic.
1788+ return Identifier.lookupInner(this.getName(), nm);
1789+ }
1790+ }
1791+
1792+ /**
1793+ * While resolving import directives, the question has arisen:
1794+ * does a given inner class exist? If the top-level class exists,
1795+ * we ask it about an inner class via this method.
1796+ * This method looks only at the literal name of the class,
1797+ * and does not attempt to follow inheritance links.
1798+ * This is necessary, since at the time imports are being
1799+ * processed, inheritance links have not been resolved yet.
1800+ * (Thus, an import directive must always spell a class
1801+ * name exactly.)
1802+ */
1803+ public boolean innerClassExists(Identifier nm) {
1804+ for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {
1805+ if (field.isInnerClass()) {
1806+ if (field.getInnerClass().isLocal()) {
1807+ continue; // ignore this name; it is internally generated
1808+ }
1809+ return !nm.isQualified() ||
1810+ field.getInnerClass().innerClassExists(nm.getTail());
1811+ }
1812+ }
1813+ return false;
1814+ }
1815+
1816+ /**
1817+ * Find any method with a given name.
1818+ */
1819+ public MemberDefinition findAnyMethod(Environment env, Identifier nm) throws ClassNotFound {
1820+ MemberDefinition f;
1821+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1822+ if (f.isMethod()) {
1823+ return f;
1824+ }
1825+ }
1826+
1827+ // look in the super class
1828+ ClassDeclaration sup = getSuperClass();
1829+ if (sup == null)
1830+ return null;
1831+ return sup.getClassDefinition(env).findAnyMethod(env, nm);
1832+ }
1833+
1834+ /**
1835+ * Given the fact that this class has no method "nm" matching "argTypes",
1836+ * find out if the mismatch can be blamed on a particular actual argument
1837+ * which disagrees with all of the overloadings.
1838+ * If so, return the code (i<<2)+(castOK<<1)+ambig, where
1839+ * "i" is the number of the offending argument, and
1840+ * "castOK" is 1 if a cast could fix the problem.
1841+ * The target type for the argument is returned in margTypeResult[0].
1842+ * If not all methods agree on this type, "ambig" is 1.
1843+ * If there is more than one method, the choice of target type is
1844+ * arbitrary.<p>
1845+ * Return -1 if every argument is acceptable to at least one method.
1846+ * Return -2 if there are no methods of the required arity.
1847+ * The value "start" gives the index of the first argument to begin
1848+ * checking.
1849+ */
1850+ public int diagnoseMismatch(Environment env, Identifier nm, Type argTypes[],
1851+ int start, Type margTypeResult[]) throws ClassNotFound {
1852+ int haveMatch[] = new int[argTypes.length];
1853+ Type margType[] = new Type[argTypes.length];
1854+ if (!diagnoseMismatch(env, nm, argTypes, start, haveMatch, margType))
1855+ return -2;
1856+ for (int i = start; i < argTypes.length; i++) {
1857+ if (haveMatch[i] < 4) {
1858+ margTypeResult[0] = margType[i];
1859+ return (i<<2) | haveMatch[i];
1860+ }
1861+ }
1862+ return -1;
1863+ }
1864+
1865+ private boolean diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start,
1866+ int haveMatch[], Type margType[]) throws ClassNotFound {
1867+ // look in the current class
1868+ boolean haveOne = false;
1869+ MemberDefinition f;
1870+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1871+ if (!f.isMethod()) {
1872+ continue;
1873+ }
1874+ Type fArgTypes[] = f.getType().getArgumentTypes();
1875+ if (fArgTypes.length == argTypes.length) {
1876+ haveOne = true;
1877+ for (int i = start; i < argTypes.length; i++) {
1878+ Type at = argTypes[i];
1879+ Type ft = fArgTypes[i];
1880+ if (env.implicitCast(at, ft)) {
1881+ haveMatch[i] = 4;
1882+ continue;
1883+ } else if (haveMatch[i] <= 2 && env.explicitCast(at, ft)) {
1884+ if (haveMatch[i] < 2) margType[i] = null;
1885+ haveMatch[i] = 2;
1886+ } else if (haveMatch[i] > 0) {
1887+ continue;
1888+ }
1889+ if (margType[i] == null)
1890+ margType[i] = ft;
1891+ else if (margType[i] != ft)
1892+ haveMatch[i] |= 1;
1893+ }
1894+ }
1895+ }
1896+
1897+ // constructors are not inherited
1898+ if (nm.equals(idInit)) {
1899+ return haveOne;
1900+ }
1901+
1902+ // look in the super class
1903+ ClassDeclaration sup = getSuperClass();
1904+ if (sup != null) {
1905+ if (sup.getClassDefinition(env).diagnoseMismatch(env, nm, argTypes, start,
1906+ haveMatch, margType))
1907+ haveOne = true;
1908+ }
1909+ return haveOne;
1910+ }
1911+
1912+ /**
1913+ * Add a field (no checks)
1914+ */
1915+ public void addMember(MemberDefinition field) {
1916+ //System.out.println("ADD = " + field);
1917+ if (firstMember == null) {
1918+ firstMember = lastMember = field;
1919+ } else if (field.isSynthetic() && field.isFinal()
1920+ && field.isVariable()) {
1921+ // insert this at the front, because of initialization order
1922+ field.nextMember = firstMember;
1923+ firstMember = field;
1924+ field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1925+ } else {
1926+ lastMember.nextMember = field;
1927+ lastMember = field;
1928+ field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1929+ }
1930+ fieldHash.put(field.name, field);
1931+ }
1932+
1933+ /**
1934+ * Add a field (subclasses make checks)
1935+ */
1936+ public void addMember(Environment env, MemberDefinition field) {
1937+ addMember(field);
1938+ if (resolved) {
1939+ // a late addition
1940+ field.resolveTypeStructure(env);
1941+ }
1942+ }
1943+
1944+ /**
1945+ * Find or create an uplevel reference for the given target.
1946+ */
1947+ public UplevelReference getReference(LocalMember target) {
1948+ for (UplevelReference r = references; r != null; r = r.getNext()) {
1949+ if (r.getTarget() == target) {
1950+ return r;
1951+ }
1952+ }
1953+ return addReference(target);
1954+ }
1955+
1956+ protected UplevelReference addReference(LocalMember target) {
1957+ if (target.getClassDefinition() == this) {
1958+ throw new CompilerError("addReference "+target);
1959+ }
1960+ referencesMustNotBeFrozen();
1961+ UplevelReference r = new UplevelReference(this, target);
1962+ references = r.insertInto(references);
1963+ return r;
1964+ }
1965+
1966+ /**
1967+ * Return the list of all uplevel references.
1968+ */
1969+ public UplevelReference getReferences() {
1970+ return references;
1971+ }
1972+
1973+ /**
1974+ * Return the same value as getReferences.
1975+ * Also, mark the set of references frozen.
1976+ * After that, it is an error to add new references.
1977+ */
1978+ public UplevelReference getReferencesFrozen() {
1979+ referencesFrozen = true;
1980+ return references;
1981+ }
1982+
1983+ /**
1984+ * assertion check
1985+ */
1986+ public final void referencesMustNotBeFrozen() {
1987+ if (referencesFrozen) {
1988+ throw new CompilerError("referencesMustNotBeFrozen "+this);
1989+ }
1990+ }
1991+
1992+ /**
1993+ * Get helper method for class literal lookup.
1994+ */
1995+ public MemberDefinition getClassLiteralLookup(long fwhere) {
1996+ throw new CompilerError("binary class");
1997+ }
1998+
1999+ /**
2000+ * Add a dependency
2001+ */
2002+ public void addDependency(ClassDeclaration c) {
2003+ throw new CompilerError("addDependency");
2004+ }
2005+
2006+ /**
2007+ * Maintain a hash table of local and anonymous classes
2008+ * whose internal names are prefixed by the current class.
2009+ * The key is the simple internal name, less the prefix.
2010+ */
2011+
2012+ public ClassDefinition getLocalClass(String name) {
2013+ if (localClasses == null) {
2014+ return null;
2015+ } else {
2016+ return (ClassDefinition)localClasses.get(name);
2017+ }
2018+ }
2019+
2020+ public void addLocalClass(ClassDefinition c, String name) {
2021+ if (localClasses == null) {
2022+ localClasses = new Hashtable(LOCAL_CLASSES_SIZE);
2023+ }
2024+ localClasses.put(name, c);
2025+ }
2026+
2027+
2028+ /**
2029+ * Print for debugging
2030+ */
2031+ public void print(PrintStream out) {
2032+ if (isPublic()) {
2033+ out.print("public ");
2034+ }
2035+ if (isInterface()) {
2036+ out.print("interface ");
2037+ } else {
2038+ out.print("class ");
2039+ }
2040+ out.print(getName() + " ");
2041+ if (getSuperClass() != null) {
2042+ out.print("extends " + getSuperClass().getName() + " ");
2043+ }
2044+ if (interfaces.length > 0) {
2045+ out.print("implements ");
2046+ for (int i = 0 ; i < interfaces.length ; i++) {
2047+ if (i > 0) {
2048+ out.print(", ");
2049+ }
2050+ out.print(interfaces[i].getName());
2051+ out.print(" ");
2052+ }
2053+ }
2054+ out.println("{");
2055+
2056+ for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2057+ out.print(" ");
2058+ f.print(out);
2059+ }
2060+
2061+ out.println("}");
2062+ }
2063+
2064+ /**
2065+ * Convert to String
2066+ */
2067+ public String toString() {
2068+ return getClassDeclaration().toString();
2069+ }
2070+
2071+ /**
2072+ * After the class has been written to disk, try to free up
2073+ * some storage.
2074+ */
2075+ public void cleanup(Environment env) {
2076+ if (env.dump()) {
2077+ env.output("[cleanup " + getName() + "]");
2078+ }
2079+ for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2080+ f.cleanup(env);
2081+ }
2082+ // keep "references" around, for the sake of local subclasses
2083+ documentation = null;
2084+ }
2085+}