2674 lines · 109.2 KB · Java
RawDownload
/* * Copyright (c) 1994, 2004, 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.javac; import sun.tools.java.*;import sun.tools.tree.*;import sun.tools.tree.CompoundStatement;import sun.tools.asm.Assembler;import sun.tools.asm.ConstantPool;import java.util.Vector;import java.util.Enumeration;import java.util.Hashtable;import java.util.Iterator;import java.io.IOException;import java.io.OutputStream;import java.io.DataOutputStream;import java.io.ByteArrayOutputStream;import java.io.File; /** * This class represents an Java class as it is read from * an Java source file. * * 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. */@Deprecatedpublicclass SourceClass extends ClassDefinition {     /**     * The toplevel environment, shared with the parser     */    Environment toplevelEnv;     /**     * The default constructor     */    SourceMember defConstructor;     /**     * The constant pool     */    ConstantPool tab = new ConstantPool();    /**     * The list of class dependencies     */    Hashtable deps = new Hashtable(11);     /**     * The field used to represent "this" in all of my code.     */    LocalMember thisArg;     /**     * Last token of class, as reported by parser.     */    long endPosition;     /**     * Access methods for constructors are distinguished from     * the constructors themselves by a dummy first argument.     * A unique type used for this purpose and shared by all     * constructor access methods within a package-member class is     * maintained here.     * <p>     * This field is null except in an outermost class containing     * one or more classes needing such an access method.     */    private Type dummyArgumentType = null;     /**     * Constructor     */    public SourceClass(Environment env, long where,                       ClassDeclaration declaration, String documentation,                       int modifiers, IdentifierToken superClass,                       IdentifierToken interfaces[],                       SourceClass outerClass, Identifier localName) {        super(env.getSource(), where,              declaration, modifiers, superClass, interfaces);        setOuterClass(outerClass);         this.toplevelEnv = env;        this.documentation = documentation;         if (ClassDefinition.containsDeprecated(documentation)) {            this.modifiers |= M_DEPRECATED;        }         // Check for a package level class which is declared static.        if (isStatic() && outerClass == null) {            env.error(where, "static.class", this);            this.modifiers &=~ M_STATIC;        }         // Inner classes cannot be static, nor can they be interfaces        // (which are implicitly static).  Static classes and interfaces        // can only occur as top-level entities.        //        // Note that we do not have to check for local classes declared        // to be static (this is currently caught by the parser) but        // we check anyway in case the parser is modified to allow this.        if (isLocal() || (outerClass != null && !outerClass.isTopLevel())) {            if (isInterface()) {                env.error(where, "inner.interface");            } else if (isStatic()) {                env.error(where, "static.inner.class", this);                this.modifiers &=~ M_STATIC;                if (innerClassMember != null) {                    innerClassMember.subModifiers(M_STATIC);                }            }        }         if (isPrivate() && outerClass == null) {            env.error(where, "private.class", this);            this.modifiers &=~ M_PRIVATE;        }        if (isProtected() && outerClass == null) {            env.error(where, "protected.class", this);            this.modifiers &=~ M_PROTECTED;        }        /*----*        if ((isPublic() || isProtected()) && isInsideLocal()) {            env.error(where, "warn.public.local.class", this);        }         *----*/         // maybe define an uplevel "A.this" current instance field        if (!isTopLevel() && !isLocal()) {            LocalMember outerArg = ((SourceClass)outerClass).getThisArgument();            UplevelReference r = getReference(outerArg);            setOuterMember(r.getLocalField(env));        }         // Set simple, unmangled local name for a local or anonymous class.        // NOTE: It would be OK to do this unconditionally, as null is the        // correct value for a member (non-local) class.        if (localName != null)            setLocalName(localName);         // Check for inner class with same simple name as one of        // its enclosing classes.  Note that 'getLocalName' returns        // the simple, unmangled source-level name of any class.        // The previous version of this code was not careful to avoid        // mangled local class names.  This version fixes 4047746.        Identifier thisName = getLocalName();        if (thisName != idNull) {            // Test above suppresses error for nested anonymous classes,            // which have an internal "name", but are not named in source code.            for (ClassDefinition scope = outerClass; scope != null;                  scope = scope.getOuterClass()) {                Identifier outerName = scope.getLocalName();                if (thisName.equals(outerName))                    env.error(where, "inner.redefined", thisName);            }        }    }     /**     * Return last position in this class.     * @see #getWhere     */    public long getEndPosition() {        return endPosition;    }     public void setEndPosition(long endPosition) {        this.endPosition = endPosition;    }  // JCOV    /**     * Return absolute name of source file     */    public String getAbsoluteName() {        String AbsName = ((ClassFile)getSource()).getAbsoluteName();         return AbsName;    }//end JCOV     /**     * Return imports     */    public Imports getImports() {        return toplevelEnv.getImports();    }     /**     * Find or create my "this" argument, which is used for all methods.     */    public LocalMember getThisArgument() {        if (thisArg == null) {            thisArg = new LocalMember(where, this, 0, getType(), idThis);        }        return thisArg;    }     /**     * Add a dependency     */    public void addDependency(ClassDeclaration c) {        if (tab != null) {            tab.put(c);        }        // If doing -xdepend option, save away list of class dependencies        //   making sure to NOT include duplicates or the class we are in        //   (Hashtable's put() makes sure we don't have duplicates)        if ( toplevelEnv.print_dependencies() && c != getClassDeclaration() ) {            deps.put(c,c);        }    }     /**     * Add a field (check it first)     */    public void addMember(Environment env, MemberDefinition f) {        // Make sure the access permissions are self-consistent:        switch (f.getModifiers() & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) {        case M_PUBLIC:        case M_PRIVATE:        case M_PROTECTED:        case 0:            break;        default:            env.error(f.getWhere(), "inconsistent.modifier", f);            // Cut out the more restrictive modifier(s):            if (f.isPublic()) {                f.subModifiers(M_PRIVATE | M_PROTECTED);            } else {                f.subModifiers(M_PRIVATE);            }            break;        }         // Note exemption for synthetic members below.        if (f.isStatic() && !isTopLevel() && !f.isSynthetic()) {            if (f.isMethod()) {                env.error(f.getWhere(), "static.inner.method", f, this);                f.subModifiers(M_STATIC);            } else if (f.isVariable()) {                if (!f.isFinal() || f.isBlankFinal()) {                    env.error(f.getWhere(), "static.inner.field", f.getName(), this);                    f.subModifiers(M_STATIC);                }                // Even if a static passes this test, there is still another                // check in 'SourceMember.check'.  The check is delayed so                // that the initializer may be inspected more closely, using                // 'isConstant()'.  Part of fix for 4095568.            } else {                // Static inner classes are diagnosed in 'SourceClass.<init>'.                f.subModifiers(M_STATIC);            }        }         if (f.isMethod()) {            if (f.isConstructor()) {                if (f.getClassDefinition().isInterface()) {                    env.error(f.getWhere(), "intf.constructor");                    return;                }                if (f.isNative() || f.isAbstract() ||                      f.isStatic() || f.isSynchronized() || f.isFinal()) {                    env.error(f.getWhere(), "constr.modifier", f);                    f.subModifiers(M_NATIVE | M_ABSTRACT |                                   M_STATIC | M_SYNCHRONIZED | M_FINAL);                }            } else if (f.isInitializer()) {                if (f.getClassDefinition().isInterface()) {                    env.error(f.getWhere(), "intf.initializer");                    return;                }            }             // f is not allowed to return an array of void            if ((f.getType().getReturnType()).isVoidArray()) {                env.error(f.getWhere(), "void.array");            }             if (f.getClassDefinition().isInterface() &&                (f.isStatic() || f.isSynchronized() || f.isNative()                 || f.isFinal() || f.isPrivate() || f.isProtected())) {                env.error(f.getWhere(), "intf.modifier.method", f);                f.subModifiers(M_STATIC |  M_SYNCHRONIZED | M_NATIVE |                               M_FINAL | M_PRIVATE);            }            if (f.isTransient()) {                env.error(f.getWhere(), "transient.meth", f);                f.subModifiers(M_TRANSIENT);            }            if (f.isVolatile()) {                env.error(f.getWhere(), "volatile.meth", f);                f.subModifiers(M_VOLATILE);            }            if (f.isAbstract()) {                if (f.isPrivate()) {                    env.error(f.getWhere(), "abstract.private.modifier", f);                    f.subModifiers(M_PRIVATE);                }                if (f.isStatic()) {                    env.error(f.getWhere(), "abstract.static.modifier", f);                    f.subModifiers(M_STATIC);                }                if (f.isFinal()) {                    env.error(f.getWhere(), "abstract.final.modifier", f);                    f.subModifiers(M_FINAL);                }                if (f.isNative()) {                    env.error(f.getWhere(), "abstract.native.modifier", f);                    f.subModifiers(M_NATIVE);                }                if (f.isSynchronized()) {                    env.error(f.getWhere(),"abstract.synchronized.modifier",f);                    f.subModifiers(M_SYNCHRONIZED);                }            }            if (f.isAbstract() || f.isNative()) {                if (f.getValue() != null) {                    env.error(f.getWhere(), "invalid.meth.body", f);                    f.setValue(null);                }            } else {                if (f.getValue() == null) {                    if (f.isConstructor()) {                        env.error(f.getWhere(), "no.constructor.body", f);                    } else {                        env.error(f.getWhere(), "no.meth.body", f);                    }                    f.addModifiers(M_ABSTRACT);                }            }            Vector arguments = f.getArguments();            if (arguments != null) {                // arguments can be null if this is an implicit abstract method                int argumentLength = arguments.size();                Type argTypes[] = f.getType().getArgumentTypes();                for (int i = 0; i < argTypes.length; i++) {                    Object arg = arguments.elementAt(i);                    long where = f.getWhere();                    if (arg instanceof MemberDefinition) {                        where = ((MemberDefinition)arg).getWhere();                        arg = ((MemberDefinition)arg).getName();                    }                    // (arg should be an Identifier now)                    if (argTypes[i].isType(TC_VOID)                        || argTypes[i].isVoidArray()) {                        env.error(where, "void.argument", arg);                    }                }            }        } else if (f.isInnerClass()) {            if (f.isVolatile() ||                f.isTransient() || f.isNative() || f.isSynchronized()) {                env.error(f.getWhere(), "inner.modifier", f);                f.subModifiers(M_VOLATILE | M_TRANSIENT |                               M_NATIVE | M_SYNCHRONIZED);            }            // same check as for fields, below:            if (f.getClassDefinition().isInterface() &&                  (f.isPrivate() || f.isProtected())) {                env.error(f.getWhere(), "intf.modifier.field", f);                f.subModifiers(M_PRIVATE | M_PROTECTED);                f.addModifiers(M_PUBLIC);                // Fix up the class itself to agree with                // the inner-class member.                ClassDefinition c = f.getInnerClass();                c.subModifiers(M_PRIVATE | M_PROTECTED);                c.addModifiers(M_PUBLIC);            }        } else {            if (f.getType().isType(TC_VOID) || f.getType().isVoidArray()) {                env.error(f.getWhere(), "void.inst.var", f.getName());                // REMIND: set type to error                return;            }             if (f.isSynchronized() || f.isAbstract() || f.isNative()) {                env.error(f.getWhere(), "var.modifier", f);                f.subModifiers(M_SYNCHRONIZED | M_ABSTRACT | M_NATIVE);            }            if (f.isStrict()) {                env.error(f.getWhere(), "var.floatmodifier", f);                f.subModifiers(M_STRICTFP);            }            if (f.isTransient() && isInterface()) {                env.error(f.getWhere(), "transient.modifier", f);                f.subModifiers(M_TRANSIENT);            }            if (f.isVolatile() && (isInterface() || f.isFinal())) {                env.error(f.getWhere(), "volatile.modifier", f);                f.subModifiers(M_VOLATILE);            }            if (f.isFinal() && (f.getValue() == null) && isInterface()) {                env.error(f.getWhere(), "initializer.needed", f);                f.subModifiers(M_FINAL);            }             if (f.getClassDefinition().isInterface() &&                  (f.isPrivate() || f.isProtected())) {                env.error(f.getWhere(), "intf.modifier.field", f);                f.subModifiers(M_PRIVATE | M_PROTECTED);                f.addModifiers(M_PUBLIC);            }        }        // Do not check for repeated methods here:  Types are not yet resolved.        if (!f.isInitializer()) {            for (MemberDefinition f2 = getFirstMatch(f.getName());                         f2 != null; f2 = f2.getNextMatch()) {                if (f.isVariable() && f2.isVariable()) {                    env.error(f.getWhere(), "var.multidef", f, f2);                    return;                } else if (f.isInnerClass() && f2.isInnerClass() &&                           !f.getInnerClass().isLocal() &&                           !f2.getInnerClass().isLocal()) {                    // Found a duplicate inner-class member.                    // Duplicate local classes are detected in                    // 'VarDeclarationStatement.checkDeclaration'.                    env.error(f.getWhere(), "inner.class.multidef", f);                    return;                }            }        }         super.addMember(env, f);    }     /**     * Create an environment suitable for checking this class.     * Make sure the source and imports are set right.     * Make sure the environment contains no context information.     * (Actually, throw away env altogether and use toplevelEnv instead.)     */    public Environment setupEnv(Environment env) {        // In some cases, we go to some trouble to create the 'env' argument        // that is discarded.  We should remove the 'env' argument entirely        // as well as the vestigial code that supports it.  See comments on        // 'newEnvironment' in 'checkInternal' below.        return new Environment(toplevelEnv, this);    }     /**     * A source class never reports deprecation, since the compiler     * allows access to deprecated features that are being compiled     * in the same job.     */    public boolean reportDeprecated(Environment env) {        return false;    }     /**     * See if the source file of this class is right.     * @see ClassDefinition#noteUsedBy     */    public void noteUsedBy(ClassDefinition ref, long where, Environment env) {        // If this class is not public, watch for cross-file references.        super.noteUsedBy(ref, where, env);        ClassDefinition def = this;        while (def.isInnerClass()) {            def = def.getOuterClass();        }        if (def.isPublic()) {            return;             // already checked        }        while (ref.isInnerClass()) {            ref = ref.getOuterClass();        }        if (def.getSource().equals(ref.getSource())) {            return;             // intra-file reference        }        ((SourceClass)def).checkSourceFile(env, where);    } 

Lines 1–500 of 2674.