langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 17582 4079713129dd
parent 16975 124c8436d59c
child 17804 6bed8a263318
equal deleted inserted replaced
17581:69b191cb1d7e 17582:4079713129dd
    35 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
    35 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
    36 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
    36 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
    37 import com.sun.tools.javac.comp.Infer.InferenceContext;
    37 import com.sun.tools.javac.comp.Infer.InferenceContext;
    38 import com.sun.tools.javac.comp.Infer.FreeTypeListener;
    38 import com.sun.tools.javac.comp.Infer.FreeTypeListener;
    39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
    39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
       
    40 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.DiagnosticRewriter;
       
    41 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template;
    40 import com.sun.tools.javac.jvm.*;
    42 import com.sun.tools.javac.jvm.*;
       
    43 import com.sun.tools.javac.main.Option;
    41 import com.sun.tools.javac.tree.*;
    44 import com.sun.tools.javac.tree.*;
    42 import com.sun.tools.javac.tree.JCTree.*;
    45 import com.sun.tools.javac.tree.JCTree.*;
    43 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
    46 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
    44 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
    47 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
    45 import com.sun.tools.javac.util.*;
    48 import com.sun.tools.javac.util.*;
    92     public final boolean varargsEnabled; // = source.allowVarargs();
    95     public final boolean varargsEnabled; // = source.allowVarargs();
    93     public final boolean allowMethodHandles;
    96     public final boolean allowMethodHandles;
    94     public final boolean allowDefaultMethods;
    97     public final boolean allowDefaultMethods;
    95     public final boolean allowStructuralMostSpecific;
    98     public final boolean allowStructuralMostSpecific;
    96     private final boolean debugResolve;
    99     private final boolean debugResolve;
       
   100     private final boolean compactMethodDiags;
    97     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
   101     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
    98 
   102 
    99     Scope polymorphicSignatureScope;
   103     Scope polymorphicSignatureScope;
   100 
   104 
   101     protected Resolve(Context context) {
   105     protected Resolve(Context context) {
   122         Source source = Source.instance(context);
   126         Source source = Source.instance(context);
   123         boxingEnabled = source.allowBoxing();
   127         boxingEnabled = source.allowBoxing();
   124         varargsEnabled = source.allowVarargs();
   128         varargsEnabled = source.allowVarargs();
   125         Options options = Options.instance(context);
   129         Options options = Options.instance(context);
   126         debugResolve = options.isSet("debugresolve");
   130         debugResolve = options.isSet("debugresolve");
       
   131         compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
       
   132                 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics");
   127         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
   133         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
   128         Target target = Target.instance(context);
   134         Target target = Target.instance(context);
   129         allowMethodHandles = target.hasMethodHandles();
   135         allowMethodHandles = target.hasMethodHandles();
   130         allowDefaultMethods = source.allowDefaultMethods();
   136         allowDefaultMethods = source.allowDefaultMethods();
   131         allowStructuralMostSpecific = source.allowStructuralMostSpecific();
   137         allowStructuralMostSpecific = source.allowStructuralMostSpecific();
   659 
   665 
   660         MethodCheckDiag(String basicKey, String inferKey) {
   666         MethodCheckDiag(String basicKey, String inferKey) {
   661             this.basicKey = basicKey;
   667             this.basicKey = basicKey;
   662             this.inferKey = inferKey;
   668             this.inferKey = inferKey;
   663         }
   669         }
       
   670 
       
   671         String regex() {
       
   672             return String.format("([a-z]*\\.)*(%s|%s)", basicKey, inferKey);
       
   673         }
   664     }
   674     }
   665 
   675 
   666     /**
   676     /**
   667      * Dummy method check object. All methods are deemed applicable, regardless
   677      * Dummy method check object. All methods are deemed applicable, regardless
   668      * of their formal parameter types.
   678      * of their formal parameter types.
   689                                     List<Type> argtypes,
   699                                     List<Type> argtypes,
   690                                     List<Type> formals,
   700                                     List<Type> formals,
   691                                     Warner warn) {
   701                                     Warner warn) {
   692             //should we expand formals?
   702             //should we expand formals?
   693             boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
   703             boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
       
   704             List<JCExpression> trees = TreeInfo.args(env.tree);
   694 
   705 
   695             //inference context used during this method check
   706             //inference context used during this method check
   696             InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
   707             InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
   697 
   708 
   698             Type varargsFormal = useVarargs ? formals.last() : null;
   709             Type varargsFormal = useVarargs ? formals.last() : null;
   699 
   710 
   700             if (varargsFormal == null &&
   711             if (varargsFormal == null &&
   701                     argtypes.size() != formals.size()) {
   712                     argtypes.size() != formals.size()) {
   702                 reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
   713                 reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
   703             }
   714             }
   704 
   715 
   705             while (argtypes.nonEmpty() && formals.head != varargsFormal) {
   716             while (argtypes.nonEmpty() && formals.head != varargsFormal) {
   706                 checkArg(false, argtypes.head, formals.head, deferredAttrContext, warn);
   717                 DiagnosticPosition pos = trees != null ? trees.head : null;
       
   718                 checkArg(pos, false, argtypes.head, formals.head, deferredAttrContext, warn);
   707                 argtypes = argtypes.tail;
   719                 argtypes = argtypes.tail;
   708                 formals = formals.tail;
   720                 formals = formals.tail;
       
   721                 trees = trees != null ? trees.tail : trees;
   709             }
   722             }
   710 
   723 
   711             if (formals.head != varargsFormal) {
   724             if (formals.head != varargsFormal) {
   712                 reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
   725                 reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
   713             }
   726             }
   714 
   727 
   715             if (useVarargs) {
   728             if (useVarargs) {
   716                 //note: if applicability check is triggered by most specific test,
   729                 //note: if applicability check is triggered by most specific test,
   717                 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
   730                 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
   718                 final Type elt = types.elemtype(varargsFormal);
   731                 final Type elt = types.elemtype(varargsFormal);
   719                 while (argtypes.nonEmpty()) {
   732                 while (argtypes.nonEmpty()) {
   720                     checkArg(true, argtypes.head, elt, deferredAttrContext, warn);
   733                     DiagnosticPosition pos = trees != null ? trees.head : null;
       
   734                     checkArg(pos, true, argtypes.head, elt, deferredAttrContext, warn);
   721                     argtypes = argtypes.tail;
   735                     argtypes = argtypes.tail;
       
   736                     trees = trees != null ? trees.tail : trees;
   722                 }
   737                 }
   723             }
   738             }
   724         }
   739         }
   725 
   740 
   726         /**
   741         /**
   727          * Does the actual argument conforms to the corresponding formal?
   742          * Does the actual argument conforms to the corresponding formal?
   728          */
   743          */
   729         abstract void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn);
   744         abstract void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn);
   730 
   745 
   731         protected void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
   746         protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
   732             boolean inferDiag = inferenceContext != infer.emptyContext;
   747             boolean inferDiag = inferenceContext != infer.emptyContext;
   733             InapplicableMethodException ex = inferDiag ?
   748             InapplicableMethodException ex = inferDiag ?
   734                     infer.inferenceException : inapplicableMethodException;
   749                     infer.inferenceException : inapplicableMethodException;
   735             if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
   750             if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
   736                 Object[] args2 = new Object[args.length + 1];
   751                 Object[] args2 = new Object[args.length + 1];
   737                 System.arraycopy(args, 0, args2, 1, args.length);
   752                 System.arraycopy(args, 0, args2, 1, args.length);
   738                 args2[0] = inferenceContext.inferenceVars();
   753                 args2[0] = inferenceContext.inferenceVars();
   739                 args = args2;
   754                 args = args2;
   740             }
   755             }
   741             throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
   756             String key = inferDiag ? diag.inferKey : diag.basicKey;
       
   757             throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
   742         }
   758         }
   743 
   759 
   744         public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
   760         public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
   745             return nilMethodCheck;
   761             return nilMethodCheck;
   746         }
   762         }
   750      * Arity-based method check. A method is applicable if the number of actuals
   766      * Arity-based method check. A method is applicable if the number of actuals
   751      * supplied conforms to the method signature.
   767      * supplied conforms to the method signature.
   752      */
   768      */
   753     MethodCheck arityMethodCheck = new AbstractMethodCheck() {
   769     MethodCheck arityMethodCheck = new AbstractMethodCheck() {
   754         @Override
   770         @Override
   755         void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
   771         void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
   756             //do nothing - actual always compatible to formals
   772             //do nothing - actual always compatible to formals
   757         }
   773         }
   758     };
   774     };
   759 
   775 
   760     /**
   776     /**
   776      * A method check handler (see above) is used in order to report errors.
   792      * A method check handler (see above) is used in order to report errors.
   777      */
   793      */
   778     MethodCheck resolveMethodCheck = new AbstractMethodCheck() {
   794     MethodCheck resolveMethodCheck = new AbstractMethodCheck() {
   779 
   795 
   780         @Override
   796         @Override
   781         void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
   797         void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
   782             ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
   798             ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
   783             mresult.check(null, actual);
   799             mresult.check(pos, actual);
   784         }
   800         }
   785 
   801 
   786         @Override
   802         @Override
   787         public void argumentsAcceptable(final Env<AttrContext> env,
   803         public void argumentsAcceptable(final Env<AttrContext> env,
   788                                     DeferredAttrContext deferredAttrContext,
   804                                     DeferredAttrContext deferredAttrContext,
   807                     }
   823                     }
   808                 });
   824                 });
   809             } else {
   825             } else {
   810                 if (!isAccessible(env, t)) {
   826                 if (!isAccessible(env, t)) {
   811                     Symbol location = env.enclClass.sym;
   827                     Symbol location = env.enclClass.sym;
   812                     reportMC(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
   828                     reportMC(env.tree, MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
   813                 }
   829                 }
   814             }
   830             }
   815         }
   831         }
   816 
   832 
   817         private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
   833         private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
   820                 MethodCheckDiag methodDiag = varargsCheck ?
   836                 MethodCheckDiag methodDiag = varargsCheck ?
   821                                  MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
   837                                  MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
   822 
   838 
   823                 @Override
   839                 @Override
   824                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
   840                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
   825                     reportMC(methodDiag, deferredAttrContext.inferenceContext, details);
   841                     reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details);
   826                 }
   842                 }
   827             };
   843             };
   828             return new MethodResultInfo(to, checkContext);
   844             return new MethodResultInfo(to, checkContext);
   829         }
   845         }
   830 
   846 
  3325                 return diags.create(dkind, log.currentSource(), pos,
  3341                 return diags.create(dkind, log.currentSource(), pos,
  3326                         key, name, first, second);
  3342                         key, name, first, second);
  3327             }
  3343             }
  3328             else {
  3344             else {
  3329                 Candidate c = errCandidate();
  3345                 Candidate c = errCandidate();
       
  3346                 if (compactMethodDiags) {
       
  3347                     for (Map.Entry<Template, DiagnosticRewriter> _entry :
       
  3348                             MethodResolutionDiagHelper.rewriters.entrySet()) {
       
  3349                         if (_entry.getKey().matches(c.details)) {
       
  3350                             JCDiagnostic simpleDiag =
       
  3351                                     _entry.getValue().rewriteDiagnostic(diags, pos,
       
  3352                                         log.currentSource(), dkind, c.details);
       
  3353                             simpleDiag.setFlag(DiagnosticFlag.COMPRESSED);
       
  3354                             return simpleDiag;
       
  3355                         }
       
  3356                     }
       
  3357                 }
  3330                 Symbol ws = c.sym.asMemberOf(site, types);
  3358                 Symbol ws = c.sym.asMemberOf(site, types);
  3331                 return diags.create(dkind, log.currentSource(), pos,
  3359                 return diags.create(dkind, log.currentSource(), pos,
  3332                           "cant.apply.symbol",
  3360                           "cant.apply.symbol",
  3333                           kindName(ws),
  3361                           kindName(ws),
  3334                           ws.name == names.init ? ws.owner.name : ws.name,
  3362                           ws.name == names.init ? ws.owner.name : ws.name,
  3373                 Symbol location,
  3401                 Symbol location,
  3374                 Type site,
  3402                 Type site,
  3375                 Name name,
  3403                 Name name,
  3376                 List<Type> argtypes,
  3404                 List<Type> argtypes,
  3377                 List<Type> typeargtypes) {
  3405                 List<Type> typeargtypes) {
  3378             if (!resolveContext.candidates.isEmpty()) {
  3406             Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates();
       
  3407             Map<Symbol, JCDiagnostic> filteredCandidates = filterCandidates(candidatesMap);
       
  3408             if (filteredCandidates.isEmpty()) {
       
  3409                 filteredCandidates = candidatesMap;
       
  3410             }
       
  3411             boolean truncatedDiag = candidatesMap.size() != filteredCandidates.size();
       
  3412             if (filteredCandidates.size() > 1) {
  3379                 JCDiagnostic err = diags.create(dkind,
  3413                 JCDiagnostic err = diags.create(dkind,
       
  3414                         null,
       
  3415                         truncatedDiag ?
       
  3416                             EnumSet.of(DiagnosticFlag.COMPRESSED) :
       
  3417                             EnumSet.noneOf(DiagnosticFlag.class),
  3380                         log.currentSource(),
  3418                         log.currentSource(),
  3381                         pos,
  3419                         pos,
  3382                         "cant.apply.symbols",
  3420                         "cant.apply.symbols",
  3383                         name == names.init ? KindName.CONSTRUCTOR : absentKind(kind),
  3421                         name == names.init ? KindName.CONSTRUCTOR : absentKind(kind),
  3384                         name == names.init ? site.tsym.name : name,
  3422                         name == names.init ? site.tsym.name : name,
  3385                         methodArguments(argtypes));
  3423                         methodArguments(argtypes));
  3386                 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(site));
  3424                 return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(filteredCandidates, site));
       
  3425             } else if (filteredCandidates.size() == 1) {
       
  3426                 JCDiagnostic d =  new InapplicableSymbolError(resolveContext).getDiagnostic(dkind, pos,
       
  3427                     location, site, name, argtypes, typeargtypes);
       
  3428                 if (truncatedDiag) {
       
  3429                     d.setFlag(DiagnosticFlag.COMPRESSED);
       
  3430                 }
       
  3431                 return d;
  3387             } else {
  3432             } else {
  3388                 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
  3433                 return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
  3389                     location, site, name, argtypes, typeargtypes);
  3434                     location, site, name, argtypes, typeargtypes);
  3390             }
  3435             }
  3391         }
  3436         }
  3392 
       
  3393         //where
  3437         //where
  3394         List<JCDiagnostic> candidateDetails(Type site) {
  3438             private Map<Symbol, JCDiagnostic> mapCandidates() {
  3395             Map<Symbol, JCDiagnostic> details = new LinkedHashMap<Symbol, JCDiagnostic>();
  3439                 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<Symbol, JCDiagnostic>();
  3396             for (Candidate c : resolveContext.candidates) {
  3440                 for (Candidate c : resolveContext.candidates) {
  3397                 if (c.isApplicable()) continue;
  3441                     if (c.isApplicable()) continue;
  3398                 JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
  3442                     candidates.put(c.sym, c.details);
  3399                         Kinds.kindName(c.sym),
  3443                 }
  3400                         c.sym.location(site, types),
  3444                 return candidates;
  3401                         c.sym.asMemberOf(site, types),
  3445             }
  3402                         c.details);
  3446 
  3403                 details.put(c.sym, detailDiag);
  3447             Map<Symbol, JCDiagnostic> filterCandidates(Map<Symbol, JCDiagnostic> candidatesMap) {
  3404             }
  3448                 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<Symbol, JCDiagnostic>();
  3405             return List.from(details.values());
  3449                 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) {
  3406         }
  3450                     JCDiagnostic d = _entry.getValue();
       
  3451                     if (!compactMethodDiags ||
       
  3452                             !new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) {
       
  3453                         candidates.put(_entry.getKey(), d);
       
  3454                     }
       
  3455                 }
       
  3456                 return candidates;
       
  3457             }
       
  3458 
       
  3459             private List<JCDiagnostic> candidateDetails(Map<Symbol, JCDiagnostic> candidatesMap, Type site) {
       
  3460                 List<JCDiagnostic> details = List.nil();
       
  3461                 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) {
       
  3462                     Symbol sym = _entry.getKey();
       
  3463                     JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
       
  3464                             Kinds.kindName(sym),
       
  3465                             sym.location(site, types),
       
  3466                             sym.asMemberOf(site, types),
       
  3467                             _entry.getValue());
       
  3468                     details = details.prepend(detailDiag);
       
  3469                 }
       
  3470                 //typically members are visited in reverse order (see Scope)
       
  3471                 //so we need to reverse the candidate list so that candidates
       
  3472                 //conform to source order
       
  3473                 return details;
       
  3474             }
  3407     }
  3475     }
  3408 
  3476 
  3409     /**
  3477     /**
  3410      * An InvalidSymbolError error class indicating that a symbol is not
  3478      * An InvalidSymbolError error class indicating that a symbol is not
  3411      * accessible from a given site
  3479      * accessible from a given site
  3622         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
  3690         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
  3623             return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes);
  3691             return delegatedError.getDiagnostic(dkind, pos, location, site, name, argtypes, typeargtypes);
  3624         }
  3692         }
  3625     }
  3693     }
  3626 
  3694 
       
  3695     /**
       
  3696      * Helper class for method resolution diagnostic simplification.
       
  3697      * Certain resolution diagnostic are rewritten as simpler diagnostic
       
  3698      * where the enclosing resolution diagnostic (i.e. 'inapplicable method')
       
  3699      * is stripped away, as it doesn't carry additional info. The logic
       
  3700      * for matching a given diagnostic is given in terms of a template
       
  3701      * hierarchy: a diagnostic template can be specified programmatically,
       
  3702      * so that only certain diagnostics are matched. Each templete is then
       
  3703      * associated with a rewriter object that carries out the task of rewtiting
       
  3704      * the diagnostic to a simpler one.
       
  3705      */
       
  3706     static class MethodResolutionDiagHelper {
       
  3707 
       
  3708         /**
       
  3709          * A diagnostic rewriter transforms a method resolution diagnostic
       
  3710          * into a simpler one
       
  3711          */
       
  3712         interface DiagnosticRewriter {
       
  3713             JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
       
  3714                     DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
       
  3715                     DiagnosticType preferredKind, JCDiagnostic d);
       
  3716         }
       
  3717 
       
  3718         /**
       
  3719          * A diagnostic template is made up of two ingredients: (i) a regular
       
  3720          * expression for matching a diagnostic key and (ii) a list of sub-templates
       
  3721          * for matching diagnostic arguments.
       
  3722          */
       
  3723         static class Template {
       
  3724 
       
  3725             /** regex used to match diag key */
       
  3726             String regex;
       
  3727 
       
  3728             /** templates used to match diagnostic args */
       
  3729             Template[] subTemplates;
       
  3730 
       
  3731             Template(String key, Template... subTemplates) {
       
  3732                 this.regex = key;
       
  3733                 this.subTemplates = subTemplates;
       
  3734             }
       
  3735 
       
  3736             /**
       
  3737              * Returns true if the regex matches the diagnostic key and if
       
  3738              * all diagnostic arguments are matches by corresponding sub-templates.
       
  3739              */
       
  3740             boolean matches(Object o) {
       
  3741                 JCDiagnostic d = (JCDiagnostic)o;
       
  3742                 Object[] args = d.getArgs();
       
  3743                 if (!d.getCode().matches(regex) ||
       
  3744                         subTemplates.length != d.getArgs().length) {
       
  3745                     return false;
       
  3746                 }
       
  3747                 for (int i = 0; i < args.length ; i++) {
       
  3748                     if (!subTemplates[i].matches(args[i])) {
       
  3749                         return false;
       
  3750                     }
       
  3751                 }
       
  3752                 return true;
       
  3753             }
       
  3754         }
       
  3755 
       
  3756         /** a dummy template that match any diagnostic argument */
       
  3757         static final Template skip = new Template("") {
       
  3758             @Override
       
  3759             boolean matches(Object d) {
       
  3760                 return true;
       
  3761             }
       
  3762         };
       
  3763 
       
  3764         /** rewriter map used for method resolution simplification */
       
  3765         static final Map<Template, DiagnosticRewriter> rewriters =
       
  3766                 new LinkedHashMap<Template, DiagnosticRewriter>();
       
  3767 
       
  3768         static {
       
  3769             String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex();
       
  3770             rewriters.put(new Template(argMismatchRegex, new Template("(.*)(bad.arg.types.in.lambda)", skip, skip)),
       
  3771                     new DiagnosticRewriter() {
       
  3772                 @Override
       
  3773                 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
       
  3774                         DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
       
  3775                         DiagnosticType preferredKind, JCDiagnostic d) {
       
  3776                     return (JCDiagnostic)((JCDiagnostic)d.getArgs()[0]).getArgs()[1];
       
  3777                 }
       
  3778             });
       
  3779 
       
  3780             rewriters.put(new Template(argMismatchRegex, skip),
       
  3781                     new DiagnosticRewriter() {
       
  3782                 @Override
       
  3783                 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
       
  3784                         DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
       
  3785                         DiagnosticType preferredKind, JCDiagnostic d) {
       
  3786                     JCDiagnostic cause = (JCDiagnostic)d.getArgs()[0];
       
  3787                     return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(),
       
  3788                             "prob.found.req", cause);
       
  3789                 }
       
  3790             });
       
  3791         }
       
  3792     }
       
  3793 
  3627     enum MethodResolutionPhase {
  3794     enum MethodResolutionPhase {
  3628         BASIC(false, false),
  3795         BASIC(false, false),
  3629         BOX(true, false),
  3796         BOX(true, false),
  3630         VARARITY(true, true) {
  3797         VARARITY(true, true) {
  3631             @Override
  3798             @Override