<commit_before>package org.jetbrains.plugins.scala
package debugger

import java.util
import java.util.Collections

import com.intellij.debugger.engine._
import com.intellij.debugger.requests.ClassPrepareRequestor
import com.intellij.debugger.{MultiRequestPositionManager, NoDataException, PositionManager, SourcePosition}
import com.intellij.openapi.editor.Document
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.impl.DirectoryIndex
import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi._
import com.intellij.psi.search.{FilenameIndex, GlobalSearchScope}
import com.intellij.psi.util.CachedValueProvider.Result
import com.intellij.psi.util.{CachedValueProvider, CachedValuesManager, PsiTreeUtil}
import com.intellij.util.{Processor, Query}
import com.sun.jdi._
import com.sun.jdi.request.ClassPrepareRequest
import org.jetbrains.annotations.{NotNull, Nullable}
import org.jetbrains.plugins.scala.caches.ScalaShortNamesCacheManager
import org.jetbrains.plugins.scala.debugger.ScalaPositionManager._
import org.jetbrains.plugins.scala.debugger.evaluation.ScalaEvaluatorBuilderUtil
import org.jetbrains.plugins.scala.debugger.evaluation.evaluator.ScalaCompilingEvaluator
import org.jetbrains.plugins.scala.debugger.evaluation.util.DebuggerUtil
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import org.jetbrains.plugins.scala.lang.psi.api.ScalaFile
import org.jetbrains.plugins.scala.lang.psi.api.base.patterns.{ScBindingPattern, ScConstructorPattern, ScInfixPattern}
import org.jetbrains.plugins.scala.lang.psi.api.expr._
import org.jetbrains.plugins.scala.lang.psi.api.statements._
import org.jetbrains.plugins.scala.lang.psi.api.statements.params.{ScParameter, ScParameters}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef._
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiManager
import org.jetbrains.plugins.scala.lang.psi.types.ValueClassType
import org.jetbrains.plugins.scala.lang.refactoring.util.ScalaNamesUtil
import org.jetbrains.plugins.scala.util.macroDebug.ScalaMacroDebuggingUtil

import scala.annotation.tailrec
import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.NameTransformer
import scala.util.Try

/**
  * @author ilyas
  */
class ScalaPositionManager(val debugProcess: DebugProcess) extends PositionManager with MultiRequestPositionManager with LocationLineManager {

  protected val caches = ScalaPositionManagerCaches.instance(debugProcess)
  import caches._

  @Nullable
  def getSourcePosition(@Nullable location: Location): SourcePosition = {
    if (shouldSkip(location)) return null

    val position =
      for {
        loc <- location.toOption
        psiFile <- getPsiFileByReferenceType(debugProcess.getProject, loc.declaringType).toOption
        lineNumber = exactLineNumber(location)
        if lineNumber >= 0
      } yield {
        calcPosition(psiFile, location, lineNumber).getOrElse {
          SourcePosition.createFromLine(psiFile, lineNumber)
        }
      }
    position match {
      case Some(p) => p
      case None => throw NoDataException.INSTANCE
    }
  }

  @NotNull
  def getAllClasses(@NotNull position: SourcePosition): util.List[ReferenceType] = {

    val file = position.getFile
    throwIfNotScalaFile(file)

    val generatedClassName = file.getUserData(ScalaCompilingEvaluator.classNameKey)

    def hasLocations(refType: ReferenceType, position: SourcePosition): Boolean = {
      try {
        val generated = generatedClassName != null && refType.name().contains(generatedClassName)
        lazy val sameFile = getPsiFileByReferenceType(file.getProject, refType) == file

        generated || sameFile && locationsOfLine(refType, position).size > 0
      } catch {
        case _: NoDataException | _: AbsentInformationException | _: ClassNotPreparedException | _: ObjectCollectedException => false
      }
    }

    val possiblePositions = positionsOnLine(file, position.getLine)

    val exactClasses = ArrayBuffer[ReferenceType]()
    val namePatterns = mutable.Set[NamePattern]()
    inReadAction {
      val onTheLine = possiblePositions.map(findGeneratingClassOrMethodParent)
      if (onTheLine.isEmpty) return Collections.emptyList()
      val nonLambdaParent =
        if (isCompiledWithIndyLambdas(file)) {
          val nonStrictParents = Iterator(onTheLine.head) ++ onTheLine.head.parentsInFile
          nonStrictParents.find(p => ScalaEvaluatorBuilderUtil.isGenerateNonAnonfunClass(p))
        } else None

      val sourceImages = onTheLine ++ nonLambdaParent
      sourceImages.foreach {
        case null =>
        case td: ScTypeDefinition if !DebuggerUtil.isLocalClass(td) =>
          val qName = getSpecificNameForDebugger(td)
          val delayedBodyName = if (isDelayedInit(td)) Seq(s"$qName$delayedInitBody") else Nil
          (qName +: delayedBodyName).foreach { name =>
            exactClasses ++= debugProcess.getVirtualMachineProxy.classesByName(name).asScala
          }
        case elem =>
          val namePattern = NamePattern.forElement(elem)
          namePatterns ++= Option(namePattern)
      }
    }
    val packageName: Option[String] = Option(inReadAction(file.asInstanceOf[ScalaFile].getPackageName))

    val foundWithPattern = filterAllClasses(c => hasLocations(c, position) && namePatterns.exists(_.matches(c)), packageName)
    (exactClasses ++ foundWithPattern).distinct.asJava
  }

  @NotNull
  def locationsOfLine(@NotNull refType: ReferenceType, @NotNull position: SourcePosition): util.List[Location] = {

    throwIfNotScalaFile(position.getFile)
    checkForIndyLambdas(refType)

    try {
      val line: Int = position.getLine
      locationsOfLine(refType, line).asJava
    }
    catch {
      case e: AbsentInformationException => Collections.emptyList()
    }
  }

  def createPrepareRequest(@NotNull requestor: ClassPrepareRequestor, @NotNull position: SourcePosition): ClassPrepareRequest = {<commit_msg>small optimization (cherry picked from commit 2856c39)<commit_after>package org.jetbrains.plugins.scala
package debugger

import java.util
import java.util.Collections

import com.intellij.debugger.engine._
import com.intellij.debugger.requests.ClassPrepareRequestor
import com.intellij.debugger.{MultiRequestPositionManager, NoDataException, PositionManager, SourcePosition}
import com.intellij.openapi.editor.Document
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.impl.DirectoryIndex
import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi._
import com.intellij.psi.search.{FilenameIndex, GlobalSearchScope}
import com.intellij.psi.util.CachedValueProvider.Result
import com.intellij.psi.util.{CachedValueProvider, CachedValuesManager, PsiTreeUtil}
import com.intellij.util.{Processor, Query}
import com.sun.jdi._
import com.sun.jdi.request.ClassPrepareRequest
import org.jetbrains.annotations.{NotNull, Nullable}
import org.jetbrains.plugins.scala.caches.ScalaShortNamesCacheManager
import org.jetbrains.plugins.scala.debugger.ScalaPositionManager._
import org.jetbrains.plugins.scala.debugger.evaluation.ScalaEvaluatorBuilderUtil
import org.jetbrains.plugins.scala.debugger.evaluation.evaluator.ScalaCompilingEvaluator
import org.jetbrains.plugins.scala.debugger.evaluation.util.DebuggerUtil
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import org.jetbrains.plugins.scala.lang.psi.api.ScalaFile
import org.jetbrains.plugins.scala.lang.psi.api.base.patterns.{ScBindingPattern, ScConstructorPattern, ScInfixPattern}
import org.jetbrains.plugins.scala.lang.psi.api.expr._
import org.jetbrains.plugins.scala.lang.psi.api.statements._
import org.jetbrains.plugins.scala.lang.psi.api.statements.params.{ScParameter, ScParameters}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef._
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiManager
import org.jetbrains.plugins.scala.lang.psi.types.ValueClassType
import org.jetbrains.plugins.scala.lang.refactoring.util.ScalaNamesUtil
import org.jetbrains.plugins.scala.util.macroDebug.ScalaMacroDebuggingUtil

import scala.annotation.tailrec
import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.NameTransformer
import scala.util.Try

/**
  * @author ilyas
  */
class ScalaPositionManager(val debugProcess: DebugProcess) extends PositionManager with MultiRequestPositionManager with LocationLineManager {

  protected val caches = ScalaPositionManagerCaches.instance(debugProcess)
  import caches._

  @Nullable
  def getSourcePosition(@Nullable location: Location): SourcePosition = {
    if (shouldSkip(location)) return null

    val position =
      for {
        loc <- location.toOption
        psiFile <- getPsiFileByReferenceType(debugProcess.getProject, loc.declaringType).toOption
        lineNumber = exactLineNumber(location)
        if lineNumber >= 0
      } yield {
        calcPosition(psiFile, location, lineNumber).getOrElse {
          SourcePosition.createFromLine(psiFile, lineNumber)
        }
      }
    position match {
      case Some(p) => p
      case None => throw NoDataException.INSTANCE
    }
  }

  @NotNull
  def getAllClasses(@NotNull position: SourcePosition): util.List[ReferenceType] = {

    val file = position.getFile
    throwIfNotScalaFile(file)

    val generatedClassName = file.getUserData(ScalaCompilingEvaluator.classNameKey)

    def hasLocations(refType: ReferenceType, position: SourcePosition): Boolean = {
      try {
        val generated = generatedClassName != null && refType.name().contains(generatedClassName)
        lazy val sameFile = getPsiFileByReferenceType(file.getProject, refType) == file

        generated || sameFile && locationsOfLine(refType, position).size > 0
      } catch {
        case _: NoDataException | _: AbsentInformationException | _: ClassNotPreparedException | _: ObjectCollectedException => false
      }
    }

    val possiblePositions = positionsOnLine(file, position.getLine)

    val exactClasses = ArrayBuffer[ReferenceType]()
    val namePatterns = mutable.Set[NamePattern]()
    inReadAction {
      val onTheLine = possiblePositions.map(findGeneratingClassOrMethodParent)
      if (onTheLine.isEmpty) return Collections.emptyList()
      val nonLambdaParent =
        if (isCompiledWithIndyLambdas(file)) {
          val nonStrictParents = Iterator(onTheLine.head) ++ onTheLine.head.parentsInFile
          nonStrictParents.find(p => ScalaEvaluatorBuilderUtil.isGenerateNonAnonfunClass(p))
        } else None

      val sourceImages = onTheLine ++ nonLambdaParent
      sourceImages.foreach {
        case null =>
        case td: ScTypeDefinition if !DebuggerUtil.isLocalClass(td) =>
          val qName = getSpecificNameForDebugger(td)
          val delayedBodyName = if (isDelayedInit(td)) Seq(s"$qName$delayedInitBody") else Nil
          (qName +: delayedBodyName).foreach { name =>
            exactClasses ++= debugProcess.getVirtualMachineProxy.classesByName(name).asScala
          }
        case elem =>
          val namePattern = NamePattern.forElement(elem)
          namePatterns ++= Option(namePattern)
      }
    }
    val packageName: Option[String] = Option(inReadAction(file.asInstanceOf[ScalaFile].getPackageName))

    val foundWithPattern =
      if (namePatterns.isEmpty) Nil
      else filterAllClasses(c => hasLocations(c, position) && namePatterns.exists(_.matches(c)), packageName)

    (exactClasses ++ foundWithPattern).distinct.asJava
  }

  @NotNull
  def locationsOfLine(@NotNull refType: ReferenceType, @NotNull position: SourcePosition): util.List[Location] = {

    throwIfNotScalaFile(position.getFile)
    checkForIndyLambdas(refType)

    try {
      val line: Int = position.getLine
      locationsOfLine(refType, line).asJava
    }
    catch {
      case e: AbsentInformationException => Collections.emptyList()
    }
  }

  def createPrepareRequest(@NotNull requestor: ClassPrepareRequestor, @NotNull position: SourcePosition): ClassPrepareRequest = {
{'fraction_non_alphanumeric': 0.0912940793224204, 'fraction_numerical': 0.0008143985666585227, 'mean_word_length': 4.465064530485091, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, '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': '3751182', 'n_tokens_mistral': 3653, 'n_tokens_neox': 3527, 'n_words': 618}