2085 lines · 77.0 KB · Java
RawDownload
/* * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.tools.java; import java.util.*;import java.io.OutputStream;import java.io.PrintStream;import sun.tools.tree.Context;import sun.tools.tree.Vset;import sun.tools.tree.Expression;import sun.tools.tree.LocalMember;import sun.tools.tree.UplevelReference; /** * This class is a Java class definition * * WARNING: The contents of this source file are not part of any * supported API.  Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */publicclass ClassDefinition implements Constants {     protected Object source;    protected long where;    protected int modifiers;    protected Identifier localName; // for local classes    protected ClassDeclaration declaration;    protected IdentifierToken superClassId;    protected IdentifierToken interfaceIds[];    protected ClassDeclaration superClass;    protected ClassDeclaration interfaces[];    protected ClassDefinition outerClass;    protected MemberDefinition outerMember;    protected MemberDefinition innerClassMember;        // field for me in outerClass    protected MemberDefinition firstMember;    protected MemberDefinition lastMember;    protected boolean resolved;    protected String documentation;    protected boolean error;    protected boolean nestError;    protected UplevelReference references;    protected boolean referencesFrozen;    private Hashtable fieldHash = new Hashtable(31);    private int abstr;     // Table of local and anonymous classes whose internal names are constructed    // using the current class as a prefix.  This is part of a fix for    // bugid 4054523 and 4030421.  See also 'Environment.getClassDefinition'    // and 'BatchEnvironment.makeClassDefinition'.  Allocated on demand.    private Hashtable localClasses = null;    private final int LOCAL_CLASSES_SIZE = 31;     // The immediately surrounding context in which the class appears.    // Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.    // Null for classes that are not local or inside a local class.    // At present, this field exists only for the benefit of 'resolveName' as part    // of the fix for 4095716.    protected Context classContext;     // The saved class context is now also used in 'SourceClass.getAccessMember'.    // Provide read-only access via this method.  Part of fix for 4098093.    public Context getClassContext() {        return classContext;    }      /**     * Constructor     */    protected ClassDefinition(Object source, long where, ClassDeclaration declaration,                              int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {        this.source = source;        this.where = where;        this.declaration = declaration;        this.modifiers = modifiers;        this.superClassId = superClass;        this.interfaceIds = interfaces;    }     /**     * Get the source of the class     */    public final Object getSource() {        return source;    }     /**     * Check if there were any errors in this class.     */    public final boolean getError() {        return error;    }     /**     * Mark this class to be erroneous.     */    public final void setError() {        this.error = true;        setNestError();    }     /**     * Check if there were any errors in our class nest.     */    public final boolean getNestError() {        // Check to see if our error value is set, or if any of our        // outer classes' error values are set.  This will work in        // conjunction with setError(), which sets the error value        // of its outer class, to yield true is any of our nest        // siblings has an error.  This addresses bug 4111488: either        // code should be generated for all classes in a nest, or        // none of them.        return nestError || ((outerClass != null) ? outerClass.getNestError() : false);    }     /**     * Mark this class, and all siblings in its class nest, to be     * erroneous.     */    public final void setNestError() {        this.nestError = true;        if (outerClass != null) {            // If we have an outer class, set it to be erroneous as well.            // This will work in conjunction with getError(), which checks            // the error value of its outer class, to set the whole class            // nest to be erroneous.  This address bug 4111488: either            // code should be generated for all classes in a nest, or            // none of them.            outerClass.setNestError();        }    }     /**     * Get the position in the input     */    public final long getWhere() {        return where;    }     /**     * Get the class declaration     */    public final ClassDeclaration getClassDeclaration() {        return declaration;    }     /**     * Get the class' modifiers     */    public final int getModifiers() {        return modifiers;    }    public final void subModifiers(int mod) {        modifiers &= ~mod;    }    public final void addModifiers(int mod) {        modifiers |= mod;    }     // *** DEBUG ***    protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);     /**     * Get the class' super class     */    public final ClassDeclaration getSuperClass() {        /*---        if (superClass == null && superClassId != null)            throw new CompilerError("getSuperClass "+superClassId);        // There are obscure cases where null is the right answer,        // in order to enable some error reporting later on.        // For example:  class T extends T.N { class N { } }        ---*/         // *** DEBUG ***        // This method should not be called if the superclass has not been resolved.        if (!supersCheckStarted) throw new CompilerError("unresolved super");         return superClass;    }     /**     * Get the super class, and resolve names now if necessary.     *     * It is only possible to resolve names at this point if we are     * a source class.  The provision of this method at this level     * in the class hierarchy is dubious, but see 'getInnerClass' below.     * All other calls to 'getSuperClass(env)' appear in 'SourceClass'.     * NOTE: An older definition of this method has been moved to     * 'SourceClass', where it overrides this one.     *     * @see #resolveTypeStructure     */     public ClassDeclaration getSuperClass(Environment env) {        return getSuperClass();    }     /**     * Get the class' interfaces     */    public final ClassDeclaration getInterfaces()[] {        if (interfaces == null)  throw new CompilerError("getInterfaces");        return interfaces;    }     /**     * Get the class' enclosing class (or null if not inner)     */    public final ClassDefinition getOuterClass() {        return outerClass;    }     /**     * Set the class' enclosing class.  Must be done at most once.     */    protected final void setOuterClass(ClassDefinition outerClass) {        if (this.outerClass != null)  throw new CompilerError("setOuterClass");        this.outerClass = outerClass;    }     /**     * Set the class' enclosing current instance pointer.     * Must be done at most once.     */    protected final void setOuterMember(MemberDefinition outerMember) {         if (isStatic() || !isInnerClass())  throw new CompilerError("setOuterField");        if (this.outerMember != null)  throw new CompilerError("setOuterField");        this.outerMember = outerMember;    }     /**     * Tell if the class is inner.     * This predicate also returns true for top-level nested types.     * To test for a true inner class as seen by the programmer,     * use <tt>!isTopLevel()</tt>.     */    public final boolean isInnerClass() {        return outerClass != null;    }     /**     * Tell if the class is a member of another class.     * This is false for package members and for block-local classes.     */    public final boolean isMember() {        return outerClass != null && !isLocal();    }     /**     * Tell if the class is "top-level", which is either a package member,     * or a static member of another top-level class.     */    public final boolean isTopLevel() {        return outerClass == null || isStatic() || isInterface();    }     /**     * Tell if the class is local or inside a local class,     * which means it cannot be mentioned outside of its file.     */     // The comment above is true only because M_LOCAL is set    // whenever M_ANONYMOUS is.  I think it is risky to assume that    // isAnonymous(x) => isLocal(x).     public final boolean isInsideLocal() {        return isLocal() ||            (outerClass != null && outerClass.isInsideLocal());    }     /**     * Tell if the class is local or or anonymous class, or inside     * such a class, which means it cannot be mentioned outside of     * its file.     */    public final boolean isInsideLocalOrAnonymous() {        return isLocal() || isAnonymous () ||            (outerClass != null && outerClass.isInsideLocalOrAnonymous());    }     /**     * Return a simple identifier for this class (idNull if anonymous).     */    public Identifier getLocalName() {        if (localName != null) {            return localName;        }        // This is also the name of the innerClassMember, if any:        return getName().getFlatName().getName();    }     /**     * Set the local name of a class.  Must be a local class.     */    public void setLocalName(Identifier name) {        if (isLocal()) {            localName = name;        }    }     /**     * If inner, get the field for this class in the enclosing class     */    public final MemberDefinition getInnerClassMember() {        if (outerClass == null)            return null;        if (innerClassMember == null) {            // We must find the field in the outer class.            Identifier nm = getName().getFlatName().getName();            for (MemberDefinition field = outerClass.getFirstMatch(nm);                 field != null; field = field.getNextMatch()) {                if (field.isInnerClass()) {                    innerClassMember = field;                    break;                }            }            if (innerClassMember == null)                throw new CompilerError("getInnerClassField");        }        return innerClassMember;    }     /**     * If inner, return an innermost uplevel self pointer, if any exists.     * Otherwise, return null.     */    public final MemberDefinition findOuterMember() {        return outerMember;    }     /**     * See if this is a (nested) static class.     */    public final boolean isStatic() {        return (modifiers & ACC_STATIC) != 0;    }     /**     * Get the class' top-level enclosing class     */    public final ClassDefinition getTopClass() {        ClassDefinition p, q;        for (p = this; (q = p.outerClass) != null; p = q)            ;        return p;    }     /**     * Get the class' first field or first match     */    public final MemberDefinition getFirstMember() {        return firstMember;    }    public final MemberDefinition getFirstMatch(Identifier name) {        return (MemberDefinition)fieldHash.get(name);    }     /**     * Get the class' name     */    public final Identifier getName() {        return declaration.getName();    }     /**     * Get the class' type     */    public final Type getType() {        return declaration.getType();    }     /**     * Get the class' documentation     */    public String getDocumentation() {        return documentation;    }     /**     * Return true if the given documentation string contains a deprecation     * paragraph.  This is true if the string contains the tag @deprecated     * is the first word in a line.     */    public static boolean containsDeprecated(String documentation) {        if (documentation == null) {            return false;        }    doScan:        for (int scan = 0;             (scan = documentation.indexOf(paraDeprecated, scan)) >= 0;             scan += paraDeprecated.length()) {            // make sure there is only whitespace between this word            // and the beginning of the line            for (int beg = scan-1; beg >= 0; beg--) {                char ch = documentation.charAt(beg);                if (ch == '\n' || ch == '\r') {                    break;      // OK                }                if (!Character.isSpace(ch)) {                    continue doScan;                }            }            // make sure the char after the word is space or end of line            int end = scan+paraDeprecated.length();            if (end < documentation.length()) {                char ch = documentation.charAt(end);                if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {                    continue doScan;                }            }            return true;        }        return false;    }     public final boolean inSamePackage(ClassDeclaration c) {        // find out if the class stored in c is defined in the same        // package as the current class.        return inSamePackage(c.getName().getQualifier());    }     public final boolean inSamePackage(ClassDefinition c) {        // find out if the class stored in c is defined in the same        // package as the current class.        return inSamePackage(c.getName().getQualifier());    }     public final boolean inSamePackage(Identifier packageName) {        return (getName().getQualifier().equals(packageName));    }     /**     * Checks     */    public final boolean isInterface() {        return (getModifiers() & M_INTERFACE) != 0;    }    public final boolean isClass() {        return (getModifiers() & M_INTERFACE) == 0;    }    public final boolean isPublic() {        return (getModifiers() & M_PUBLIC) != 0;    }    public final boolean isPrivate() {        return (getModifiers() & M_PRIVATE) != 0;    }    public final boolean isProtected() {        return (getModifiers() & M_PROTECTED) != 0;    }    public final boolean isPackagePrivate() {        return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;    }    public final boolean isFinal() {        return (getModifiers() & M_FINAL) != 0;    }    public final boolean isAbstract() {        return (getModifiers() & M_ABSTRACT) != 0;    }    public final boolean isSynthetic() {        return (getModifiers() & M_SYNTHETIC) != 0;    }    public final boolean isDeprecated() {        return (getModifiers() & M_DEPRECATED) != 0;    }    public final boolean isAnonymous() {        return (getModifiers() & M_ANONYMOUS) != 0;    }    public final boolean isLocal() {        return (getModifiers() & M_LOCAL) != 0;    }    public final boolean hasConstructor() {        return getFirstMatch(idInit) != null;    } 

Lines 1–500 of 2085.