mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
method reference on getClass: fix method reference constraint
This commit is contained in:
@@ -104,7 +104,7 @@ public class PsiMethodReferenceUtil {
|
||||
final PsiElement resolve = result.getElement();
|
||||
if (resolve instanceof PsiMethod) {
|
||||
containingClass = ((PsiMethod)resolve).getContainingClass();
|
||||
methodReturnType = PsiTypesUtil.patchMethodGetClassReturnType(expression, expression, (PsiMethod)resolve, null, PsiUtil.getLanguageLevel(expression));
|
||||
methodReturnType = PsiTypesUtil.patchMethodGetClassReturnType(expression, (PsiMethod)resolve);
|
||||
if (methodReturnType == null) {
|
||||
methodReturnType = ((PsiMethod)resolve).getReturnType();
|
||||
if (PsiType.VOID.equals(methodReturnType)) {
|
||||
|
||||
@@ -138,6 +138,15 @@ public class PsiTypesUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PsiType patchMethodGetClassReturnType(@NotNull PsiMethodReferenceExpression methodExpression,
|
||||
@NotNull PsiMethod method) {
|
||||
if (isGetClass(method)) {
|
||||
final PsiType qualifierType = PsiMethodReferenceUtil.getQualifierType(methodExpression);
|
||||
return qualifierType != null ? createJavaLangClassType(methodExpression, qualifierType, true) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PsiType patchMethodGetClassReturnType(@NotNull PsiExpression call,
|
||||
@NotNull PsiReferenceExpression methodExpression,
|
||||
@NotNull PsiMethod method,
|
||||
@@ -145,10 +154,6 @@ public class PsiTypesUtil {
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
//JLS3 15.8.2
|
||||
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && isGetClass(method)) {
|
||||
if (methodExpression instanceof PsiMethodReferenceExpression) {
|
||||
final PsiType qualifierType = PsiMethodReferenceUtil.getQualifierType((PsiMethodReferenceExpression)methodExpression);
|
||||
return qualifierType != null ? createJavaLangClassType(methodExpression, qualifierType, true) : null;
|
||||
}
|
||||
PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
PsiType qualifierType = null;
|
||||
final Project project = call.getProject();
|
||||
|
||||
+9
-6
@@ -21,10 +21,7 @@ import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfacePa
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -79,7 +76,6 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
|
||||
PsiSubstitutor psiSubstitutor = getSubstitutor(signature, qualifierResolveResult, applicableMember, applicableMemberContainingClass);
|
||||
|
||||
PsiType applicableMethodReturnType = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getReturnType() : null;
|
||||
int idx = 0;
|
||||
for (PsiTypeParameter param : ((PsiTypeParameterListOwner)applicableMember).getTypeParameters()) {
|
||||
if (idx < typeParameters.length) {
|
||||
@@ -110,6 +106,12 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
return false;
|
||||
}
|
||||
if (!PsiType.VOID.equals(returnType) && returnType != null) {
|
||||
PsiType applicableMethodReturnType = null;
|
||||
if (applicableMember instanceof PsiMethod) {
|
||||
final PsiType getClassReturnType = PsiTypesUtil.patchMethodGetClassReturnType(myExpression, (PsiMethod)applicableMember);
|
||||
applicableMethodReturnType = getClassReturnType != null ? getClassReturnType : ((PsiMethod)applicableMember).getReturnType();
|
||||
}
|
||||
|
||||
if (PsiType.VOID.equals(applicableMethodReturnType)) {
|
||||
session.registerIncompatibleErrorMessage("Incompatible types: expected not void but compile-time declaration for the method reference has void return type");
|
||||
return false;
|
||||
@@ -171,7 +173,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
referencedMethodReturnType = JavaPsiFacade.getElementFactory(method.getProject()).createType(containingClass, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
else {
|
||||
referencedMethodReturnType = method.getReturnType();
|
||||
final PsiType getClassReturnType = PsiTypesUtil.patchMethodGetClassReturnType(myExpression, method);
|
||||
referencedMethodReturnType = getClassReturnType != null ? getClassReturnType : method.getReturnType();
|
||||
}
|
||||
LOG.assertTrue(referencedMethodReturnType != null, method);
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Test {
|
||||
public <T> void some() {
|
||||
Function<AtomicReference<T>, ? extends Class<? extends AtomicReference>> a = AtomicReference<T>::getClass;
|
||||
Function<AtomicReference<T>, ? extends Class<? extends AtomicReference>> b = AtomicReference::getClass;
|
||||
}
|
||||
}
|
||||
|
||||
class Test1<M> {
|
||||
|
||||
public <T> void some(Stream<Test1<T>> stream) {
|
||||
stream.map(Test1::getClass);
|
||||
stream.map(Test1<T>::getClass);
|
||||
}
|
||||
public String getClass(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2<M> {
|
||||
|
||||
public <T> void some(Stream<Test2<T>> stream) {
|
||||
stream.map(Test2::getClass);
|
||||
stream.map(Test2<T>::getClass);
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
class Test {
|
||||
public <T> void some() {
|
||||
Function<AtomicReference<T>, ? extends Class<? extends AtomicReference>> a = AtomicReference<T>::getClass;
|
||||
Function<AtomicReference<T>, ? extends Class<? extends AtomicReference>> b = AtomicReference::getClass;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -490,7 +490,7 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testGetClassReturnTypeInMethodRefrence() throws Exception {
|
||||
public void testGetClassReturnTypeInMethodReference() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user