📄 resolve.java
字号:
case WRONG_MTH: return wrongMethods; default: return bestSoFar; } } if (!isAccessible(env, site, sym)) { return (bestSoFar.kind == ABSENT_MTH) ? new AccessError(sym) : bestSoFar; } return (bestSoFar.kind > AMBIGUOUS) ? sym : mostSpecific(sym, bestSoFar, env, site); } Symbol mostSpecific(Symbol m1, Symbol m2, Env env, Type site) { switch (m2.kind) { case MTH: if (m1 == m2) return m1; Type mt1 = site.memberType(m1); boolean m1SignatureMoreSpecific = instantiate(env, site, m2, mt1.argtypes()) != null; Type mt2 = site.memberType(m2); boolean m2SignatureMoreSpecific = instantiate(env, site, m1, mt2.argtypes()) != null; if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) { if (methodsInherited(m1.owner, m2.owner)) return m1; if (methodsInherited(m2.owner, m1.owner)) return m2; boolean m1Abstract = (m1.flags() & ABSTRACT) != 0; if (!m1Abstract) return m1; boolean m2Abstract = (m2.flags() & ABSTRACT) != 0; if (!m2Abstract) return m2; Symbol result = mt1.restype().isSubType(mt2.restype()) ? m1 : m2; result = result.clone(result.owner); result.type = (Type) result.type.clone(); result.type.setThrown(Check.intersect(mt1.thrown(), mt2.thrown())); return result; } if (m1SignatureMoreSpecific) return m1; if (m2SignatureMoreSpecific) return m2; return new AmbiguityError(m1, m2); case AMBIGUOUS: AmbiguityError e = (AmbiguityError) m2; Symbol err1 = mostSpecific(m1, e.sym1, env, site); Symbol err2 = mostSpecific(m1, e.sym2, env, site); if (err1 == err2) return err1; if (err1 == e.sym1 && err2 == e.sym2) return m2; return new AmbiguityError(err1, err2); default: throw new AssertionError(); } } private boolean methodsInherited(Symbol subclass, Symbol superclass) { return subclass.isSubClass(superclass) && !((subclass.flags() & INTERFACE) != 0 && superclass.type == syms.objectType); } /** * Find best qualified method matching given name, type and value parameters. * @param env The current environment. * @param site The original type from where the selection takes place. * @param name The method's name. * @param argtypes The method's value parameters. */ Symbol findMethod(Env env, Type site, Name name, List argtypes) { return findMethod(env, site, name, argtypes, site.tsym.type, true, methodNotFound); } private Symbol findMethod(Env env, Type site, Name name, List argtypes, Type intype, boolean abstractok, Symbol bestSoFar) { for (Type ct = intype; ct.tag == CLASS; ct = ct.supertype()) { ClassSymbol c = (ClassSymbol) ct.tsym; if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) abstractok = false; for (Scope.Entry e = c.members().lookup(name); e.scope != null; e = e.next()) { if (e.sym.kind == MTH && (e.sym.flags_field & SYNTHETIC) == 0) { bestSoFar = selectBest(env, site, argtypes, e.sym, bestSoFar); } } if (abstractok) { for (List l = c.type.interfaces(); l.nonEmpty(); l = l.tail) { bestSoFar = findMethod(env, site, name, argtypes, (Type) l.head, abstractok, bestSoFar); } } } return bestSoFar; } /** * Find unqualified method matching given name, type and value parameters. * @param env The current environment. * @param name The method's name. * @param argtypes The method's value parameters. */ Symbol findFun(Env env, Name name, List argtypes) { Symbol bestSoFar = methodNotFound; Symbol sym; Env env1 = env; boolean staticOnly = false; while (env1.outer != null) { if (isStatic(env1)) staticOnly = true; sym = findMethod(env1, env1.enclClass.sym.type, name, argtypes); if (sym.kind <= AMBIGUOUS || sym.kind == WRONG_MTHS || sym.kind == WRONG_MTH) { if (staticOnly && sym.kind == MTH && sym.owner.kind == TYP && (sym.flags() & STATIC) == 0) return new StaticError(sym); else return sym; } else if (sym.kind < bestSoFar.kind) { bestSoFar = sym; } if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; env1 = env1.outer; } sym = findMethod(env, syms.predefClass.type, name, argtypes); if (sym.kind <= AMBIGUOUS) return sym; else return bestSoFar; } /** * Load toplevel or member class with given fully qualified name and * verify that it is accessible. * @param env The current environment. * @param name The fully qualified name of the class to be loaded. */ Symbol loadClass(Env env, Name name) { try { ClassSymbol c = reader.loadClass(name); if (isAccessible(env, c)) return c; else return new AccessError(c); } catch (ClassReader.BadClassFile err) { throw err; } catch (CompletionFailure ex) { return typeNotFound; } } /** * Find qualified member type. * @param env The current environment. * @param site The original type from where the selection takes place. * @param name The type's name. * @param c The class to search for the member type. This is always * a superclass or implemented interface of site's class. */ Symbol findMemberType(Env env, Type site, Name name, TypeSymbol c) { Symbol bestSoFar = typeNotFound; Symbol sym; Scope.Entry e = c.members().lookup(name); while (e.scope != null) { if (e.sym.kind == TYP) { return isAccessible(env, site, e.sym) ? e.sym : new AccessError(e.sym); } e = e.next(); } Type st = c.type.supertype(); if (st != null && st.tag == CLASS) { sym = findMemberType(env, site, name, st.tsym); if (sym.kind < bestSoFar.kind) bestSoFar = sym; } for (List l = c.type.interfaces(); bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) { sym = findMemberType(env, site, name, ((Type) l.head).tsym); if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS && sym.owner != bestSoFar.owner) bestSoFar = new AmbiguityError(bestSoFar, sym); else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } return bestSoFar; } /** * Find a global type in given scope and load corresponding class. * @param env The current environment. * @param scope The scope in which to look for the type. * @param name The type's name. */ Symbol findGlobalType(Env env, Scope scope, Name name) { Symbol bestSoFar = typeNotFound; Scope.Entry e = scope.lookup(name); while (e.scope != null) { if (e.scope.owner == e.sym.owner) { Symbol sym = loadClass(env, e.sym.flatName()); if (bestSoFar.kind == TYP && sym.kind == TYP && bestSoFar != sym) return new AmbiguityError(bestSoFar, sym); else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } e = e.next(); } return bestSoFar; } /** * Find an unqualified type symbol. * @param env The current environment. * @param name The type's name. */ Symbol findType(Env env, Name name) { Symbol bestSoFar = typeNotFound; Symbol sym; Env env1 = env; boolean staticOnly = false; while (env1.outer != null) { if (isStatic(env1)) staticOnly = true; Scope.Entry e = ((AttrContext) env1.info).scope.lookup(name); while (e.scope != null) { if (e.sym.kind == TYP) { return e.sym; } e = e.next(); } sym = findMemberType(env1, env1.enclClass.sym.type, name, env1.enclClass.sym); if (staticOnly && sym.kind == TYP && sym.type.tag == CLASS && sym.type.outer().isParameterized()) return new StaticError(sym); else if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; long flags = env1.enclClass.sym.flags(); if ((flags & STATIC) != 0) staticOnly = true; env1 = env1.outer; } if (env.tree.tag != Tree.IMPORT) { sym = findGlobalType(env, env.toplevel.namedImportScope, name); if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; sym = findGlobalType(env, env.toplevel.packge.members(), name); if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; sym = findGlobalType(env, env.toplevel.starImportScope, name); if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } return bestSoFar; } /** * Find an unqualified identifier which matches a specified kind set. * @param env The current environment. * @param name The indentifier's name. * @param kind Indicates the possible symbol kinds * (a subset of VAL, TYP, PCK). */ Symbol findIdent(Env env, Name name, int kind) { Symbol bestSoFar = typeNotFound; Symbol sym; if ((kind & VAR) != 0) { sym = findVar(env, name); if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } if ((kind & TYP) != 0) { sym = findType(env, name); if (sym.kind <= AMBIGUOUS) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } if ((kind & PCK) != 0) return reader.enterPackage(name); else return bestSoFar; } /** * Find an identifier in a package which matches a specified kind set. * @param env The current environment. * @param name The identifier's name. * @param kind Indicates the possible symbol kinds * (a nonempty subset of TYP, PCK). */ Symbol findIdentInPackage(Env env, TypeSymbol pck, Name name, int kind) { Name fullname = TypeSymbol.formFullName(name, pck); Symbol bestSoFar = typeNotFound; PackageSymbol pack = null; if ((kind & PCK) != 0) { pack = reader.enterPackage(fullname); if (pack.exists()) return pack; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -