📄 enter.java
字号:
/**
* @(#)Enter.java 1.83 03/01/23
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.tools.javac.v8.comp;
import java.io.File;
import com.sun.tools.javac.v8.util.*;
import com.sun.tools.javac.v8.code.*;
import com.sun.tools.javac.v8.tree.*;
import com.sun.tools.javac.v8.code.Type.*;
import com.sun.tools.javac.v8.code.Symbol.*;
import com.sun.tools.javac.v8.tree.Tree.*;
/**
* This class enters symbols for all encountered definitions into
* the symbol table. The pass consists of two phases, organized as
* follows:
*
* In the first phase, all class symbols are intered into their enclosing scope,
* descending recursively down the tree for classes which are members of other
* classes. The class symbols are given a CompleteEnter object as completer.
*
* In the second phase classes are completed using CompleteEnter.complete().
* Completion might occur on demand, but any classes that are not completed that
* way will be eventually completed by processing the `uncompleted' queue.
* Completion entails (1) determination of a classe's parameters, supertype and
* interfaces, as well as (2) entering all symbols defined in the class into its
* scope, with the exception of class symbols which have been entered in phase 1.
* (2) depends on (1) having been completed for a class and all its superclasses
* and enclosing classes. That's why, after doing (1), we put classes in a
* `halfcompleted' queue. Only when we have performed (1) for a class and all it's
* superclasses and enclosing classes, we proceed to (2).
*
* Whereas the first phase is organized as a sweep through all compiled
* syntax trees, the second phase is demand. Members of a class are entered
* when the contents of a class are first accessed. This is accomplished
* by installing completer objects in class symbols for compiled classes
* which invoke the member-enter phase for the corresponding class tree.
*
* Classes migrate from one phase to the next via queues:
*
* class enter -> (uncompleted) --> member enter (1)
* -> (halfcompleted) --> member enter (2)
* -> (todo) --> attribute // only for toplevel classes
*/
public class Enter extends Tree.Visitor implements Flags, Kinds, TypeTags {
private static final Context.Key enterKey = new Context.Key();
private Log log;
private Symtab syms;
private Resolve rs;
private Check chk;
private TreeMaker make;
private Attr attr;
private ClassReader reader;
private Name.Table names;
protected MemberEnter phase2;
/**
* A queue of all as yet unattributed toplevel classes
*/
Todo todo;
public static Enter instance(Context context) {
Enter instance = (Enter) context.get(enterKey);
if (instance == null)
instance = new Enter(context);
return instance;
}
protected Enter(Context context) {
super();
context.put(enterKey, this);
names = Name.Table.instance(context);
log = Log.instance(context);
reader = ClassReader.instance(context);
make = TreeMaker.instance(context);
todo = Todo.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
chk = Check.instance(context);
attr = Attr.instance(context);
phase2 = new MemberEnter();
predefClassDef = new ClassDef(PUBLIC, syms.predefClass.name, null, null, null,
null, syms.predefClass);
}
/**
* A switch to determine whether we check for package/class conflicts
*/
static final boolean checkClash = true;
/**
* A hashtable mapping classes to the environments current at the point
* of the class declaration's local definitions.
*/
Hashtable classEnvs = Hashtable.make();
/**
* Accessor for classEnvs
*/
public Env getEnv(ClassSymbol c) {
return (Env) classEnvs.get(c);
}
/**
* The queue of all classes that might still need to be completed;
* saved and initialized by main().
*/
ListBuffer uncompleted;
/**
* A queue for classes whose members still need to be entered into the
* symbol table.
*/
ListBuffer halfcompleted = new ListBuffer();
/**
* A dummy class to serve as enclClass for toplevel environments.
*/
private ClassDef predefClassDef;
/**
* A flag to enable/disable class completion. This is
* necessary to prevent false cyclic dependencies involving imports.
* Example (due to Todd Turnbridge): Consider the following three files:
*
* A.java: public class A extends B {}
* B.java: public class B extends C {}
* C.java: import A; public class C {}
*
* Now compile B.java. The (import A;) is not allowed to go beyond enter
* phase, or a false cycle will occur.
*/
private boolean completionEnabled = true;
/**
* Generate call to superclass constructor. This is:
*
* super(id_0, ..., id_n)
*
* or, if based == true
*
* id_0.super(id_1,...,id_n)
*
* where id_0, ..., id_n are the names of the given parameters.
*
* @param make The tree factory
* @param params The parameters that need to be passed to super
* @param based Is first parameter a this$n?
*/
Tree SuperCall(TreeMaker make, List params, boolean based) {
Tree meth;
if (based) {
meth = make.Select(make.Ident((Tree.VarDef) params.head), names._super);
params = params.tail;
} else {
meth = make.Ident(names._super);
}
return make.Exec(make.Apply(meth, make.Idents(params)));
}
/**
* Generate default constructor for given class. For classes different
* from java.lang.Object, this is:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* super(x_0, ..., x_n)
* }
*
* or, if based == true:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* x_0.super(x_1, ..., x_n)
* }
*
* @param make The tree factory.
* @param c The class owning the default constructor.
* @param argtypes The parameter types of the constructor.
* @param thrown The thrown exceptions of the constructor.
* @param based Is first parameter a this$n?
*/
Tree DefaultConstructor(TreeMaker make, ClassSymbol c, List argtypes,
List thrown, boolean based) {
List params = make.Params(argtypes, syms.noSymbol);
List stats = Tree.emptyList;
if (c.type != syms.objectType)
stats = stats.prepend(SuperCall(make, params, based));
long flags = c.flags() & Check.AccessFlags;
if (c.name.len == 0)
flags |= ANONCONSTR;
Tree result = make.MethodDef(flags, names.init, null, TypeParameter.emptyList,
params, make.Types(thrown), make.Block(0, stats));
return result;
}
/**
* Report duplicate declaration error.
*/
private void duplicateError(int pos, Symbol sym) {
if (!sym.type.isErroneous()) {
log.error(pos, "already.defined", sym.toJava(), sym.javaLocation());
}
}
/**
* Check that symbol is unique in given scope.
* @param pos Position for error reporting.
* @param sym The symbol.
* @param s The scope.
*/
private boolean checkUnique(int pos, Symbol sym, Scope s) {
if (sym.owner.name == names.any)
return false;
for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
if (sym != e.sym && sym.kind == e.sym.kind && sym.name != names.error &&
(sym.kind != MTH || sym.type.hasSameArgs(e.sym.type))) {
duplicateError(pos, e.sym);
return false;
}
}
return true;
}
/**
* Check that single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
* @param pos Position for error reporting.
* @param sym The symbol.
* @param env The current environment.
*/
private boolean checkUniqueImport(int pos, Symbol sym, Env env) {
Scope s = env.toplevel.namedImportScope;
for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) {
boolean isClassDecl = e.scope == s;
if ((isClassDecl || sym != e.sym) && sym.kind == e.sym.kind &&
sym.name != names.error) {
if (!e.sym.type.isErroneous()) {
String what = e.sym.toJava();
if (!isClassDecl)
log.error(pos, "already.defined.single.import", what);
else if (sym != e.sym)
log.error(pos, "already.defined.this.unit", what);
}
return false;
}
}
return true;
}
/**
* Check that variable does not hide variable with same name in
* immediately enclosing local scope.
* @param pos Position for error reporting.
* @param sym The symbol.
* @param s The scope.
*/
private void checkTransparentVar(int pos, VarSymbol v, Scope s) {
if (s.next != null) {
for (Scope.Entry e = s.next.lookup(v.name);
e.scope != null && e.sym.owner == v.owner; e = e.next()) {
if (e.sym.kind == VAR && (e.sym.owner.kind & (VAR | MTH)) != 0 &&
v.name != names.error) {
duplicateError(pos, e.sym);
return;
}
}
}
}
/**
* Check that a class or interface does not hide a class or
* interface with same name in immediately enclosing local scope.
* @param pos Position for error reporting.
* @param sym The symbol.
* @param s The scope.
*/
private void checkTransparentClass(int pos, ClassSymbol c, Scope s) {
if (s.next != null) {
for (Scope.Entry e = s.next.lookup(c.name);
e.scope != null && e.sym.owner == c.owner; e = e.next()) {
if (e.sym.kind == TYP && (e.sym.owner.kind & (VAR | MTH)) != 0 &&
c.name != names.error) {
duplicateError(pos, e.sym);
return;
}
}
}
}
/**
* Check that class does not have the same name as one of
* its enclosing classes, or as a class defined in its enclosing scope.
* return true if class is unique in its enclosing scope.
* @param pos Position for error reporting.
* @param name The class name.
* @param s The enclosing scope.
*/
private boolean checkUniqueClassName(int pos, Name name, Scope s) {
for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
if (e.sym.kind == TYP && e.sym.name != names.error) {
duplicateError(pos, e.sym);
return false;
}
}
for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
duplicateError(pos, sym);
return true;
}
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -