1、duplicate declaration checking
/** Check that variable does not hide variable with same name in
* immediately enclosing local scope.
*
* e.g
* public void m1(boolean a){
* int a = 3;
* boolean a = true; // 不调用checkTransparentVar()方法,因为调用checkUnique()方法时能测出冲突
* }
*
* @param pos Position for error reporting.
* @param v The symbol.
* @param s The scope.
*/
void checkTransparentVar(DiagnosticPosition 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;
}
}
}
}
e.g
public void m1(boolean a){
int a = 3;
for(int x = 0;x<2;x++){
int x = 3;
}
}
其中int a = 3与int x= 3将调用checkTransparentVar()方法检测出重复声明。
/** 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 c The symbol.
* @param s The scope.
*/
void checkTransparentClass(DiagnosticPosition 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.type.tag != TYPEVAR &&
(e.sym.owner.kind & (VAR | MTH)) != 0 &&
c.name != names.error) {
duplicateError(pos, e.sym);
return;
}
}
}
}
e.g
public void m1() {
class A{}
{
class A{} // err Duplicate nested type A
}
而对于e.sym.owner.kind为VAR的情况还没有举出例子。
/** 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.
*/
boolean checkUniqueClassName(DiagnosticPosition 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;
}
e.g
{
class A {}
interface A{} // A类型的冲突将由checkUniqueClassName()方法来检测
}
{
class B {
class B {
}
}
}
2、Class name generation
/** Return name of local class. * This is of the form$ n * where * enclClass is the flat name of the enclosing class, * classname is the simple name of the local class */ Name localClassName(ClassSymbol c) { for (int i=1; ; i++) { Name flatname = names. fromString("" + c.owner.enclClass().flatname + syntheticNameChar + i + c.name); if (compiled.get(flatname) == null) return flatname; } }
e.g
package com.test07; public class Test3{ interface I { } // com.test07.Test3$1 final I i1 = new I() { }; // com.test07.Test3$2 final I i2 = new I() { }; { // com.test07.Test3$1B class B { } } public void m1() { // com.test07.Test3$2B class B { } // com.test07.Test3$1C class C { } // com.test07.Test3$3 final I i3 = new I() { }; } public void m2() { // com.test07.Test3$3B class B { } // com.test07.Test3$1D class D { } } }
3、Type Checking
/** Check that a given type is assignable to a given proto-type. * If it is, return the type, otherwise return errType. * @param pos Position to be used for error reporting. * @param found The type that was found. * @param req The type that was required. */ Type checkType(DiagnosticPosition pos, Type found, Type req) { // 不兼容的类型 return checkType(pos, found, req, "incompatible.types"); } Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { if (req.tag == ERROR) return req; if (found.tag == FORALL) return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); if (req.tag == NONE) return found; if (types.isAssignable(found, req, convertWarner(pos, found, req))) return found; if (found.tag <= DOUBLE && req.tag <= DOUBLE) // 可能损失精度 return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req); if (found.isSuperBound()) { // 从 super-bound 类型{0}进行分配 log.error(pos, "assignment.from.super-bound", found); return types.createErrorType(found); } if (req.isExtendsBound()) { log.error(pos, "assignment.to.extends-bound", req); return types.createErrorType(found); } return typeError(pos, diags.fragment(errKey), found, req); }
checkType方法主要是在Attr类中的check()方法调用的,这个方法的代码如下:
/** Check kind and type of given tree against protokind and prototype. * If check succeeds, store type in tree and return it. * If check fails, store errType in tree and return it. * No checks are performed if the prototype is a method type. * It is not necessary in this case since we know that kind and type * are correct. * * @param tree The tree whose kind and type is checked * @param owntype The computed type of the tree * @param ownkind The computed kind of the tree * @param protokind The expected kind (or: protokind) of the tree * @param prototype The expected type (or: prototype) of the tree */ Type check(JCTree tree, Type owntype, int ownkind, int protokind, Type prototype) { // prototype不允许为method type if (owntype.tag != ERROR && prototype.tag != METHOD && prototype.tag != FORALL) { if ((ownkind & ~protokind) == 0) { owntype = chk.checkType(tree.pos(), owntype, prototype, errKey); } else { log.error(tree.pos(), "unexpected.type",kindNames(protokind),kindName(ownkind)); owntype = types.createErrorType(owntype); } } tree.type = owntype; return owntype; }
owntype与prototype都是Type类型,其tag取值是TypeTags类中的预先定义好的值。
ownkind与protokind都是int类型,其取值是Kinds预先定义好的值。
通过比较如上的两类型值,其实也就是比较了语法节点的Type类型与Symbol类型。
/** Check that a type is within some bounds. * * Used in TypeApply to verify that, e.g., X in Vis a valid type argument. * @param pos Position to be used for error reporting. * @param a The type that should be bounded by bs. * @param bs The bound. */ private boolean checkExtends(Type a, Type bound) { if (a.isUnbound()) { return true; } else if (a.tag != WILDCARD) { a = types.upperBound(a); return types.isSubtype(a, bound); } else if (a.isExtendsBound()) { Type ut = types.upperBound(a); boolean result = types.isCastable(bound, ut , Warner.noWarnings); return result; } else if (a.isSuperBound()) { Type lt = types.lowerBound(a); boolean result = !types.notSoftSubtype(lt, bound); return result; } return true; }
e.g
class BC{ public void test() { BC a = null; BC extends InputStream> b = null; BC super InputStream> c = null; } }
当a.isExtendsBound()时调用了isCastable()方法。
当a.isSuperBound()时调用了notSoftSubtype()方法。