Method from com.sun.tools.javac.comp.Resolve Detail: |
Symbol access(Symbol sym,
DiagnosticPosition pos,
Type site,
Name name,
boolean qualified) {
return access(sym, pos, site.tsym, site, name, qualified);
}
Same as original access(), but without location, type arguments and arguments. |
Symbol access(Symbol sym,
DiagnosticPosition pos,
Symbol location,
Type site,
Name name,
boolean qualified) {
if (sym.kind >= AMBIGUOUS)
return access(sym, pos, location, site, name, qualified, List.< Type >nil(), null);
else
return sym;
}
Same as original access(), but without type arguments and arguments. |
Symbol access(Symbol sym,
DiagnosticPosition pos,
Type site,
Name name,
boolean qualified,
List<Type> argtypes,
List<Type> typeargtypes) {
return access(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
}
Same as original access(), but without location. |
Symbol access(Symbol sym,
DiagnosticPosition pos,
Symbol location,
Type site,
Name name,
boolean qualified,
List<Type> argtypes,
List<Type> typeargtypes) {
if (sym.kind >= AMBIGUOUS) {
ResolveError errSym = (ResolveError)sym;
if (!site.isErroneous() &&
!Type.isErroneous(argtypes) &&
(typeargtypes==null || !Type.isErroneous(typeargtypes)))
logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
}
return sym;
}
If `sym' is a bad symbol: report error and return errSymbol
else pass through unchanged,
additional arguments duplicate what has been used in trying to find the
symbol (--> flyweight pattern). This improves performance since we
expect misses to happen frequently. |
Symbol ambiguityError(Symbol m1,
Symbol m2) {
if (((m1.flags() | m2.flags()) & CLASH) != 0) {
return (m1.flags() & CLASH) == 0 ? m1 : m2;
} else {
return new AmbiguityError(m1, m2);
}
}
|
boolean argumentsAcceptable(Env<AttrContext> env,
List<Type> argtypes,
List<Type> formals,
boolean allowBoxing,
boolean useVarargs,
Warner warn) {
try {
checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn);
return true;
} catch (InapplicableMethodException ex) {
return false;
}
}
Check if a parameter list accepts a list of args. |
void checkNonAbstract(DiagnosticPosition pos,
Symbol sym) {
if ((sym.flags() & ABSTRACT) != 0)
log.error(pos, "abstract.cant.be.accessed.directly",
kindName(sym), sym, sym.location());
}
Check that sym is not an abstract method. |
void checkRawArgumentsAcceptable(Env<AttrContext> env,
List<Type> argtypes,
List<Type> formals,
boolean allowBoxing,
boolean useVarargs,
Warner warn) {
Type varargsFormal = useVarargs ? formals.last() : null;
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
}
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
boolean works = allowBoxing
? types.isConvertible(argtypes.head, formals.head, warn)
: types.isSubtypeUnchecked(argtypes.head, formals.head, warn);
if (!works)
throw inapplicableMethodException.setMessage("no.conforming.assignment.exists",
argtypes.head,
formals.head);
argtypes = argtypes.tail;
formals = formals.tail;
}
if (formals.head != varargsFormal)
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
if (useVarargs) {
Type elt = types.elemtype(varargsFormal);
while (argtypes.nonEmpty()) {
if (!types.isConvertible(argtypes.head, elt, warn))
throw inapplicableMethodException.setMessage("varargs.argument.mismatch",
argtypes.head,
elt);
argtypes = argtypes.tail;
}
//check varargs element type accessibility
if (!isAccessible(env, elt)) {
Symbol location = env.enclClass.sym;
throw inapplicableMethodException.setMessage("inaccessible.varargs.type",
elt,
Kinds.kindName(location),
location);
}
}
return;
}
|
Symbol findField(Env<AttrContext> env,
Type site,
Name name,
TypeSymbol c) {
while (c.type.tag == TYPEVAR)
c = c.type.getUpperBound().tsym;
Symbol bestSoFar = varNotFound;
Symbol sym;
Scope.Entry e = c.members().lookup(name);
while (e.scope != null) {
if (e.sym.kind == VAR && (e.sym.flags_field & SYNTHETIC) == 0) {
return isAccessible(env, site, e.sym)
? e.sym : new AccessError(env, site, e.sym);
}
e = e.next();
}
Type st = types.supertype(c.type);
if (st != null && (st.tag == CLASS || st.tag == TYPEVAR)) {
sym = findField(env, site, name, st.tsym);
if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
for (List< Type > l = types.interfaces(c.type);
bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
l = l.tail) {
sym = findField(env, site, name, 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 field. Synthetic fields are always skipped. |
Symbol findFun(Env<AttrContext> env,
Name name,
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs) {
Symbol bestSoFar = methodNotFound;
Symbol sym;
Env< AttrContext > env1 = env;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
sym = findMethod(
env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
allowBoxing, useVarargs, false);
if (sym.exists()) {
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,
typeargtypes, allowBoxing, useVarargs, false);
if (sym.exists())
return sym;
Scope.Entry e = env.toplevel.namedImportScope.lookup(name);
for (; e.scope != null; e = e.next()) {
sym = e.sym;
Type origin = e.getOrigin().owner.type;
if (sym.kind == MTH) {
if (e.sym.owner.type != origin)
sym = sym.clone(e.getOrigin().owner);
if (!isAccessible(env, origin, sym))
sym = new AccessError(env, origin, sym);
bestSoFar = selectBest(env, origin,
argtypes, typeargtypes,
sym, bestSoFar,
allowBoxing, useVarargs, false);
}
}
if (bestSoFar.exists())
return bestSoFar;
e = env.toplevel.starImportScope.lookup(name);
for (; e.scope != null; e = e.next()) {
sym = e.sym;
Type origin = e.getOrigin().owner.type;
if (sym.kind == MTH) {
if (e.sym.owner.type != origin)
sym = sym.clone(e.getOrigin().owner);
if (!isAccessible(env, origin, sym))
sym = new AccessError(env, origin, sym);
bestSoFar = selectBest(env, origin,
argtypes, typeargtypes,
sym, bestSoFar,
allowBoxing, useVarargs, false);
}
}
return bestSoFar;
}
Find unqualified method matching given name, type and value arguments. |
Symbol findGlobalType(Env<AttrContext> env,
Scope scope,
Name name) {
Symbol bestSoFar = typeNotFound;
for (Scope.Entry e = scope.lookup(name); e.scope != null; e = e.next()) {
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;
}
return bestSoFar;
}
Find a global type in given scope and load corresponding class. |
Symbol findIdent(Env<AttrContext> env,
Name name,
int kind) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
if ((kind & VAR) != 0) {
sym = findVar(env, name);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
if ((kind & TYP) != 0) {
sym = findType(env, name);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
if ((kind & PCK) != 0) return reader.enterPackage(name);
else return bestSoFar;
}
Find an unqualified identifier which matches a specified kind set. |
Symbol findIdentInPackage(Env<AttrContext> 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;
}
if ((kind & TYP) != 0) {
Symbol sym = loadClass(env, fullname);
if (sym.exists()) {
// don't allow programs to use flatnames
if (name == sym.name) return sym;
}
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
return (pack != null) ? pack : bestSoFar;
}
Find an identifier in a package which matches a specified kind set. |
Symbol findIdentInType(Env<AttrContext> env,
Type site,
Name name,
int kind) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
if ((kind & VAR) != 0) {
sym = findField(env, site, name, site.tsym);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
if ((kind & TYP) != 0) {
sym = findMemberType(env, site, name, site.tsym);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
return bestSoFar;
}
Find an identifier among the members of a given type `site'. |
Symbol findMemberType(Env<AttrContext> 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(env, site, e.sym);
}
e = e.next();
}
Type st = types.supertype(c.type);
if (st != null && st.tag == CLASS) {
sym = findMemberType(env, site, name, st.tsym);
if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
for (List< Type > l = types.interfaces(c.type);
bestSoFar.kind != AMBIGUOUS && l.nonEmpty();
l = l.tail) {
sym = findMemberType(env, site, name, 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 qualified member type. |
Symbol findMethod(Env<AttrContext> env,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
Symbol bestSoFar = methodNotFound;
return findMethod(env,
site,
name,
argtypes,
typeargtypes,
site.tsym.type,
true,
bestSoFar,
allowBoxing,
useVarargs,
operator,
new HashSet< TypeSymbol >());
}
Find best qualified method matching given name, type and value
arguments. |
Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
Type site,
Name name,
MethodSymbol spMethod,
List<Type> argtypes) {
Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
site, name, spMethod, argtypes);
long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE |
(spMethod != null ?
spMethod.flags() & Flags.AccessFlags :
Flags.PUBLIC | Flags.STATIC);
Symbol m = null;
for (Scope.Entry e = polymorphicSignatureScope.lookup(name);
e.scope != null;
e = e.next()) {
Symbol sym = e.sym;
if (types.isSameType(mtype, sym.type) &&
(sym.flags() & Flags.STATIC) == (flags & Flags.STATIC) &&
types.isSameType(sym.owner.type, site)) {
m = sym;
break;
}
}
if (m == null) {
// create the desired method
m = new MethodSymbol(flags, name, mtype, site.tsym);
polymorphicSignatureScope.enter(m);
}
return m;
}
Find or create an implicit method of exactly the given type (after erasure).
Searches in a side table, not the main scope of the site.
This emulates the lookup process required by JSR 292 in JVM. |
Symbol findType(Env<AttrContext> env,
Name name) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
boolean staticOnly = false;
for (Env< AttrContext > env1 = env; env1.outer != null; env1 = env1.outer) {
if (isStatic(env1)) staticOnly = true;
for (Scope.Entry e = env1.info.scope.lookup(name);
e.scope != null;
e = e.next()) {
if (e.sym.kind == TYP) {
if (staticOnly &&
e.sym.type.tag == TYPEVAR &&
e.sym.owner.kind == TYP) return new StaticError(e.sym);
return e.sym;
}
}
sym = findMemberType(env1, env1.enclClass.sym.type, name,
env1.enclClass.sym);
if (staticOnly && sym.kind == TYP &&
sym.type.tag == CLASS &&
sym.type.getEnclosingType().tag == CLASS &&
env1.enclClass.sym.type.isParameterized() &&
sym.type.getEnclosingType().isParameterized())
return new StaticError(sym);
else if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass;
if ((encl.sym.flags() & STATIC) != 0)
staticOnly = true;
}
if (env.tree.getTag() != JCTree.IMPORT) {
sym = findGlobalType(env, env.toplevel.namedImportScope, name);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
sym = findGlobalType(env, env.toplevel.packge.members(), name);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
sym = findGlobalType(env, env.toplevel.starImportScope, name);
if (sym.exists()) return sym;
else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
}
return bestSoFar;
}
Find an unqualified type symbol. |
Symbol findVar(Env<AttrContext> env,
Name name) {
Symbol bestSoFar = varNotFound;
Symbol sym;
Env< AttrContext > env1 = env;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
Scope.Entry e = env1.info.scope.lookup(name);
while (e.scope != null &&
(e.sym.kind != VAR ||
(e.sym.flags_field & SYNTHETIC) != 0))
e = e.next();
sym = (e.scope != null)
? e.sym
: findField(
env1, env1.enclClass.sym.type, name, env1.enclClass.sym);
if (sym.exists()) {
if (staticOnly &&
sym.kind == VAR &&
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 = findField(env, syms.predefClass.type, name, syms.predefClass);
if (sym.exists())
return sym;
if (bestSoFar.exists())
return bestSoFar;
Scope.Entry e = env.toplevel.namedImportScope.lookup(name);
for (; e.scope != null; e = e.next()) {
sym = e.sym;
Type origin = e.getOrigin().owner.type;
if (sym.kind == VAR) {
if (e.sym.owner.type != origin)
sym = sym.clone(e.getOrigin().owner);
return isAccessible(env, origin, sym)
? sym : new AccessError(env, origin, sym);
}
}
Symbol origin = null;
e = env.toplevel.starImportScope.lookup(name);
for (; e.scope != null; e = e.next()) {
sym = e.sym;
if (sym.kind != VAR)
continue;
// invariant: sym.kind == VAR
if (bestSoFar.kind < AMBIGUOUS && sym.owner != bestSoFar.owner)
return new AmbiguityError(bestSoFar, sym);
else if (bestSoFar.kind >= VAR) {
origin = e.getOrigin().owner;
bestSoFar = isAccessible(env, origin.type, sym)
? sym : new AccessError(env, origin.type, sym);
}
}
if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type)
return bestSoFar.clone(origin);
else
return bestSoFar;
}
Find unqualified variable or field with given name.
Synthetic fields always skipped. |
public static Resolve instance(Context context) {
Resolve instance = context.get(resolveKey);
if (instance == null)
instance = new Resolve(context);
return instance;
}
|
Type instantiate(Env<AttrContext> env,
Type site,
Symbol m,
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
Warner warn) {
try {
return rawInstantiate(env, site, m, argtypes, typeargtypes,
allowBoxing, useVarargs, warn);
} catch (InapplicableMethodException ex) {
return null;
}
}
Same but returns null instead throwing a NoInstanceException |
public boolean isAccessible(Env<AttrContext> env,
TypeSymbol c) {
return isAccessible(env, c, false);
}
Is class accessible in given evironment? |
boolean isAccessible(Env<AttrContext> env,
Type t) {
return isAccessible(env, t, false);
}
|
public boolean isAccessible(Env<AttrContext> env,
TypeSymbol c,
boolean checkInner) {
boolean isAccessible = false;
switch ((short)(c.flags() & AccessFlags)) {
case PRIVATE:
isAccessible =
env.enclClass.sym.outermostClass() ==
c.owner.outermostClass();
break;
case 0:
isAccessible =
env.toplevel.packge == c.owner // fast special case
||
env.toplevel.packge == c.packge()
||
// Hack: this case is added since synthesized default constructors
// of anonymous classes should be allowed to access
// classes which would be inaccessible otherwise.
env.enclMethod != null &&
(env.enclMethod.mods.flags & ANONCONSTR) != 0;
break;
default: // error recovery
case PUBLIC:
isAccessible = true;
break;
case PROTECTED:
isAccessible =
env.toplevel.packge == c.owner // fast special case
||
env.toplevel.packge == c.packge()
||
isInnerSubClass(env.enclClass.sym, c.owner);
break;
}
return (checkInner == false || c.type.getEnclosingType() == Type.noType) ?
isAccessible :
isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner);
}
|
boolean isAccessible(Env<AttrContext> env,
Type t,
boolean checkInner) {
return (t.tag == ARRAY)
? isAccessible(env, types.elemtype(t))
: isAccessible(env, t.tsym, checkInner);
}
|
public boolean isAccessible(Env<AttrContext> env,
Type site,
Symbol sym) {
return isAccessible(env, site, sym, false);
}
Is symbol accessible as a member of given type in given evironment? |
public boolean isAccessible(Env<AttrContext> env,
Type site,
Symbol sym,
boolean checkInner) {
if (sym.name == names.init && sym.owner != site.tsym) return false;
switch ((short)(sym.flags() & AccessFlags)) {
case PRIVATE:
return
(env.enclClass.sym == sym.owner // fast special case
||
env.enclClass.sym.outermostClass() ==
sym.owner.outermostClass())
&&
sym.isInheritedIn(site.tsym, types);
case 0:
return
(env.toplevel.packge == sym.owner.owner // fast special case
||
env.toplevel.packge == sym.packge())
&&
isAccessible(env, site, checkInner)
&&
sym.isInheritedIn(site.tsym, types)
&&
notOverriddenIn(site, sym);
case PROTECTED:
return
(env.toplevel.packge == sym.owner.owner // fast special case
||
env.toplevel.packge == sym.packge()
||
isProtectedAccessible(sym, env.enclClass.sym, site)
||
// OK to select instance method or field from 'super' or type name
// (but type names should be disallowed elsewhere!)
env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP)
&&
isAccessible(env, site, checkInner)
&&
notOverriddenIn(site, sym);
default: // this case includes erroneous combinations as well
return isAccessible(env, site, checkInner) && notOverriddenIn(site, sym);
}
}
|
static boolean isInitializer(Env<AttrContext> env) {
Symbol owner = env.info.scope.owner;
return owner.isConstructor() ||
owner.owner.kind == TYP &&
(owner.kind == VAR ||
owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
(owner.flags() & STATIC) == 0;
}
An environment is an "initializer" if it is a constructor or
an instance initializer. |
static boolean isStatic(Env<AttrContext> env) {
return env.info.staticLevel > env.outer.info.staticLevel;
}
An environment is "static" if its static level is greater than
the one of its outer environment |
Symbol loadClass(Env<AttrContext> env,
Name name) {
try {
ClassSymbol c = reader.loadClass(name);
return isAccessible(env, c) ? c : new AccessError(c);
} catch (ClassReader.BadClassFile err) {
throw err;
} catch (CompletionFailure ex) {
return typeNotFound;
}
}
Load toplevel or member class with given fully qualified name and
verify that it is accessible. |
public void logAccessError(Env<AttrContext> env,
JCTree tree,
Type type) {
AccessError error = new AccessError(env, type.getEnclosingType(), type.tsym);
logResolveError(error, tree.pos(), type.getEnclosingType().tsym, type.getEnclosingType(), null, null, null);
}
|
public Object methodArguments(List<Type> argtypes) {
return argtypes.isEmpty() ? noArgs : argtypes;
}
|
Symbol mostSpecific(Symbol m1,
Symbol m2,
Env<AttrContext> env,
Type site,
boolean allowBoxing,
boolean useVarargs) {
switch (m2.kind) {
case MTH:
if (m1 == m2) return m1;
boolean m1SignatureMoreSpecific = signatureMoreSpecific(env, site, m1, m2, allowBoxing, useVarargs);
boolean m2SignatureMoreSpecific = signatureMoreSpecific(env, site, m2, m1, allowBoxing, useVarargs);
if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
Type mt1 = types.memberType(site, m1);
Type mt2 = types.memberType(site, m2);
if (!types.overrideEquivalent(mt1, mt2))
return ambiguityError(m1, m2);
// same signature; select (a) the non-bridge method, or
// (b) the one that overrides the other, or (c) the concrete
// one, or (d) merge both abstract signatures
if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
// if one overrides or hides the other, use it
TypeSymbol m1Owner = (TypeSymbol)m1.owner;
TypeSymbol m2Owner = (TypeSymbol)m2.owner;
if (types.asSuper(m1Owner.type, m2Owner) != null &&
((m1.owner.flags_field & INTERFACE) == 0 ||
(m2.owner.flags_field & INTERFACE) != 0) &&
m1.overrides(m2, m1Owner, types, false))
return m1;
if (types.asSuper(m2Owner.type, m1Owner) != null &&
((m2.owner.flags_field & INTERFACE) == 0 ||
(m1.owner.flags_field & INTERFACE) != 0) &&
m2.overrides(m1, m2Owner, types, false))
return m2;
boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
if (m1Abstract && !m2Abstract) return m2;
if (m2Abstract && !m1Abstract) return m1;
// both abstract or both concrete
if (!m1Abstract && !m2Abstract)
return ambiguityError(m1, m2);
// check that both signatures have the same erasure
if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
m2.erasure(types).getParameterTypes()))
return ambiguityError(m1, m2);
// both abstract, neither overridden; merge throws clause and result type
Symbol mostSpecific;
if (types.returnTypeSubstitutable(mt1, mt2))
mostSpecific = m1;
else if (types.returnTypeSubstitutable(mt2, mt1))
mostSpecific = m2;
else {
// Theoretically, this can't happen, but it is possible
// due to error recovery or mixing incompatible class files
return ambiguityError(m1, m2);
}
List< Type > allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
MethodSymbol result = new MethodSymbol(
mostSpecific.flags(),
mostSpecific.name,
newSig,
mostSpecific.owner) {
@Override
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
if (origin == site.tsym)
return this;
else
return super.implementation(origin, types, checkResult);
}
};
return result;
}
if (m1SignatureMoreSpecific) return m1;
if (m2SignatureMoreSpecific) return m2;
return ambiguityError(m1, m2);
case AMBIGUOUS:
AmbiguityError e = (AmbiguityError)m2;
Symbol err1 = mostSpecific(m1, e.sym, env, site, allowBoxing, useVarargs);
Symbol err2 = mostSpecific(m1, e.sym2, env, site, allowBoxing, useVarargs);
if (err1 == err2) return err1;
if (err1 == e.sym && err2 == e.sym2) return m2;
if (err1 instanceof AmbiguityError &&
err2 instanceof AmbiguityError &&
((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
return ambiguityError(m1, m2);
else
return ambiguityError(err1, err2);
default:
throw new AssertionError();
}
}
|
public void printscopes(Scope s) {
while (s != null) {
if (s.owner != null)
System.err.print(s.owner + ": ");
for (Scope.Entry e = s.elems; e != null; e = e.sibling) {
if ((e.sym.flags() & ABSTRACT) != 0)
System.err.print("abstract ");
System.err.print(e.sym + " ");
}
System.err.println();
s = s.next;
}
}
print all scopes starting with scope s and proceeding outwards.
used for debugging. |
void printscopes(Env<AttrContext> env) {
while (env.outer != null) {
System.err.println("------------------------------");
printscopes(env.info.scope);
env = env.outer;
}
}
|
public void printscopes(Type t) {
while (t.tag == CLASS) {
printscopes(t.tsym.members());
t = types.supertype(t);
}
}
|
Type rawInstantiate(Env<AttrContext> env,
Type site,
Symbol m,
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
Warner warn) throws InferenceException {
boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles;
if (useVarargs && (m.flags() & VARARGS) == 0)
throw inapplicableMethodException.setMessage();
Type mt = types.memberType(site, m);
// tvars is the list of formal type variables for which type arguments
// need to inferred.
List< Type > tvars = null;
if (env.info.tvars != null) {
tvars = types.newInstances(env.info.tvars);
mt = types.subst(mt, env.info.tvars, tvars);
}
if (typeargtypes == null) typeargtypes = List.nil();
if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
// This is not a polymorphic method, but typeargs are supplied
// which is fine, see JLS 15.12.2.1
} else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
ForAll pmt = (ForAll) mt;
if (typeargtypes.length() != pmt.tvars.length())
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
// Check type arguments are within bounds
List< Type > formals = pmt.tvars;
List< Type > actuals = typeargtypes;
while (formals.nonEmpty() && actuals.nonEmpty()) {
List< Type > bounds = types.subst(types.getBounds((TypeVar)formals.head),
pmt.tvars, typeargtypes);
for (; bounds.nonEmpty(); bounds = bounds.tail)
if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
formals = formals.tail;
actuals = actuals.tail;
}
mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes);
} else if (mt.tag == FORALL) {
ForAll pmt = (ForAll) mt;
List< Type > tvars1 = types.newInstances(pmt.tvars);
tvars = tvars.appendList(tvars1);
mt = types.subst(pmt.qtype, pmt.tvars, tvars1);
}
// find out whether we need to go the slow route via infer
boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/
polymorphicSignature;
for (List< Type > l = argtypes;
l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
l = l.tail) {
if (l.head.tag == FORALL) instNeeded = true;
}
if (instNeeded)
return polymorphicSignature ?
infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes) :
infer.instantiateMethod(env,
tvars,
(MethodType)mt,
m,
argtypes,
allowBoxing,
useVarargs,
warn);
checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(),
allowBoxing, useVarargs, warn);
return mt;
}
Try to instantiate the type of a method so that it fits
given type arguments and argument types. If succesful, return
the method's instantiated type, else return null.
The instantiation will take into account an additional leading
formal parameter if the method is an instance method seen as a member
of un underdetermined site In this case, we treat site as an additional
parameter and the parameters of the class containing the method as
additional type variables that get instantiated. |
Symbol resolveBinaryOperator(DiagnosticPosition pos,
int optag,
Env<AttrContext> env,
Type left,
Type right) {
return resolveOperator(pos, optag, env, List.of(left, right));
}
|
Symbol resolveConstructor(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = startResolution();
List< MethodResolutionPhase > steps = methodResolutionSteps;
while (steps.nonEmpty() &&
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
sym.kind >= ERRONEOUS) {
currentStep = steps.head;
sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
steps.head.isBoxingRequired(),
env.info.varArgs = steps.head.isVarargsRequired());
methodResolutionCache.put(steps.head, sym);
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
pos, site, names.init, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired();
}
return sym;
}
|
Symbol resolveConstructor(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs) {
Symbol sym = findMethod(env, site,
names.init, argtypes,
typeargtypes, allowBoxing,
useVarargs, false);
chk.checkDeprecated(pos, env.info.scope.owner, sym);
return sym;
}
|
Symbol resolveDiamond(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = startResolution();
List< MethodResolutionPhase > steps = methodResolutionSteps;
while (steps.nonEmpty() &&
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
sym.kind >= ERRONEOUS) {
currentStep = steps.head;
sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
steps.head.isBoxingRequired(),
env.info.varArgs = steps.head.isVarargsRequired());
methodResolutionCache.put(steps.head, sym);
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {
final JCDiagnostic details = sym.kind == WRONG_MTH ?
((InapplicableSymbolError)sym).explanation :
null;
Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
@Override
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
Symbol location, Type site, Name name, List< Type > argtypes, List< Type > typeargtypes) {
String key = details == null ?
"cant.apply.diamond" :
"cant.apply.diamond.1";
return diags.create(dkind, log.currentSource(), pos, key,
diags.fragment("diamond", site.tsym), details);
}
};
MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired();
}
return sym;
}
Resolve constructor using diamond inference. |
Symbol resolveIdent(DiagnosticPosition pos,
Env<AttrContext> env,
Name name,
int kind) {
return access(
findIdent(env, name, kind),
pos, env.enclClass.sym.type, name, false);
}
Resolve an unqualified (non-method) identifier. |
Type resolveImplicitThis(DiagnosticPosition pos,
Env<AttrContext> env,
Type t) {
return resolveImplicitThis(pos, env, t, false);
}
Resolve an appropriate implicit this instance for t's container.
JLS 8.8.5.1 and 15.9.2 |
Type resolveImplicitThis(DiagnosticPosition pos,
Env<AttrContext> env,
Type t,
boolean isSuperCall) {
Type thisType = (((t.tsym.owner.kind & (MTH|VAR)) != 0)
? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this)
: resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type;
if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym)
log.error(pos, "cant.ref.before.ctor.called", "this");
return thisType;
}
|
public MethodSymbol resolveInternalConstructor(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = resolveConstructor(
pos, env, site, argtypes, typeargtypes);
if (sym.kind == MTH) return (MethodSymbol)sym;
else throw new FatalError(
diags.fragment("fatal.err.cant.locate.ctor", site));
}
Resolve a constructor, throw a fatal error if not found. |
public VarSymbol resolveInternalField(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
Name name) {
Symbol sym = findField(env, site, name, site.tsym);
if (sym.kind == VAR) return (VarSymbol)sym;
else throw new FatalError(
diags.fragment("fatal.err.cant.locate.field",
name));
}
Resolve a field identifier, throw a fatal error if not found. |
public MethodSymbol resolveInternalMethod(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = resolveQualifiedMethod(
pos, env, site.tsym, site, name, argtypes, typeargtypes);
if (sym.kind == MTH) return (MethodSymbol)sym;
else throw new FatalError(
diags.fragment("fatal.err.cant.locate.meth",
name));
}
Resolve a qualified method identifier, throw a fatal error if not
found. |
Symbol resolveMethod(DiagnosticPosition pos,
Env<AttrContext> env,
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = startResolution();
List< MethodResolutionPhase > steps = methodResolutionSteps;
while (steps.nonEmpty() &&
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
sym.kind >= ERRONEOUS) {
currentStep = steps.head;
sym = findFun(env, name, argtypes, typeargtypes,
steps.head.isBoxingRequired,
env.info.varArgs = steps.head.isVarargsRequired);
methodResolutionCache.put(steps.head, sym);
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
MethodResolutionPhase errPhase =
firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired;
}
return sym;
}
Resolve an unqualified method identifier. |
Symbol resolveOperator(DiagnosticPosition pos,
int optag,
Env<AttrContext> env,
List<Type> argtypes) {
Name name = treeinfo.operatorName(optag);
Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
null, false, false, true);
if (boxingEnabled && sym.kind >= WRONG_MTHS)
sym = findMethod(env, syms.predefClass.type, name, argtypes,
null, true, false, true);
return access(sym, pos, env.enclClass.sym.type, name,
false, argtypes, null);
}
|
Symbol resolveQualifiedMethod(DiagnosticPosition pos,
Env<AttrContext> env,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes);
}
Resolve a qualified method identifier |
Symbol resolveQualifiedMethod(DiagnosticPosition pos,
Env<AttrContext> env,
Symbol location,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = startResolution();
List< MethodResolutionPhase > steps = methodResolutionSteps;
while (steps.nonEmpty() &&
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
sym.kind >= ERRONEOUS) {
currentStep = steps.head;
sym = findMethod(env, site, name, argtypes, typeargtypes,
steps.head.isBoxingRequired(),
env.info.varArgs = steps.head.isVarargsRequired(), false);
methodResolutionCache.put(steps.head, sym);
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {
if (site.tsym.isPolymorphicSignatureGeneric()) {
//polymorphic receiver - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
site, name, null, argtypes);
}
else {
//if nothing is found return the 'first' error
MethodResolutionPhase errPhase =
firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
pos, location, site, name, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired;
}
} else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
//non-instantiated polymorphic signature - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
site, name, (MethodSymbol)sym, argtypes);
}
return sym;
}
|
Symbol resolveSelf(DiagnosticPosition pos,
Env<AttrContext> env,
TypeSymbol c,
Name name) {
Env< AttrContext > env1 = env;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
if (env1.enclClass.sym == c) {
Symbol sym = env1.info.scope.lookup(name).sym;
if (sym != null) {
if (staticOnly) sym = new StaticError(sym);
return access(sym, pos, env.enclClass.sym.type,
name, true);
}
}
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
env1 = env1.outer;
}
log.error(pos, "not.encl.class", c);
return syms.errSymbol;
}
Resolve `c.name' where name == this or name == super. |
Symbol resolveSelfContaining(DiagnosticPosition pos,
Env<AttrContext> env,
Symbol member,
boolean isSuperCall) {
Name name = names._this;
Env< AttrContext > env1 = isSuperCall ? env.outer : env;
boolean staticOnly = false;
if (env1 != null) {
while (env1 != null && env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
if (env1.enclClass.sym.isSubClass(member.owner, types)) {
Symbol sym = env1.info.scope.lookup(name).sym;
if (sym != null) {
if (staticOnly) sym = new StaticError(sym);
return access(sym, pos, env.enclClass.sym.type,
name, true);
}
}
if ((env1.enclClass.sym.flags() & STATIC) != 0)
staticOnly = true;
env1 = env1.outer;
}
}
log.error(pos, "encl.class.required", member);
return syms.errSymbol;
}
Resolve `c.this' for an enclosing class c that contains the
named member. |
Symbol resolveUnaryOperator(DiagnosticPosition pos,
int optag,
Env<AttrContext> env,
Type arg) {
return resolveOperator(pos, optag, env, List.of(arg));
}
|
Symbol selectBest(Env<AttrContext> env,
Type site,
List<Type> argtypes,
List<Type> typeargtypes,
Symbol sym,
Symbol bestSoFar,
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
if (sym.kind == ERR) return bestSoFar;
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
Assert.check(sym.kind < AMBIGUOUS);
try {
rawInstantiate(env, site, sym, argtypes, typeargtypes,
allowBoxing, useVarargs, Warner.noWarnings);
} catch (InapplicableMethodException ex) {
switch (bestSoFar.kind) {
case ABSENT_MTH:
return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
case WRONG_MTH:
wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
case WRONG_MTHS:
return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
default:
return bestSoFar;
}
}
if (!isAccessible(env, site, sym)) {
return (bestSoFar.kind == ABSENT_MTH)
? new AccessError(env, site, sym)
: bestSoFar;
}
return (bestSoFar.kind > AMBIGUOUS)
? sym
: mostSpecific(sym, bestSoFar, env, site,
allowBoxing && operator, useVarargs);
}
Select the best method for a call site among two choices. |