<commit_before>package org.jetbrains.plugins.scala.lang
package refactoring.extractMethod

import _root_.com.intellij.psi._
import _root_.com.intellij.refactoring.util.ParameterTablePanel.VariableData
import _root_.org.jetbrains.annotations.Nullable
import _root_.org.jetbrains.plugins.scala.lang.psi.api.base.ScReferenceElement
import _root_.org.jetbrains.plugins.scala.lang.psi.{ScalaPsiUtil, ScalaPsiElement}
import _root_.org.jetbrains.plugins.scala.lang.resolve.ScalaResolveResult
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiElementFactory
import java.util.ArrayList
import com.intellij.refactoring.util.ParameterTablePanel
import org.jetbrains.plugins.scala.ScalaFileType
import org.jetbrains.plugins.scala.lang.psi.fake.FakePsiParameter
import org.jetbrains.plugins.scala.lang.psi.dataFlow.impl.reachingDefs.VariableInfo
import org.jetbrains.plugins.scala.lang.psi.types.result.TypingContext
import java.lang.String
import collection.mutable.ArrayBuffer
import psi.api.{ScalaElementVisitor, ScalaRecursiveElementVisitor}
import psi.api.toplevel.{ScTypeParametersOwner, ScNamedElement, ScTypedDefinition}
import psi.api.expr._
import psi.api.statements.{ScValue, ScFunction}
import psi.api.statements.params.{ScParameter, ScTypeParam}
import scala.util.Sorting
import psi.types.nonvalue.Parameter
import psi.types._
import org.jetbrains.plugins.scala.extensions.toPsiNamedElementExt

/**
 * User: <NAME>
 * Date: 11.01.2010
 */

object ScalaExtractMethodUtils {
  def createMethodFromSettings(settings: ScalaExtractMethodSettings): ScFunction = {
    val builder: StringBuilder = new StringBuilder
    builder.append(settings.visibility)
    builder.append("def ").append(settings.methodName)
    val tp: ArrayBuffer[ScTypeParam] = new ArrayBuffer
    var elem: PsiElement = settings.elements.apply(0)
    while (elem != null && !(elem.getTextRange.contains(settings.nextSibling.getTextRange) &&
            !elem.getTextRange.equalsToRange(settings.nextSibling.getTextRange.getStartOffset,
              settings.nextSibling.getTextRange.getEndOffset))) {
      elem match {
        case tpo: ScTypeParametersOwner => tp ++= tpo.typeParameters
        case _ =>
      }
      elem = elem.getParent
    }
    if (tp.length != 0) {
      builder.append(tp.reverse.map(_.getText).mkString("[", ", ", "]"))
    }
    if (settings.parameters.filter(_.passAsParameter).length != 0) {
      builder.append("(")
      for (param <- settings.parameters) {
        if (param.passAsParameter) {
          builder.append(if (!param.needMirror) param.oldName else "_" + param.newName).append(": ").
                  append(if (param.isCallByNameParameter) "=> " else "").
                  append(ScType.presentableText(param.tp)).append(", ")
        }
      }
      builder.delete(builder.length - 2, builder.length)
      builder.append(")")
    }
    if (settings.calcReturnTypeIsUnit) {
        builder.append("{\n")
    } else {
        builder.append(": ")
        builder.append(settings.calcReturnTypeText)
        builder.append(" = {\n")
    }
    for (param <- settings.parameters) {
      if (!param.passAsParameter) {
        builder.append(if (param.needMirror) "var " else "val ").append(param.oldName).append(": ").
                append(ScType.presentableText(param.tp)).
                append(" = _\n")
      } else if (param.needMirror) {
        builder.append("var ").append(param.oldName).append(": ").append(ScType.presentableText(param.tp)).
                append(" = _").append(param.newName).append("\n")
      }
    }
    val offset = builder.length
    val elementsToAdd: Iterator[PsiElement] = settings.elements.toSeq match {
      case Seq(x: ScBlockExpr) => x.children.toSeq.drop(1).dropRight(1).toIterator // drop '{' and '}'
      case x => x.toIterator
    }
    for (element <- elementsToAdd) {
      builder.append(element.getText)
    }
    if (!settings.lastReturn) {
      settings.returnType match {
        case Some(psi.types.Unit) => {
          if (settings.returns.length == 1) {
            builder.append("\n(false, Some(").append(settings.returns(0).oldParamName).append("))")
          }
          else if (settings.returns.length > 1) {
            builder.append("\n(false, Some(").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")")).
              append("))")
          } else builder.append("\nfalse")
        }
        case Some(tp) => {
          if (settings.returns.length == 1) {
            builder.append("\n(None, Some(").append(settings.returns(0).oldParamName).append("))")
          }
          else if (settings.returns.length > 1) {
            builder.append("\n(None, Some(").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")")).
              append("))")
          } else builder.append("\nNone")
        }
        case _ => {
          if (settings.returns.length == 1) {
            builder.append("\n").append(settings.returns(0).oldParamName)
          }
          else if (settings.returns.length > 1) {
            builder.append("\n").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")"))
          }
        }
      }
    }
    builder.append("\n}")
    val method = ScalaPsiElementFactory.createMethodFromText(builder.toString(), settings.elements.apply(0).getManager)


    val returnVisitor = new ScalaRecursiveElementVisitor {
      override def visitReturnStatement(ret: ScReturnStmt) {
        if (ret.returnFunction != Some(method)) return
        val text = ret.expr match {
          case Some(t) if !settings.lastReturn => "Some(" + t.getText + ")"
          case Some(t) => t.getText
          case _ if !settings.lastReturn => "true"
          case _ => ""
        }
        val retText = new StringBuilder("return ")
        if (settings.returns.length == 0 || settings.lastReturn) retText.append(text)
        else retText.append("(").append(text).append(", None)")
        val retElem = ScalaPsiElementFactory.createExpressionFromText(retText.toString(), ret.getManager)
        ret.replace(retElem)
        super.visitReturnStatement(ret)
      }
    }
    returnVisitor.visitElement(method: ScalaPsiElement)

    settings.returnType match {
      case Some(tp) => {

      }
      case _ => //Nothing to do
    }

    val visitor = new ScalaRecursiveElementVisitor() {
      override def visitReference(ref: ScReferenceElement) {
        ref.bind() match {
          case Some(ScalaResolveResult(named: PsiNamedElement, subst: ScSubstitutor)) =>{
            if (named.getContainingFile == method.getContainingFile && named.getTextOffset < offset &&
                    !named.name.startsWith("_")) {
              val oldName = named.name
              var break = false
              for (param <- settings.parameters if !break) {
                if (param.oldName == oldName) {
                  def tail() {
                    if (param.oldName != param.newName) {
                      val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName, method.getManager)
                      ref.getParent.getNode.replaceChild(ref.getNode, newRef.getNode)
                    }
                  }
                  ref.getParent match {
                    case sect: ScUnderscoreSection if param.isFunction => {
                      val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName, method.getManager)
                      sect.getParent.getNode.replaceChild(sect.getNode, newRef.getNode)
                    }
                    case _ if param.isEmptyParamFunction => {
                      ref.getParent match {
                        case ref: ScReferenceElement if ref.refName == "apply" => tail()
                        case call: ScMethodCall => tail()
                        case _ => {
                          ref.asInstanceOf[ScExpression].expectedType() match {
                            case Some(ScFunctionType(_, params)) if params.length == 0 => tail()
                            case _ => {
                              //we need to replace by method call
                              val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName + "()", method.getManager)
                              ref.getParent.getNode.replaceChild(ref.getNode, newRef.getNode)
                            }
                          }
                        }
                      }
                    }
                    case _ => {
                      tail()
                    }
                  }
                  break = true
                }
              }
            }
          }
          case _ =>
        }
      }
    }
    visitor.visitElement(method)

    val bindTo = new ArrayBuffer[(PsiNamedElement, String)]
    val newVisitor = new ScalaRecursiveElementVisitor() {
      override def visitElement(element: ScalaPsiElement) {
        element match {
          case named: PsiNamedElement if named != method && named.getTextOffset < offset => {
            var break = false
            for (param <- settings.parameters if !break) {
              if (param.oldName == named.name) {
                if (param.oldName != param.newName) {
                  bindTo += ((named, param.newName))
                }
                break = true
              }
            }
          }
          case _ =>
        }
        super.visitElement(element)
      }
    }<commit_msg>Fixed rename parameter for extract method.<commit_after>package org.jetbrains.plugins.scala.lang
package refactoring.extractMethod

import _root_.com.intellij.psi._
import _root_.com.intellij.refactoring.util.ParameterTablePanel.VariableData
import _root_.org.jetbrains.annotations.Nullable
import _root_.org.jetbrains.plugins.scala.lang.psi.api.base.ScReferenceElement
import _root_.org.jetbrains.plugins.scala.lang.psi.{ScalaPsiUtil, ScalaPsiElement}
import _root_.org.jetbrains.plugins.scala.lang.resolve.ScalaResolveResult
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiElementFactory
import java.util.ArrayList
import com.intellij.refactoring.util.ParameterTablePanel
import org.jetbrains.plugins.scala.ScalaFileType
import org.jetbrains.plugins.scala.lang.psi.fake.FakePsiParameter
import org.jetbrains.plugins.scala.lang.psi.dataFlow.impl.reachingDefs.VariableInfo
import org.jetbrains.plugins.scala.lang.psi.types.result.TypingContext
import java.lang.String
import collection.mutable.ArrayBuffer
import psi.api.{ScalaElementVisitor, ScalaRecursiveElementVisitor}
import psi.api.toplevel.{ScTypeParametersOwner, ScNamedElement, ScTypedDefinition}
import psi.api.expr._
import psi.api.statements.{ScValue, ScFunction}
import psi.api.statements.params.{ScParameter, ScTypeParam}
import scala.util.Sorting
import psi.types.nonvalue.Parameter
import psi.types._
import org.jetbrains.plugins.scala.extensions.toPsiNamedElementExt

/**
 * User: <NAME>
 * Date: 11.01.2010
 */

object ScalaExtractMethodUtils {
  def createMethodFromSettings(settings: ScalaExtractMethodSettings): ScFunction = {
    val builder: StringBuilder = new StringBuilder
    builder.append(settings.visibility)
    builder.append("def ").append(settings.methodName)
    val tp: ArrayBuffer[ScTypeParam] = new ArrayBuffer
    var elem: PsiElement = settings.elements.apply(0)
    while (elem != null && !(elem.getTextRange.contains(settings.nextSibling.getTextRange) &&
            !elem.getTextRange.equalsToRange(settings.nextSibling.getTextRange.getStartOffset,
              settings.nextSibling.getTextRange.getEndOffset))) {
      elem match {
        case tpo: ScTypeParametersOwner => tp ++= tpo.typeParameters
        case _ =>
      }
      elem = elem.getParent
    }
    if (tp.length != 0) {
      builder.append(tp.reverse.map(_.getText).mkString("[", ", ", "]"))
    }
    if (settings.parameters.filter(_.passAsParameter).length != 0) {
      builder.append("(")
      for (param <- settings.parameters) {
        if (param.passAsParameter) {
          builder.append(if (!param.needMirror) param.oldName else "_" + param.newName).append(": ").
                  append(if (param.isCallByNameParameter) "=> " else "").
                  append(ScType.presentableText(param.tp)).append(", ")
        }
      }
      builder.delete(builder.length - 2, builder.length)
      builder.append(")")
    }
    if (settings.calcReturnTypeIsUnit) {
        builder.append("{\n")
    } else {
        builder.append(": ")
        builder.append(settings.calcReturnTypeText)
        builder.append(" = {\n")
    }
    for (param <- settings.parameters) {
      if (!param.passAsParameter) {
        builder.append(if (param.needMirror) "var " else "val ").append(param.oldName).append(": ").
                append(ScType.presentableText(param.tp)).
                append(" = _\n")
      } else if (param.needMirror) {
        builder.append("var ").append(param.oldName).append(": ").append(ScType.presentableText(param.tp)).
                append(" = _").append(param.newName).append("\n")
      }
    }
    val offset = builder.length
    val elementsToAdd: Iterator[PsiElement] = settings.elements.toSeq match {
      case Seq(x: ScBlockExpr) => x.children.toSeq.drop(1).dropRight(1).toIterator // drop '{' and '}'
      case x => x.toIterator
    }
    for (element <- elementsToAdd) {
      builder.append(element.getText)
    }
    if (!settings.lastReturn) {
      settings.returnType match {
        case Some(psi.types.Unit) => {
          if (settings.returns.length == 1) {
            builder.append("\n(false, Some(").append(settings.returns(0).oldParamName).append("))")
          }
          else if (settings.returns.length > 1) {
            builder.append("\n(false, Some(").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")")).
              append("))")
          } else builder.append("\nfalse")
        }
        case Some(tp) => {
          if (settings.returns.length == 1) {
            builder.append("\n(None, Some(").append(settings.returns(0).oldParamName).append("))")
          }
          else if (settings.returns.length > 1) {
            builder.append("\n(None, Some(").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")")).
              append("))")
          } else builder.append("\nNone")
        }
        case _ => {
          if (settings.returns.length == 1) {
            builder.append("\n").append(settings.returns(0).oldParamName)
          }
          else if (settings.returns.length > 1) {
            builder.append("\n").append(settings.returns.map(_.oldParamName).mkString("(", ", ", ")"))
          }
        }
      }
    }
    builder.append("\n}")
    val method = ScalaPsiElementFactory.createMethodFromText(builder.toString(), settings.elements.apply(0).getManager)


    val returnVisitor = new ScalaRecursiveElementVisitor {
      override def visitReturnStatement(ret: ScReturnStmt) {
        if (ret.returnFunction != Some(method)) return
        val text = ret.expr match {
          case Some(t) if !settings.lastReturn => "Some(" + t.getText + ")"
          case Some(t) => t.getText
          case _ if !settings.lastReturn => "true"
          case _ => ""
        }
        val retText = new StringBuilder("return ")
        if (settings.returns.length == 0 || settings.lastReturn) retText.append(text)
        else retText.append("(").append(text).append(", None)")
        val retElem = ScalaPsiElementFactory.createExpressionFromText(retText.toString(), ret.getManager)
        ret.replace(retElem)
        super.visitReturnStatement(ret)
      }
    }
    returnVisitor.visitElement(method: ScalaPsiElement)

    settings.returnType match {
      case Some(tp) => {

      }
      case _ => //Nothing to do
    }

    val visitor = new ScalaRecursiveElementVisitor() {
      override def visitReference(ref: ScReferenceElement) {
        ref.bind() match {
          case Some(ScalaResolveResult(named: PsiNamedElement, subst: ScSubstitutor)) =>{
            if (named.getContainingFile == method.getContainingFile && named.getTextOffset < offset &&
                    !named.name.startsWith("_")) {
              val oldName = named.name
              var break = false
              for (param <- settings.parameters if !break) {
                if (param.oldName == oldName) {
                  def tail() {
                    if (param.oldName != param.newName) {
                      val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName, method.getManager)
                      ref.getParent.getNode.replaceChild(ref.getNode, newRef.getNode)
                    }
                  }
                  ref.getParent match {
                    case sect: ScUnderscoreSection if param.isFunction => {
                      val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName, method.getManager)
                      sect.getParent.getNode.replaceChild(sect.getNode, newRef.getNode)
                    }
                    case _ if param.isEmptyParamFunction => {
                      ref.getParent match {
                        case ref: ScReferenceElement if ref.refName == "apply" => tail()
                        case call: ScMethodCall => tail()
                        case _ => {
                          ref.asInstanceOf[ScExpression].expectedType() match {
                            case Some(ScFunctionType(_, params)) if params.length == 0 => tail()
                            case _ => {
                              //we need to replace by method call
                              val newRef = ScalaPsiElementFactory.createExpressionFromText(param.newName + "()", method.getManager)
                              ref.getParent.getNode.replaceChild(ref.getNode, newRef.getNode)
                            }
                          }
                        }
                      }
                    }
                    case _ => {
                      tail()
                    }
                  }
                  break = true
                }
              }
            }
          }
          case _ =>
        }
        super.visitReference(ref)
      }
    }
    visitor.visitElement(method)

    val bindTo = new ArrayBuffer[(PsiNamedElement, String)]
    val newVisitor = new ScalaRecursiveElementVisitor() {
      override def visitElement(element: ScalaPsiElement) {
        element match {
          case named: PsiNamedElement if named != method && named.getTextOffset < offset => {
            var break = false
            for (param <- settings.parameters if !break) {
              if (param.oldName == named.name) {
                if (param.oldName != param.newName) {
                  bindTo += ((named, param.newName))
                }
                break = true
              }
            }
          }
          case _ =>
        }
        super.visitElement(element)
      }
    }
{'fraction_non_alphanumeric': 0.12207613918369502, 'fraction_numerical': 0.002745657109667881, 'mean_word_length': 2.127993393889348, 'pattern_counts': {'":': 8, '<': 19, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1121273', 'n_tokens_mistral': 5286, 'n_tokens_neox': 5163, 'n_words': 878}