📄 check.java
字号:
log.error(pos, "undetermined.type" + (d!=null ? ".1" : ""), t, d); return syms.errType; } else { JCDiagnostic d = ex.getDiagnostic(); return typeError(pos, JCDiagnostic.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), t, pt); } } } } /** Check that a given type can be cast to a given target type. * Return the result of the cast. * @param pos Position to be used for error reporting. * @param found The type that is being cast. * @param req The target type of the cast. */ Type checkCastable(DiagnosticPosition pos, Type found, Type req) { if (found.tag == FORALL) { instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); return req; } else if (types.isCastable(found, req, castWarner(pos, found, req))) { return req; } else { return typeError(pos, JCDiagnostic.fragment("inconvertible.types"), found, req); } }//where /** Is type a type variable, or a (possibly multi-dimensional) array of * type variables? */ boolean isTypeVar(Type t) { return t.tag == TYPEVAR || t.tag == ARRAY && isTypeVar(types.elemtype(t)); } /** 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 void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { if (a.isUnbound()) { return; } else if (a.tag != WILDCARD) { a = types.upperBound(a); for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { if (!types.isSubtype(a, l.head)) { log.error(pos, "not.within.bounds", a); return; } } } else if (a.isExtendsBound()) { if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) log.error(pos, "not.within.bounds", a); } else if (a.isSuperBound()) { if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) log.error(pos, "not.within.bounds", a); } } /** Check that type is different from 'void'. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkNonVoid(DiagnosticPosition pos, Type t) { if (t.tag == VOID) { log.error(pos, "void.not.allowed.here"); return syms.errType; } else { return t; } } /** Check that type is a class or interface type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkClassType(DiagnosticPosition pos, Type t) { if (t.tag != CLASS && t.tag != ERROR) return typeTagError(pos, JCDiagnostic.fragment("type.req.class"), (t.tag == TYPEVAR) ? JCDiagnostic.fragment("type.parameter", t) : t); else return t; } /** Check that type is a class or interface type. * @param pos Position to be used for error reporting. * @param t The type to be checked. * @param noBounds True if type bounds are illegal here. */ Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { t = checkClassType(pos, t); if (noBounds && t.isParameterized()) { List<Type> args = t.getTypeArguments(); while (args.nonEmpty()) { if (args.head.tag == WILDCARD) return typeTagError(pos, log.getLocalizedString("type.req.exact"), args.head); args = args.tail; } } return t; } /** Check that type is a reifiable class, interface or array type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) { return typeTagError(pos, JCDiagnostic.fragment("type.req.class.array"), t); } else if (!types.isReifiable(t)) { log.error(pos, "illegal.generic.type.for.instof"); return syms.errType; } else { return t; } } /** Check that type is a reference type, i.e. a class, interface or array type * or a type variable. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkRefType(DiagnosticPosition pos, Type t) { switch (t.tag) { case CLASS: case ARRAY: case TYPEVAR: case WILDCARD: case ERROR: return t; default: return typeTagError(pos, JCDiagnostic.fragment("type.req.ref"), t); } } /** Check that type is a null or reference type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkNullOrRefType(DiagnosticPosition pos, Type t) { switch (t.tag) { case CLASS: case ARRAY: case TYPEVAR: case WILDCARD: case BOT: case ERROR: return t; default: return typeTagError(pos, JCDiagnostic.fragment("type.req.ref"), t); } } /** Check that flag set does not contain elements of two conflicting sets. s * Return true if it doesn't. * @param pos Position to be used for error reporting. * @param flags The set of flags to be checked. * @param set1 Conflicting flags set #1. * @param set2 Conflicting flags set #2. */ boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { if ((flags & set1) != 0 && (flags & set2) != 0) { log.error(pos, "illegal.combination.of.modifiers", TreeInfo.flagNames(TreeInfo.firstFlag(flags & set1)), TreeInfo.flagNames(TreeInfo.firstFlag(flags & set2))); return false; } else return true; } /** Check that given modifiers are legal for given symbol and * return modifiers together with any implicit modififiers for that symbol. * Warning: we can't use flags() here since this method * is called during class enter, when flags() would cause a premature * completion. * @param pos Position to be used for error reporting. * @param flags The set of modifiers given in a definition. * @param sym The defined symbol. */ long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { long mask; long implicit = 0; switch (sym.kind) { case VAR: if (sym.owner.kind != TYP) mask = LocalVarFlags; else if ((sym.owner.flags_field & INTERFACE) != 0) mask = implicit = InterfaceVarFlags; else mask = VarFlags; break; case MTH: if (sym.name == names.init) { if ((sym.owner.flags_field & ENUM) != 0) { // enum constructors cannot be declared public or // protected and must be implicitly or explicitly // private implicit = PRIVATE; mask = PRIVATE; } else mask = ConstructorFlags; } else if ((sym.owner.flags_field & INTERFACE) != 0) mask = implicit = InterfaceMethodFlags; else { mask = MethodFlags; } // Imply STRICTFP if owner has STRICTFP set. if (((flags|implicit) & Flags.ABSTRACT) == 0) implicit |= sym.owner.flags_field & STRICTFP; break; case TYP: if (sym.isLocal()) { mask = LocalClassFlags; if (sym.name.len == 0) { // Anonymous class // Anonymous classes in static methods are themselves static; // that's why we admit STATIC here. mask |= STATIC; // JLS: Anonymous classes are final. implicit |= FINAL; } if ((sym.owner.flags_field & STATIC) == 0 && (flags & ENUM) != 0) log.error(pos, "enums.must.be.static"); } else if (sym.owner.kind == TYP) { mask = MemberClassFlags; if (sym.owner.owner.kind == PCK || (sym.owner.flags_field & STATIC) != 0) mask |= STATIC; else if ((flags & ENUM) != 0) log.error(pos, "enums.must.be.static"); // Nested interfaces and enums are always STATIC (Spec ???) if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; } else { mask = ClassFlags; } // Interfaces are always ABSTRACT if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; if ((flags & ENUM) != 0) { // enums can't be declared abstract or final mask &= ~(ABSTRACT | FINAL); implicit |= implicitEnumFinalFlag(tree); } // Imply STRICTFP if owner has STRICTFP set. implicit |= sym.owner.flags_field & STRICTFP; break; default: throw new AssertionError(); } long illegal = flags & StandardFlags & ~mask; if (illegal != 0) { if ((illegal & INTERFACE) != 0) { log.error(pos, "intf.not.allowed.here"); mask |= INTERFACE; } else { log.error(pos, "mod.not.allowed.here", TreeInfo.flagNames(illegal)); } } else if ((sym.kind == TYP || // ISSUE: Disallowing abstract&private is no longer appropriate // in the presence of inner classes. Should it be deleted here? checkDisjoint(pos, flags, ABSTRACT, PRIVATE | STATIC)) && checkDisjoint(pos, flags, ABSTRACT | INTERFACE, FINAL | NATIVE | SYNCHRONIZED) && checkDisjoint(pos, flags, PUBLIC, PRIVATE | PROTECTED) && checkDisjoint(pos, flags, PRIVATE, PUBLIC | PROTECTED) && checkDisjoint(pos, flags, FINAL, VOLATILE) && (sym.kind == TYP || checkDisjoint(pos, flags, ABSTRACT | NATIVE, STRICTFP))) { // skip } return flags & (mask | ~StandardFlags) | implicit; } /** Determine if this enum should be implicitly final. * * If the enum has no specialized enum contants, it is final. * * If the enum does have specialized enum contants, it is * <i>not</i> final. */ private long implicitEnumFinalFlag(JCTree tree) { if (tree.getTag() != JCTree.CLASSDEF) return 0; class SpecialTreeVisitor extends JCTree.Visitor { boolean specialized; SpecialTreeVisitor() { this.specialized = false; }; public void visitTree(JCTree tree) { /* no-op */ } public void visitVarDef(JCVariableDecl tree) { if ((tree.mods.flags & ENUM) != 0) { if (tree.init instanceof JCNewClass && ((JCNewClass) tree.init).def != null) { specialized = true; } } } } SpecialTreeVisitor sts = new SpecialTreeVisitor(); JCClassDecl cdef = (JCClassDecl) tree; for (JCTree defs: cdef.defs) { defs.accept(sts); if (sts.specialized) return 0; } return FINAL; }/* ************************************************************************* * Type Validation **************************************************************************/ /** Validate a type expression. That is, * check that all type arguments of a parametric type are within * their bounds. This must be done in a second phase after type attributon * since a class might have a subclass as type parameter bound. E.g: * * class B<A extends C> { ... } * class C extends B<C> { ... } * * and we can't make sure that the bound is already attributed because * of possible cycles. */ private Validator validator = new Validator(); /** Visitor method: Validate a type expression, if it is not null, catching * and reporting any completion failures. */ void validate(JCTree tree) { try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -