mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
diamonds: resolve conflicts based on type params from constructor and containing class (IDEA-123518)
This commit is contained in:
@@ -22,8 +22,13 @@ 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;
|
||||
import com.intellij.psi.scope.PsiConflictResolver;
|
||||
import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
|
||||
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -33,9 +38,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
@@ -139,10 +142,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
final PsiSubstitutor inferredSubstitutor = ourDiamondGuard.doPreventingRecursion(context, false, new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
final PsiMethod constructor = findConstructor(psiClass, newExpression);
|
||||
PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass);
|
||||
|
||||
final PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params, newExpression.getClassReference());
|
||||
final PsiMethod staticFactory = findConstructorStaticFactory(psiClass, newExpression);
|
||||
if (staticFactory == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -177,14 +177,42 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
|
||||
|
||||
@Nullable
|
||||
private static PsiMethod findConstructor(PsiClass containingClass, PsiNewExpression newExpression) {
|
||||
private static PsiMethod findConstructorStaticFactory(final PsiClass containingClass, PsiNewExpression newExpression) {
|
||||
final PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
final Project project = newExpression.getProject();
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
final PsiResolveHelper resolveHelper = facade.getResolveHelper();
|
||||
final JavaResolveResult result =
|
||||
resolveHelper.resolveConstructor(facade.getElementFactory().createType(containingClass, PsiSubstitutor.EMPTY), argumentList, argumentList);
|
||||
return (PsiMethod)result.getElement();
|
||||
if (argumentList == null) return null;
|
||||
|
||||
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(newExpression);
|
||||
final List<CandidateInfo> conflicts = new ArrayList<CandidateInfo>();
|
||||
PsiMethod[] constructors = containingClass.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) {
|
||||
@Override
|
||||
protected boolean isAccepted(PsiMethod candidate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiClass getContainingClass(PsiMethod method) {
|
||||
return containingClass;
|
||||
}
|
||||
};
|
||||
processor.setArgumentList(argumentList);
|
||||
|
||||
for (PsiMethod constructor : constructors) {
|
||||
final PsiTypeParameter[] params = getAllTypeParams(constructor, containingClass);
|
||||
final PsiMethod staticFactory = generateStaticFactory(constructor, containingClass, 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;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -220,7 +248,11 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
PsiTypeParameter[] params,
|
||||
PsiJavaCodeReferenceElement reference) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
buf.append("public static ");
|
||||
buf.append(constructor != null ? constructor.getModifierList().getText() : containingClass.getModifierList().getText());
|
||||
if (buf.length() > 0) {
|
||||
buf.append(" ");
|
||||
}
|
||||
buf.append("static ");
|
||||
buf.append("<");
|
||||
buf.append(StringUtil.join(params, new Function<PsiTypeParameter, String>() {
|
||||
@Override
|
||||
|
||||
+7
-3
@@ -51,7 +51,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
}
|
||||
|
||||
public void addMethod(@NotNull PsiMethod method, final PsiSubstitutor substitutor, final boolean staticProblem) {
|
||||
final boolean isAccessible = JavaResolveUtil.isAccessible(method, method.getContainingClass(), method.getModifierList(),
|
||||
final boolean isAccessible = JavaResolveUtil.isAccessible(method, getContainingClass(method), method.getModifierList(),
|
||||
myPlace, myAccessClass, myCurrentFileContext, myPlaceFile) &&
|
||||
!isShadowed(method);
|
||||
if (isAccepted(method)) {
|
||||
@@ -63,6 +63,10 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
protected PsiClass getContainingClass(PsiMethod method) {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
|
||||
protected boolean acceptVarargs() {
|
||||
return false;
|
||||
}
|
||||
@@ -106,10 +110,10 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
|
||||
if (!candidate.isConstructor()) return false;
|
||||
if (myAccessClass == null) return true;
|
||||
if (myAccessClass instanceof PsiAnonymousClass) {
|
||||
final PsiClass containingClass = candidate.getContainingClass();
|
||||
final PsiClass containingClass = getContainingClass(candidate);
|
||||
return containingClass != null && containingClass.equals(myAccessClass.getSuperClass());
|
||||
}
|
||||
return myAccessClass.isEquivalentTo(candidate.getContainingClass());
|
||||
return myAccessClass.isEquivalentTo(getContainingClass(candidate));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import java.util.*;
|
||||
|
||||
class XTest {
|
||||
public void setStuff(String stuff) {
|
||||
setStuff(new ArrayList<>(Arrays.asList(stuff)));
|
||||
}
|
||||
|
||||
private void setStuff(List<String> stuff) {
|
||||
}
|
||||
}
|
||||
+1
@@ -98,6 +98,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testDiamondNeg13() { doTest(false, false); }
|
||||
public void testDiamondNeg14() { doTest(false, false); }
|
||||
public void testDiamondMisc() { doTest(false, false); }
|
||||
public void testMultipleConstructors() { doTest(false, false); }
|
||||
public void testHighlightInaccessibleFromClassModifierList() { doTest(false, false); }
|
||||
public void testInnerInTypeArguments() { doTest(false, false); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user