check function type's parameters/return type accessibility (IDEA-181036)

This commit is contained in:
Anna.Kozlova
2017-10-25 19:50:25 +02:00
parent c415cde83e
commit f4166d3f05
3 changed files with 35 additions and 4 deletions
@@ -334,7 +334,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
.descriptionAndTooltip(notFunctionalMessage).create());
}
else {
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType, true);
}
}
else if (LambdaUtil.getFunctionalInterfaceType(expression, true) != null) {
@@ -1372,7 +1372,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
if (!myHolder.hasErrorResults()) {
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType, true);
}
if (!myHolder.hasErrorResults()) {
String errorMessage = PsiMethodReferenceUtil.checkMethodReferenceContext(expression);
@@ -1474,7 +1474,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
// 15.13 | 15.27
// It is a compile-time error if any class or interface mentioned by either U or the function type of U
// is not accessible from the class or interface in which the method reference expression appears.
private void checkFunctionalInterfaceTypeAccessible(@NotNull PsiFunctionalExpression expression, PsiType functionalInterfaceType) {
private boolean checkFunctionalInterfaceTypeAccessible(@NotNull PsiFunctionalExpression expression, PsiType functionalInterfaceType,
boolean checkFunctionalTypeSignature) {
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
PsiClass psiClass = resolveResult.getElement();
if (psiClass != null) {
@@ -1486,13 +1487,25 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (problem.second != null) {
problem.second.forEach(fix -> QuickFixAction.registerQuickFixAction(info, fix));
}
return true;
}
else {
for (PsiType type : resolveResult.getSubstitutor().getSubstitutionMap().values()) {
checkFunctionalInterfaceTypeAccessible(expression, type);
if (checkFunctionalInterfaceTypeAccessible(expression, type, false)) return true;
}
PsiMethod psiMethod = checkFunctionalTypeSignature ? LambdaUtil.getFunctionalInterfaceMethod(resolveResult) : null;
if (psiMethod != null) {
PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(psiMethod, resolveResult);
for (PsiParameter parameter : psiMethod.getParameterList().getParameters()) {
if (checkFunctionalInterfaceTypeAccessible(expression, substitutor.substitute(parameter.getType()), false)) return true;
}
if (checkFunctionalInterfaceTypeAccessible(expression, substitutor.substitute(psiMethod.getReturnType()), false)) return true;
}
}
}
return false;
}
@Override
@@ -0,0 +1,9 @@
package p;
import test.*;
class Test {
{
I i = <error descr="'test.A' is not public in 'test'. Cannot be accessed from outside package">(a) -> {}</error>;
J j = <error descr="'test.A' is not public in 'test'. Cannot be accessed from outside package">() -> null</error>;
}
}
@@ -48,6 +48,15 @@ public class LightAdvHighlightingFixtureTest extends LightCodeInsightFixtureTest
assertNull(ReferencesSearch.search(aClass).findFirst());
}
public void testInaccessibleFunctionalTypeParameter() {
myFixture.addClass("package test; class A {}");
myFixture.addClass("package test; public interface I { void m(A a);}");
myFixture.addClass("package test; public interface J { A m();}");
myFixture.configureByFile(getTestName(false) + ".java");
myFixture.checkHighlighting();
}
public void testBoundsPromotionWithCapturedWildcards() {
myFixture.addClass("package a; public interface Provider<A> {}");
myFixture.addClass("package b; public interface Provider<B> {}");