<commit_before>package org.jetbrains.plugins.scala
package lang
package psi
package types

import com.intellij.openapi.util.Key
import collection.immutable.{Map, HashMap}
import java.lang.String
import nonvalue.{Parameter, TypeParameter, ScTypePolymorphicType, ScMethodType}
import com.intellij.psi._
import api.toplevel.ScTypedDefinition
import result.TypingContext

/**
* @author ven
*/
object ScSubstitutor {
  val empty: ScSubstitutor = new ScSubstitutor()

  val key: Key[ScSubstitutor] = Key.create("scala substitutor key")
}

class ScSubstitutor(val tvMap: Map[(String, String), ScType],
                    val aliasesMap: Map[String, Suspension[ScType]],
                    val updateThisType: Option[ScType]) {
  def this() = this(Map.empty, Map.empty, None)

  def this(updateThisType: ScType) {
    this(Map.empty, Map.empty, Some(updateThisType))
  }

  def this(tvMap: Map[(String, String), ScType],
                    aliasesMap: Map[String, Suspension[ScType]],
                    updateThisType: Option[ScType],
                    follower: ScSubstitutor) = {
    this(tvMap, aliasesMap, updateThisType)
    this.follower = follower
  }

  private var follower: ScSubstitutor = null

  def getFollower: ScSubstitutor = follower

  override def toString: String = "ScSubstitutor(" + tvMap + ", " + aliasesMap + ")" +
    (if (follower != null) " followed " + follower.toString else "")

  def bindT(name : (String, String), t: ScType) =
    new ScSubstitutor(tvMap + ((name, t)), aliasesMap, updateThisType, follower)
  def bindA(name: String, t: ScType) =
    new ScSubstitutor(tvMap, aliasesMap + ((name, new Suspension[ScType](t))), updateThisType, follower)
  def bindA(name: String, f: () => ScType) =
    new ScSubstitutor(tvMap, aliasesMap + ((name, new Suspension[ScType](f))), updateThisType, follower)
  def addUpdateThisType(tp: ScType): ScSubstitutor = {
    this followed (new ScSubstitutor(Map.empty, Map.empty, Some(tp)))
  }
  def followed(s: ScSubstitutor): ScSubstitutor = {
    if (follower == null && tvMap.size + aliasesMap.size  == 0 && updateThisType == None) s
    else if (s.getFollower == null && s.tvMap.size + s.aliasesMap.size == 0 && s.updateThisType == None) this
    else new ScSubstitutor(tvMap, aliasesMap, updateThisType,
      if (follower != null) follower followed s else s)
  }

  def subst(t: ScType): ScType = try {
    if (follower != null) follower.subst(substInternal(t)) else substInternal(t)
  }
  catch {
    case s: StackOverflowError =>
      throw new RuntimeException("StackOverFlow during ScSubstitutor.subst(" + t + ") this = " + this, s)
  }

  private def extractTpt(tpt: ScTypeParameterType, t: ScType): ScType = {
    if (tpt.args.length == 0) t
    else t match {
      case ScParameterizedType(t, _) => t
      case _ => t
    }
  }

  protected def substInternal(t: ScType) : ScType = {
    t match {
      case f@ScFunctionType(ret, params) => new ScFunctionType(substInternal(ret), params.map(substInternal(_)))(f.getProject, f.getScope)
      case t1@ScTupleType(comps) => new ScTupleType(comps.map(substInternal))(t1.getProject, t1.getScope)
      case ScProjectionType(proj, element, subst) => new ScProjectionType(substInternal(proj), element, subst)
      case m@ScMethodType(retType, params, isImplicit) => new ScMethodType(substInternal(retType),
        params.map(p => p.copy(paramType = substInternal(p.paramType))), isImplicit)(m.project, m.scope)
      case ScTypePolymorphicType(internalType, typeParameters) => {
        ScTypePolymorphicType(substInternal(internalType), typeParameters.map(tp => {
          TypeParameter(tp.name, substInternal(tp.lowerType), substInternal(tp.upperType), tp.ptp)
        }))
      }
      case ScThisType(clazz) => {
        updateThisType match {
          case Some(oldTp) => {
            var tp = oldTp
            def update(typez: ScType): ScType = {
              ScType.extractDesignated(typez) match {
                case Some((cl: PsiClass, subst)) => {
                  if (cl == clazz) tp
                  else if (cl.isInheritor(clazz, true)) tp
                  else null
                }
                case Some((named: ScTypedDefinition, subst)) =>
                  update(named.getType(TypingContext.empty).getOrElse(Any))
                case _ =>
                  typez match {
                    case ScCompoundType(types, _, _, _) =>
                      val iter = types.iterator
                      while (iter.hasNext) {
                        val tps = iter.next()
                        ScType.extractClass(tps) match {<commit_msg>SCL-3452 Substitute the expected type of a Parameter.<commit_after>package org.jetbrains.plugins.scala
package lang
package psi
package types

import com.intellij.openapi.util.Key
import collection.immutable.{Map, HashMap}
import java.lang.String
import nonvalue.{Parameter, TypeParameter, ScTypePolymorphicType, ScMethodType}
import com.intellij.psi._
import api.toplevel.ScTypedDefinition
import result.TypingContext

/**
* @author ven
*/
object ScSubstitutor {
  val empty: ScSubstitutor = new ScSubstitutor()

  val key: Key[ScSubstitutor] = Key.create("scala substitutor key")
}

class ScSubstitutor(val tvMap: Map[(String, String), ScType],
                    val aliasesMap: Map[String, Suspension[ScType]],
                    val updateThisType: Option[ScType]) {
  def this() = this(Map.empty, Map.empty, None)

  def this(updateThisType: ScType) {
    this(Map.empty, Map.empty, Some(updateThisType))
  }

  def this(tvMap: Map[(String, String), ScType],
                    aliasesMap: Map[String, Suspension[ScType]],
                    updateThisType: Option[ScType],
                    follower: ScSubstitutor) = {
    this(tvMap, aliasesMap, updateThisType)
    this.follower = follower
  }

  private var follower: ScSubstitutor = null

  def getFollower: ScSubstitutor = follower

  override def toString: String = "ScSubstitutor(" + tvMap + ", " + aliasesMap + ")" +
    (if (follower != null) " followed " + follower.toString else "")

  def bindT(name : (String, String), t: ScType) =
    new ScSubstitutor(tvMap + ((name, t)), aliasesMap, updateThisType, follower)
  def bindA(name: String, t: ScType) =
    new ScSubstitutor(tvMap, aliasesMap + ((name, new Suspension[ScType](t))), updateThisType, follower)
  def bindA(name: String, f: () => ScType) =
    new ScSubstitutor(tvMap, aliasesMap + ((name, new Suspension[ScType](f))), updateThisType, follower)
  def addUpdateThisType(tp: ScType): ScSubstitutor = {
    this followed (new ScSubstitutor(Map.empty, Map.empty, Some(tp)))
  }
  def followed(s: ScSubstitutor): ScSubstitutor = {
    if (follower == null && tvMap.size + aliasesMap.size  == 0 && updateThisType == None) s
    else if (s.getFollower == null && s.tvMap.size + s.aliasesMap.size == 0 && s.updateThisType == None) this
    else new ScSubstitutor(tvMap, aliasesMap, updateThisType,
      if (follower != null) follower followed s else s)
  }

  def subst(t: ScType): ScType = try {
    if (follower != null) follower.subst(substInternal(t)) else substInternal(t)
  }
  catch {
    case s: StackOverflowError =>
      throw new RuntimeException("StackOverFlow during ScSubstitutor.subst(" + t + ") this = " + this, s)
  }

  private def extractTpt(tpt: ScTypeParameterType, t: ScType): ScType = {
    if (tpt.args.length == 0) t
    else t match {
      case ScParameterizedType(t, _) => t
      case _ => t
    }
  }

  protected def substInternal(t: ScType) : ScType = {
    t match {
      case f@ScFunctionType(ret, params) => new ScFunctionType(substInternal(ret), params.map(substInternal(_)))(f.getProject, f.getScope)
      case t1@ScTupleType(comps) => new ScTupleType(comps.map(substInternal))(t1.getProject, t1.getScope)
      case ScProjectionType(proj, element, subst) => new ScProjectionType(substInternal(proj), element, subst)
      case m@ScMethodType(retType, params, isImplicit) => new ScMethodType(substInternal(retType),
        params.map(p => p.copy(paramType = substInternal(p.paramType), expectedType = substInternal(p.expectedType))), isImplicit)(m.project, m.scope)
      case ScTypePolymorphicType(internalType, typeParameters) => {
        ScTypePolymorphicType(substInternal(internalType), typeParameters.map(tp => {
          TypeParameter(tp.name, substInternal(tp.lowerType), substInternal(tp.upperType), tp.ptp)
        }))
      }
      case ScThisType(clazz) => {
        updateThisType match {
          case Some(oldTp) => {
            var tp = oldTp
            def update(typez: ScType): ScType = {
              ScType.extractDesignated(typez) match {
                case Some((cl: PsiClass, subst)) => {
                  if (cl == clazz) tp
                  else if (cl.isInheritor(clazz, true)) tp
                  else null
                }
                case Some((named: ScTypedDefinition, subst)) =>
                  update(named.getType(TypingContext.empty).getOrElse(Any))
                case _ =>
                  typez match {
                    case ScCompoundType(types, _, _, _) =>
                      val iter = types.iterator
                      while (iter.hasNext) {
                        val tps = iter.next()
                        ScType.extractClass(tps) match {
{'fraction_non_alphanumeric': 0.11934997847610848, 'fraction_numerical': 0.0017219113215669393, 'mean_word_length': 2.9511054421768708, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4154138', 'n_tokens_mistral': 3021, 'n_tokens_neox': 2878, 'n_words': 667}