private void processParameterListWithStructuralChanges(
      JetChangeInfo changeInfo,
      PsiElement element,
      JetParameterList parameterList,
      JetPsiFactory psiFactory) {
    int parametersCount = changeInfo.getNonReceiverParametersCount();
    boolean isLambda = element instanceof JetFunctionLiteral;
    boolean canReplaceEntireList = false;

    JetParameterList newParameterList = null;
    if (isLambda) {
      if (parametersCount == 0 && ((JetFunctionLiteral) element).getTypeReference() == null) {
        if (parameterList != null) {
          parameterList.delete();
          ASTNode arrowNode = ((JetFunctionLiteral) element).getArrowNode();
          if (arrowNode != null) {
            arrowNode.getPsi().delete();
          }
          parameterList = null;
        }
      } else {
        newParameterList =
            psiFactory.createFunctionLiteralParameterList(
                changeInfo.getNewParametersSignature(
                    (JetFunctionDefinitionUsage<PsiElement>) this));
        canReplaceEntireList = true;
      }
    } else {
      newParameterList =
          psiFactory.createParameterList(
              changeInfo.getNewParametersSignature((JetFunctionDefinitionUsage<PsiElement>) this));
    }

    if (newParameterList == null) return;

    if (parameterList != null) {
      if (canReplaceEntireList) {
        newParameterList = (JetParameterList) parameterList.replace(newParameterList);
      } else {
        newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList);
      }
    } else {
      if (element instanceof JetClass) {
        PsiElement anchor = ((JetClass) element).getTypeParameterList();

        if (anchor == null) {
          anchor = ((JetClass) element).getNameIdentifier();
        }
        if (anchor != null) {
          JetPrimaryConstructor constructor =
              (JetPrimaryConstructor)
                  element.addAfter(psiFactory.createPrimaryConstructor(), anchor);
          JetParameterList oldParameterList = constructor.getValueParameterList();
          assert oldParameterList != null : "primary constructor from factory has parameter list";
          newParameterList = (JetParameterList) oldParameterList.replace(newParameterList);
        }
      } else if (isLambda) {
        //noinspection ConstantConditions
        JetFunctionLiteral functionLiteral = (JetFunctionLiteral) element;
        PsiElement anchor = functionLiteral.getLBrace();
        newParameterList = (JetParameterList) element.addAfter(newParameterList, anchor);
        if (functionLiteral.getArrowNode() == null) {
          Pair<PsiElement, PsiElement> whitespaceAndArrow = psiFactory.createWhitespaceAndArrow();
          element.addRangeAfter(
              whitespaceAndArrow.getFirst(), whitespaceAndArrow.getSecond(), newParameterList);
        }
      }
    }

    if (newParameterList != null) {
      ShortenPackage.addToShorteningWaitSet(newParameterList, Options.DEFAULT);
    }
  }
  @Override
  public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) {
    JetParameterList parameterList;

    JetPsiFactory psiFactory = JetPsiFactory(element.getProject());
    if (element instanceof JetFunction) {
      JetFunction function = (JetFunction) element;
      parameterList = function.getValueParameterList();

      if (changeInfo.isNameChanged()) {
        PsiElement identifier = function.getNameIdentifier();

        if (identifier != null) {
          identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName()));
        }
      }

      boolean returnTypeIsNeeded =
          (changeInfo.isRefactoringTarget(originalFunctionDescriptor)
                  || !(function instanceof JetFunctionLiteral)
                  || function.getTypeReference() != null)
              && !(function instanceof JetSecondaryConstructor);
      if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) {
        function.setTypeReference(null);
        String returnTypeText =
            changeInfo.renderReturnType((JetFunctionDefinitionUsage<PsiElement>) this);

        // TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready
        if (!KotlinBuiltIns.getInstance().getUnitType().toString().equals(returnTypeText)) {
          ShortenPackage.addToShorteningWaitSet(
              function.setTypeReference(JetPsiFactory(function).createType(returnTypeText)),
              Options.DEFAULT);
        }
      }
    } else {
      parameterList = ((JetClass) element).getPrimaryConstructorParameterList();
    }

    if (changeInfo.isParameterSetOrOrderChanged()) {
      processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory);
    } else if (parameterList != null) {
      int paramIndex = 0;

      for (JetParameter parameter : parameterList.getParameters()) {
        JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex];
        changeParameter(paramIndex, parameter, parameterInfo);
        paramIndex++;
      }

      ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
    }

    if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) {
      //noinspection unchecked
      String receiverTypeText =
          changeInfo.renderReceiverType((JetFunctionDefinitionUsage<PsiElement>) this);
      JetTypeReference receiverTypeRef =
          receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
      JetTypeReference newReceiverTypeRef =
          TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef);
      if (newReceiverTypeRef != null) {
        ShortenPackage.addToShorteningWaitSet(
            newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
      }
    }

    if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) {
      changeVisibility(changeInfo, element);
    }

    return true;
  }