1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Oct 24 13:00:20 2011 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Oct 24 13:00:30 2011 +0100 1.3 @@ -25,29 +25,33 @@ 1.4 1.5 package com.sun.tools.javac.comp; 1.6 1.7 -import com.sun.tools.javac.util.*; 1.8 -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.9 +import com.sun.tools.javac.api.Formattable.LocalizedString; 1.10 import com.sun.tools.javac.code.*; 1.11 +import com.sun.tools.javac.code.Type.*; 1.12 +import com.sun.tools.javac.code.Symbol.*; 1.13 import com.sun.tools.javac.jvm.*; 1.14 import com.sun.tools.javac.tree.*; 1.15 -import com.sun.tools.javac.api.Formattable.LocalizedString; 1.16 -import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 1.17 +import com.sun.tools.javac.tree.JCTree.*; 1.18 +import com.sun.tools.javac.util.*; 1.19 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 1.20 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.21 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 1.22 1.23 -import com.sun.tools.javac.code.Type.*; 1.24 -import com.sun.tools.javac.code.Symbol.*; 1.25 -import com.sun.tools.javac.tree.JCTree.*; 1.26 +import java.util.Arrays; 1.27 +import java.util.Collection; 1.28 +import java.util.EnumSet; 1.29 +import java.util.HashMap; 1.30 +import java.util.HashSet; 1.31 +import java.util.LinkedHashMap; 1.32 +import java.util.Map; 1.33 +import java.util.Set; 1.34 + 1.35 +import javax.lang.model.element.ElementVisitor; 1.36 1.37 import static com.sun.tools.javac.code.Flags.*; 1.38 import static com.sun.tools.javac.code.Kinds.*; 1.39 import static com.sun.tools.javac.code.TypeTags.*; 1.40 -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 1.41 -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 1.42 -import javax.lang.model.element.ElementVisitor; 1.43 - 1.44 -import java.util.Map; 1.45 -import java.util.Set; 1.46 -import java.util.HashMap; 1.47 -import java.util.HashSet; 1.48 +import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 1.49 1.50 /** Helper class for name resolution, used mostly by the attribution phase. 1.51 * 1.52 @@ -73,9 +77,45 @@ 1.53 public final boolean varargsEnabled; // = source.allowVarargs(); 1.54 public final boolean allowMethodHandles; 1.55 private final boolean debugResolve; 1.56 + final EnumSet<VerboseResolutionMode> verboseResolutionMode; 1.57 1.58 Scope polymorphicSignatureScope; 1.59 1.60 + enum VerboseResolutionMode { 1.61 + SUCCESS("success"), 1.62 + FAILURE("failure"), 1.63 + APPLICABLE("applicable"), 1.64 + INAPPLICABLE("inapplicable"), 1.65 + DEFERRED_INST("deferred-inference"), 1.66 + PREDEF("predef"), 1.67 + OBJECT_INIT("object-init"), 1.68 + INTERNAL("internal"); 1.69 + 1.70 + String opt; 1.71 + 1.72 + private VerboseResolutionMode(String opt) { 1.73 + this.opt = opt; 1.74 + } 1.75 + 1.76 + static EnumSet<VerboseResolutionMode> getVerboseResolutionMode(Options opts) { 1.77 + String s = opts.get("verboseResolution"); 1.78 + EnumSet<VerboseResolutionMode> res = EnumSet.noneOf(VerboseResolutionMode.class); 1.79 + if (s == null) return res; 1.80 + if (s.contains("all")) { 1.81 + res = EnumSet.allOf(VerboseResolutionMode.class); 1.82 + } 1.83 + Collection<String> args = Arrays.asList(s.split(",")); 1.84 + for (VerboseResolutionMode mode : values()) { 1.85 + if (args.contains(mode.opt)) { 1.86 + res.add(mode); 1.87 + } else if (args.contains("-" + mode.opt)) { 1.88 + res.remove(mode); 1.89 + } 1.90 + } 1.91 + return res; 1.92 + } 1.93 + } 1.94 + 1.95 public static Resolve instance(Context context) { 1.96 Resolve instance = context.get(resolveKey); 1.97 if (instance == null) 1.98 @@ -111,6 +151,7 @@ 1.99 varargsEnabled = source.allowVarargs(); 1.100 Options options = Options.instance(context); 1.101 debugResolve = options.isSet("debugresolve"); 1.102 + verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 1.103 Target target = Target.instance(context); 1.104 allowMethodHandles = target.hasMethodHandles(); 1.105 polymorphicSignatureScope = new Scope(syms.noSymbol); 1.106 @@ -684,9 +725,11 @@ 1.107 if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; 1.108 Assert.check(sym.kind < AMBIGUOUS); 1.109 try { 1.110 - rawInstantiate(env, site, sym, argtypes, typeargtypes, 1.111 + Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes, 1.112 allowBoxing, useVarargs, Warner.noWarnings); 1.113 + if (!operator) addVerboseApplicableCandidateDiag(sym ,mt); 1.114 } catch (InapplicableMethodException ex) { 1.115 + if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic()); 1.116 switch (bestSoFar.kind) { 1.117 case ABSENT_MTH: 1.118 return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); 1.119 @@ -709,6 +752,34 @@ 1.120 : mostSpecific(sym, bestSoFar, env, site, 1.121 allowBoxing && operator, useVarargs); 1.122 } 1.123 + //where 1.124 + void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) { 1.125 + if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) 1.126 + return; 1.127 + 1.128 + JCDiagnostic subDiag = null; 1.129 + if (inst.getReturnType().tag == FORALL) { 1.130 + Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(), 1.131 + ((ForAll)inst.getReturnType()).qtype); 1.132 + subDiag = diags.fragment("partial.inst.sig", diagType); 1.133 + } else if (sym.type.tag == FORALL) { 1.134 + subDiag = diags.fragment("full.inst.sig", inst.asMethodType()); 1.135 + } 1.136 + 1.137 + String key = subDiag == null ? 1.138 + "applicable.method.found" : 1.139 + "applicable.method.found.1"; 1.140 + 1.141 + verboseResolutionCandidateDiags.put(sym, 1.142 + diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag)); 1.143 + } 1.144 + 1.145 + void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) { 1.146 + if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE)) 1.147 + return; 1.148 + verboseResolutionCandidateDiags.put(sym, 1.149 + diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag)); 1.150 + } 1.151 1.152 /* Return the most specific of the two methods for a call, 1.153 * given that both are accessible and applicable. 1.154 @@ -906,8 +977,9 @@ 1.155 boolean allowBoxing, 1.156 boolean useVarargs, 1.157 boolean operator) { 1.158 + verboseResolutionCandidateDiags.clear(); 1.159 Symbol bestSoFar = methodNotFound; 1.160 - return findMethod(env, 1.161 + bestSoFar = findMethod(env, 1.162 site, 1.163 name, 1.164 argtypes, 1.165 @@ -919,6 +991,8 @@ 1.166 useVarargs, 1.167 operator, 1.168 new HashSet<TypeSymbol>()); 1.169 + reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar); 1.170 + return bestSoFar; 1.171 } 1.172 // where 1.173 private Symbol findMethod(Env<AttrContext> env, 1.174 @@ -976,6 +1050,37 @@ 1.175 } 1.176 return bestSoFar; 1.177 } 1.178 + //where 1.179 + void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 1.180 + boolean success = bestSoFar.kind < ERRONEOUS; 1.181 + 1.182 + if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 1.183 + return; 1.184 + } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 1.185 + return; 1.186 + } 1.187 + 1.188 + if (bestSoFar.name == names.init && 1.189 + bestSoFar.owner == syms.objectType.tsym && 1.190 + !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 1.191 + return; //skip diags for Object constructor resolution 1.192 + } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 1.193 + return; //skip spurious diags for predef symbols (i.e. operators) 1.194 + } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 1.195 + return; 1.196 + } 1.197 + 1.198 + int pos = 0; 1.199 + for (Symbol s : verboseResolutionCandidateDiags.keySet()) { 1.200 + if (s == bestSoFar) break; 1.201 + pos++; 1.202 + } 1.203 + String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 1.204 + JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep, 1.205 + methodArguments(argtypes), methodArguments(typeargtypes)); 1.206 + JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()]))); 1.207 + log.report(d); 1.208 + } 1.209 1.210 /** Find unqualified method matching given name, type and value arguments. 1.211 * @param env The current environment. 1.212 @@ -1544,12 +1649,19 @@ 1.213 Type site, Name name, 1.214 List<Type> argtypes, 1.215 List<Type> typeargtypes) { 1.216 - Symbol sym = resolveQualifiedMethod( 1.217 - pos, env, site.tsym, site, name, argtypes, typeargtypes); 1.218 - if (sym.kind == MTH) return (MethodSymbol)sym; 1.219 - else throw new FatalError( 1.220 - diags.fragment("fatal.err.cant.locate.meth", 1.221 - name)); 1.222 + boolean prevInternal = internalResolution; 1.223 + try { 1.224 + internalResolution = true; 1.225 + Symbol sym = resolveQualifiedMethod( 1.226 + pos, env, site.tsym, site, name, argtypes, typeargtypes); 1.227 + if (sym.kind == MTH) return (MethodSymbol)sym; 1.228 + else throw new FatalError( 1.229 + diags.fragment("fatal.err.cant.locate.meth", 1.230 + name)); 1.231 + } 1.232 + finally { 1.233 + internalResolution = prevInternal; 1.234 + } 1.235 } 1.236 1.237 /** Resolve constructor. 1.238 @@ -1830,7 +1942,7 @@ 1.239 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); 1.240 1.241 public Object methodArguments(List<Type> argtypes) { 1.242 - return argtypes.isEmpty() ? noArgs : argtypes; 1.243 + return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes; 1.244 } 1.245 1.246 /** 1.247 @@ -2377,10 +2489,15 @@ 1.248 private Map<MethodResolutionPhase, Symbol> methodResolutionCache = 1.249 new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length); 1.250 1.251 + private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags = 1.252 + new LinkedHashMap<Symbol, JCDiagnostic>(); 1.253 + 1.254 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 1.255 1.256 private MethodResolutionPhase currentStep = null; 1.257 1.258 + private boolean internalResolution = false; 1.259 + 1.260 private MethodResolutionPhase firstErroneousResolutionPhase() { 1.261 MethodResolutionPhase bestSoFar = BASIC; 1.262 Symbol sym = methodNotFound;