Example #1
0
 private static PsiType createType(PsiClass cls, PsiSubstitutor currentSubstitutor, int arrayDim) {
   final PsiElementFactory elementFactory =
       JavaPsiFacade.getInstance(cls.getProject()).getElementFactory();
   PsiType newType = elementFactory.createType(cls, currentSubstitutor);
   for (int i = 0; i < arrayDim; i++) {
     newType = newType.createArrayType();
   }
   return newType;
 }
  private void makeArray(PsiVariable variable) throws IncorrectOperationException {
    PsiType type = variable.getType();

    PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
    PsiType newType = type.createArrayType();

    PsiDeclarationStatement variableDeclarationStatement;
    PsiExpression initializer = variable.getInitializer();
    if (initializer == null) {
      String expression = "[1]";
      while (type instanceof PsiArrayType) {
        expression += "[1]";
        type = ((PsiArrayType) type).getComponentType();
      }
      PsiExpression init =
          factory.createExpressionFromText("new " + type.getCanonicalText() + expression, variable);
      variableDeclarationStatement =
          factory.createVariableDeclarationStatement(variable.getName(), newType, init);
    } else {
      PsiExpression init =
          factory.createExpressionFromText("{ " + initializer.getText() + " }", variable);
      variableDeclarationStatement =
          factory.createVariableDeclarationStatement(variable.getName(), newType, init);
    }
    PsiVariable newVariable = (PsiVariable) variableDeclarationStatement.getDeclaredElements()[0];
    PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, true);
    PsiElement newExpression =
        factory.createExpressionFromText(variable.getName() + "[0]", variable);

    PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null);
    if (outerCodeBlock == null) return;
    List<PsiReferenceExpression> outerReferences = new ArrayList<PsiReferenceExpression>();
    collectReferences(outerCodeBlock, variable, outerReferences);
    replaceReferences(outerReferences, newExpression);
    variable.replace(newVariable);
  }
  @NotNull
  private static PsiType getLeastUpperBound(
      PsiType type1, PsiType type2, Set<Pair<PsiType, PsiType>> compared, PsiManager manager) {
    if (type1 instanceof PsiCapturedWildcardType) {
      return getLeastUpperBound(
          ((PsiCapturedWildcardType) type1).getUpperBound(), type2, compared, manager);
    }
    if (type2 instanceof PsiCapturedWildcardType) {
      return getLeastUpperBound(
          type1, ((PsiCapturedWildcardType) type2).getUpperBound(), compared, manager);
    }

    if (type1 instanceof PsiWildcardType) {
      return getLeastUpperBound(
          ((PsiWildcardType) type1).getExtendsBound(), type2, compared, manager);
    }
    if (type2 instanceof PsiWildcardType) {
      return getLeastUpperBound(
          type1, ((PsiWildcardType) type2).getExtendsBound(), compared, manager);
    }

    if (type1 instanceof PsiArrayType && type2 instanceof PsiArrayType) {
      final PsiType componentType1 = ((PsiArrayType) type1).getComponentType();
      final PsiType componentType2 = ((PsiArrayType) type2).getComponentType();
      final PsiType componentType =
          getLeastUpperBound(componentType1, componentType2, compared, manager);
      if (componentType1 instanceof PsiPrimitiveType
          && componentType2 instanceof PsiPrimitiveType
          && componentType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
        final PsiElementFactory factory =
            JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
        final GlobalSearchScope resolveScope = GlobalSearchScope.allScope(manager.getProject());
        final PsiClassType cloneable =
            factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLONEABLE, resolveScope);
        final PsiClassType serializable =
            factory.createTypeByFQClassName(CommonClassNames.JAVA_IO_SERIALIZABLE, resolveScope);
        return PsiIntersectionType.createIntersection(componentType, cloneable, serializable);
      }
      return componentType.createArrayType();
    }
    if (type1 instanceof PsiIntersectionType) {
      Set<PsiType> newConjuncts = new LinkedHashSet<PsiType>();
      final PsiType[] conjuncts = ((PsiIntersectionType) type1).getConjuncts();
      for (PsiType type : conjuncts) {
        newConjuncts.add(getLeastUpperBound(type, type2, compared, manager));
      }
      return PsiIntersectionType.createIntersection(
          newConjuncts.toArray(PsiType.createArray(newConjuncts.size())));
    }
    if (type2 instanceof PsiIntersectionType) {
      return getLeastUpperBound(type2, type1, compared, manager);
    }
    if (type1 instanceof PsiClassType && type2 instanceof PsiClassType) {
      PsiClassType.ClassResolveResult classResolveResult1 =
          ((PsiClassType) type1).resolveGenerics();
      PsiClassType.ClassResolveResult classResolveResult2 =
          ((PsiClassType) type2).resolveGenerics();
      PsiClass aClass = classResolveResult1.getElement();
      PsiClass bClass = classResolveResult2.getElement();
      if (aClass == null || bClass == null) {
        return PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject()));
      }

      PsiClass[] supers = getLeastUpperClasses(aClass, bClass);
      if (supers.length == 0) {
        return PsiType.getJavaLangObject(manager, aClass.getResolveScope());
      }

      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;
        for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(aSuper)) {
          PsiType mapping1 = subst1.substitute(parameter);
          PsiType mapping2 = subst2.substitute(parameter);

          if (mapping1 != null && mapping2 != null) {
            substitutor =
                substitutor.put(
                    parameter,
                    getLeastContainingTypeArgument(
                        mapping1,
                        mapping2,
                        compared,
                        manager,
                        type1.equals(mapping1) && type2.equals(mapping2) ? aSuper : null,
                        parameter));
          } else {
            substitutor = substitutor.put(parameter, null);
          }
        }

        conjuncts[i] =
            JavaPsiFacade.getInstance(manager.getProject())
                .getElementFactory()
                .createType(aSuper, substitutor);
      }

      return PsiIntersectionType.createIntersection(conjuncts);
    }
    if (type2 instanceof PsiArrayType && !(type1 instanceof PsiArrayType)) {
      return getLeastUpperBound(type2, type1, compared, manager);
    }
    if (type1 instanceof PsiArrayType) {
      PsiElementFactory factory =
          JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
      GlobalSearchScope all = GlobalSearchScope.allScope(manager.getProject());
      PsiClassType serializable =
          factory.createTypeByFQClassName(CommonClassNames.JAVA_IO_SERIALIZABLE, all);
      PsiClassType cloneable =
          factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLONEABLE, all);
      PsiType arraySupers = PsiIntersectionType.createIntersection(serializable, cloneable);
      return getLeastUpperBound(arraySupers, type2, compared, manager);
    }

    return PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject()));
  }
  @Nullable
  public static PsiType getVariableTypeByExpressionType(
      @Nullable PsiType type, final boolean openCaptured) {
    if (type == null) return null;
    if (type instanceof PsiCapturedWildcardType) {
      type = ((PsiCapturedWildcardType) type).getWildcard();
    }
    PsiType transformed =
        type.accept(
            new PsiTypeVisitor<PsiType>() {
              @Override
              public PsiType visitArrayType(PsiArrayType arrayType) {
                PsiType componentType = arrayType.getComponentType();
                PsiType type = componentType.accept(this);
                if (type == componentType) return arrayType;
                return type.createArrayType();
              }

              @Override
              public PsiType visitType(PsiType type) {
                return type;
              }

              @Override
              public PsiType visitWildcardType(final PsiWildcardType wildcardType) {
                final PsiType bound = wildcardType.getBound();
                PsiManager manager = wildcardType.getManager();
                if (bound != null) {
                  final PsiType acceptedBound = bound.accept(this);
                  if (acceptedBound instanceof PsiWildcardType) {
                    if (((PsiWildcardType) acceptedBound).isExtends() != wildcardType.isExtends())
                      return PsiWildcardType.createUnbounded(manager);
                    return acceptedBound;
                  }
                  if (wildcardType.isExtends()
                      && acceptedBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT))
                    return PsiWildcardType.createUnbounded(manager);
                  if (acceptedBound.equals(bound)) return wildcardType;
                  return wildcardType.isExtends()
                      ? PsiWildcardType.createExtends(manager, acceptedBound)
                      : PsiWildcardType.createSuper(manager, acceptedBound);
                }
                return wildcardType;
              }

              @Override
              public PsiType visitCapturedWildcardType(
                  PsiCapturedWildcardType capturedWildcardType) {
                return openCaptured
                    ? capturedWildcardType.getWildcard().accept(this)
                    : capturedWildcardType;
              }

              @Override
              public PsiType visitClassType(PsiClassType classType) {
                PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
                PsiClass aClass = resolveResult.getElement();
                if (aClass == null) return classType;
                boolean toExtend = false;
                PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
                for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
                  PsiType typeArgument = resolveResult.getSubstitutor().substitute(typeParameter);
                  if (typeArgument instanceof PsiCapturedWildcardType) toExtend = true;
                  if (typeArgument instanceof PsiWildcardType
                      && ((PsiWildcardType) typeArgument).getBound()
                          instanceof PsiIntersectionType) {
                    toExtend = true;
                  }
                  PsiType toPut;
                  if (typeArgument == null) {
                    toPut = null;
                  } else {
                    final PsiType accepted = typeArgument.accept(this);
                    if (typeArgument instanceof PsiIntersectionType) {
                      toPut = PsiWildcardType.createExtends(typeParameter.getManager(), accepted);
                    } else {
                      toPut = accepted;
                    }
                  }
                  LOG.assertTrue(toPut == null || toPut.isValid(), toPut);
                  substitutor = substitutor.put(typeParameter, toPut);
                }
                final PsiAnnotation[] applicableAnnotations = classType.getApplicableAnnotations();
                if (substitutor == PsiSubstitutor.EMPTY
                    && !toExtend
                    && applicableAnnotations.length == 0
                    && !(aClass instanceof PsiTypeParameter)) return classType;
                PsiManager manager = aClass.getManager();
                PsiType result =
                    JavaPsiFacade.getInstance(manager.getProject())
                        .getElementFactory()
                        .createType(
                            aClass,
                            substitutor,
                            PsiUtil.getLanguageLevel(aClass),
                            applicableAnnotations);
                if (toExtend) result = PsiWildcardType.createExtends(manager, result);
                return result;
              }
            });

    PsiType componentType = transformed != null ? transformed.getDeepComponentType() : null;
    if (componentType instanceof PsiWildcardType) {
      componentType = ((PsiWildcardType) componentType).getExtendsBound();
      int dims = transformed.getArrayDimensions();
      for (int i = 0; i < dims; i++) componentType = componentType.createArrayType();
      return componentType;
    }

    return transformed;
  }