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

import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.plugins.scala.extensions.toPsiClassExt
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScTypeAliasDefinition
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ScClass, ScTrait, ScTypeDefinition}
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiManager
import org.jetbrains.plugins.scala.lang.psi.types.result.{Success, TypingContext}
import org.jetbrains.plugins.scala.lang.refactoring.util.ScTypeUtil.AliasType

import scala.annotation.tailrec

/**
* @author ilyas
*/
object ScFunctionType {
  def apply(returnType: ScType, params: Seq[ScType])(project: Project, scope: GlobalSearchScope): ValueType = {
    def findClass(fullyQualifiedName: String) : Option[PsiClass] = {
      Option(ScalaPsiManager.instance(project).getCachedClass(scope, fullyQualifiedName))
    }
    findClass("scala.Function" + params.length) match {
      case Some(t: ScTrait) =>
        val typeParams = params.toList :+ returnType
        ScParameterizedType(ScType.designator(t), typeParams)
      case _ => types.Nothing
    }
  }

  @tailrec
  def extractForPrefix(tp: ScType, prefix: String): Option[(ScTypeDefinition, Seq[ScType])] = {
    tp.isAliasType match {
      case Some(AliasType(t: ScTypeAliasDefinition, Success(lower, _), _)) => extractForPrefix(lower, prefix)
      case _ =>
        tp match {
          case p: ScParameterizedType =>
            def startsWith(clazz: PsiClass, qualNamePrefix: String) = clazz.qualifiedName != null && clazz.qualifiedName.startsWith(qualNamePrefix)

            ScType.extractClassType(p.designator) match {
              case Some((clazz: ScTypeDefinition, sub)) if startsWith(clazz, prefix) =>
                val result = clazz.getType(TypingContext.empty)
                result match {
                  case Success(t, _) =>
                    val substituted = (sub followed p.substitutor).subst(t)
                    substituted match {
                      case pt: ScParameterizedType => Some((clazz, pt.typeArgs))
                      case _ => None
                    }
                  case _ => None
                }
              case _ => None
            }
          case _ => None
        }
    }

  }

  def unapply(tp: ScType): Option[(ScType, Seq[ScType])] = {
    extractForPrefix(tp, "scala.Function") match {
      case Some((clazz, typeArgs)) if typeArgs.length > 0 =>
        val (params, Seq(ret)) = typeArgs.splitAt(typeArgs.length - 1)
        Some(ret, params)
      case _ => None
    }
  }

  def isFunctionType(tp: ScType): Boolean = unapply(tp).isDefined
}

object ScTupleType {
  def apply(components: Seq[ScType])(project: Project, scope: GlobalSearchScope): ValueType = {
    def findClass(fullyQualifiedName: String) : Option[PsiClass] = {
      Option(ScalaPsiManager.instance(project).getCachedClass(scope, fullyQualifiedName))
    }
    findClass("scala.Tuple" + components.length) match {
      case Some(t: ScClass) =>
        ScParameterizedType(ScType.designator(t), components)
      case _ => types.Nothing
    }
  }

  def unapply(tp: ScType): Option[Seq[ScType]] = {
    ScFunctionType.extractForPrefix(tp, "scala.Tuple") match {
      case Some((clazz, typeArgs)) if typeArgs.length > 0 =>
        Some(typeArgs)
      case _ => None
    }
  }
}
<commit_msg>Hack to avoid infinite loop for cyclic type aliases. Imagine situation that there is no type alias definition with recursion depth more than 100, then this hack just removes cyclic type aliases cases. #SCL-6880 Fixed<commit_after>package org.jetbrains.plugins.scala
package lang
package psi
package types

import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.plugins.scala.extensions.toPsiClassExt
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScTypeAliasDefinition
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ScClass, ScTrait, ScTypeDefinition}
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiManager
import org.jetbrains.plugins.scala.lang.psi.types.result.{Success, TypingContext}
import org.jetbrains.plugins.scala.lang.refactoring.util.ScTypeUtil.AliasType

import scala.annotation.tailrec

/**
* @author ilyas
*/
object ScFunctionType {
  def apply(returnType: ScType, params: Seq[ScType])(project: Project, scope: GlobalSearchScope): ValueType = {
    def findClass(fullyQualifiedName: String) : Option[PsiClass] = {
      Option(ScalaPsiManager.instance(project).getCachedClass(scope, fullyQualifiedName))
    }
    findClass("scala.Function" + params.length) match {
      case Some(t: ScTrait) =>
        val typeParams = params.toList :+ returnType
        ScParameterizedType(ScType.designator(t), typeParams)
      case _ => types.Nothing
    }
  }

  @tailrec
  def extractForPrefix(tp: ScType, prefix: String, depth: Int = 100): Option[(ScTypeDefinition, Seq[ScType])] = {
    if (depth == 0) return None //hack for http://youtrack.jetbrains.com/issue/SCL-6880 to avoid infinite loop.
    tp.isAliasType match {
      case Some(AliasType(t: ScTypeAliasDefinition, Success(lower, _), _)) => extractForPrefix(lower, prefix, depth - 1)
      case _ =>
        tp match {
          case p: ScParameterizedType =>
            def startsWith(clazz: PsiClass, qualNamePrefix: String) = clazz.qualifiedName != null && clazz.qualifiedName.startsWith(qualNamePrefix)

            ScType.extractClassType(p.designator) match {
              case Some((clazz: ScTypeDefinition, sub)) if startsWith(clazz, prefix) =>
                val result = clazz.getType(TypingContext.empty)
                result match {
                  case Success(t, _) =>
                    val substituted = (sub followed p.substitutor).subst(t)
                    substituted match {
                      case pt: ScParameterizedType => Some((clazz, pt.typeArgs))
                      case _ => None
                    }
                  case _ => None
                }
              case _ => None
            }
          case _ => None
        }
    }

  }

  def unapply(tp: ScType): Option[(ScType, Seq[ScType])] = {
    extractForPrefix(tp, "scala.Function") match {
      case Some((clazz, typeArgs)) if typeArgs.length > 0 =>
        val (params, Seq(ret)) = typeArgs.splitAt(typeArgs.length - 1)
        Some(ret, params)
      case _ => None
    }
  }

  def isFunctionType(tp: ScType): Boolean = unapply(tp).isDefined
}

object ScTupleType {
  def apply(components: Seq[ScType])(project: Project, scope: GlobalSearchScope): ValueType = {
    def findClass(fullyQualifiedName: String) : Option[PsiClass] = {
      Option(ScalaPsiManager.instance(project).getCachedClass(scope, fullyQualifiedName))
    }
    findClass("scala.Tuple" + components.length) match {
      case Some(t: ScClass) =>
        ScParameterizedType(ScType.designator(t), components)
      case _ => types.Nothing
    }
  }

  def unapply(tp: ScType): Option[Seq[ScType]] = {
    ScFunctionType.extractForPrefix(tp, "scala.Tuple") match {
      case Some((clazz, typeArgs)) if typeArgs.length > 0 =>
        Some(typeArgs)
      case _ => None
    }
  }
}

{'fraction_non_alphanumeric': 0.11118634886240521, 'fraction_numerical': 0.002979414951245937, 'mean_word_length': 3.007053716766142, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 43, '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': '5904825', 'n_tokens_mistral': 2289, 'n_tokens_neox': 2188, 'n_words': 449}