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