/* * 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. Load more
/* * 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. */ public class 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; }