Javac之Environment
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javac之Environment相关的知识,希望对你有一定的参考价值。
关于Env的源代码如下:
/** A class for environments, instances of which are passed as
* arguments to tree visitors. Environments refer to important ancestors
* of the subtree that‘s currently visited, such as the enclosing method,
* the enclosing class, or the enclosing toplevel node. They also contain
* a generic component, represented as a type parameter, to carry further
* information specific to individual passes.
*
* 一个类的环境,它的实例将被作为树访问者的参数进行传递。环境涉及到重要的子树的先祖,子树是目前被访问过的。例如封闭的方法、
* 封闭的类或者是封闭的顶层结点。它们也包含了一个一般性的组件,被描述为类型参数,针对个别的传递携带更多的信息
*
*/
public class Environment<A> implements Iterable<Environment<A>> {
/** The next enclosing env.
*
* 下一个封闭的环境,和作用域是不同的。这个与语法树的组织嵌套是一样的
*/
public Environment<A> next;
/** The env enclosing the current class.
*
* 封闭了当前类的环境,与语法树的组织嵌套一样的,只是只保存类的上一层嵌套结构,可能是Block,Class,JCCompilationUnit与JCNewClass
* 因为只有这几个结构中可以定义类
*/
public Environment<A> outer;
/** The tree with which this env is associated.
*
* 和当前环境相关联的语法树
*/
public JCTree tree; // 查看environment主要是看tree属性,看这个环境属于哪个语法节点即可
/** The enclosing toplevel tree.
*
* 封闭的顶层语法树,语法节点类型为JCCompilationUnit
*/
public JCCompilationUnit toplevel;
/** The next enclosing class definition.
*
* 封闭当前环境的类,也是最近的那个类。类的enclosingClass就是自己
*/
public JCClassDeclaration enclosingClass;
/** The next enclosing method definition.
* 下一个封闭的方法定义
*/
public JCMethodDeclaration enclosingMethod;
/** A generic field for further information.
*
* 一个能携带将来指定信息的通用属性。在这里一般是AttrContext
*/
public A info;
/** Is this an env for evaluating a base clause?
*
* 这是评估一个基础子句的环境,查看 MemberEnter类中的baseEnvironment()方法
*/
public boolean baseClause = false;
/** Create an outermost env for a given (toplevel)tree,with a given info field.
*
* 为一个给定的(顶层)节点树和一个给定的属性相关信息创建一个最外层的环境
*/
public Environment(JCTree jcTree, A info) {
this.next = null;
this.outer = null;
this.tree = jcTree;
this.toplevel = null;
this.enclosingClass = null;
this.enclosingMethod = null;
this.info = info;
}
/** Duplicate this env, updating with given tree and info,
* and copying all other fields.
*/
public Environment<A> duplicate(JCTree jcTree, A info) {
Environment<A> environment = new Environment<A>(jcTree, info);
Environment<A> copy = duplicateto(environment);
return copy;
// return duplicateto(new Environment<A>(tree, info));
}
/** Duplicate this env into a given Environment,using its tree and info, and copying all other fields.
*/
public Environment<A> duplicateto(Environment<A> that) {
that.next = this; // 将这个对象赋值给拷贝对象的next属性
that.outer = this.outer;
that.toplevel = this.toplevel;
that.enclosingClass = this.enclosingClass;
that.enclosingMethod = this.enclosingMethod;
// tree和info信息用that自己的
return that;
}
/** Duplicate this env, updating with given tree,and copying all other fields.
*/
public Environment<A> duplicate(JCTree jcTree) {
// 只更新了tree属性,其它的信息都使用这个环境的
return duplicate(jcTree, this.info);
}
/** Return closest enclosing environment which points to a tree with given typeTag.
*/
public Environment<A> enclosing(int tag) {
Environment<A> environment1 = this;
while (environment1 != null && environment1.tree.getTag() != tag){
environment1 = environment1.next;
}
return environment1;
}
public String toString() {
return "Environment[" + info + (outer == null ? "" : ",outer=" + outer) + "]";
}
public Iterator<Environment<A>> iterator() {
Iterator<Environment<A>> itr = new Iterator<Environment<A>>() {
Environment<A> next = Environment.this;
public boolean hasNext() {
return next.outer != null;
}
public Environment<A> next() {
if (hasNext()) {
Environment<A> current = next;
next = current.outer;
return current;
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return itr;
}
}
举个例子,如下:
interface I{
void m1();
}
public class Test3{
static void t(){}
static I a = new I(){
@Override
public void m1() {
t();
}
};
}
那么t()的环境Env的结构如下截图。
这是outer属性,而next属性和语法树的组织结构是严格一致的,如下截图。
而其中的info属性一般为AttrContext,源代码如下:
/** Contains information specific to the attribute and enter * passes, to be used in place of the generic field in environments. * */ public class AttrContext { /** The scope of local symbols. */ Scope scope = null; /** The number of enclosing `static‘ modifiers. */ int staticLevel = 0; /** Is this an environment for a this(...) or super(...) call? */ boolean isSelfCall = false; /** Are we evaluating the selector of a `super‘ or type name? */ boolean selectSuper = false; /** Are arguments to current function applications boxed into an array for varargs? */ boolean varArgs = false; /** A list of type variables that are all-quantifed in current context. */ List<Type> tvars = List.nil(); /** A record of the lint/SuppressWarnings currently in effect */ Lint lint; /** The variable whose initializer is being attributed * useful for detecting self-references in variable initializers */ Symbol enclVar = null; /** Duplicate this context, replacing scope field and copying all others. */ AttrContext dup(Scope scope) { AttrContext info = new AttrContext(); info.scope = scope; info.staticLevel = staticLevel; info.isSelfCall = isSelfCall; info.selectSuper = selectSuper; info.varArgs = varArgs; info.tvars = tvars; info.lint = lint; info.enclVar = enclVar; return info; } /** Duplicate this context, copying all fields. */ AttrContext dup() { return dup(scope); } public Iterable<Symbol> getLocalElements() { if (scope == null) return List.nil(); return scope.getElements(); } public String toString() { return "AttrContext[" + scope.toString() + "]"; } }
在如上的例子中,JCVariableDecl节点及子结点的staticLevel都为1,而其父结节点及以上为0。再举个例子,如下:
public class Test3{ static{ // staticLevel = 1 // 在static块中不允许再有static出现,如 // static int a = 1; // static class A{} // class A{ // public static void m1(){} // } int a = 1; // staticLevel = 1 } // 这个类的staticLevel为0,与一般类没有任何区别 static class Inner{ // staticLevel = 0 public static void m1(){ // staticLevel = 1 int b = 1; // staticLevel = 1 } } }
以上是关于Javac之Environment的主要内容,如果未能解决你的问题,请参考以下文章
Maven之java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTags异常分析