mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
glb: ensure each super class processed once (IDEA-176779)
This commit is contained in:
@@ -110,38 +110,46 @@ public class GenericsUtil {
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
PsiClassType[] conjuncts = new PsiClassType[supers.length];
|
||||
for (int i = 0; i < supers.length; i++) {
|
||||
PsiClass aSuper = supers[i];
|
||||
PsiSubstitutor subst1 = TypeConversionUtil.getSuperClassSubstitutor(aSuper, aClass, classResolveResult1.getSubstitutor());
|
||||
PsiSubstitutor subst2 = TypeConversionUtil.getSuperClassSubstitutor(aSuper, bClass, classResolveResult2.getSubstitutor());
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
Set<Couple<PsiType>> siblings = new HashSet<>();
|
||||
try {
|
||||
for (int i = 0; i < supers.length; i++) {
|
||||
PsiClass aSuper = supers[i];
|
||||
PsiSubstitutor subst1 = TypeConversionUtil.getSuperClassSubstitutor(aSuper, aClass, classResolveResult1.getSubstitutor());
|
||||
PsiSubstitutor subst2 = TypeConversionUtil.getSuperClassSubstitutor(aSuper, bClass, classResolveResult2.getSubstitutor());
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
|
||||
final Couple<PsiType> types = Couple.of(elementFactory.createType(aSuper, subst1), elementFactory.createType(aSuper, subst2));
|
||||
final Couple<PsiType> types = Couple.of(elementFactory.createType(aSuper, subst1), elementFactory.createType(aSuper, subst2));
|
||||
boolean skip = compared.contains(types);
|
||||
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(aSuper)) {
|
||||
PsiType mapping1 = subst1.substitute(parameter);
|
||||
PsiType mapping2 = subst2.substitute(parameter);
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(aSuper)) {
|
||||
PsiType mapping1 = subst1.substitute(parameter);
|
||||
PsiType mapping2 = subst2.substitute(parameter);
|
||||
|
||||
if (mapping1 != null && mapping2 != null) {
|
||||
if (compared.contains(types)) {
|
||||
substitutor = substitutor.put(parameter, PsiWildcardType.createUnbounded(manager));
|
||||
if (mapping1 != null && mapping2 != null) {
|
||||
if (skip) {
|
||||
substitutor = substitutor.put(parameter, PsiWildcardType.createUnbounded(manager));
|
||||
}
|
||||
else {
|
||||
compared.add(types);
|
||||
try {
|
||||
PsiType argument = getLeastContainingTypeArgument(mapping1, mapping2, compared, manager);
|
||||
substitutor = substitutor.put(parameter, argument);
|
||||
}
|
||||
finally {
|
||||
siblings.add(types);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
compared.add(types);
|
||||
try {
|
||||
substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager));
|
||||
}
|
||||
finally {
|
||||
compared.remove(types);
|
||||
}
|
||||
substitutor = substitutor.put(parameter, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
substitutor = substitutor.put(parameter, null);
|
||||
}
|
||||
}
|
||||
|
||||
conjuncts[i] = elementFactory.createType(aSuper, substitutor);
|
||||
conjuncts[i] = elementFactory.createType(aSuper, substitutor);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
compared.removeAll(siblings);
|
||||
}
|
||||
|
||||
return PsiIntersectionType.createIntersection(conjuncts);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class LeastUpperBoundTest {
|
||||
void f(Stream<Klass> klasses) {
|
||||
klasses.flatMap(d -> concat(Stream.of(d),
|
||||
d.getMethods().stream(),
|
||||
d.getMethods().stream()));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static <T> Stream<T> concat(Stream<? extends T>... streams) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface Node {}
|
||||
interface A<T extends Node> {}
|
||||
interface B<T extends Node> {}
|
||||
interface C<T extends Node> {}
|
||||
interface D<T extends Node> {}
|
||||
interface E<T extends Node> {}
|
||||
interface E1<T extends Node> {}
|
||||
interface E2<T extends Node> {}
|
||||
|
||||
class Klass implements Node, A<Klass>, B<Klass>, C<Klass>, D<Klass>, E<Klass>, E1<Klass> {
|
||||
public List<Method> getMethods() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
class Method implements Node, A<Method>, B<Method>, C<Method>, D<Method>, E<Method>, E1<Method> {}
|
||||
|
||||
@@ -32,6 +32,10 @@ public class InferencePerformanceTest extends LightDaemonAnalyzerTestCase {
|
||||
PlatformTestUtil.startPerformanceTest("50 diamond constructor calls passed to Arrays.asList", 12000, this::doTest).usesAllCPUCores().assertTiming();
|
||||
}
|
||||
|
||||
public void testLeastUpperBoundWithLotsOfSupers() {
|
||||
PlatformTestUtil.startPerformanceTest("7 unrelated intersection conjuncts", 12000, this::doTest).usesAllCPUCores().assertTiming();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
|
||||
Reference in New Issue
Block a user