PsiType (@NotNull PsiType type1, @NotNull PsiType type2, @NotNull PsiManager manager) { if (type1 == PsiTypes.nullType()) return type2; if (type2 == PsiTypes.nullType()) return type1; { PsiType numericLUB = getNumericLUB(type1, type2); if (numericLUB != null) return numericLUB; } if (type1 instanceof GrTupleType tuple1 && type2 instanceof GrTupleType tuple2) { List<PsiType> components1 = tuple1.getComponentTypes(); List<PsiType> components2 = tuple2.getComponentTypes(); if (components1.isEmpty()) return genNewListBy(type2, manager); if (components2.isEmpty()) return genNewListBy(type1, manager); PsiType[] components3 = PsiType.createArray(Math.min(components1.size(), components2.size())); for (int i = 0; i < components3.length; i++) { PsiType c1 = components1.get(i); PsiType c2 = components2.get(i); if (c1 == null || c2 == null) { components3[i] = null; } else { components3[i] = getLeastUpperBound(c1, c2, manager); } } return new GrImmediateTupleType(Arrays.asList(components3), JavaPsiFacade.getInstance(manager.getProject()), tuple1.getResolveScope().intersectWith(tuple2.getResolveScope())); } else if (checkEmptyListAndList(type1, type2)) { return genNewListBy(type2, manager); } else if (checkEmptyListAndList(type2, type1)) { return genNewListBy(type1, manager); } else if (type1 instanceof GrMapType && type2 instanceof GrMapType) { return GrMapType.merge(((GrMapType)type1), ((GrMapType)type2)); } else if (checkEmptyMapAndMap(type1, type2)) { return genNewMapBy(type2, manager); } else if (checkEmptyMapAndMap(type2, type1)) { return genNewMapBy(type1, manager); } else if (type1 instanceof GrClosureType clType1 && type2 instanceof GrClosureType clType2) { List<GrSignature> signatures1 = clType1.getSignatures(); List<GrSignature> signatures2 = clType2.getSignatures(); if (signatures1.size() == 1 && signatures2.size() == 1) { final GrSignature signature1 = signatures1.get(0); final GrSignature signature2 = signatures2.get(0); if (signature1.getParameterCount() == signature2.getParameterCount()) { final GrSignature signature = GrImmediateClosureSignatureImpl.getLeastUpperBound(signature1, signature2, manager); if (signature != null) { GlobalSearchScope scope = clType1.getResolveScope().intersectWith(clType2.getResolveScope()); final LanguageLevel languageLevel = ComparatorUtil.max(clType1.getLanguageLevel(), clType2.getLanguageLevel()); return GrClosureType.create(Collections.singletonList(signature), scope, JavaPsiFacade.getInstance(manager.getProject()), languageLevel, true); } } } } else if (GroovyCommonClassNames.GROOVY_LANG_GSTRING.equals(getQualifiedName(type1)) && CommonClassNames.JAVA_LANG_STRING.equals(getQualifiedName(type2))) { return type2; } else if (GroovyCommonClassNames.GROOVY_LANG_GSTRING.equals(getQualifiedName(type2)) && CommonClassNames.JAVA_LANG_STRING.equals(getQualifiedName(type1))) { return type1; } return GenericsUtil.getLeastUpperBound(type1, type2, manager); }