279
280 /** An environment is "static" if its static level is greater than
281 * the one of its outer environment
282 */
283 protected static boolean isStatic(Env<AttrContext> env) {
284 return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel;
285 }
286
287 /** An environment is an "initializer" if it is a constructor or
288 * an instance initializer.
289 */
290 static boolean isInitializer(Env<AttrContext> env) {
291 Symbol owner = env.info.scope.owner;
292 return owner.isConstructor() ||
293 owner.owner.kind == TYP &&
294 (owner.kind == VAR ||
295 owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
296 (owner.flags() & STATIC) == 0;
297 }
298
299 /** Is class accessible in given evironment?
300 * @param env The current environment.
301 * @param c The class whose accessibility is checked.
302 */
303 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) {
304 return isAccessible(env, c, false);
305 }
306
307 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) {
308
309 /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor
310 to refer to an inaccessible type
311 */
312 if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0)
313 return true;
314
315 if (env.info.visitingServiceImplementation &&
316 env.toplevel.modle == c.packge().modle) {
317 return true;
318 }
319
3207 }
3208 }
3209 };
3210
3211 /**
3212 * This chooser implements the selection strategy used during an arity-based lookup; this logic
3213 * is described in JLS SE 8 (15.12.2.1).
3214 */
3215 ReferenceChooser structuralReferenceChooser = new ReferenceChooser() {
3216
3217 @Override
3218 ReferenceLookupResult boundResult(ReferenceLookupResult boundRes) {
3219 return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ?
3220 boundRes : //the search has at least one applicable non-static method
3221 ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.sym, false));
3222 }
3223
3224 @Override
3225 ReferenceLookupResult unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) {
3226 if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) {
3227 //the first serach has at least one applicable static method
3228 return boundRes;
3229 } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) {
3230 //the second search has at least one applicable non-static method
3231 return unboundRes;
3232 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) {
3233 //either the first search produces a non-static method, or second search produces
3234 //a non-static method (error recovery)
3235 return ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.isSuccess() ?
3236 boundRes.sym : unboundRes.sym, true));
3237 } else {
3238 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery)
3239 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ?
3240 unboundRes : boundRes;
3241 }
3242 }
3243 };
3244
3245 /**
3246 * Helper for defining custom method-like lookup logic; a lookup helper
3247 * provides hooks for (i) the actual lookup logic and (ii) accessing the
4570
4571 /**
4572 * Helper class for method resolution diagnostic simplification.
4573 * Certain resolution diagnostic are rewritten as simpler diagnostic
4574 * where the enclosing resolution diagnostic (i.e. 'inapplicable method')
4575 * is stripped away, as it doesn't carry additional info. The logic
4576 * for matching a given diagnostic is given in terms of a template
4577 * hierarchy: a diagnostic template can be specified programmatically,
4578 * so that only certain diagnostics are matched. Each templete is then
4579 * associated with a rewriter object that carries out the task of rewtiting
4580 * the diagnostic to a simpler one.
4581 */
4582 static class MethodResolutionDiagHelper {
4583
4584 /**
4585 * A diagnostic rewriter transforms a method resolution diagnostic
4586 * into a simpler one
4587 */
4588 interface DiagnosticRewriter {
4589 JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
4590 DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
4591 DiagnosticType preferredKind, JCDiagnostic d);
4592 }
4593
4594 /**
4595 * A diagnostic template is made up of two ingredients: (i) a regular
4596 * expression for matching a diagnostic key and (ii) a list of sub-templates
4597 * for matching diagnostic arguments.
4598 */
4599 static class Template {
4600
4601 /** regex used to match diag key */
4602 String regex;
4603
4604 /** templates used to match diagnostic args */
4605 Template[] subTemplates;
4606
4607 Template(String key, Template... subTemplates) {
4608 this.regex = key;
4609 this.subTemplates = subTemplates;
4610 }
4626 }
4627 }
4628 return true;
4629 }
4630 }
4631
4632 /**
4633 * Common rewriter for all argument mismatch simplifications.
4634 */
4635 static class ArgMismatchRewriter implements DiagnosticRewriter {
4636
4637 /** the index of the subdiagnostic to be used as primary. */
4638 int causeIndex;
4639
4640 public ArgMismatchRewriter(int causeIndex) {
4641 this.causeIndex = causeIndex;
4642 }
4643
4644 @Override
4645 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
4646 DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
4647 DiagnosticType preferredKind, JCDiagnostic d) {
4648 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex];
4649 DiagnosticPosition pos = d.getDiagnosticPosition();
4650 if (pos == null) {
4651 pos = preferedPos;
4652 }
4653 return diags.create(preferredKind, preferredSource, pos,
4654 "prob.found.req", cause);
4655 }
4656 }
4657
4658 /** a dummy template that match any diagnostic argument */
4659 static final Template skip = new Template("") {
4660 @Override
4661 boolean matches(Object d) {
4662 return true;
4663 }
4664 };
4665
4666 /** template for matching inference-free arguments mismatch failures */
4667 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip);
4668
4669 /** template for matching inference related arguments mismatch failures */
4670 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) {
4671 @Override
|
279
280 /** An environment is "static" if its static level is greater than
281 * the one of its outer environment
282 */
283 protected static boolean isStatic(Env<AttrContext> env) {
284 return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel;
285 }
286
287 /** An environment is an "initializer" if it is a constructor or
288 * an instance initializer.
289 */
290 static boolean isInitializer(Env<AttrContext> env) {
291 Symbol owner = env.info.scope.owner;
292 return owner.isConstructor() ||
293 owner.owner.kind == TYP &&
294 (owner.kind == VAR ||
295 owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
296 (owner.flags() & STATIC) == 0;
297 }
298
299 /** Is class accessible in given environment?
300 * @param env The current environment.
301 * @param c The class whose accessibility is checked.
302 */
303 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) {
304 return isAccessible(env, c, false);
305 }
306
307 public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) {
308
309 /* 15.9.5.1: Note that it is possible for the signature of the anonymous constructor
310 to refer to an inaccessible type
311 */
312 if (env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0)
313 return true;
314
315 if (env.info.visitingServiceImplementation &&
316 env.toplevel.modle == c.packge().modle) {
317 return true;
318 }
319
3207 }
3208 }
3209 };
3210
3211 /**
3212 * This chooser implements the selection strategy used during an arity-based lookup; this logic
3213 * is described in JLS SE 8 (15.12.2.1).
3214 */
3215 ReferenceChooser structuralReferenceChooser = new ReferenceChooser() {
3216
3217 @Override
3218 ReferenceLookupResult boundResult(ReferenceLookupResult boundRes) {
3219 return (!boundRes.isSuccess() || !boundRes.hasKind(StaticKind.STATIC)) ?
3220 boundRes : //the search has at least one applicable non-static method
3221 ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.sym, false));
3222 }
3223
3224 @Override
3225 ReferenceLookupResult unboundResult(ReferenceLookupResult boundRes, ReferenceLookupResult unboundRes) {
3226 if (boundRes.isSuccess() && !boundRes.hasKind(StaticKind.NON_STATIC)) {
3227 //the first search has at least one applicable static method
3228 return boundRes;
3229 } else if (unboundRes.isSuccess() && !unboundRes.hasKind(StaticKind.STATIC)) {
3230 //the second search has at least one applicable non-static method
3231 return unboundRes;
3232 } else if (boundRes.isSuccess() || unboundRes.isSuccess()) {
3233 //either the first search produces a non-static method, or second search produces
3234 //a non-static method (error recovery)
3235 return ReferenceLookupResult.error(new BadMethodReferenceError(boundRes.isSuccess() ?
3236 boundRes.sym : unboundRes.sym, true));
3237 } else {
3238 //both searches fail to produce a result - pick 'better' error using heuristics (error recovery)
3239 return (boundRes.canIgnore() && !unboundRes.canIgnore()) ?
3240 unboundRes : boundRes;
3241 }
3242 }
3243 };
3244
3245 /**
3246 * Helper for defining custom method-like lookup logic; a lookup helper
3247 * provides hooks for (i) the actual lookup logic and (ii) accessing the
4570
4571 /**
4572 * Helper class for method resolution diagnostic simplification.
4573 * Certain resolution diagnostic are rewritten as simpler diagnostic
4574 * where the enclosing resolution diagnostic (i.e. 'inapplicable method')
4575 * is stripped away, as it doesn't carry additional info. The logic
4576 * for matching a given diagnostic is given in terms of a template
4577 * hierarchy: a diagnostic template can be specified programmatically,
4578 * so that only certain diagnostics are matched. Each templete is then
4579 * associated with a rewriter object that carries out the task of rewtiting
4580 * the diagnostic to a simpler one.
4581 */
4582 static class MethodResolutionDiagHelper {
4583
4584 /**
4585 * A diagnostic rewriter transforms a method resolution diagnostic
4586 * into a simpler one
4587 */
4588 interface DiagnosticRewriter {
4589 JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
4590 DiagnosticPosition preferredPos, DiagnosticSource preferredSource,
4591 DiagnosticType preferredKind, JCDiagnostic d);
4592 }
4593
4594 /**
4595 * A diagnostic template is made up of two ingredients: (i) a regular
4596 * expression for matching a diagnostic key and (ii) a list of sub-templates
4597 * for matching diagnostic arguments.
4598 */
4599 static class Template {
4600
4601 /** regex used to match diag key */
4602 String regex;
4603
4604 /** templates used to match diagnostic args */
4605 Template[] subTemplates;
4606
4607 Template(String key, Template... subTemplates) {
4608 this.regex = key;
4609 this.subTemplates = subTemplates;
4610 }
4626 }
4627 }
4628 return true;
4629 }
4630 }
4631
4632 /**
4633 * Common rewriter for all argument mismatch simplifications.
4634 */
4635 static class ArgMismatchRewriter implements DiagnosticRewriter {
4636
4637 /** the index of the subdiagnostic to be used as primary. */
4638 int causeIndex;
4639
4640 public ArgMismatchRewriter(int causeIndex) {
4641 this.causeIndex = causeIndex;
4642 }
4643
4644 @Override
4645 public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
4646 DiagnosticPosition preferredPos, DiagnosticSource preferredSource,
4647 DiagnosticType preferredKind, JCDiagnostic d) {
4648 JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex];
4649 DiagnosticPosition pos = d.getDiagnosticPosition();
4650 if (pos == null) {
4651 pos = preferredPos;
4652 }
4653 return diags.create(preferredKind, preferredSource, pos,
4654 "prob.found.req", cause);
4655 }
4656 }
4657
4658 /** a dummy template that match any diagnostic argument */
4659 static final Template skip = new Template("") {
4660 @Override
4661 boolean matches(Object d) {
4662 return true;
4663 }
4664 };
4665
4666 /** template for matching inference-free arguments mismatch failures */
4667 static final Template argMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip);
4668
4669 /** template for matching inference related arguments mismatch failures */
4670 static final Template inferArgMismatchTemplate = new Template(MethodCheckDiag.ARG_MISMATCH.regex(), skip, skip) {
4671 @Override
|