src/share/classes/com/sun/tools/javac/comp/Resolve.java

changeset 1114
05814303a056
parent 1110
366c233eb838
child 1127
ca49d50318dc
     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;

mercurial