📄 enter.java
字号:
/**
* Check that name does not clash with internal names used in the
* translation process.
*/
private void checkNotReserved(int pos, Name name) {
if (name == names.classDollar || name.startsWith(names.thisDollar)) {
log.error(pos, "name.reserved.for.internal.use", name.toJava());
}
}
/**
* Create a fresh environment for method bodies.
* @param tree The method definition.
* @param env The environment current outside of the method definition.
*/
Env methodEnv(MethodDef tree, Env env) {
Env localEnv = env.dup(tree,
((AttrContext) env.info).dup(
((AttrContext) env.info).scope.dupUnshared()));
localEnv.enclMethod = tree;
((AttrContext) localEnv.info).scope.owner = tree.sym;
if ((tree.flags & STATIC) != 0)
((AttrContext) localEnv.info).staticLevel++;
return localEnv;
}
/**
* Create a fresh environment for class bodies.
* This will create a fresh scope for local symbols of a class, referred
* to by the environments info.scope field.
* This scope will contain
* - symbols for this and super
* - symbols for any type parameters
* In addition, it serves as an anchor for scopes of methods and initializers
* which are nested in this scope via Scope.dup().
* This scope should not be confused with the members scope of a class.
*
* @param tree The class definition.
* @param env The environment current outside of the class definition.
*/
public Env classEnv(ClassDef tree, Env env) {
Env localEnv =
env.dup(tree, ((AttrContext) env.info).dup(new Scope(tree.sym)));
localEnv.enclClass = tree;
localEnv.outer = env;
((AttrContext) localEnv.info).isSelfCall = false;
return localEnv;
}
/**
* Create a fresh environment for toplevels.
* @param tree The toplevel tree.
*/
Env topLevelEnv(TopLevel tree) {
Env localEnv = new Env(tree, new AttrContext());
localEnv.toplevel = tree;
localEnv.enclClass = predefClassDef;
tree.namedImportScope = new Scope(tree.packge);
tree.starImportScope = new Scope(tree.packge);
((AttrContext) localEnv.info).scope = tree.namedImportScope;
return localEnv;
}
/**
* Create a fresh environment for a variable's initializer.
* If the variable is a field, the owner of the environment's scope
* is be the variable itself, otherwise the owner is the method
* enclosing the variable definition.
*
* @param tree The variable definition.
* @param env The environment current outside of the variable definition.
*/
Env initEnv(VarDef tree, Env env) {
Env localEnv =
env.dupto(new AttrContextEnv(tree, ((AttrContext) env.info).dup()));
if (tree.sym.owner.kind == TYP) {
((AttrContext) localEnv.info).scope =
((AttrContext) env.info).scope.dup();
((AttrContext) localEnv.info).scope.owner = tree.sym;
}
if ((tree.flags & STATIC) != 0 ||
(env.enclClass.sym.flags() & INTERFACE) != 0)
((AttrContext) localEnv.info).staticLevel++;
return localEnv;
}
/**
* The scope in which a member definition in environment env is to be entered
* This is usually the environment's scope, except for class environments,
* where the local scope is for type variables, and the this and super symbol
* only, and members go into the class member scope.
*/
Scope enterScope(Env env) {
return (env.tree.tag == Tree.CLASSDEF) ?
((ClassDef) env.tree).sym.members_field :
((AttrContext) env.info).scope;
}
/**
* Visitor argument: the current environment.
*/
protected Env env;
/**
* Visitor result: the computed type.
*/
Type result;
/**
* Visitor method: enter all classes in given tree, catching any
* completion failure exceptions. Return the tree's type.
*
* @param tree The tree to be visited.
* @param env The environment visitor argument.
*/
Type classEnter(Tree tree, Env env) {
Env prevEnv = this.env;
try {
this.env = env;
tree.accept(this);
return result;
} catch (CompletionFailure ex) {
return chk.completionError(tree.pos, ex);
}
finally { this.env = prevEnv;
} }
/**
* Visitor method: enter classes of a list of trees, returning a list of types.
*/
List classEnter(List trees, Env env) {
ListBuffer ts = new ListBuffer();
for (List l = trees; l.nonEmpty(); l = l.tail)
ts.append(classEnter((Tree) l.head, env));
return ts.toList();
}
public void visitTopLevel(TopLevel tree) {
Name prev = log.useSource(tree.sourcefile);
if (tree.pid != null) {
tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
} else {
tree.packge = syms.emptyPackage;
}
tree.packge.complete();
classEnter(tree.defs, topLevelEnv(tree));
log.useSource(prev);
result = null;
}
public void visitClassDef(ClassDef tree) {
Symbol owner = ((AttrContext) env.info).scope.owner;
Scope enclScope = enterScope(env);
ClassSymbol c;
if (owner.kind == PCK) {
PackageSymbol packge = (PackageSymbol) owner;
for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
q.flags_field |= EXISTS;
c = reader.enterClass(tree.name, packge);
packge.members().enterIfAbsent(c);
if ((tree.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
log.error(tree.pos, "class.public.should.be.in.file",
tree.name.toJava());
}
} else {
if (tree.name.len != 0 &&
!checkUniqueClassName(tree.pos, tree.name, enclScope)) {
result = null;
return;
}
if (owner.kind == TYP) {
c = reader.enterClass(tree.name, (TypeSymbol) owner);
if ((owner.flags_field & INTERFACE) != 0) {
tree.flags |= PUBLIC | STATIC;
}
} else {
c = reader.defineClass(tree.name, owner);
c.flatname = chk.localClassName(c);
if (c.name.len != 0)
checkTransparentClass(tree.pos, c,
((AttrContext) env.info).scope);
}
}
tree.sym = c;
if (chk.compiled.get(c.flatname) != null) {
duplicateClass(tree.pos, c);
result = new ErrorType(tree.name, (TypeSymbol) owner);
tree.sym = (ClassSymbol) result.tsym;
return;
}
chk.compiled.put(c.flatname, c);
enclScope.enter(c);
Env localEnv = classEnv(tree, env);
classEnvs.put(c, localEnv);
c.completer = new CompleteEnter();
c.flags_field = chk.checkFlags(tree.pos, tree.flags, c);
c.sourcefile = env.toplevel.sourcefile;
c.members_field = new Scope(c);
ClassType ct = (ClassType) c.type;
if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
Symbol owner1 = owner;
while ((owner1.kind & (VAR | MTH)) != 0 &&
(owner1.flags_field & STATIC) == 0) {
owner1 = owner1.owner;
}
if (owner1.kind == TYP) {
ct.outer_field = owner1.type;
}
}
ct.typarams_field = classEnter(tree.typarams, localEnv);
if (!c.isLocal() && uncompleted != null)
uncompleted.append(c);
classEnter(tree.defs, localEnv);
result = c.type;
}
/**
* Does class have the same name as the file it appears in?
*/
private static boolean classNameMatchesFileName(ClassSymbol c, Env env) {
String fname = env.toplevel.sourcefile.toString();
String cname = c.name + ".java";
try {
return endsWith(fname, cname) ||
endsWith(new File(fname).getCanonicalPath(), cname);
} catch (java.io.IOException ex) {
return false;
}
}
/**
* Does path name have file name as last component?
*/
private static boolean endsWith(String pathname, String filename) {
return pathname.endsWith(filename) &&
(pathname.length() == filename.length() ||
pathname.charAt(pathname.length() - filename.length() - 1) ==
File.separatorChar);
}
/**
* Complain about a duplicate class.
*/
protected void duplicateClass(int pos, ClassSymbol c) {
log.error(pos, "duplicate.class", c.fullname.toJava());
}
/**
* Default class enter visitor method: do nothing.
*/
public void visitTree(Tree tree) {
result = null;
}
/**
* Main method: enter all classes in a list of toplevel trees.
* @param trees The list of trees to be processed.
*/
public void main(List trees) {
complete(trees, null);
}
/**
* Main method: enter one class from a list of toplevel trees and
* place the rest on uncompleted for later processing.
* @param trees The list of trees to be processed.
* @param c The class symbol to be processed.
*/
public void complete(List trees, ClassSymbol c) {
ListBuffer prevUncompleted = uncompleted;
if (completionEnabled)
uncompleted = new ListBuffer();
try {
classEnter(trees, null);
if (completionEnabled) {
while (uncompleted.nonEmpty()) {
ClassSymbol clazz = (Symbol.ClassSymbol) uncompleted.next();
if (c == null || c == clazz || prevUncompleted == null)
clazz.complete();
else
prevUncompleted.append(clazz);
}
for (List l = trees; l.nonEmpty(); l = l.tail) {
TopLevel tree = (TopLevel) l.head;
if (tree.starImportScope.elems == null) {
Name prev = log.useSource(tree.sourcefile);
phase2.memberEnter(tree, topLevelEnv(tree));
log.useSource(prev);
}
}
}
}
finally { uncompleted = prevUncompleted;
} }
/**
* Enter all members of a class. This is done in a second phase
* after the classes themselves have been entered.
*/
protected class MemberEnter extends Tree.Visitor {
protected MemberEnter() {
super();
}
/**
* Given a class, and an (import) scope, is there already a
* class with same fully qualified name in this scope?
*/
private boolean isIncluded(Symbol c, Scope scope) {
for (Scope.Entry e = scope.lookup(c.name); e.scope == scope;
e = e.next()) {
if (e.sym.kind == c.kind && e.sym.fullName() == c.fullName())
return true;
}
return false;
}
/**
* Import all classes of a class or package on demand.
* @param pos Position to be used for error reporting.
* @param tsym The class or package the members of which are imported.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -