mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
proceed static factories instead of constructors to calculate expected types when diamonds are used (IDEA-153520)
This commit is contained in:
@@ -23,11 +23,13 @@ import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.PsiDiamondTypeUtil;
|
||||
import com.intellij.psi.impl.source.resolve.CompletionParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
|
||||
@@ -595,6 +597,14 @@ public class ExpectedTypesProvider {
|
||||
|
||||
private void getExpectedArgumentsTypesForNewExpression(@NotNull final PsiNewExpression newExpr,
|
||||
@NotNull final PsiExpressionList list) {
|
||||
if (PsiDiamondTypeUtil.hasDiamond(newExpr)) {
|
||||
final JavaResolveResult[] candidates = PsiDiamondTypeImpl.collectStaticFactories(newExpr, DuplicateConflictResolver.INSTANCE);
|
||||
if (candidates != null) {
|
||||
final PsiExpressionList argumentList = newExpr.getArgumentList();
|
||||
Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(ContainerUtil.map(candidates, (candidate) -> (CandidateInfo)candidate, CandidateInfo.EMPTY_ARRAY), argumentList, myExpr, myForCompletion));
|
||||
}
|
||||
return;
|
||||
}
|
||||
PsiType newType = newExpr.getType();
|
||||
if (newType instanceof PsiClassType) {
|
||||
JavaResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(newType);
|
||||
|
||||
@@ -24,7 +24,6 @@ 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.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
@@ -221,13 +220,9 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiClass psiClass = findClass(newExpression);
|
||||
if (psiClass == null) {
|
||||
//should not happens: unresolved class reference would be first and inference won't start
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiMethod staticFactory = findConstructorStaticFactory(psiClass, newExpression);
|
||||
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;
|
||||
@@ -238,7 +233,6 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return staticFactoryCandidateInfo;
|
||||
}
|
||||
|
||||
final JavaMethodsConflictResolver resolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(argumentList));
|
||||
final ArrayList<CandidateInfo> conflicts = new ArrayList<CandidateInfo>();
|
||||
conflicts.add(staticFactoryCandidateInfo);
|
||||
conflicts.add(createMethodCandidate(staticFactory, context, true, argumentList));
|
||||
@@ -246,20 +240,27 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiMethod findConstructorStaticFactory(final PsiClass containingClass, PsiNewExpression newExpression) {
|
||||
final PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
if (argumentList == null) return null;
|
||||
public static JavaResolveResult[] collectStaticFactories(PsiNewExpression newExpression, final PsiConflictResolver... conflictResolvers) {
|
||||
PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(newExpression);
|
||||
final List<CandidateInfo> conflicts = new ArrayList<CandidateInfo>();
|
||||
PsiMethod[] constructors = containingClass.getConstructors();
|
||||
final PsiClass psiClass = findClass(newExpression);
|
||||
if (psiClass == null) {
|
||||
//should not happens: unresolved class reference would be first and inference won't start
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<CandidateInfo> candidates = new ArrayList<CandidateInfo>();
|
||||
PsiMethod[] constructors = psiClass.getConstructors();
|
||||
if (constructors.length == 0) {
|
||||
//default constructor
|
||||
constructors = new PsiMethod[] {null};
|
||||
}
|
||||
|
||||
final PsiConflictResolver[] conflictResolvers = {new JavaMethodsConflictResolver(argumentList, languageLevel)};
|
||||
final MethodCandidatesProcessor processor = new MethodCandidatesProcessor(argumentList, argumentList.getContainingFile(), conflictResolvers, conflicts) {
|
||||
final MethodCandidatesProcessor
|
||||
processor = new MethodCandidatesProcessor(argumentList, argumentList.getContainingFile(), conflictResolvers, candidates) {
|
||||
@Override
|
||||
protected boolean isAccepted(PsiMethod candidate) {
|
||||
return true;
|
||||
@@ -267,7 +268,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
|
||||
@Override
|
||||
protected PsiClass getContainingClass(PsiMethod method) {
|
||||
return containingClass;
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -278,15 +279,14 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
processor.setArgumentList(argumentList);
|
||||
|
||||
for (PsiMethod constructor : constructors) {
|
||||
final PsiTypeParameter[] params = getAllTypeParams(constructor, containingClass);
|
||||
final PsiMethod staticFactory = generateStaticFactory(constructor, containingClass, params, newExpression.getClassReference());
|
||||
final PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass);
|
||||
final PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params, newExpression.getClassReference());
|
||||
if (staticFactory != null) {
|
||||
processor.add(staticFactory, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
final JavaResolveResult[] result = processor.getResult();
|
||||
return result.length == 1 ? (PsiMethod)result[0].getElement() : null;
|
||||
return processor.getResult();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class Outer <U, V> {
|
||||
|
||||
|
||||
Outer(Foo<? super U> a) {}
|
||||
Outer(Bar<? super U, ? extends V> a) {}
|
||||
|
||||
{
|
||||
Outer<String, String> o = new Outer<>(new Foo<String>() {
|
||||
@Override
|
||||
public void m() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface Foo<A> {
|
||||
void m();
|
||||
}
|
||||
interface Bar<A, B> {}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Outer <U, V> {
|
||||
|
||||
|
||||
Outer(Foo<? super U> a) {}
|
||||
Outer(Bar<? super U, ? extends V> a) {}
|
||||
|
||||
{
|
||||
Outer<String, String> o = new Outer<>(new F<caret>);
|
||||
}
|
||||
}
|
||||
|
||||
interface Foo<A> {
|
||||
void m();
|
||||
}
|
||||
interface Bar<A, B> {}
|
||||
+7
@@ -153,6 +153,13 @@ public void testConvertToObjectStream() {
|
||||
checkResultByFile("/" + getTestName(false) + "-out.java");
|
||||
}
|
||||
|
||||
public void testInsideNewExpressionWithDiamondAndOverloadConstructors() throws Exception {
|
||||
configureByTestName();
|
||||
myFixture.complete(CompletionType.SMART, 1);
|
||||
myFixture.type('\n');
|
||||
checkResultByFile("/" + getTestName(false) + "-out.java");
|
||||
}
|
||||
|
||||
public void testCollectorsToList() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user