private static PsiType doNormalizeWildcardByPosition(
      PsiType type, @NotNull PsiExpression expression, PsiExpression topLevel) {

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(topLevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, topLevel);
      if (normalizedComponentType != componentType) {
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
 @NotNull
 public static PsiType[] typesByTypeElements(@NotNull PsiTypeElement[] typeElements) {
   PsiType[] types = PsiType.createArray(typeElements.length);
   for (int i = 0; i < types.length; i++) {
     types[i] = typeElements[i].getType();
   }
   if (types.length == 1 && types[0] instanceof PsiDiamondType) {
     return ((PsiDiamondType) types[0]).resolveInferredTypes().getTypes();
   }
   return types;
 }
  /** Types should be proceed by the callers themselves */
  @Deprecated
  public static PsiType normalizeWildcardTypeByPosition(
      @NotNull PsiType type, @NotNull PsiExpression expression) {
    PsiUtilCore.ensureValid(expression);
    PsiUtil.ensureValidType(type);

    PsiExpression topLevel = expression;
    while (topLevel.getParent() instanceof PsiArrayAccessExpression
        && ((PsiArrayAccessExpression) topLevel.getParent()).getArrayExpression() == topLevel) {
      topLevel = (PsiExpression) topLevel.getParent();
    }

    if (topLevel instanceof PsiArrayAccessExpression && !PsiUtil.isAccessedForWriting(topLevel)) {
      return PsiUtil.captureToplevelWildcards(type, expression);
    }

    final PsiType normalized = doNormalizeWildcardByPosition(type, expression, topLevel);
    LOG.assertTrue(normalized.isValid(), type);
    if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(topLevel)) {
      return PsiUtil.captureToplevelWildcards(normalized, expression);
    }

    return normalized;
  }