<commit_before>package org.jetbrains.plugins.scala
package lang
package psi
package api
package expr

import base.patterns.ScCaseClause
import statements._
import params.ScParameter
import psi.impl.toplevel.synthetic.ScSyntheticFunction
import base.{ScConstructor, ScReferenceElement}
import collection.mutable.ArrayBuffer
import types._
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi._
import nonvalue.{TypeParameter, Parameter, ScTypePolymorphicType, ScMethodType}
import toplevel.{ScTypeParametersOwner, ScTypedDefinition}
import result.{TypeResult, Success, TypingContext}
import base.types.{ScParameterizedTypeElement, ScSimpleTypeElement, ScSequenceArg, ScTypeElement}
import collection.immutable.HashMap
import lang.resolve.{StdKinds, ScalaResolveResult}
import lang.resolve.processor.{MethodResolveProcessor, ResolveProcessor}
import types.Compatibility.Expression

/**
 * @author ilyas
 *
 * Utility object to calculate expected type of any expression
 */

private[expr] object ExpectedTypes {
  /**
   * Do not use this method inside of resolve or type inference.
   * Using this leads to SOE.
   */
  def smartExpectedType(expr: ScExpression): Option[ScType] = smartExpectedTypeEx(expr).map(_._1)

  def smartExpectedTypeEx(expr: ScExpression): Option[(ScType, Option[ScTypeElement])] = {
    val types = expectedExprTypes(expr, true)
    types.length match {
      case 1 => Some(types(0))
      case _ => None
    }
  }
  
  def expectedExprType(expr: ScExpression): Option[(ScType, Option[ScTypeElement])] = {
    val types = expr.expectedTypesEx
    types.length match {
      case 1 => Some(types(0))
      case _ => None
    }
  }

  implicit def typeToPair(tpe: ScType): (ScType, Option[ScTypeElement]) = (tpe, None) // TODO jzaugg remove

  /**
   * @return (expectedType, expectedTypeElement)
   */
  def expectedExprTypes(expr: ScExpression, withResolvedFunction: Boolean = false): Array[(ScType, Option[ScTypeElement])] = {
    //this method needs to replace expected type to return type if it's placholder function expression
    def finalize(expr: ScExpression): Array[(ScType, Option[ScTypeElement])] = {
      ScUnderScoreSectionUtil.underscores(expr).length match {
        case 0 => expr.expectedTypesEx
        case _ => {
          val res = new ArrayBuffer[(ScType, Option[ScTypeElement])]
          for (tp <- expr.expectedTypes) {
            ScType.extractFunctionType(tp._1) match {
              case Some(ScFunctionType(rt: ScType, _)) => res += rt
              case None =>
            }
          }
          res.toArray
        }
      }
    }
    expr.getContext match {
      case p: ScParenthesisedExpr => p.expectedTypesEx
      //see SLS[6.11]
      case b: ScBlockExpr => b.lastExpr match {
        case Some(e) if e == expr => finalize(b)
        case _ => Array.empty
      }
      //see SLS[6.16]
      case cond: ScIfStmt if cond.condition.getOrElse(null: ScExpression) == expr => Array((types.Boolean, None))
      case cond: ScIfStmt if cond.elseBranch != None => finalize(cond)
      //see SLA[6.22]
      case tb: ScTryBlock => tb.lastExpr match {
        case Some(e) if e == expr => finalize(tb.getContext.asInstanceOf[ScTryStmt])
        case _ => Array.empty
      }
      case fb: ScFinallyBlock => Array((types.Unit, None))
      //see SLS[8.4]
      case c: ScCaseClause => c.getContext.getContext match {
        case m: ScMatchStmt => finalize(m)
        case b: ScBlockExpr if b.isAnonymousFunction => {
          finalize(b).flatMap(tp => ScType.extractFunctionType(tp._1) match {
            case Some(ScFunctionType(retType, _)) => Array[(ScType, Option[ScTypeElement])]((retType, None))
            case _ => ScType.extractPartialFunctionType(tp._1) match {
              case Some((des, param, ret)) => Array[(ScType, Option[ScTypeElement])]((ret, None))
              case None => Array[(ScType, Option[ScTypeElement])]()
            }
          })
        }
        case cb: ScCatchBlock =>
          finalize(cb.getContext.asInstanceOf[ScTryStmt])
        case _ => Array.empty
      }
      //see SLS[6.23]
      case f: ScFunctionExpr => finalize(f).flatMap(tp => ScType.extractFunctionType(tp._1) match {
        case Some(ScFunctionType(retType, _)) => Array[(ScType, Option[ScTypeElement])]((retType, None))
        case _ => Array[(ScType, Option[ScTypeElement])]()
      })
      case t: ScTypedStmt if t.getLastChild.isInstanceOf[ScSequenceArg] => {
        t.expectedTypesEx
      }
      //SLS[6.13]
      case t: ScTypedStmt => {
        t.typeElement match {
          case Some(te) => Array((te.getType(TypingContext.empty).getOrElse(Any), Some(te)))
          case _ => Array.empty<commit_msg>SCL-3133 Expected type for `e` within `throw e` is `java.lang.Throwable`.<commit_after>package org.jetbrains.plugins.scala
package lang
package psi
package api
package expr

import base.patterns.ScCaseClause
import statements._
import params.ScParameter
import psi.impl.toplevel.synthetic.ScSyntheticFunction
import base.{ScConstructor, ScReferenceElement}
import collection.mutable.ArrayBuffer
import types._
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi._
import nonvalue.{TypeParameter, Parameter, ScTypePolymorphicType, ScMethodType}
import toplevel.{ScTypeParametersOwner, ScTypedDefinition}
import result.{TypeResult, Success, TypingContext}
import base.types.{ScParameterizedTypeElement, ScSimpleTypeElement, ScSequenceArg, ScTypeElement}
import collection.immutable.HashMap
import lang.resolve.{StdKinds, ScalaResolveResult}
import lang.resolve.processor.{MethodResolveProcessor, ResolveProcessor}
import types.Compatibility.Expression

/**
 * @author ilyas
 *
 * Utility object to calculate expected type of any expression
 */

private[expr] object ExpectedTypes {
  /**
   * Do not use this method inside of resolve or type inference.
   * Using this leads to SOE.
   */
  def smartExpectedType(expr: ScExpression): Option[ScType] = smartExpectedTypeEx(expr).map(_._1)

  def smartExpectedTypeEx(expr: ScExpression): Option[(ScType, Option[ScTypeElement])] = {
    val types = expectedExprTypes(expr, true)
    types.length match {
      case 1 => Some(types(0))
      case _ => None
    }
  }
  
  def expectedExprType(expr: ScExpression): Option[(ScType, Option[ScTypeElement])] = {
    val types = expr.expectedTypesEx
    types.length match {
      case 1 => Some(types(0))
      case _ => None
    }
  }

  implicit def typeToPair(tpe: ScType): (ScType, Option[ScTypeElement]) = (tpe, None) // TODO jzaugg remove

  /**
   * @return (expectedType, expectedTypeElement)
   */
  def expectedExprTypes(expr: ScExpression, withResolvedFunction: Boolean = false): Array[(ScType, Option[ScTypeElement])] = {
    //this method needs to replace expected type to return type if it's placholder function expression
    def finalize(expr: ScExpression): Array[(ScType, Option[ScTypeElement])] = {
      ScUnderScoreSectionUtil.underscores(expr).length match {
        case 0 => expr.expectedTypesEx
        case _ => {
          val res = new ArrayBuffer[(ScType, Option[ScTypeElement])]
          for (tp <- expr.expectedTypes) {
            ScType.extractFunctionType(tp._1) match {
              case Some(ScFunctionType(rt: ScType, _)) => res += rt
              case None =>
            }
          }
          res.toArray
        }
      }
    }
    expr.getContext match {
      case p: ScParenthesisedExpr => p.expectedTypesEx
      //see SLS[6.11]
      case b: ScBlockExpr => b.lastExpr match {
        case Some(e) if e == expr => finalize(b)
        case _ => Array.empty
      }
      //see SLS[6.16]
      case cond: ScIfStmt if cond.condition.getOrElse(null: ScExpression) == expr => Array((types.Boolean, None))
      case cond: ScIfStmt if cond.elseBranch != None => finalize(cond)
      //see SLA[6.22]
      case tb: ScTryBlock => tb.lastExpr match {
        case Some(e) if e == expr => finalize(tb.getContext.asInstanceOf[ScTryStmt])
        case _ => Array.empty
      }
      case fb: ScFinallyBlock => Array((types.Unit, None))
      case te: ScThrowStmt =>
        // Not in the SLS, but in the implementation.
        val throwableClass = JavaPsiFacade.getInstance(te.getProject).findClass("java.lang.Throwable", te.getResolveScope)
        val throwableType = if (throwableClass != null) new ScDesignatorType(throwableClass) else Any
        Array((throwableType, None))
      //see SLS[8.4]
      case c: ScCaseClause => c.getContext.getContext match {
        case m: ScMatchStmt => finalize(m)
        case b: ScBlockExpr if b.isAnonymousFunction => {
          finalize(b).flatMap(tp => ScType.extractFunctionType(tp._1) match {
            case Some(ScFunctionType(retType, _)) => Array[(ScType, Option[ScTypeElement])]((retType, None))
            case _ => ScType.extractPartialFunctionType(tp._1) match {
              case Some((des, param, ret)) => Array[(ScType, Option[ScTypeElement])]((ret, None))
              case None => Array[(ScType, Option[ScTypeElement])]()
            }
          })
        }
        case cb: ScCatchBlock =>
          finalize(cb.getContext.asInstanceOf[ScTryStmt])
        case _ => Array.empty
      }
      //see SLS[6.23]
      case f: ScFunctionExpr => finalize(f).flatMap(tp => ScType.extractFunctionType(tp._1) match {
        case Some(ScFunctionType(retType, _)) => Array[(ScType, Option[ScTypeElement])]((retType, None))
        case _ => Array[(ScType, Option[ScTypeElement])]()
      })
      case t: ScTypedStmt if t.getLastChild.isInstanceOf[ScSequenceArg] => {
        t.expectedTypesEx
      }
      //SLS[6.13]
      case t: ScTypedStmt => {
        t.typeElement match {
          case Some(te) => Array((te.getType(TypingContext.empty).getOrElse(Any), Some(te)))
          case _ => Array.empty
{'fraction_non_alphanumeric': 0.11681289532748419, 'fraction_numerical': 0.005917159763313609, 'mean_word_length': 3.1467851099830795, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 76, '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': '6036590', 'n_tokens_mistral': 2959, 'n_tokens_neox': 2954, 'n_words': 684}