mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
clear diamond inference errors when overload resolution fails
This commit is contained in:
@@ -179,4 +179,6 @@ public abstract class PsiDiamondType extends PsiType {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract JavaResolveResult getStaticFactory();
|
||||
}
|
||||
|
||||
@@ -497,7 +497,15 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
return clearErrorMessageInSubexpressions(((PsiConditionalExpression)expression).getElseExpression());
|
||||
}
|
||||
else if (expression instanceof PsiCallExpression) {
|
||||
final JavaResolveResult result = ((PsiCallExpression)expression).resolveMethodGenerics();
|
||||
final JavaResolveResult result;
|
||||
if (expression instanceof PsiNewExpression) {
|
||||
PsiDiamondType diamondType = PsiDiamondType.getDiamondType((PsiNewExpression)expression);
|
||||
result = diamondType != null ? diamondType.getStaticFactory()
|
||||
: ((PsiCallExpression)expression).resolveMethodGenerics();
|
||||
}
|
||||
else {
|
||||
result = ((PsiCallExpression)expression).resolveMethodGenerics();
|
||||
}
|
||||
if (result instanceof MethodCandidateInfo) {
|
||||
final String message = ((MethodCandidateInfo)result).getInferenceErrorMessage();
|
||||
((MethodCandidateInfo)result).setInferenceError(null);
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
@@ -104,8 +103,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
|
||||
@Override
|
||||
public DiamondInferenceResult resolveInferredTypes() {
|
||||
PsiElement typeElementWithDiamondTypeArgument = myTypeElement.getParent();
|
||||
final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(typeElementWithDiamondTypeArgument, PsiNewExpression.class, true, PsiTypeElement.class);
|
||||
final PsiNewExpression newExpression = getNewExpression();
|
||||
if (newExpression == null) {
|
||||
return PsiDiamondTypeImpl.DiamondInferenceResult.NULL_RESULT;
|
||||
}
|
||||
@@ -113,6 +111,17 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return resolveInferredTypes(newExpression);
|
||||
}
|
||||
|
||||
private PsiNewExpression getNewExpression() {
|
||||
PsiElement typeElementWithDiamondTypeArgument = myTypeElement.getParent();
|
||||
return PsiTreeUtil.getParentOfType(typeElementWithDiamondTypeArgument, PsiNewExpression.class, true, PsiTypeElement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaResolveResult getStaticFactory() {
|
||||
final PsiNewExpression newExpression = getNewExpression();
|
||||
return newExpression != null ? getStaticFactory(newExpression, newExpression) : null;
|
||||
}
|
||||
|
||||
public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) {
|
||||
return resolveInferredTypes(newExpression, newExpression);
|
||||
}
|
||||
@@ -145,41 +154,38 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return inferenceResult;
|
||||
}
|
||||
|
||||
private static JavaResolveResult getStaticFactory(final PsiNewExpression newExpression, final PsiElement context) {
|
||||
return context == newExpression
|
||||
? CachedValuesManager.getCachedValue(newExpression, new CachedValueProvider<JavaResolveResult>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<JavaResolveResult> compute() {
|
||||
return new Result<JavaResolveResult>(getStaticFactoryCandidateInfo(newExpression, newExpression),
|
||||
PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
})
|
||||
: getStaticFactoryCandidateInfo(newExpression, context);
|
||||
}
|
||||
|
||||
public static DiamondInferenceResult resolveInferredTypesNoCheck(final PsiNewExpression newExpression, final PsiElement context) {
|
||||
final Ref<JavaResolveResult> staticFactoryRef = new Ref<JavaResolveResult>();
|
||||
final JavaResolveResult staticFactoryCandidateInfo = getStaticFactory(newExpression, context);
|
||||
if (staticFactoryCandidateInfo == null) {
|
||||
return DiamondInferenceResult.NULL_RESULT;
|
||||
}
|
||||
final PsiSubstitutor inferredSubstitutor = ourDiamondGuard.doPreventingRecursion(context, false, new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
final JavaResolveResult staticFactoryCandidateInfo =
|
||||
context == newExpression
|
||||
? CachedValuesManager.getCachedValue(newExpression, new CachedValueProvider<JavaResolveResult>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<JavaResolveResult> compute() {
|
||||
return new Result<JavaResolveResult>(getStaticFactoryCandidateInfo(newExpression, newExpression), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
})
|
||||
: getStaticFactoryCandidateInfo(newExpression, context);
|
||||
staticFactoryRef.set(staticFactoryCandidateInfo);
|
||||
if (staticFactoryCandidateInfo != null) {
|
||||
PsiSubstitutor substitutor = staticFactoryCandidateInfo.getSubstitutor();
|
||||
return staticFactoryCandidateInfo instanceof MethodCandidateInfo && ((MethodCandidateInfo)staticFactoryCandidateInfo).getInferenceErrorMessage() != null
|
||||
? null : substitutor;
|
||||
}
|
||||
return null;
|
||||
PsiSubstitutor substitutor = staticFactoryCandidateInfo.getSubstitutor();
|
||||
return staticFactoryCandidateInfo instanceof MethodCandidateInfo &&
|
||||
((MethodCandidateInfo)staticFactoryCandidateInfo).getInferenceErrorMessage() != null
|
||||
? null : substitutor;
|
||||
}
|
||||
});
|
||||
if (inferredSubstitutor == null) {
|
||||
return DiamondInferenceResult.NULL_RESULT;
|
||||
}
|
||||
|
||||
final JavaResolveResult staticFactoryInfo = staticFactoryRef.get();
|
||||
if (staticFactoryInfo == null) {
|
||||
LOG.error(inferredSubstitutor);
|
||||
return DiamondInferenceResult.NULL_RESULT;
|
||||
}
|
||||
|
||||
if (!(staticFactoryInfo instanceof MethodCandidateInfo)) {
|
||||
if (!(staticFactoryCandidateInfo instanceof MethodCandidateInfo)) {
|
||||
return DiamondInferenceResult.UNRESOLVED_CONSTRUCTOR;
|
||||
}
|
||||
|
||||
@@ -189,7 +195,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return DiamondInferenceResult.RAW_RESULT;
|
||||
}
|
||||
|
||||
final PsiMethod staticFactory = ((MethodCandidateInfo)staticFactoryInfo).getElement();
|
||||
final PsiMethod staticFactory = ((MethodCandidateInfo)staticFactoryCandidateInfo).getElement();
|
||||
final PsiTypeParameter[] parameters = staticFactory.getTypeParameters();
|
||||
final PsiElement staticFactoryContext = staticFactory.getContext();
|
||||
final PsiClass psiClass = PsiTreeUtil.getContextOfType(staticFactoryContext, PsiClass.class, false);
|
||||
@@ -223,31 +229,37 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JavaResolveResult getStaticFactoryCandidateInfo(PsiNewExpression newExpression,
|
||||
PsiElement context) {
|
||||
final PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
//token expected diagnostic is provided by parser
|
||||
return null;
|
||||
}
|
||||
private static JavaResolveResult getStaticFactoryCandidateInfo(final PsiNewExpression newExpression,
|
||||
final PsiElement context) {
|
||||
return ourDiamondGuard.doPreventingRecursion(context, false, new Computable<JavaResolveResult>() {
|
||||
@Override
|
||||
public JavaResolveResult compute() {
|
||||
|
||||
final JavaMethodsConflictResolver resolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(newExpression));
|
||||
final JavaResolveResult[] result = collectStaticFactories(newExpression, resolver);
|
||||
final PsiMethod staticFactory = result != null && result.length == 1 ? (PsiMethod)result[0].getElement() : null;
|
||||
if (staticFactory == null) {
|
||||
//additional diagnostics: inference fails due to unresolved constructor
|
||||
return JavaResolveResult.EMPTY;
|
||||
}
|
||||
final PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
//token expected diagnostic is provided by parser
|
||||
return null;
|
||||
}
|
||||
|
||||
final MethodCandidateInfo staticFactoryCandidateInfo = createMethodCandidate(staticFactory, context, false, argumentList);
|
||||
if (!staticFactory.isVarArgs()) {
|
||||
return staticFactoryCandidateInfo;
|
||||
}
|
||||
final JavaMethodsConflictResolver resolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(newExpression));
|
||||
final JavaResolveResult[] result = collectStaticFactories(newExpression, resolver);
|
||||
final PsiMethod staticFactory = result != null && result.length == 1 ? (PsiMethod)result[0].getElement() : null;
|
||||
if (staticFactory == null) {
|
||||
//additional diagnostics: inference fails due to unresolved constructor
|
||||
return JavaResolveResult.EMPTY;
|
||||
}
|
||||
|
||||
final ArrayList<CandidateInfo> conflicts = new ArrayList<CandidateInfo>();
|
||||
conflicts.add(staticFactoryCandidateInfo);
|
||||
conflicts.add(createMethodCandidate(staticFactory, context, true, argumentList));
|
||||
return resolver.resolveConflict(conflicts);
|
||||
final MethodCandidateInfo staticFactoryCandidateInfo = createMethodCandidate(staticFactory, context, false, argumentList);
|
||||
if (!staticFactory.isVarArgs()) {
|
||||
return staticFactoryCandidateInfo;
|
||||
}
|
||||
|
||||
final ArrayList<CandidateInfo> conflicts = new ArrayList<CandidateInfo>();
|
||||
conflicts.add(staticFactoryCandidateInfo);
|
||||
conflicts.add(createMethodCandidate(staticFactory, context, true, argumentList));
|
||||
return resolver.resolveConflict(conflicts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class Test {
|
||||
|
||||
void m(StringBuilder builder){
|
||||
builder.append(new Foo<>((Collection)null));
|
||||
}
|
||||
|
||||
static class Foo<T> {
|
||||
public Foo(Collection<? extends T> c) {}
|
||||
public Foo(Foo<T> t) {}
|
||||
}
|
||||
}
|
||||
+16
-4
@@ -79,6 +79,10 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
doTestAllMethodCallExpressions();
|
||||
}
|
||||
|
||||
public void testObjectOverloadsWithDiamondsOverMultipleConstructors() throws Exception {
|
||||
doTestAllMethodCallExpressions();
|
||||
}
|
||||
|
||||
public void testNonCachingFolding() throws Exception {
|
||||
final String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
configureByFile(filePath);
|
||||
@@ -149,11 +153,19 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
assertNotNull("Failed inference for: " + expression.getText(), expression.getType());
|
||||
}
|
||||
|
||||
final Collection<PsiReferenceParameterList> parameterLists = PsiTreeUtil.findChildrenOfType(getFile(), PsiReferenceParameterList.class);
|
||||
for (PsiReferenceParameterList list : parameterLists) {
|
||||
final Collection<PsiNewExpression> parameterLists = PsiTreeUtil.findChildrenOfType(getFile(), PsiNewExpression.class);
|
||||
for (PsiNewExpression newExpression : parameterLists) {
|
||||
getPsiManager().dropResolveCaches();
|
||||
final PsiType[] arguments = list.getTypeArguments();
|
||||
assertNotNull("Failed inference for: " + list.getParent().getText(), arguments);
|
||||
final PsiType[] arguments = newExpression.getTypeArguments();
|
||||
String failMessage = "Failed inference for: " + newExpression.getParent().getText();
|
||||
assertNotNull(failMessage, arguments);
|
||||
PsiDiamondType diamondType = PsiDiamondType.getDiamondType(newExpression);
|
||||
if (diamondType != null) {
|
||||
JavaResolveResult staticFactory = diamondType.getStaticFactory();
|
||||
assertNotNull(staticFactory);
|
||||
assertTrue(staticFactory instanceof MethodCandidateInfo);
|
||||
assertNull(failMessage, ((MethodCandidateInfo)staticFactory).getInferenceErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user