lambda/method refs: check functional interface accessibility

This commit is contained in:
anna
2013-02-20 20:32:26 +01:00
parent 9634bb390e
commit a82225975a
4 changed files with 41 additions and 5 deletions

View File

@@ -231,7 +231,7 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
private static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiJavaCodeReferenceElement place) {
private static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiElement place) {
if (place instanceof PsiReferenceExpression) {
// check for package local classes in the middle
PsiReferenceExpression expression = (PsiReferenceExpression)place;
@@ -1440,12 +1440,12 @@ public class HighlightUtil extends HighlightUtilBase {
}
@NotNull
static String buildProblemWithAccessDescription(@NotNull final PsiJavaCodeReferenceElement reference, @NotNull final JavaResolveResult result) {
static String buildProblemWithAccessDescription(@NotNull final PsiElement reference, @NotNull final JavaResolveResult result) {
return buildProblemWithAccessDescription(reference, result, result.getElement());
}
@NotNull
static String buildProblemWithAccessDescription(@NotNull final PsiJavaCodeReferenceElement reference,
static String buildProblemWithAccessDescription(@NotNull final PsiElement reference,
@NotNull final JavaResolveResult result,
@NotNull final PsiElement resolved) {
assert resolved instanceof PsiModifierListOwner : resolved;

View File

@@ -268,7 +268,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(result);
}
else {
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
if (interfaceMethod != null) {
final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters();
final PsiParameter[] lambdaParameters = expression.getParameterList().getParameters();
@@ -279,7 +280,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(result);
}
else {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
for (int i = 0; i < lambdaParameters.length; i++) {
PsiParameter lambdaParameter = lambdaParameters[i];
if (!TypeConversionUtil.isAssignable(lambdaParameter.getType(),
@@ -293,6 +293,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
}
if (!myHolder.hasErrorResults()) {
final PsiClass samClass = resolveResult.getElement();
if (!PsiUtil.isAccessible(samClass, expression, null)) {
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
.descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create());
}
}
}
}
}
@@ -1056,6 +1063,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
}
if (!myHolder.hasErrorResults()) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
final PsiClass psiClass = resolveResult.getElement();
if (psiClass != null && !PsiUtil.isAccessible(psiClass, expression, null)) {
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
.descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create());
}
}
}
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, expression.getTextRange()));

View File

@@ -0,0 +1,17 @@
class Outer {
private interface Inner {
void m();
}
void m(Inner i) {}
}
class Usage {
void test(Outer outer) {
outer.m(<error descr="'Outer.Inner' has private access in 'Outer'">() -> {}</error>);
outer.m(<error descr="'Outer.Inner' has private access in 'Outer'">this::foo</error>);
}
void foo() {}
}

View File

@@ -216,6 +216,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testCheckFunctionalInterfaceAccess() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(false);
}