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 <enclClass> $ n <classname>
* 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 V<X> is 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<T extends Closeable> {
public void test() {
BC<InputStream> a = null;
BC<? extends InputStream> b = null;
BC<? super InputStream> c = null;
}
}
当a.isExtendsBound()时调用了isCastable()方法。
当a.isSuperBound()时调用了notSoftSubtype()方法。