当进行完MemberEnter后就可以调用Attr类的一些标记方法了,如下:
while (!todo.isEmpty()){
Environment<AttrContext> a = todo.remove();
Environment<AttrContext> b = attribute(a); // 标注
Queue<Environment<AttrContext>> c = flow(b); // 数据流分析
Queue<Pair<Environment<AttrContext>, JCClassDeclaration>> d = desugar(c); // 解语法糖
generate(d); // 生成字节码
// generate(desugar(flow(attribute(todo.remove()))));
}
在之前的MemberEnter类中visitImport()方法中有如下一个方法调用,如下:
Type type = attr.attribTree(jcFieldAccess.selected, localEnvironment, protoKind, Type.noType); // protoKind=_TYPE|_PCK,Type.noType=JCNoType
其中JCFieldAccess为java.util.ArrayList,而jcFieldAccess.selected为java.util。
其中的scope为ImportScope。
在标识前,所有的selected的symbol与type都为null。先要进行JCIdentifier的处理,主要经历的方法有三个:
首先visitIdentifier(),在这个方法中调用resolveIdentifier()方法,接着也会调用checkIndentifier()方法。
resolveIdentifier()中会调用findIdentifier()方法查找到name对应的符号Symbol,这个方法的具体代码实现如下:
/** Find an unqualified identifier which matches a specified kind set.
* @param environment The current environment.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds (a subset of _VAL, _TYP, _PCK).
*
*/
public Symbol findIdentifier(Environment<AttrContext> environment, Name name, int kind) {
Symbol bestSoFar = typeNotFound;
Symbol symbol;
if ((kind & _VAR) != 0) {
symbol = findVariable(environment, name);
if (symbol.exists()){
return symbol;
}else if (symbol.kind < bestSoFar.kind){
bestSoFar = symbol;
}
}
if ((kind & _TYP) != 0) {
symbol = findType(environment, name);
if (symbol.exists()){
return symbol;
}else if (symbol.kind < bestSoFar.kind){ // ??
bestSoFar = symbol;
}
}
if ((kind & _PCK) != 0){
return classReader.enterPackage(name);
}else{
return bestSoFar;
}
}
name除了代表方法的名称外,其余就是变量、类型和包名称了。优先进行变量名的查找,由于变量名有局部变量和全局变量,所以对应的查找方法就有findVariable()与findField()。
其中findVariable()方法如下:
/** Find unqualified variable or field with given name.
* Synthetic fields always skipped.
* @param environment The current environment.
* @param name The name of the variable or field.
*/
Symbol findVariable(Environment<AttrContext> environment, Name name) {
Symbol bestSoFar = variableNotFound;
Symbol symbol;
Environment<AttrContext> env1 = environment;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)){
staticOnly = true;
}
Entry entry = env1.info.scope.lookup(name);
while (
entry.scope != null &&
(entry.symbol.kind != _VAR || (entry.symbol.flags_field & SYNTHETIC) != 0) // 非变量或者是合成的那就需要继续查找
){
entry = entry.next();
}
// 走到这里说明entry.symbol.kind==_VAR或者(entry.symbol.flags_field & SYNTHETIC)==0(非合成的变量)
// 如果findVariable查找不到就要调用findField进行查找
if(entry.scope != null){
symbol = entry.symbol;
}else{
symbol = findField(env1, env1.enclosingClass.classSymbol.type, name, env1.enclosingClass.classSymbol);
}
if( symbol.exists()) {
if( staticOnly &&
symbol.kind == _VAR &&
symbol.ownerSymbol.kind == _TYP &&
(symbol.flags() & STATIC) == 0) {
// 静态上下文中引用非静态的变量
return new StaticError(symbol, this);
}else{
return symbol;
}
} else if (symbol.kind < bestSoFar.kind) {
bestSoFar = symbol;
}
if ((env1.enclosingClass.classSymbol.flags() & STATIC) != 0){
staticOnly = true;
}
env1 = env1.outer;
}// end while
symbol = findField(environment, symbolTable.predefinedClass.type, name, symbolTable.predefinedClass);
if (symbol.exists()){
return symbol;
}
if (bestSoFar.exists()){
return bestSoFar;
}
Entry entry = environment.toplevel.namedImportScope.lookup(name);
for (; entry.scope != null; entry = entry.next()) {
symbol = entry.symbol;
Type origin = entry.getOrigin().owner.type;
if (symbol.kind == _VAR) {
if (entry.symbol.ownerSymbol.type != origin){
symbol = symbol.clone(entry.getOrigin().owner);
}
if(isAccessible(environment, origin, symbol)){
return symbol;
}else{
return new AccessError(environment, origin, symbol, this);
}
}
}
Symbol origin = null;
entry = environment.toplevel.starImportScope.lookup(name);
for (; entry.scope != null; entry = entry.next()) {
symbol = entry.symbol;
if (symbol.kind != _VAR){
continue;
}
// invariant: classSymbol.kind == _VAR
if (bestSoFar.kind < _AMBIGUOUS && symbol.ownerSymbol != bestSoFar.ownerSymbol){
return new AmbiguityError(bestSoFar, symbol, this);
}
else if (bestSoFar.kind >= _VAR) {
origin = entry.getOrigin().owner;
if(isAccessible(environment, origin.type, symbol)){
bestSoFar = symbol;
}else{
bestSoFar = new AccessError(environment, origin.type, symbol, this);
}
}
}
// ???
if (bestSoFar.kind == _VAR && bestSoFar.ownerSymbol.type != origin.type){
return bestSoFar.clone(origin);
}else{
return bestSoFar;
}
}
而findField()方法的代码如下:
/** Find field. Synthetic fields are always skipped.
* @param environment The current environment.
* @param site The original type from where the selection takes place.
* @param name The name of the field.
* @param typeSymbol The class to search for the field. This is always a superclass or implemented interface of site's class.
*/
Symbol findField(Environment<AttrContext> environment,
Type site,
Name name,
TypeSymbol typeSymbol) {
while (typeSymbol.type.typeTag == TYPEVARIABLE){
typeSymbol = typeSymbol.type.getUpperBound().typeSymbol;
}
Symbol bestSoFar = variableNotFound;
Symbol symbol;
// 查找本类
Entry entry = typeSymbol.members().lookup(name);
while (entry.scope != null) {
// 符号是变量且不是合成的
if (entry.symbol.kind == _VAR && (entry.symbol.flags_field & SYNTHETIC) == 0) {
if(isAccessible(environment, site, entry.symbol)){
return entry.symbol;
}else{
return new AccessError(environment, site, entry.symbol,this);
}
}
entry = entry.next();
}
// 查找父类
Type superType = types.supertype(typeSymbol.type);
if (superType != null && (superType.typeTag == CLASS || superType.typeTag == TYPEVARIABLE)) {
symbol = findField(environment, site, name, superType.typeSymbol); // 递归调用
if (symbol.kind < bestSoFar.kind){
bestSoFar = symbol;
}
}
// 查找所有的接口类
for (List<Type> l = types.interfaces(typeSymbol.type); bestSoFar.kind != _AMBIGUOUS && l.nonEmpty(); l = l.tail) {
symbol = findField(environment, site, name, l.head.typeSymbol); // 递归调用
if (bestSoFar.kind < _AMBIGUOUS && symbol.kind < _AMBIGUOUS && symbol.ownerSymbol != bestSoFar.ownerSymbol){
bestSoFar = new AmbiguityError(bestSoFar, symbol, this);
}
else if (symbol.kind < bestSoFar.kind){
bestSoFar = symbol;
}
}
return bestSoFar;
}