public @NotNull PsiTypeElement setupTypeElement(@NotNull PsiTypeElement typeElement,
                                                  ExpectedTypeInfo @NotNull [] infos,
                                                  @Nullable PsiElement context,
                                                  @NotNull PsiClass targetClass) {
    LOG.assertTrue(typeElement.isValid());
    if (typeElement.isPhysical()) {
      ApplicationManager.getApplication().assertWriteAccessAllowed();
    }

    GlobalSearchScope scope = typeElement.getResolveScope();

    if (infos.length == 1 && mySubstitutor != PsiSubstitutor.EMPTY) {
      ExpectedTypeInfo info = infos[0];

      final PsiType expectedType = info.getType();

      final List<PsiTypeParameter> matchedParameters = matchingTypeParameters(mySubstitutor, expectedType, info.getKind());
      if (!matchedParameters.isEmpty()) {
        final List<PsiType> types = new SmartList<>(map(matchedParameters, it -> myFactory.createType(it)));
        ContainerUtil.addAll(types, ExpectedTypesProvider.processExpectedTypes(infos, new MyTypeVisitor(myManager, scope), myProject));
        myBuilder.replaceElement(typeElement, new TypeExpression(myProject, types));
        return typeElement;
      }

      typeElement = replaceTypeElement(typeElement, info.getType());

      PsiSubstitutor rawingSubstitutor = getRawingSubstitutor(myProject, context, targetClass);
      int substitionResult = hasNullSubstitutions(mySubstitutor)
                             ? SUBSTITUTED_NONE
                             : substituteToTypeParameters(typeElement, expectedType, rawingSubstitutor, true);
      if (substitionResult == SUBSTITUTED_IN_PARAMETERS) {
        PsiJavaCodeReferenceElement refElement = typeElement.getInnermostComponentReferenceElement();
        LOG.assertTrue(refElement != null);
        PsiElement qualifier = refElement.getQualifier();
        if (qualifier != null) {
          // Consider type element `java.util.List<java.lang.String>`.
          // At this point there is a template on `java.lang.String` type element already.
          //
          // We need java.util.List element to put the second template on,
          // but there is no such element, because type element consists of:
          // - qualifier `java.util`
          // - dot
          // - reference name element `List`
          // - reference type parameters `<java.lang.String>`
          //
          // Removing the qualifier also removes the dot, so in the end we get `List<java.lang.String>`
          // and we are safe to put the template on the reference name element `List`.
          //
          // Actual shortening or using of FQNs is then handled by com.intellij.codeInsight.template.impl.ShortenFQNamesProcessor.
          qualifier.delete();
        }
        PsiElement referenceNameElement = refElement.getReferenceNameElement();
        LOG.assertTrue(referenceNameElement != null);
        PsiClassType defaultType = getComponentType(info.getDefaultType());
        LOG.assertTrue(defaultType != null);
        PsiClassType rawDefaultType = defaultType.rawType();
        ExpectedTypeInfo info1 = ExpectedTypesProvider.createInfo(rawDefaultType, TYPE_STRICTLY, rawDefaultType, info.getTailType());
        MyTypeVisitor visitor = new MyTypeVisitor(myManager, scope);
        PsiType[] types = ExpectedTypesProvider.processExpectedTypes(new ExpectedTypeInfo[]{info1}, visitor, myProject);
        myBuilder.replaceElement(referenceNameElement, new TypeExpression(myProject, types));
        return typeElement;
      }
      else if (substitionResult != SUBSTITUTED_NONE) {
        return typeElement;
      }
    }

    PsiType[] types = infos.length == 0
                      ? new PsiType[]{typeElement.getType()}
                      : ExpectedTypesProvider.processExpectedTypes(infos, new MyTypeVisitor(myManager, scope), myProject);
    myBuilder.replaceElement(typeElement, new TypeExpression(myProject, types));
    return typeElement;
  }
public @NotNull PsiTypeElement setupTypeElement(@NotNull PsiTypeElement typeElement,
                                                  ExpectedTypeInfo @NotNull [] infos,
                                                  @Nullable PsiElement context,
                                                  @NotNull PsiClass targetClass)