Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/ClassDefinition.java
38918 views
/*1* Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.java;2627import java.util.*;28import java.io.OutputStream;29import java.io.PrintStream;30import sun.tools.tree.Context;31import sun.tools.tree.Vset;32import sun.tools.tree.Expression;33import sun.tools.tree.LocalMember;34import sun.tools.tree.UplevelReference;3536/**37* This class is a Java class definition38*39* WARNING: The contents of this source file are not part of any40* supported API. Code that depends on them does so at its own risk:41* they are subject to change or removal without notice.42*/43public44class ClassDefinition implements Constants {4546protected Object source;47protected long where;48protected int modifiers;49protected Identifier localName; // for local classes50protected ClassDeclaration declaration;51protected IdentifierToken superClassId;52protected IdentifierToken interfaceIds[];53protected ClassDeclaration superClass;54protected ClassDeclaration interfaces[];55protected ClassDefinition outerClass;56protected MemberDefinition outerMember;57protected MemberDefinition innerClassMember; // field for me in outerClass58protected MemberDefinition firstMember;59protected MemberDefinition lastMember;60protected boolean resolved;61protected String documentation;62protected boolean error;63protected boolean nestError;64protected UplevelReference references;65protected boolean referencesFrozen;66private Hashtable fieldHash = new Hashtable(31);67private int abstr;6869// Table of local and anonymous classes whose internal names are constructed70// using the current class as a prefix. This is part of a fix for71// bugid 4054523 and 4030421. See also 'Environment.getClassDefinition'72// and 'BatchEnvironment.makeClassDefinition'. Allocated on demand.73private Hashtable localClasses = null;74private final int LOCAL_CLASSES_SIZE = 31;7576// The immediately surrounding context in which the class appears.77// Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.78// Null for classes that are not local or inside a local class.79// At present, this field exists only for the benefit of 'resolveName' as part80// of the fix for 4095716.81protected Context classContext;8283// The saved class context is now also used in 'SourceClass.getAccessMember'.84// Provide read-only access via this method. Part of fix for 4098093.85public Context getClassContext() {86return classContext;87}888990/**91* Constructor92*/93protected ClassDefinition(Object source, long where, ClassDeclaration declaration,94int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {95this.source = source;96this.where = where;97this.declaration = declaration;98this.modifiers = modifiers;99this.superClassId = superClass;100this.interfaceIds = interfaces;101}102103/**104* Get the source of the class105*/106public final Object getSource() {107return source;108}109110/**111* Check if there were any errors in this class.112*/113public final boolean getError() {114return error;115}116117/**118* Mark this class to be erroneous.119*/120public final void setError() {121this.error = true;122setNestError();123}124125/**126* Check if there were any errors in our class nest.127*/128public final boolean getNestError() {129// Check to see if our error value is set, or if any of our130// outer classes' error values are set. This will work in131// conjunction with setError(), which sets the error value132// of its outer class, to yield true is any of our nest133// siblings has an error. This addresses bug 4111488: either134// code should be generated for all classes in a nest, or135// none of them.136return nestError || ((outerClass != null) ? outerClass.getNestError() : false);137}138139/**140* Mark this class, and all siblings in its class nest, to be141* erroneous.142*/143public final void setNestError() {144this.nestError = true;145if (outerClass != null) {146// If we have an outer class, set it to be erroneous as well.147// This will work in conjunction with getError(), which checks148// the error value of its outer class, to set the whole class149// nest to be erroneous. This address bug 4111488: either150// code should be generated for all classes in a nest, or151// none of them.152outerClass.setNestError();153}154}155156/**157* Get the position in the input158*/159public final long getWhere() {160return where;161}162163/**164* Get the class declaration165*/166public final ClassDeclaration getClassDeclaration() {167return declaration;168}169170/**171* Get the class' modifiers172*/173public final int getModifiers() {174return modifiers;175}176public final void subModifiers(int mod) {177modifiers &= ~mod;178}179public final void addModifiers(int mod) {180modifiers |= mod;181}182183// *** DEBUG ***184protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);185186/**187* Get the class' super class188*/189public final ClassDeclaration getSuperClass() {190/*---191if (superClass == null && superClassId != null)192throw new CompilerError("getSuperClass "+superClassId);193// There are obscure cases where null is the right answer,194// in order to enable some error reporting later on.195// For example: class T extends T.N { class N { } }196---*/197198// *** DEBUG ***199// This method should not be called if the superclass has not been resolved.200if (!supersCheckStarted) throw new CompilerError("unresolved super");201202return superClass;203}204205/**206* Get the super class, and resolve names now if necessary.207*208* It is only possible to resolve names at this point if we are209* a source class. The provision of this method at this level210* in the class hierarchy is dubious, but see 'getInnerClass' below.211* All other calls to 'getSuperClass(env)' appear in 'SourceClass'.212* NOTE: An older definition of this method has been moved to213* 'SourceClass', where it overrides this one.214*215* @see #resolveTypeStructure216*/217218public ClassDeclaration getSuperClass(Environment env) {219return getSuperClass();220}221222/**223* Get the class' interfaces224*/225public final ClassDeclaration getInterfaces()[] {226if (interfaces == null) throw new CompilerError("getInterfaces");227return interfaces;228}229230/**231* Get the class' enclosing class (or null if not inner)232*/233public final ClassDefinition getOuterClass() {234return outerClass;235}236237/**238* Set the class' enclosing class. Must be done at most once.239*/240protected final void setOuterClass(ClassDefinition outerClass) {241if (this.outerClass != null) throw new CompilerError("setOuterClass");242this.outerClass = outerClass;243}244245/**246* Set the class' enclosing current instance pointer.247* Must be done at most once.248*/249protected final void setOuterMember(MemberDefinition outerMember) {250251if (isStatic() || !isInnerClass()) throw new CompilerError("setOuterField");252if (this.outerMember != null) throw new CompilerError("setOuterField");253this.outerMember = outerMember;254}255256/**257* Tell if the class is inner.258* This predicate also returns true for top-level nested types.259* To test for a true inner class as seen by the programmer,260* use <tt>!isTopLevel()</tt>.261*/262public final boolean isInnerClass() {263return outerClass != null;264}265266/**267* Tell if the class is a member of another class.268* This is false for package members and for block-local classes.269*/270public final boolean isMember() {271return outerClass != null && !isLocal();272}273274/**275* Tell if the class is "top-level", which is either a package member,276* or a static member of another top-level class.277*/278public final boolean isTopLevel() {279return outerClass == null || isStatic() || isInterface();280}281282/**283* Tell if the class is local or inside a local class,284* which means it cannot be mentioned outside of its file.285*/286287// The comment above is true only because M_LOCAL is set288// whenever M_ANONYMOUS is. I think it is risky to assume that289// isAnonymous(x) => isLocal(x).290291public final boolean isInsideLocal() {292return isLocal() ||293(outerClass != null && outerClass.isInsideLocal());294}295296/**297* Tell if the class is local or or anonymous class, or inside298* such a class, which means it cannot be mentioned outside of299* its file.300*/301public final boolean isInsideLocalOrAnonymous() {302return isLocal() || isAnonymous () ||303(outerClass != null && outerClass.isInsideLocalOrAnonymous());304}305306/**307* Return a simple identifier for this class (idNull if anonymous).308*/309public Identifier getLocalName() {310if (localName != null) {311return localName;312}313// This is also the name of the innerClassMember, if any:314return getName().getFlatName().getName();315}316317/**318* Set the local name of a class. Must be a local class.319*/320public void setLocalName(Identifier name) {321if (isLocal()) {322localName = name;323}324}325326/**327* If inner, get the field for this class in the enclosing class328*/329public final MemberDefinition getInnerClassMember() {330if (outerClass == null)331return null;332if (innerClassMember == null) {333// We must find the field in the outer class.334Identifier nm = getName().getFlatName().getName();335for (MemberDefinition field = outerClass.getFirstMatch(nm);336field != null; field = field.getNextMatch()) {337if (field.isInnerClass()) {338innerClassMember = field;339break;340}341}342if (innerClassMember == null)343throw new CompilerError("getInnerClassField");344}345return innerClassMember;346}347348/**349* If inner, return an innermost uplevel self pointer, if any exists.350* Otherwise, return null.351*/352public final MemberDefinition findOuterMember() {353return outerMember;354}355356/**357* See if this is a (nested) static class.358*/359public final boolean isStatic() {360return (modifiers & ACC_STATIC) != 0;361}362363/**364* Get the class' top-level enclosing class365*/366public final ClassDefinition getTopClass() {367ClassDefinition p, q;368for (p = this; (q = p.outerClass) != null; p = q)369;370return p;371}372373/**374* Get the class' first field or first match375*/376public final MemberDefinition getFirstMember() {377return firstMember;378}379public final MemberDefinition getFirstMatch(Identifier name) {380return (MemberDefinition)fieldHash.get(name);381}382383/**384* Get the class' name385*/386public final Identifier getName() {387return declaration.getName();388}389390/**391* Get the class' type392*/393public final Type getType() {394return declaration.getType();395}396397/**398* Get the class' documentation399*/400public String getDocumentation() {401return documentation;402}403404/**405* Return true if the given documentation string contains a deprecation406* paragraph. This is true if the string contains the tag @deprecated407* is the first word in a line.408*/409public static boolean containsDeprecated(String documentation) {410if (documentation == null) {411return false;412}413doScan:414for (int scan = 0;415(scan = documentation.indexOf(paraDeprecated, scan)) >= 0;416scan += paraDeprecated.length()) {417// make sure there is only whitespace between this word418// and the beginning of the line419for (int beg = scan-1; beg >= 0; beg--) {420char ch = documentation.charAt(beg);421if (ch == '\n' || ch == '\r') {422break; // OK423}424if (!Character.isSpace(ch)) {425continue doScan;426}427}428// make sure the char after the word is space or end of line429int end = scan+paraDeprecated.length();430if (end < documentation.length()) {431char ch = documentation.charAt(end);432if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {433continue doScan;434}435}436return true;437}438return false;439}440441public final boolean inSamePackage(ClassDeclaration c) {442// find out if the class stored in c is defined in the same443// package as the current class.444return inSamePackage(c.getName().getQualifier());445}446447public final boolean inSamePackage(ClassDefinition c) {448// find out if the class stored in c is defined in the same449// package as the current class.450return inSamePackage(c.getName().getQualifier());451}452453public final boolean inSamePackage(Identifier packageName) {454return (getName().getQualifier().equals(packageName));455}456457/**458* Checks459*/460public final boolean isInterface() {461return (getModifiers() & M_INTERFACE) != 0;462}463public final boolean isClass() {464return (getModifiers() & M_INTERFACE) == 0;465}466public final boolean isPublic() {467return (getModifiers() & M_PUBLIC) != 0;468}469public final boolean isPrivate() {470return (getModifiers() & M_PRIVATE) != 0;471}472public final boolean isProtected() {473return (getModifiers() & M_PROTECTED) != 0;474}475public final boolean isPackagePrivate() {476return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;477}478public final boolean isFinal() {479return (getModifiers() & M_FINAL) != 0;480}481public final boolean isAbstract() {482return (getModifiers() & M_ABSTRACT) != 0;483}484public final boolean isSynthetic() {485return (getModifiers() & M_SYNTHETIC) != 0;486}487public final boolean isDeprecated() {488return (getModifiers() & M_DEPRECATED) != 0;489}490public final boolean isAnonymous() {491return (getModifiers() & M_ANONYMOUS) != 0;492}493public final boolean isLocal() {494return (getModifiers() & M_LOCAL) != 0;495}496public final boolean hasConstructor() {497return getFirstMatch(idInit) != null;498}499500501/**502* Check to see if a class must be abstract. This method replaces503* isAbstract(env)504*/505public final boolean mustBeAbstract(Environment env) {506// If it is declared abstract, return true.507// (Fix for 4110534.)508if (isAbstract()) {509return true;510}511512// Check to see if the class should have been declared to be513// abstract.514515// We make sure that the inherited method collection has been516// performed.517collectInheritedMethods(env);518519// We check for any abstract methods inherited or declared520// by this class.521Iterator methods = getMethods();522while (methods.hasNext()) {523MemberDefinition method = (MemberDefinition) methods.next();524525if (method.isAbstract()) {526return true;527}528}529530// We check for hidden "permanently abstract" methods in531// our superclasses.532return getPermanentlyAbstractMethods().hasNext();533}534535/**536* Check if this is a super class of another class537*/538public boolean superClassOf(Environment env, ClassDeclaration otherClass)539throws ClassNotFound {540while (otherClass != null) {541if (getClassDeclaration().equals(otherClass)) {542return true;543}544otherClass = otherClass.getClassDefinition(env).getSuperClass();545}546return false;547}548549/**550* Check if this is an enclosing class of another class551*/552public boolean enclosingClassOf(ClassDefinition otherClass) {553while ((otherClass = otherClass.getOuterClass()) != null) {554if (this == otherClass) {555return true;556}557}558return false;559}560561/**562* Check if this is a sub class of another class563*/564public boolean subClassOf(Environment env, ClassDeclaration otherClass) throws ClassNotFound {565ClassDeclaration c = getClassDeclaration();566while (c != null) {567if (c.equals(otherClass)) {568return true;569}570c = c.getClassDefinition(env).getSuperClass();571}572return false;573}574575/**576* Check if this class is implemented by another class577*/578public boolean implementedBy(Environment env, ClassDeclaration c) throws ClassNotFound {579for (; c != null ; c = c.getClassDefinition(env).getSuperClass()) {580if (getClassDeclaration().equals(c)) {581return true;582}583ClassDeclaration intf[] = c.getClassDefinition(env).getInterfaces();584for (int i = 0 ; i < intf.length ; i++) {585if (implementedBy(env, intf[i])) {586return true;587}588}589}590return false;591}592593/**594* Check to see if a class which implements interface `this' could595* possibly implement the interface `intDef'. Note that the only596* way that this can fail is if `this' and `intDef' have methods597* which are of the same signature and different return types. This598* method is used by Environment.explicitCast() to determine if a599* cast between two interfaces is legal.600*601* This method should only be called on a class after it has been602* basicCheck()'ed.603*/604public boolean couldImplement(ClassDefinition intDef) {605// Check to see if we could have done the necessary checks.606if (!doInheritanceChecks) {607throw new CompilerError("couldImplement: no checks");608}609610// This method should only be called for interfaces.611if (!isInterface() || !intDef.isInterface()) {612throw new CompilerError("couldImplement: not interface");613}614615// Make sure we are not called before we have collected our616// inheritance information.617if (allMethods == null) {618throw new CompilerError("couldImplement: called early");619}620621// Get the other classes' methods. getMethods() in622// general can return methods which are not visible to the623// current package. We need to make sure that these do not624// prevent this class from being implemented.625Iterator otherMethods = intDef.getMethods();626627while (otherMethods.hasNext()) {628// Get one of the methods from intDef...629MemberDefinition method =630(MemberDefinition) otherMethods.next();631632Identifier name = method.getName();633Type type = method.getType();634635// See if we implement a method of the same signature...636MemberDefinition myMethod = allMethods.lookupSig(name, type);637638//System.out.println("Comparing\n\t" + myMethod +639// "\nand\n\t" + method);640641if (myMethod != null) {642// We do. Make sure the methods have the same return type.643if (!myMethod.sameReturnType(method)) {644return false;645}646}647}648649return true;650}651652/**653* Check if another class can be accessed from the 'extends' or 'implements'654* clause of this class.655*/656public boolean extendsCanAccess(Environment env, ClassDeclaration c) throws ClassNotFound {657658// Names in the 'extends' or 'implements' clause of an inner class659// are checked as if they appeared in the body of the surrounding class.660if (outerClass != null) {661return outerClass.canAccess(env, c);662}663664// We are a package member.665666ClassDefinition cdef = c.getClassDefinition(env);667668if (cdef.isLocal()) {669// No locals should be in scope in the 'extends' or670// 'implements' clause of a package member.671throw new CompilerError("top local");672}673674if (cdef.isInnerClass()) {675MemberDefinition f = cdef.getInnerClassMember();676677// Access to public member is always allowed.678if (f.isPublic()) {679return true;680}681682// Private access is ok only from the same class nest. This can683// happen only if the class represented by 'this' encloses the inner684// class represented by 'f'.685if (f.isPrivate()) {686return getClassDeclaration().equals(f.getTopClass().getClassDeclaration());687}688689// Protected or default access -- allow access if in same package.690return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());691}692693// Access to public member is always allowed.694if (cdef.isPublic()) {695return true;696}697698// Default access -- allow access if in same package.699return getName().getQualifier().equals(c.getName().getQualifier());700}701702/**703* Check if another class can be accessed from within the body of this class.704*/705public boolean canAccess(Environment env, ClassDeclaration c) throws ClassNotFound {706ClassDefinition cdef = c.getClassDefinition(env);707708if (cdef.isLocal()) {709// if it's in scope, it's accessible710return true;711}712713if (cdef.isInnerClass()) {714return canAccess(env, cdef.getInnerClassMember());715}716717// Public access is always ok718if (cdef.isPublic()) {719return true;720}721722// It must be in the same package723return getName().getQualifier().equals(c.getName().getQualifier());724}725726/**727* Check if a field can be accessed from a class728*/729730public boolean canAccess(Environment env, MemberDefinition f)731throws ClassNotFound {732733// Public access is always ok734if (f.isPublic()) {735return true;736}737// Protected access is ok from a subclass738if (f.isProtected() && subClassOf(env, f.getClassDeclaration())) {739return true;740}741// Private access is ok only from the same class nest742if (f.isPrivate()) {743return getTopClass().getClassDeclaration()744.equals(f.getTopClass().getClassDeclaration());745}746// It must be in the same package747return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());748}749750/**751* Check if a class is entitled to inline access to a class from752* another class.753*/754public boolean permitInlinedAccess(Environment env, ClassDeclaration c)755throws ClassNotFound {756757return (env.opt() && c.equals(declaration)) ||758(env.opt_interclass() && canAccess(env, c));759}760761/**762* Check if a class is entitled to inline access to a method from763* another class.764*/765public boolean permitInlinedAccess(Environment env, MemberDefinition f)766throws ClassNotFound {767return (env.opt()768&& (f.clazz.getClassDeclaration().equals(declaration))) ||769(env.opt_interclass() && canAccess(env, f));770}771772/**773* We know the the field is marked protected (and not public) and that774* the field is visible (as per canAccess). Can we access the field as775* <accessor>.<field>, where <accessor> has the type <accessorType>?776*777* Protected fields can only be accessed when the accessorType is a778* subclass of the current class779*/780public boolean protectedAccess(Environment env, MemberDefinition f,781Type accessorType)782throws ClassNotFound783{784785return786// static protected fields are accessible787f.isStatic()788|| // allow array.clone()789(accessorType.isType(TC_ARRAY) && (f.getName() == idClone)790&& (f.getType().getArgumentTypes().length == 0))791|| // <accessorType> is a subtype of the current class792(accessorType.isType(TC_CLASS)793&& env.getClassDefinition(accessorType.getClassName())794.subClassOf(env, getClassDeclaration()))795|| // we are accessing the field from a friendly class (same package)796(getName().getQualifier()797.equals(f.getClassDeclaration().getName().getQualifier()));798}799800801/**802* Find or create an access method for a private member,803* or return null if this is not possible.804*/805public MemberDefinition getAccessMember(Environment env, Context ctx,806MemberDefinition field, boolean isSuper) {807throw new CompilerError("binary getAccessMember");808}809810/**811* Find or create an update method for a private member,812* or return null if this is not possible.813*/814public MemberDefinition getUpdateMember(Environment env, Context ctx,815MemberDefinition field, boolean isSuper) {816throw new CompilerError("binary getUpdateMember");817}818819/**820* Get a field from this class. Report ambiguous fields.821* If no accessible field is found, this method may return an822* inaccessible field to allow a useful error message.823*824* getVariable now takes the source class `source' as an argument.825* This allows getVariable to check whether a field is inaccessible826* before it signals that a field is ambiguous. The compiler used to827* signal an ambiguity even when one of the fields involved was not828* accessible. (bug 4053724)829*/830public MemberDefinition getVariable(Environment env,831Identifier nm,832ClassDefinition source)833throws AmbiguousMember, ClassNotFound {834835return getVariable0(env, nm, source, true, true);836}837838/*839* private fields are never inherited. package-private fields are840* not inherited across package boundaries. To capture this, we841* take two booleans as parameters: showPrivate indicates whether842* we have passed a class boundary, and showPackage indicates whether843* we have crossed a package boundary.844*/845private MemberDefinition getVariable0(Environment env,846Identifier nm,847ClassDefinition source,848boolean showPrivate,849boolean showPackage)850throws AmbiguousMember, ClassNotFound {851852// Check to see if this field is defined in the current class853for (MemberDefinition member = getFirstMatch(nm);854member != null;855member = member.getNextMatch()) {856if (member.isVariable()) {857if ((showPrivate || !member.isPrivate()) &&858(showPackage || !member.isPackagePrivate())) {859// It is defined in this class.860return member;861} else {862// Even though this definition is not inherited,863// it hides all definitions in supertypes.864return null;865}866}867}868869// Find the field in our superclass.870ClassDeclaration sup = getSuperClass();871MemberDefinition field = null;872if (sup != null) {873field =874sup.getClassDefinition(env)875.getVariable0(env, nm, source,876false,877showPackage && inSamePackage(sup));878}879880// Find the field in our superinterfaces.881for (int i = 0 ; i < interfaces.length ; i++) {882// Try to look up the field in an interface. Since interfaces883// only have public fields, the values of the two boolean884// arguments are not important.885MemberDefinition field2 =886interfaces[i].getClassDefinition(env)887.getVariable0(env, nm, source, true, true);888889if (field2 != null) {890// If we have two different, accessible fields, then891// we've found an ambiguity.892if (field != null &&893source.canAccess(env, field) &&894field2 != field) {895896throw new AmbiguousMember(field2, field);897}898field = field2;899}900}901return field;902}903904/**905* Tells whether to report a deprecation error for this class.906*/907public boolean reportDeprecated(Environment env) {908return (isDeprecated()909|| (outerClass != null && outerClass.reportDeprecated(env)));910}911912/**913* Note that this class is being used somehow by <tt>ref</tt>.914* Report deprecation errors, etc.915*/916public void noteUsedBy(ClassDefinition ref, long where, Environment env) {917// (Have this deal with canAccess() checks, too?)918if (reportDeprecated(env)) {919env.error(where, "warn.class.is.deprecated", this);920}921}922923/**924* Get an inner class.925* Look in supers but not outers.926* (This is used directly to resolve expressions like "site.K", and927* inside a loop to resolve lone names like "K" or the "K" in "K.L".)928*929* Called from 'Context' and 'FieldExpression' as well as this class.930*931* @see FieldExpression.checkCommon932* @see resolveName933*/934public MemberDefinition getInnerClass(Environment env, Identifier nm)935throws ClassNotFound {936// Note: AmbiguousClass will not be thrown unless and until937// inner classes can be defined inside interfaces.938939// Check if it is defined in the current class940for (MemberDefinition field = getFirstMatch(nm);941field != null ; field = field.getNextMatch()) {942if (field.isInnerClass()) {943if (field.getInnerClass().isLocal()) {944continue; // ignore this name; it is internally generated945}946return field;947}948}949950// Get it from the super class951// It is likely that 'getSuperClass()' could be made to work here952// but we would have to assure somehow that 'resolveTypeStructure'953// has been called on the current class nest. Since we can get954// here from 'resolveName', which is called from 'resolveSupers',955// it is possible that the first attempt to resolve the superclass956// will originate here, instead of in the call to 'getSuperClass'957// in 'checkSupers'. See 'resolveTypeStructure', in which a call958// to 'resolveSupers' precedes the call to 'checkSupers'. Why is959// name resolution done twice, first in 'resolveName'?960// NOTE: 'SourceMember.resolveTypeStructure' may initiate type961// structure resolution for an inner class. Normally, this962// occurs during the resolution of the outer class, but fields963// added after the resolution of their containing class will964// be resolved late -- see 'addMember(env,field)' below.965// This should only happen for synthetic members, which should966// never be an inner class.967ClassDeclaration sup = getSuperClass(env);968if (sup != null)969return sup.getClassDefinition(env).getInnerClass(env, nm);970971return null;972}973974/**975* Lookup a method. This code implements the method lookup976* mechanism specified in JLS 15.11.2.977*978* This mechanism cannot be used to lookup synthetic methods.979*/980private MemberDefinition matchMethod(Environment env,981ClassDefinition accessor,982Identifier methodName,983Type[] argumentTypes,984boolean isAnonConstCall,985Identifier accessPackage)986throws AmbiguousMember, ClassNotFound {987988if (allMethods == null || !allMethods.isFrozen()) {989// This may be too restrictive.990throw new CompilerError("matchMethod called early");991// collectInheritedMethods(env);992}993994// A tentative maximally specific method.995MemberDefinition tentative = null;996997// A list of other methods which may be maximally specific too.998List candidateList = null;9991000// Get all the methods inherited by this class which1001// have the name `methodName'.1002Iterator methods = allMethods.lookupName(methodName);10031004while (methods.hasNext()) {1005MemberDefinition method = (MemberDefinition)methods.next();10061007// See if this method is applicable.1008if (!env.isApplicable(method, argumentTypes)) {1009continue;1010}10111012// See if this method is accessible.1013if (accessor != null) {1014if (!accessor.canAccess(env, method)) {1015continue;1016}1017} else if (isAnonConstCall) {1018if (method.isPrivate() ||1019(method.isPackagePrivate() &&1020accessPackage != null &&1021!inSamePackage(accessPackage))) {1022// For anonymous constructor accesses, we1023// haven't yet built an accessing class.1024// We disallow anonymous classes from seeing1025// private/package-private inaccessible1026// constructors in their superclass.1027continue;1028}1029} else {1030// If accessor is null, we assume that the access1031// is allowed. Query: is this option used?1032}10331034if (tentative == null) {1035// `method' becomes our tentative maximally specific match.1036tentative = method;1037} else {1038if (env.isMoreSpecific(method, tentative)) {1039// We have found a method which is a strictly better1040// match than `tentative'. Replace it.1041tentative = method;1042} else {1043// If this method could possibly be another1044// maximally specific method, add it to our1045// list of other candidates.1046if (!env.isMoreSpecific(tentative,method)) {1047if (candidateList == null) {1048candidateList = new ArrayList();1049}1050candidateList.add(method);1051}1052}1053}1054}10551056if (tentative != null && candidateList != null) {1057// Find out if our `tentative' match is a uniquely1058// maximally specific.1059Iterator candidates = candidateList.iterator();1060while (candidates.hasNext()) {1061MemberDefinition method = (MemberDefinition)candidates.next();1062if (!env.isMoreSpecific(tentative, method)) {1063throw new AmbiguousMember(tentative, method);1064}1065}1066}10671068return tentative;1069}10701071/**1072* Lookup a method. This code implements the method lookup1073* mechanism specified in JLS 15.11.2.1074*1075* This mechanism cannot be used to lookup synthetic methods.1076*/1077public MemberDefinition matchMethod(Environment env,1078ClassDefinition accessor,1079Identifier methodName,1080Type[] argumentTypes)1081throws AmbiguousMember, ClassNotFound {10821083return matchMethod(env, accessor, methodName,1084argumentTypes, false, null);1085}10861087/**1088* Lookup a method. This code implements the method lookup1089* mechanism specified in JLS 15.11.2.1090*1091* This mechanism cannot be used to lookup synthetic methods.1092*/1093public MemberDefinition matchMethod(Environment env,1094ClassDefinition accessor,1095Identifier methodName)1096throws AmbiguousMember, ClassNotFound {10971098return matchMethod(env, accessor, methodName,1099Type.noArgs, false, null);1100}11011102/**1103* A version of matchMethod to be used only for constructors1104* when we cannot pass in a sourceClass argument. We just assert1105* our package name.1106*1107* This is used only for anonymous classes, where we have to look up1108* a (potentially) protected constructor with no valid sourceClass1109* parameter available.1110*/1111public MemberDefinition matchAnonConstructor(Environment env,1112Identifier accessPackage,1113Type argumentTypes[])1114throws AmbiguousMember, ClassNotFound {11151116return matchMethod(env, null, idInit, argumentTypes,1117true, accessPackage);1118}11191120/**1121* Find a method, ie: exact match in this class or any of the super1122* classes.1123*1124* Only called by javadoc. For now I am holding off rewriting this1125* code to rely on collectInheritedMethods(), as that code has1126* not gotten along with javadoc in the past.1127*/1128public MemberDefinition findMethod(Environment env, Identifier nm, Type t)1129throws ClassNotFound {1130// look in the current class1131MemberDefinition f;1132for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {1133// Note that non-method types return false for equalArguments().1134if (f.getType().equalArguments(t)) {1135return f;1136}1137}11381139// constructors are not inherited1140if (nm.equals(idInit)) {1141return null;1142}11431144// look in the super class1145ClassDeclaration sup = getSuperClass();1146if (sup == null)1147return null;11481149return sup.getClassDefinition(env).findMethod(env, nm, t);1150}11511152// We create a stub for this. Source classes do more work.1153protected void basicCheck(Environment env) throws ClassNotFound {1154// Do the outer class first.1155if (outerClass != null)1156outerClass.basicCheck(env);1157}11581159/**1160* Check this class.1161*/1162public void check(Environment env) throws ClassNotFound {1163}11641165public Vset checkLocalClass(Environment env, Context ctx,1166Vset vset, ClassDefinition sup,1167Expression args[], Type argTypes[]1168) throws ClassNotFound {1169throw new CompilerError("checkLocalClass");1170}11711172//---------------------------------------------------------------1173// The non-synthetic methods defined in this class or in any1174// of its parents (class or interface). This member is used1175// to cache work done in collectInheritedMethods for use by1176// getMethods() and matchMethod(). It should be accessed by1177// no other method without forethought.1178MethodSet allMethods = null;11791180// One of our superclasses may contain an abstract method which1181// we are unable to ever implement. This happens when there is1182// a package-private abstract method in our parent and we are in1183// a different package than our parent. In these cases, we1184// keep a list of the "permanently abstract" or "unimplementable"1185// methods so that we can correctly detect that this class is1186// indeed abstract and so that we can give somewhat comprehensible1187// error messages.1188private List permanentlyAbstractMethods = new ArrayList();11891190/**1191* This method returns an Iterator of all abstract methods1192* in our superclasses which we are unable to implement.1193*/1194protected Iterator getPermanentlyAbstractMethods() {1195// This method can only be called after collectInheritedMethods.1196if (allMethods == null) {1197throw new CompilerError("isPermanentlyAbstract() called early");1198}11991200return permanentlyAbstractMethods.iterator();1201}12021203/**1204* A flag used by turnOffInheritanceChecks() to indicate if1205* inheritance checks are on or off.1206*/1207protected static boolean doInheritanceChecks = true;12081209/**1210* This is a workaround to allow javadoc to turn off certain1211* inheritance/override checks which interfere with javadoc1212* badly. In the future it might be good to eliminate the1213* shared sources of javadoc and javac to avoid the need for this1214* sort of workaround.1215*/1216public static void turnOffInheritanceChecks() {1217doInheritanceChecks = false;1218}12191220/**1221* Add all of the methods declared in or above `parent' to1222* `allMethods', the set of methods in the current class.1223* `myMethods' is the set of all methods declared in this1224* class, and `mirandaMethods' is a repository for Miranda methods.1225* If mirandaMethods is null, no mirandaMethods will be1226* generated.1227*1228* For a definition of Miranda methods, see the comment above the1229* method addMirandaMethods() which occurs later in this file.1230*/1231private void collectOneClass(Environment env,1232ClassDeclaration parent,1233MethodSet myMethods,1234MethodSet allMethods,1235MethodSet mirandaMethods) {12361237// System.out.println("Inheriting methods from " + parent);12381239try {1240ClassDefinition pClass = parent.getClassDefinition(env);1241Iterator methods = pClass.getMethods(env);1242while (methods.hasNext()) {1243MemberDefinition method =1244(MemberDefinition) methods.next();12451246// Private methods are not inherited.1247//1248// Constructors are not inherited.1249//1250// Any non-abstract methods in an interface come1251// from java.lang.Object. This means that they1252// should have already been added to allMethods1253// when we walked our superclass lineage.1254if (method.isPrivate() ||1255method.isConstructor() ||1256(pClass.isInterface() && !method.isAbstract())) {12571258continue;1259}12601261// Get the components of the methods' signature.1262Identifier name = method.getName();1263Type type = method.getType();12641265// Check for a method of the same signature which1266// was locally declared.1267MemberDefinition override =1268myMethods.lookupSig(name, type);12691270// Is this method inaccessible due to package-private1271// visibility?1272if (method.isPackagePrivate() &&1273!inSamePackage(method.getClassDeclaration())) {12741275if (override != null && this instanceof1276sun.tools.javac.SourceClass) {1277// We give a warning when a class shadows an1278// inaccessible package-private method from1279// its superclass. This warning is meant1280// to prevent people from relying on overriding1281// when it does not happen. This warning should1282// probably be removed to be consistent with the1283// general "no warnings" policy of this1284// compiler.1285//1286// The `instanceof' above is a hack so that only1287// SourceClass generates this warning, not a1288// BinaryClass, for example.1289env.error(method.getWhere(),1290"warn.no.override.access",1291override,1292override.getClassDeclaration(),1293method.getClassDeclaration());1294}12951296// If our superclass has a package-private abstract1297// method that we have no access to, then we add1298// this method to our list of permanently abstract1299// methods. The idea is, since we cannot override1300// the method, we can never make this class1301// non-abstract.1302if (method.isAbstract()) {1303permanentlyAbstractMethods.add(method);1304}13051306// `method' is inaccessible. We do not inherit it.1307continue;1308}13091310if (override != null) {1311// `method' and `override' have the same signature.1312// We are required to check that `override' is a1313// legal override of `method'13141315//System.out.println ("About to check override of " +1316// method);13171318override.checkOverride(env, method);1319} else {1320// In the absence of a definition in the class1321// itself, we check to see if this definition1322// can be successfully merged with any other1323// inherited definitions.13241325// Have we added a member of the same signature1326// to `allMethods' already?1327MemberDefinition formerMethod =1328allMethods.lookupSig(name, type);13291330// If the previous definition is nonexistent or1331// ignorable, replace it.1332if (formerMethod == null) {1333//System.out.println("Added " + method + " to " +1334// this);13351336if (mirandaMethods != null &&1337pClass.isInterface() && !isInterface()) {1338// Whenever a class inherits a method1339// from an interface, that method is1340// one of our "miranda" methods. Early1341// VMs require that these methods be1342// added as true members to the class1343// to enable method lookup to work in the1344// VM.1345method =1346new sun.tools.javac.SourceMember(method,this,1347env);1348mirandaMethods.add(method);13491350//System.out.println("Added " + method +1351// " to " + this + " as a Miranda");1352}13531354// There is no previous inherited definition.1355// Add `method' to `allMethods'.1356allMethods.add(method);1357} else if (isInterface() &&1358!formerMethod.isAbstract() &&1359method.isAbstract()) {1360// If we are in an interface and we have inherited1361// both an abstract method and a non-abstract method1362// then we know that the non-abstract method is1363// a placeholder from Object put in for type checking1364// and the abstract method was already checked to1365// be proper by our superinterface.1366allMethods.replace(method);13671368} else {1369// Okay, `formerMethod' and `method' both have the1370// same signature. See if they are compatible.13711372//System.out.println ("About to check meet of " +1373// method);13741375if (!formerMethod.checkMeet(env,1376method,1377this.getClassDeclaration())) {1378// The methods are incompatible. Skip to1379// next method.1380continue;1381}13821383if (formerMethod.couldOverride(env, method)) {1384// Do nothing. The current definition1385// is specific enough.13861387//System.out.println("trivial meet of " +1388// method);1389continue;1390}13911392if (method.couldOverride(env, formerMethod)) {1393// `method' is more specific than1394// `formerMethod'. replace `formerMethod'.13951396//System.out.println("new def of " + method);1397if (mirandaMethods != null &&1398pClass.isInterface() && !isInterface()) {1399// Whenever a class inherits a method1400// from an interface, that method is1401// one of our "miranda" methods. Early1402// VMs require that these methods be1403// added as true members to the class1404// to enable method lookup to work in the1405// VM.1406method =1407new sun.tools.javac.SourceMember(method,1408this,env);14091410mirandaMethods.replace(method);14111412//System.out.println("Added " + method +1413// " to " + this + " as a Miranda");1414}14151416allMethods.replace(method);14171418continue;1419}14201421// Neither method is more specific than the other.1422// Oh well. We need to construct a nontrivial1423// meet of the two methods.1424//1425// This is not yet implemented, so we give1426// a message with a helpful workaround.1427env.error(this.where,1428"nontrivial.meet", method,1429formerMethod.getClassDefinition(),1430method.getClassDeclaration()1431);1432}1433}1434}1435} catch (ClassNotFound ee) {1436env.error(getWhere(), "class.not.found", ee.name, this);1437}1438}14391440/**1441* <p>Collect all methods defined in this class or inherited from1442* any of our superclasses or interfaces. Look for any1443* incompatible definitions.1444*1445* <p>This function is also responsible for collecting the1446* <em>Miranda</em> methods for a class. For a definition of1447* Miranda methods, see the comment in addMirandaMethods()1448* below.1449*/1450protected void collectInheritedMethods(Environment env) {1451// The methods defined in this class.1452MethodSet myMethods;1453MethodSet mirandaMethods;14541455//System.out.println("Called collectInheritedMethods() for " +1456// this);14571458if (allMethods != null) {1459if (allMethods.isFrozen()) {1460// We have already done the collection. No need to1461// do it again.1462return;1463} else {1464// We have run into a circular need to collect our methods.1465// This should not happen at this stage.1466throw new CompilerError("collectInheritedMethods()");1467}1468}14691470myMethods = new MethodSet();1471allMethods = new MethodSet();14721473// For testing, do not generate miranda methods.1474if (env.version12()) {1475mirandaMethods = null;1476} else {1477mirandaMethods = new MethodSet();1478}14791480// Any methods defined in the current class get added1481// to both the myMethods and the allMethods MethodSets.14821483for (MemberDefinition member = getFirstMember();1484member != null;1485member = member.nextMember) {14861487// We only collect methods. Initializers are not relevant.1488if (member.isMethod() &&1489!member.isInitializer()) {14901491//System.out.println("Declared in " + this + ", " + member);14921493////////////////////////////////////////////////////////////1494// PCJ 2003-07-30 modified the following code because with1495// the covariant return type feature of the 1.5 compiler,1496// there might be multiple methods with the same signature1497// but different return types, and MethodSet doesn't1498// support that. We use a new utility method that attempts1499// to ensure that the appropriate method winds up in the1500// MethodSet. See 4892308.1501////////////////////////////////////////////////////////////1502// myMethods.add(member);1503// allMethods.add(member);1504////////////////////////////////////////////////////////////1505methodSetAdd(env, myMethods, member);1506methodSetAdd(env, allMethods, member);1507////////////////////////////////////////////////////////////1508}1509}15101511// We're ready to start adding inherited methods. First add1512// the methods from our superclass.15131514//System.out.println("About to start superclasses for " + this);15151516ClassDeclaration scDecl = getSuperClass(env);1517if (scDecl != null) {1518collectOneClass(env, scDecl,1519myMethods, allMethods, mirandaMethods);15201521// Make sure that we add all unimplementable methods from our1522// superclass to our list of unimplementable methods.1523ClassDefinition sc = scDecl.getClassDefinition();1524Iterator supIter = sc.getPermanentlyAbstractMethods();1525while (supIter.hasNext()) {1526permanentlyAbstractMethods.add(supIter.next());1527}1528}15291530// Now we inherit all of the methods from our interfaces.15311532//System.out.println("About to start interfaces for " + this);15331534for (int i = 0; i < interfaces.length; i++) {1535collectOneClass(env, interfaces[i],1536myMethods, allMethods, mirandaMethods);1537}1538allMethods.freeze();15391540// Now we have collected all of our methods from our superclasses1541// and interfaces into our `allMethods' member. Good. As a last1542// task, we add our collected miranda methods to this class.1543//1544// If we do not add the mirandas to the class explicitly, there1545// will be no code generated for them.1546if (mirandaMethods != null && mirandaMethods.size() > 0) {1547addMirandaMethods(env, mirandaMethods.iterator());1548}1549}15501551////////////////////////////////////////////////////////////1552// PCJ 2003-07-30 added this utility method to insulate1553// MethodSet additions from the covariant return type1554// feature of the 1.5 compiler. When there are multiple1555// methods with the same signature and different return1556// types to be added, we try to ensure that the one with1557// the most specific return type winds up in the MethodSet.1558// This logic was not put into MethodSet itself because it1559// requires access to an Environment for type relationship1560// checking. No error checking is performed here, but that1561// should be OK because this code is only still used by1562// rmic. See 4892308.1563////////////////////////////////////////////////////////////1564private static void methodSetAdd(Environment env,1565MethodSet methodSet,1566MemberDefinition newMethod)1567{1568MemberDefinition oldMethod = methodSet.lookupSig(newMethod.getName(),1569newMethod.getType());1570if (oldMethod != null) {1571Type oldReturnType = oldMethod.getType().getReturnType();1572Type newReturnType = newMethod.getType().getReturnType();1573try {1574if (env.isMoreSpecific(newReturnType, oldReturnType)) {1575methodSet.replace(newMethod);1576}1577} catch (ClassNotFound ignore) {1578}1579} else {1580methodSet.add(newMethod);1581}1582}1583////////////////////////////////////////////////////////////15841585/**1586* Get an Iterator of all methods which could be accessed in an1587* instance of this class.1588*/1589public Iterator getMethods(Environment env) {1590if (allMethods == null) {1591collectInheritedMethods(env);1592}1593return getMethods();1594}15951596/**1597* Get an Iterator of all methods which could be accessed in an1598* instance of this class. Throw a compiler error if we haven't1599* generated this information yet.1600*/1601public Iterator getMethods() {1602if (allMethods == null) {1603throw new CompilerError("getMethods: too early");1604}1605return allMethods.iterator();1606}16071608// In early VM's there was a bug -- the VM didn't walk the interfaces1609// of a class looking for a method, they only walked the superclass1610// chain. This meant that abstract methods defined only in interfaces1611// were not being found. To fix this bug, a counter-bug was introduced1612// in the compiler -- the so-called Miranda methods. If a class1613// does not provide a definition for an abstract method in one of1614// its interfaces then the compiler inserts one in the class artificially.1615// That way the VM didn't have to bother looking at the interfaces.1616//1617// This is a problem. Miranda methods are not part of the specification.1618// But they continue to be inserted so that old VM's can run new code.1619// Someday, when the old VM's are gone, perhaps classes can be compiled1620// without Miranda methods. Towards this end, the compiler has a1621// flag, -nomiranda, which can turn off the creation of these methods.1622// Eventually that behavior should become the default.1623//1624// Why are they called Miranda methods? Well the sentence "If the1625// class is not able to provide a method, then one will be provided1626// by the compiler" is very similar to the sentence "If you cannot1627// afford an attorney, one will be provided by the court," -- one1628// of the so-called "Miranda" rights in the United States.16291630/**1631* Add a list of methods to this class as miranda methods. This1632* gets overridden with a meaningful implementation in SourceClass.1633* BinaryClass should not need to do anything -- it should already1634* have its miranda methods and, if it doesn't, then that doesn't1635* affect our compilation.1636*/1637protected void addMirandaMethods(Environment env,1638Iterator mirandas) {1639// do nothing.1640}16411642//---------------------------------------------------------------16431644public void inlineLocalClass(Environment env) {1645}16461647/**1648* We create a stub for this. Source classes do more work.1649* Some calls from 'SourceClass.checkSupers' execute this method.1650* @see sun.tools.javac.SourceClass#resolveTypeStructure1651*/16521653public void resolveTypeStructure(Environment env) {1654}16551656/**1657* Look up an inner class name, from somewhere inside this class.1658* Since supers and outers are in scope, search them too.1659* <p>1660* If no inner class is found, env.resolveName() is then called,1661* to interpret the ambient package and import directives.1662* <p>1663* This routine operates on a "best-efforts" basis. If1664* at some point a class is not found, the partially-resolved1665* identifier is returned. Eventually, someone else has to1666* try to get the ClassDefinition and diagnose the ClassNotFound.1667* <p>1668* resolveName() looks at surrounding scopes, and hence1669* pulling in both inherited and uplevel types. By contrast,1670* resolveInnerClass() is intended only for interpreting1671* explicitly qualified names, and so look only at inherited1672* types. Also, resolveName() looks for package prefixes,1673* which appear similar to "very uplevel" outer classes.1674* <p>1675* A similar (but more complex) name-lookup process happens1676* when field and identifier expressions denoting qualified names1677* are type-checked. The added complexity comes from the fact1678* that variables may occur in such names, and take precedence1679* over class and package names.1680* <p>1681* In the expression type-checker, resolveInnerClass() is paralleled1682* by code in FieldExpression.checkAmbigName(), which also calls1683* ClassDefinition.getInnerClass() to interpret names of the form1684* "OuterClass.Inner" (and also outerObject.Inner). The checking1685* of an identifier expression that fails to be a variable is referred1686* directly to resolveName().1687*/1688public Identifier resolveName(Environment env, Identifier name) {1689if (tracing) env.dtEvent("ClassDefinition.resolveName: " + name);1690// This logic is pretty much exactly parallel to that of1691// Environment.resolveName().1692if (name.isQualified()) {1693// Try to resolve the first identifier component,1694// because inner class names take precedence over1695// package prefixes. (Cf. Environment.resolveName.)1696Identifier rhead = resolveName(env, name.getHead());16971698if (rhead.hasAmbigPrefix()) {1699// The first identifier component refers to an1700// ambiguous class. Limp on. We throw away the1701// rest of the classname as it is irrelevant.1702// (part of solution for 4059855).1703return rhead;1704}17051706if (!env.classExists(rhead)) {1707return env.resolvePackageQualifiedName(name);1708}1709try {1710return env.getClassDefinition(rhead).1711resolveInnerClass(env, name.getTail());1712} catch (ClassNotFound ee) {1713// return partially-resolved name someone else can fail on1714return Identifier.lookupInner(rhead, name.getTail());1715}1716}17171718// This method used to fail to look for local classes, thus a1719// reference to a local class within, e.g., the type of a member1720// declaration, would fail to resolve if the immediately enclosing1721// context was an inner class. The code added below is ugly, but1722// it works, and is lifted from existing code in 'Context.resolveName'1723// and 'Context.getClassCommon'. See the comments there about the design.1724// Fixes 4095716.17251726int ls = -2;1727LocalMember lf = null;1728if (classContext != null) {1729lf = classContext.getLocalClass(name);1730if (lf != null) {1731ls = lf.getScopeNumber();1732}1733}17341735// Look for an unqualified name in enclosing scopes.1736for (ClassDefinition c = this; c != null; c = c.outerClass) {1737try {1738MemberDefinition f = c.getInnerClass(env, name);1739if (f != null &&1740(lf == null || classContext.getScopeNumber(c) > ls)) {1741// An uplevel member was found, and was nested more deeply than1742// any enclosing local of the same name.1743return f.getInnerClass().getName();1744}1745} catch (ClassNotFound ee) {1746// a missing superclass, or something catastrophic1747}1748}17491750// No uplevel member found, so use the enclosing local if one was found.1751if (lf != null) {1752return lf.getInnerClass().getName();1753}17541755// look in imports, etc.1756return env.resolveName(name);1757}17581759/**1760* Interpret a qualified class name, which may have further subcomponents..1761* Follow inheritance links, as in:1762* class C { class N { } } class D extends C { } ... new D.N() ...1763* Ignore outer scopes and packages.1764* @see resolveName1765*/1766public Identifier resolveInnerClass(Environment env, Identifier nm) {1767if (nm.isInner()) throw new CompilerError("inner");1768if (nm.isQualified()) {1769Identifier rhead = resolveInnerClass(env, nm.getHead());1770try {1771return env.getClassDefinition(rhead).1772resolveInnerClass(env, nm.getTail());1773} catch (ClassNotFound ee) {1774// return partially-resolved name someone else can fail on1775return Identifier.lookupInner(rhead, nm.getTail());1776}1777} else {1778try {1779MemberDefinition f = getInnerClass(env, nm);1780if (f != null) {1781return f.getInnerClass().getName();1782}1783} catch (ClassNotFound ee) {1784// a missing superclass, or something catastrophic1785}1786// Fake a good name for a diagnostic.1787return Identifier.lookupInner(this.getName(), nm);1788}1789}17901791/**1792* While resolving import directives, the question has arisen:1793* does a given inner class exist? If the top-level class exists,1794* we ask it about an inner class via this method.1795* This method looks only at the literal name of the class,1796* and does not attempt to follow inheritance links.1797* This is necessary, since at the time imports are being1798* processed, inheritance links have not been resolved yet.1799* (Thus, an import directive must always spell a class1800* name exactly.)1801*/1802public boolean innerClassExists(Identifier nm) {1803for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {1804if (field.isInnerClass()) {1805if (field.getInnerClass().isLocal()) {1806continue; // ignore this name; it is internally generated1807}1808return !nm.isQualified() ||1809field.getInnerClass().innerClassExists(nm.getTail());1810}1811}1812return false;1813}18141815/**1816* Find any method with a given name.1817*/1818public MemberDefinition findAnyMethod(Environment env, Identifier nm) throws ClassNotFound {1819MemberDefinition f;1820for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {1821if (f.isMethod()) {1822return f;1823}1824}18251826// look in the super class1827ClassDeclaration sup = getSuperClass();1828if (sup == null)1829return null;1830return sup.getClassDefinition(env).findAnyMethod(env, nm);1831}18321833/**1834* Given the fact that this class has no method "nm" matching "argTypes",1835* find out if the mismatch can be blamed on a particular actual argument1836* which disagrees with all of the overloadings.1837* If so, return the code (i<<2)+(castOK<<1)+ambig, where1838* "i" is the number of the offending argument, and1839* "castOK" is 1 if a cast could fix the problem.1840* The target type for the argument is returned in margTypeResult[0].1841* If not all methods agree on this type, "ambig" is 1.1842* If there is more than one method, the choice of target type is1843* arbitrary.<p>1844* Return -1 if every argument is acceptable to at least one method.1845* Return -2 if there are no methods of the required arity.1846* The value "start" gives the index of the first argument to begin1847* checking.1848*/1849public int diagnoseMismatch(Environment env, Identifier nm, Type argTypes[],1850int start, Type margTypeResult[]) throws ClassNotFound {1851int haveMatch[] = new int[argTypes.length];1852Type margType[] = new Type[argTypes.length];1853if (!diagnoseMismatch(env, nm, argTypes, start, haveMatch, margType))1854return -2;1855for (int i = start; i < argTypes.length; i++) {1856if (haveMatch[i] < 4) {1857margTypeResult[0] = margType[i];1858return (i<<2) | haveMatch[i];1859}1860}1861return -1;1862}18631864private boolean diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start,1865int haveMatch[], Type margType[]) throws ClassNotFound {1866// look in the current class1867boolean haveOne = false;1868MemberDefinition f;1869for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {1870if (!f.isMethod()) {1871continue;1872}1873Type fArgTypes[] = f.getType().getArgumentTypes();1874if (fArgTypes.length == argTypes.length) {1875haveOne = true;1876for (int i = start; i < argTypes.length; i++) {1877Type at = argTypes[i];1878Type ft = fArgTypes[i];1879if (env.implicitCast(at, ft)) {1880haveMatch[i] = 4;1881continue;1882} else if (haveMatch[i] <= 2 && env.explicitCast(at, ft)) {1883if (haveMatch[i] < 2) margType[i] = null;1884haveMatch[i] = 2;1885} else if (haveMatch[i] > 0) {1886continue;1887}1888if (margType[i] == null)1889margType[i] = ft;1890else if (margType[i] != ft)1891haveMatch[i] |= 1;1892}1893}1894}18951896// constructors are not inherited1897if (nm.equals(idInit)) {1898return haveOne;1899}19001901// look in the super class1902ClassDeclaration sup = getSuperClass();1903if (sup != null) {1904if (sup.getClassDefinition(env).diagnoseMismatch(env, nm, argTypes, start,1905haveMatch, margType))1906haveOne = true;1907}1908return haveOne;1909}19101911/**1912* Add a field (no checks)1913*/1914public void addMember(MemberDefinition field) {1915//System.out.println("ADD = " + field);1916if (firstMember == null) {1917firstMember = lastMember = field;1918} else if (field.isSynthetic() && field.isFinal()1919&& field.isVariable()) {1920// insert this at the front, because of initialization order1921field.nextMember = firstMember;1922firstMember = field;1923field.nextMatch = (MemberDefinition)fieldHash.get(field.name);1924} else {1925lastMember.nextMember = field;1926lastMember = field;1927field.nextMatch = (MemberDefinition)fieldHash.get(field.name);1928}1929fieldHash.put(field.name, field);1930}19311932/**1933* Add a field (subclasses make checks)1934*/1935public void addMember(Environment env, MemberDefinition field) {1936addMember(field);1937if (resolved) {1938// a late addition1939field.resolveTypeStructure(env);1940}1941}19421943/**1944* Find or create an uplevel reference for the given target.1945*/1946public UplevelReference getReference(LocalMember target) {1947for (UplevelReference r = references; r != null; r = r.getNext()) {1948if (r.getTarget() == target) {1949return r;1950}1951}1952return addReference(target);1953}19541955protected UplevelReference addReference(LocalMember target) {1956if (target.getClassDefinition() == this) {1957throw new CompilerError("addReference "+target);1958}1959referencesMustNotBeFrozen();1960UplevelReference r = new UplevelReference(this, target);1961references = r.insertInto(references);1962return r;1963}19641965/**1966* Return the list of all uplevel references.1967*/1968public UplevelReference getReferences() {1969return references;1970}19711972/**1973* Return the same value as getReferences.1974* Also, mark the set of references frozen.1975* After that, it is an error to add new references.1976*/1977public UplevelReference getReferencesFrozen() {1978referencesFrozen = true;1979return references;1980}19811982/**1983* assertion check1984*/1985public final void referencesMustNotBeFrozen() {1986if (referencesFrozen) {1987throw new CompilerError("referencesMustNotBeFrozen "+this);1988}1989}19901991/**1992* Get helper method for class literal lookup.1993*/1994public MemberDefinition getClassLiteralLookup(long fwhere) {1995throw new CompilerError("binary class");1996}19971998/**1999* Add a dependency2000*/2001public void addDependency(ClassDeclaration c) {2002throw new CompilerError("addDependency");2003}20042005/**2006* Maintain a hash table of local and anonymous classes2007* whose internal names are prefixed by the current class.2008* The key is the simple internal name, less the prefix.2009*/20102011public ClassDefinition getLocalClass(String name) {2012if (localClasses == null) {2013return null;2014} else {2015return (ClassDefinition)localClasses.get(name);2016}2017}20182019public void addLocalClass(ClassDefinition c, String name) {2020if (localClasses == null) {2021localClasses = new Hashtable(LOCAL_CLASSES_SIZE);2022}2023localClasses.put(name, c);2024}202520262027/**2028* Print for debugging2029*/2030public void print(PrintStream out) {2031if (isPublic()) {2032out.print("public ");2033}2034if (isInterface()) {2035out.print("interface ");2036} else {2037out.print("class ");2038}2039out.print(getName() + " ");2040if (getSuperClass() != null) {2041out.print("extends " + getSuperClass().getName() + " ");2042}2043if (interfaces.length > 0) {2044out.print("implements ");2045for (int i = 0 ; i < interfaces.length ; i++) {2046if (i > 0) {2047out.print(", ");2048}2049out.print(interfaces[i].getName());2050out.print(" ");2051}2052}2053out.println("{");20542055for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {2056out.print(" ");2057f.print(out);2058}20592060out.println("}");2061}20622063/**2064* Convert to String2065*/2066public String toString() {2067return getClassDeclaration().toString();2068}20692070/**2071* After the class has been written to disk, try to free up2072* some storage.2073*/2074public void cleanup(Environment env) {2075if (env.dump()) {2076env.output("[cleanup " + getName() + "]");2077}2078for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {2079f.cleanup(env);2080}2081// keep "references" around, for the sake of local subclasses2082documentation = null;2083}2084}208520862087