37 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; |
37 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; |
38 import com.sun.tools.javac.comp.DeferredAttr.DeferredType; |
38 import com.sun.tools.javac.comp.DeferredAttr.DeferredType; |
39 import com.sun.tools.javac.comp.Infer.InferenceContext; |
39 import com.sun.tools.javac.comp.Infer.InferenceContext; |
40 import com.sun.tools.javac.comp.Infer.FreeTypeListener; |
40 import com.sun.tools.javac.comp.Infer.FreeTypeListener; |
41 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; |
41 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; |
42 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.DiagnosticRewriter; |
|
43 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; |
42 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template; |
44 import com.sun.tools.javac.jvm.*; |
43 import com.sun.tools.javac.jvm.*; |
45 import com.sun.tools.javac.main.Option; |
44 import com.sun.tools.javac.main.Option; |
46 import com.sun.tools.javac.tree.*; |
45 import com.sun.tools.javac.tree.*; |
47 import com.sun.tools.javac.tree.JCTree.*; |
46 import com.sun.tools.javac.tree.JCTree.*; |
53 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
54 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; |
53 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; |
55 |
54 |
56 import java.util.Arrays; |
55 import java.util.Arrays; |
57 import java.util.Collection; |
56 import java.util.Collection; |
58 import java.util.EnumMap; |
|
59 import java.util.EnumSet; |
57 import java.util.EnumSet; |
60 import java.util.Iterator; |
58 import java.util.Iterator; |
61 import java.util.LinkedHashMap; |
59 import java.util.LinkedHashMap; |
62 import java.util.Map; |
60 import java.util.Map; |
|
61 import java.util.function.BiPredicate; |
|
62 import java.util.stream.Stream; |
63 |
63 |
64 import javax.lang.model.element.ElementVisitor; |
64 import javax.lang.model.element.ElementVisitor; |
65 |
65 |
66 import static com.sun.tools.javac.code.Flags.*; |
66 import static com.sun.tools.javac.code.Flags.*; |
67 import static com.sun.tools.javac.code.Flags.BLOCK; |
67 import static com.sun.tools.javac.code.Flags.BLOCK; |
2544 sym = super.access(env, pos, location, sym); |
2544 sym = super.access(env, pos, location, sym); |
2545 } else { |
2545 } else { |
2546 final JCDiagnostic details = sym.kind == WRONG_MTH ? |
2546 final JCDiagnostic details = sym.kind == WRONG_MTH ? |
2547 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : |
2547 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : |
2548 null; |
2548 null; |
2549 sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { |
2549 sym = new DiamondError(sym, currentResolutionContext); |
2550 @Override |
|
2551 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, |
|
2552 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { |
|
2553 String key = details == null ? |
|
2554 "cant.apply.diamond" : |
|
2555 "cant.apply.diamond.1"; |
|
2556 return diags.create(dkind, log.currentSource(), pos, key, |
|
2557 diags.fragment("diamond", site.tsym), details); |
|
2558 } |
|
2559 }; |
|
2560 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); |
2550 sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); |
2561 env.info.pendingResolutionPhase = currentResolutionContext.step; |
2551 env.info.pendingResolutionPhase = currentResolutionContext.step; |
2562 } |
2552 } |
2563 } |
2553 } |
2564 return sym; |
2554 return sym; |
3722 key, name, first, second); |
3712 key, name, first, second); |
3723 } |
3713 } |
3724 else { |
3714 else { |
3725 Pair<Symbol, JCDiagnostic> c = errCandidate(); |
3715 Pair<Symbol, JCDiagnostic> c = errCandidate(); |
3726 if (compactMethodDiags) { |
3716 if (compactMethodDiags) { |
3727 for (Map.Entry<Template, DiagnosticRewriter> _entry : |
3717 JCDiagnostic simpleDiag = |
3728 MethodResolutionDiagHelper.rewriters.entrySet()) { |
3718 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd); |
3729 if (_entry.getKey().matches(c.snd)) { |
3719 if (simpleDiag != null) { |
3730 JCDiagnostic simpleDiag = |
3720 return simpleDiag; |
3731 _entry.getValue().rewriteDiagnostic(diags, pos, |
|
3732 log.currentSource(), dkind, c.snd); |
|
3733 simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); |
|
3734 return simpleDiag; |
|
3735 } |
|
3736 } |
3721 } |
3737 } |
3722 } |
3738 Symbol ws = c.fst.asMemberOf(site, types); |
3723 Symbol ws = c.fst.asMemberOf(site, types); |
3739 return diags.create(dkind, log.currentSource(), pos, |
3724 return diags.create(dkind, log.currentSource(), pos, |
3740 "cant.apply.symbol", |
3725 "cant.apply.symbol", |
3763 return new Pair<>(bestSoFar.sym, bestSoFar.details); |
3748 return new Pair<>(bestSoFar.sym, bestSoFar.details); |
3764 } |
3749 } |
3765 } |
3750 } |
3766 |
3751 |
3767 /** |
3752 /** |
3768 * ResolveError error class indicating that a set of symbols |
3753 * ResolveError error class indicating that a symbol (either methods, constructors or operand) |
3769 * (either methods, constructors or operands) is not applicable |
3754 * is not applicable given an actual arguments/type argument list. |
3770 * given an actual arguments/type argument list. |
|
3771 */ |
3755 */ |
3772 class InapplicableSymbolsError extends InapplicableSymbolError { |
3756 class InapplicableSymbolsError extends InapplicableSymbolError { |
3773 |
3757 |
3774 InapplicableSymbolsError(MethodResolutionContext context) { |
3758 InapplicableSymbolsError(MethodResolutionContext context) { |
3775 super(WRONG_MTHS, "inapplicable symbols", context); |
3759 super(WRONG_MTHS, "inapplicable symbols", context); |
3862 return details; |
3846 return details; |
3863 } |
3847 } |
3864 } |
3848 } |
3865 |
3849 |
3866 /** |
3850 /** |
|
3851 * DiamondError error class indicating that a constructor symbol is not applicable |
|
3852 * given an actual arguments/type argument list using diamond inference. |
|
3853 */ |
|
3854 class DiamondError extends InapplicableSymbolError { |
|
3855 |
|
3856 Symbol sym; |
|
3857 |
|
3858 public DiamondError(Symbol sym, MethodResolutionContext context) { |
|
3859 super(sym.kind, "diamondError", context); |
|
3860 this.sym = sym; |
|
3861 } |
|
3862 |
|
3863 JCDiagnostic getDetails() { |
|
3864 return (sym.kind == WRONG_MTH) ? |
|
3865 ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : |
|
3866 null; |
|
3867 } |
|
3868 |
|
3869 @Override |
|
3870 JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, |
|
3871 Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { |
|
3872 JCDiagnostic details = getDetails(); |
|
3873 if (details != null && compactMethodDiags) { |
|
3874 JCDiagnostic simpleDiag = |
|
3875 MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, details); |
|
3876 if (simpleDiag != null) { |
|
3877 return simpleDiag; |
|
3878 } |
|
3879 } |
|
3880 String key = details == null ? |
|
3881 "cant.apply.diamond" : |
|
3882 "cant.apply.diamond.1"; |
|
3883 return diags.create(dkind, log.currentSource(), pos, key, |
|
3884 diags.fragment("diamond", site.tsym), details); |
|
3885 } |
|
3886 } |
|
3887 |
|
3888 /** |
3867 * An InvalidSymbolError error class indicating that a symbol is not |
3889 * An InvalidSymbolError error class indicating that a symbol is not |
3868 * accessible from a given site |
3890 * accessible from a given site |
3869 */ |
3891 */ |
3870 class AccessError extends InvalidSymbolError { |
3892 class AccessError extends InvalidSymbolError { |
3871 |
3893 |
4144 } |
4166 } |
4145 return true; |
4167 return true; |
4146 } |
4168 } |
4147 } |
4169 } |
4148 |
4170 |
|
4171 /** |
|
4172 * Common rewriter for all argument mismatch simplifications. |
|
4173 */ |
|
4174 static class ArgMismatchRewriter implements DiagnosticRewriter { |
|
4175 |
|
4176 /** the index of the subdiagnostic to be used as primary. */ |
|
4177 int causeIndex; |
|
4178 |
|
4179 public ArgMismatchRewriter(int causeIndex) { |
|
4180 this.causeIndex = causeIndex; |
|
4181 } |
|
4182 |
|
4183 @Override |
|
4184 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, |
|
4185 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, |
|
4186 DiagnosticType preferredKind, JCDiagnostic d) { |
|
4187 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex]; |
|
4188 return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(), |
|
4189 "prob.found.req", cause); |
|
4190 } |
|
4191 } |
|
4192 |
4149 /** a dummy template that match any diagnostic argument */ |
4193 /** a dummy template that match any diagnostic argument */ |
4150 static final Template skip = new Template("") { |
4194 static final Template skip = new Template("") { |
4151 @Override |
4195 @Override |
4152 boolean matches(Object d) { |
4196 boolean matches(Object d) { |
4153 return true; |
4197 return true; |
4154 } |
4198 } |
4155 }; |
4199 }; |
4156 |
4200 |
|
4201 /** template for matching inference-free arguments mismatch failures */ |
|
4202 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip); |
|
4203 |
|
4204 /** template for matching inference related arguments mismatch failures */ |
|
4205 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) { |
|
4206 @Override |
|
4207 boolean matches(Object o) { |
|
4208 if (!super.matches(o)) { |
|
4209 return false; |
|
4210 } |
|
4211 JCDiagnostic d = (JCDiagnostic)o; |
|
4212 @SuppressWarnings("unchecked") |
|
4213 List<Type> tvars = (List<Type>)d.getArgs()[0]; |
|
4214 return !containsAny(d, tvars); |
|
4215 } |
|
4216 |
|
4217 BiPredicate<Object, List<Type>> containsPredicate = (o, ts) -> { |
|
4218 if (o instanceof Type) { |
|
4219 return ((Type)o).containsAny(ts); |
|
4220 } else if (o instanceof JCDiagnostic) { |
|
4221 return containsAny((JCDiagnostic)o, ts); |
|
4222 } else { |
|
4223 return false; |
|
4224 } |
|
4225 }; |
|
4226 |
|
4227 boolean containsAny(JCDiagnostic d, List<Type> ts) { |
|
4228 return Stream.of(d.getArgs()) |
|
4229 .anyMatch(o -> containsPredicate.test(o, ts)); |
|
4230 } |
|
4231 }; |
|
4232 |
4157 /** rewriter map used for method resolution simplification */ |
4233 /** rewriter map used for method resolution simplification */ |
4158 static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>(); |
4234 static final Map<Template, DiagnosticRewriter> rewriters = new LinkedHashMap<>(); |
4159 |
4235 |
4160 static { |
4236 static { |
4161 String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex(); |
4237 rewriters.put(argMismatchTemplate, new ArgMismatchRewriter(0)); |
4162 rewriters.put(new Template(argMismatchRegex, skip), |
4238 rewriters.put(inferArgMismatchTemplate, new ArgMismatchRewriter(1)); |
4163 new DiagnosticRewriter() { |
4239 } |
4164 @Override |
4240 |
4165 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, |
4241 /** |
4166 DiagnosticPosition preferedPos, DiagnosticSource preferredSource, |
4242 * Main entry point for diagnostic rewriting - given a diagnostic, see if any templates matches it, |
4167 DiagnosticType preferredKind, JCDiagnostic d) { |
4243 * and rewrite it accordingly. |
4168 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[0]; |
4244 */ |
4169 return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(), |
4245 static JCDiagnostic rewrite(JCDiagnostic.Factory diags, DiagnosticPosition pos, DiagnosticSource source, |
4170 "prob.found.req", cause); |
4246 DiagnosticType dkind, JCDiagnostic d) { |
4171 } |
4247 for (Map.Entry<Template, DiagnosticRewriter> _entry : rewriters.entrySet()) { |
4172 }); |
4248 if (_entry.getKey().matches(d)) { |
|
4249 JCDiagnostic simpleDiag = |
|
4250 _entry.getValue().rewriteDiagnostic(diags, pos, source, dkind, d); |
|
4251 simpleDiag.setFlag(DiagnosticFlag.COMPRESSED); |
|
4252 return simpleDiag; |
|
4253 } |
|
4254 } |
|
4255 return null; |
4173 } |
4256 } |
4174 } |
4257 } |
4175 |
4258 |
4176 enum MethodResolutionPhase { |
4259 enum MethodResolutionPhase { |
4177 BASIC(false, false), |
4260 BASIC(false, false), |