<commit_before>package org.jetbrains.plugins.scala
package lang
package resolve

import com.intellij.psi._
import org.jetbrains.plugins.scala.lang.psi.types._
import com.intellij.psi.util.PsiTreeUtil
import psi.ScalaPsiUtil
import psi.impl.toplevel.synthetic.ScSyntheticClass
import psi.api.toplevel.typedef.ScObject
import psi.api.base.patterns.ScBindingPattern
import psi.api.toplevel.imports.usages.{ImportExprUsed, ImportSelectorUsed, ImportWildcardSelectorUsed, ImportUsed}
import extensions.{toPsiClassExt, toPsiNamedElementExt}
import psi.api.statements.params.ScClassParameter
import psi.api.toplevel.ScNamedElement

object ScalaResolveResult {
  def empty = new ScalaResolveResult(null, ScSubstitutor.empty, Set[ImportUsed]())

  def unapply(r: ScalaResolveResult): Some[(PsiNamedElement, ScSubstitutor)] = Some(r.element, r.substitutor)
}

class ScalaResolveResult(val element: PsiNamedElement,
                         val substitutor: ScSubstitutor = ScSubstitutor.empty,
                         val importsUsed: collection.Set[ImportUsed] = collection.Set[ImportUsed](),
                         val nameShadow: Option[String] = None,
                         val implicitConversionClass: Option[PsiClass] = None,
                         val problems: Seq[ApplicabilityProblem] = Seq.empty,
                         val boundClass: PsiClass = null,
                         val implicitFunction: Option[PsiNamedElement] = None,
                         val implicitType: Option[ScType] = None,
                         val defaultParameterUsed: Boolean = false,
                         val innerResolveResult: Option[ScalaResolveResult] = None,
                         val parentElement: Option[PsiNamedElement] = None,
                         val isNamedParameter: Boolean = false,
                         val fromType: Option[ScType] = None,
                         val tuplingUsed: Boolean = false,
                         val isSetterFunction: Boolean = false,
                         val isAssignment: Boolean = false,
                         val notCheckedResolveResult: Boolean = false, 
                         val isAccessible: Boolean = true,
                         val resultUndef: Option[ScUndefinedSubstitutor] = None,
                         val prefixCompletion: Boolean = false,
                         val isDynamic: Boolean = false,
                         val isForwardReference: Boolean = false,
                         val implicitParameterType: Option[ScType] = None) extends ResolveResult {
  if (element == null) throw new NullPointerException("element is null")

  def getElement = element
  
  lazy val name: String = element.name

  /**
   * this is important to get precedence information
   */
  def getActualElement = {
    parentElement match {
      case Some(e) => e
      case None => element
    }
  }

  def isApplicable: Boolean = problems.isEmpty

  def isApplicableInternal: Boolean = {
    innerResolveResult match {
      case Some(r) => r.isApplicable
      case None => isApplicable
    }
  }

  def isValidResult = isAccessible && isApplicable

  def isCyclicReference = false

  def isRenamed: Option[String] = nameShadow

  def copy(subst: ScSubstitutor = substitutor, problems: Seq[ApplicabilityProblem] = problems,
           defaultParameterUsed: Boolean = defaultParameterUsed,
           innerResolveResult: Option[ScalaResolveResult] = innerResolveResult,
           tuplingUsed: Boolean = tuplingUsed,
           isSetterFunction: Boolean = isSetterFunction,
           isAssignment: Boolean = isAssignment,
           notCheckedResolveResult: Boolean = notCheckedResolveResult, 
           isAccessible: Boolean = isAccessible, resultUndef: Option[ScUndefinedSubstitutor] = None,
           isDynamic: Boolean = isDynamic,
           isForwardReference: Boolean = isForwardReference,
           implicitParameterType: Option[ScType] = implicitParameterType): ScalaResolveResult =
    new ScalaResolveResult(element, subst, importsUsed, nameShadow, implicitConversionClass, problems, boundClass,
      implicitFunction, implicitType, defaultParameterUsed, innerResolveResult, parentElement,
      isNamedParameter, fromType, tuplingUsed, isSetterFunction, isAssignment, notCheckedResolveResult,
      isAccessible, resultUndef, isDynamic = isDynamic, isForwardReference = isForwardReference,
      implicitParameterType = implicitParameterType)

  //In valid program we should not have two resolve results with the same element but different substitutor,
  // so factor by element
  override def equals(other: Any): Boolean = other match {
    case rr: ScalaResolveResult =>
      if (element ne rr.element) return false
      if (nameShadow != rr.nameShadow) return false
      innerResolveResult == rr.innerResolveResult
    case _ => false
  }

  override def hashCode: Int = element.hashCode + innerResolveResult.hashCode() * 31 + nameShadow.hashCode() * 31 * 31

  override def toString =  {
    val name = element match {
      case named: ScNamedElement => named.name
      case it => it.toString
    }
    s"""$name [${problems.mkString(", ")}]"""
  }

  private var precedence = -1

  /**
   * See [[org.jetbrains.plugins.scala.lang.resolve.processor.PrecedenceHelper.PrecedenceTypes]]
   */
  def getPrecedence(place: PsiElement, placePackageName: => String): Int = {
    import org.jetbrains.plugins.scala.lang.resolve.processor.PrecedenceHelper.PrecedenceTypes._
    def getPrecedenceInner: Int = {
      def getPackagePrecedence(qualifier: String): Int = {
        if (qualifier == null) return OTHER_MEMBERS
        val index: Int = qualifier.lastIndexOf('.')
        if (index == -1) return PACKAGE_LOCAL_PACKAGE
        val q = qualifier.substring(0, index)
        if (q == "java.lang") return JAVA_LANG
        else if (q == "scala") return SCALA
        else if (q == placePackageName) return OTHER_MEMBERS
        else return PACKAGE_LOCAL_PACKAGE
      }
      def getClazzPrecedence(clazz: PsiClass): Int = {
        val qualifier = clazz.qualifiedName
        if (qualifier == null) return OTHER_MEMBERS
        val index: Int = qualifier.lastIndexOf('.')
        if (index == -1) return OTHER_MEMBERS
        val q = qualifier.substring(0, index)
        if (q == "java.lang") return JAVA_LANG
        else if (q == "scala") return SCALA
        else if (PsiTreeUtil.isContextAncestor(clazz.getContainingFile, place, true)) return OTHER_MEMBERS
        else return PACKAGE_LOCAL
      }
      if (importsUsed.size == 0) {
        ScalaPsiUtil.nameContext(getActualElement) match {
          case synthetic: ScSyntheticClass => return SCALA //like scala.Int
          case obj: ScObject if obj.isPackageObject =>
            val qualifier = obj.qualifiedName
            return getPackagePrecedence(qualifier)<commit_msg>Fixed precedence between object and function with the same name.<commit_after>package org.jetbrains.plugins.scala
package lang
package resolve

import com.intellij.psi._
import org.jetbrains.plugins.scala.lang.psi.types._
import com.intellij.psi.util.PsiTreeUtil
import psi.ScalaPsiUtil
import psi.impl.toplevel.synthetic.ScSyntheticClass
import psi.api.toplevel.typedef.ScObject
import psi.api.base.patterns.ScBindingPattern
import psi.api.toplevel.imports.usages.{ImportExprUsed, ImportSelectorUsed, ImportWildcardSelectorUsed, ImportUsed}
import extensions.{toPsiClassExt, toPsiNamedElementExt}
import psi.api.statements.params.ScClassParameter
import psi.api.toplevel.ScNamedElement

object ScalaResolveResult {
  def empty = new ScalaResolveResult(null, ScSubstitutor.empty, Set[ImportUsed]())

  def unapply(r: ScalaResolveResult): Some[(PsiNamedElement, ScSubstitutor)] = Some(r.element, r.substitutor)
}

class ScalaResolveResult(val element: PsiNamedElement,
                         val substitutor: ScSubstitutor = ScSubstitutor.empty,
                         val importsUsed: collection.Set[ImportUsed] = collection.Set[ImportUsed](),
                         val nameShadow: Option[String] = None,
                         val implicitConversionClass: Option[PsiClass] = None,
                         val problems: Seq[ApplicabilityProblem] = Seq.empty,
                         val boundClass: PsiClass = null,
                         val implicitFunction: Option[PsiNamedElement] = None,
                         val implicitType: Option[ScType] = None,
                         val defaultParameterUsed: Boolean = false,
                         val innerResolveResult: Option[ScalaResolveResult] = None,
                         val parentElement: Option[PsiNamedElement] = None,
                         val isNamedParameter: Boolean = false,
                         val fromType: Option[ScType] = None,
                         val tuplingUsed: Boolean = false,
                         val isSetterFunction: Boolean = false,
                         val isAssignment: Boolean = false,
                         val notCheckedResolveResult: Boolean = false, 
                         val isAccessible: Boolean = true,
                         val resultUndef: Option[ScUndefinedSubstitutor] = None,
                         val prefixCompletion: Boolean = false,
                         val isDynamic: Boolean = false,
                         val isForwardReference: Boolean = false,
                         val implicitParameterType: Option[ScType] = None) extends ResolveResult {
  if (element == null) throw new NullPointerException("element is null")

  def getElement = element
  
  lazy val name: String = element.name

  /**
   * this is important to get precedence information
   */
  def getActualElement = {
    parentElement match {
      case Some(e) => e
      case None => element
    }
  }

  def isApplicable: Boolean = problems.isEmpty

  def isApplicableInternal: Boolean = {
    innerResolveResult match {
      case Some(r) => r.isApplicable
      case None => isApplicable
    }
  }

  def isValidResult = isAccessible && isApplicable

  def isCyclicReference = false

  def isRenamed: Option[String] = nameShadow

  def copy(subst: ScSubstitutor = substitutor, problems: Seq[ApplicabilityProblem] = problems,
           defaultParameterUsed: Boolean = defaultParameterUsed,
           innerResolveResult: Option[ScalaResolveResult] = innerResolveResult,
           tuplingUsed: Boolean = tuplingUsed,
           isSetterFunction: Boolean = isSetterFunction,
           isAssignment: Boolean = isAssignment,
           notCheckedResolveResult: Boolean = notCheckedResolveResult, 
           isAccessible: Boolean = isAccessible, resultUndef: Option[ScUndefinedSubstitutor] = None,
           isDynamic: Boolean = isDynamic,
           isForwardReference: Boolean = isForwardReference,
           implicitParameterType: Option[ScType] = implicitParameterType): ScalaResolveResult =
    new ScalaResolveResult(element, subst, importsUsed, nameShadow, implicitConversionClass, problems, boundClass,
      implicitFunction, implicitType, defaultParameterUsed, innerResolveResult, parentElement,
      isNamedParameter, fromType, tuplingUsed, isSetterFunction, isAssignment, notCheckedResolveResult,
      isAccessible, resultUndef, isDynamic = isDynamic, isForwardReference = isForwardReference,
      implicitParameterType = implicitParameterType)

  //In valid program we should not have two resolve results with the same element but different substitutor,
  // so factor by element
  override def equals(other: Any): Boolean = other match {
    case rr: ScalaResolveResult =>
      if (element ne rr.element) return false
      if (nameShadow != rr.nameShadow) return false
      innerResolveResult == rr.innerResolveResult
    case _ => false
  }

  override def hashCode: Int = element.hashCode + innerResolveResult.hashCode() * 31 + nameShadow.hashCode() * 31 * 31

  override def toString =  {
    val name = element match {
      case named: ScNamedElement => named.name
      case it => it.toString
    }
    s"""$name [${problems.mkString(", ")}]"""
  }

  private var precedence = -1

  /**
   * See [[org.jetbrains.plugins.scala.lang.resolve.processor.PrecedenceHelper.PrecedenceTypes]]
   */
  def getPrecedence(place: PsiElement, placePackageName: => String): Int = {
    import org.jetbrains.plugins.scala.lang.resolve.processor.PrecedenceHelper.PrecedenceTypes._
    def getPrecedenceInner: Int = {
      def getPackagePrecedence(qualifier: String): Int = {
        if (qualifier == null) return OTHER_MEMBERS
        val index: Int = qualifier.lastIndexOf('.')
        if (index == -1) return PACKAGE_LOCAL_PACKAGE
        val q = qualifier.substring(0, index)
        if (q == "java.lang") return JAVA_LANG
        else if (q == "scala") return SCALA
        else if (q == placePackageName) return OTHER_MEMBERS
        else return PACKAGE_LOCAL_PACKAGE
      }
      def getClazzPrecedence(clazz: PsiClass): Int = {
        val qualifier = clazz.qualifiedName
        if (qualifier == null) return OTHER_MEMBERS
        val index: Int = qualifier.lastIndexOf('.')
        if (index == -1) return OTHER_MEMBERS
        val q = qualifier.substring(0, index)
        if (q == "java.lang") return JAVA_LANG
        else if (q == "scala") return SCALA
        else if (PsiTreeUtil.isContextAncestor(clazz.getContainingFile, place, true)) return OTHER_MEMBERS
        else if (q == placePackageName) return PACKAGE_LOCAL
        else return OTHER_MEMBERS
      }
      if (importsUsed.size == 0) {
        ScalaPsiUtil.nameContext(getActualElement) match {
          case synthetic: ScSyntheticClass => return SCALA //like scala.Int
          case obj: ScObject if obj.isPackageObject =>
            val qualifier = obj.qualifiedName
            return getPackagePrecedence(qualifier)
{'fraction_non_alphanumeric': 0.08041551648990265, 'fraction_numerical': 0.0017434258317594073, 'mean_word_length': 2.7532715376226826, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, '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': '4628143', 'n_tokens_mistral': 3776, 'n_tokens_neox': 3663, 'n_words': 956}