Check类之duplicate declaration checking/Class name generation/Type Checking

 

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 V 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 {
	public void test() {
		BC a = null;
		BC b = null;
		BC c = null;		
	}
}

当a.isExtendsBound()时调用了isCastable()方法。

当a.isSuperBound()时调用了notSoftSubtype()方法。

  

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

你可能感兴趣的:(Check类之duplicate declaration checking/Class name generation/Type Checking)