All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.epfl.scala.debugadapter.internal.SourceLookUpProvider.scala Maven / Gradle / Ivy

package ch.epfl.scala.debugadapter.internal

import ch.epfl.scala.debugadapter.ClassEntry
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider
import java.net.URI
import ch.epfl.scala.debugadapter.Logger
import ch.epfl.scala.debugadapter.internal.scalasig.ScalaSig
import scala.collection.parallel.immutable.ParVector

private[debugadapter] final class SourceLookUpProvider(
    private[internal] val classPathEntries: Seq[ClassEntryLookUp],
    sourceUriToClassPathEntry: Map[URI, ClassEntryLookUp],
    fqcnToClassPathEntry: Map[String, ClassEntryLookUp]
) extends ISourceLookUpProvider {
  override def supportsRealtimeBreakpointVerification(): Boolean = true

  override def getSourceFileURI(fqcn: String, path: String): String = {
    getSourceFile(fqcn).map(_.toString).orNull
  }

  override def getSourceContents(uri: String): String = {
    val sourceUri = URI.create(uri)
    sourceUriToClassPathEntry
      .get(sourceUri)
      .flatMap(_.getSourceContent(sourceUri))
      .orNull
  }

  override def getFullyQualifiedName(
      uriRepr: String,
      lines: Array[Int],
      columns: Array[Int]
  ): Array[String] = {
    val uri = URI.create(uriRepr)
    uri.getScheme match {
      case "dap-fqcn" =>
        val resolvedName = uri.getSchemeSpecificPart
        lines.map(_ => resolvedName)
      case _ =>
        sourceUriToClassPathEntry.get(uri) match {
          case None => lines.map(_ => null)
          case Some(entry) =>
            lines.map(line => entry.getFullyQualifiedClassName(uri, line).orNull)
        }
    }
  }

  def getClassFile(fqcn: String): Option[ClassFile] =
    fqcnToClassPathEntry.get(fqcn).flatMap(_.getClassFile(fqcn))

  def getClassEntry(fqcn: String): Option[ClassEntry] =
    fqcnToClassPathEntry.get(fqcn).map(_.entry)

  def getSourceContentFromClassName(fqcn: String): Option[String] =
    fqcnToClassPathEntry.get(fqcn).flatMap(_.getSourceContentFromClassName(fqcn))

  def containsClass(fqcn: String): Boolean =
    fqcnToClassPathEntry.contains(fqcn)

  private[internal] def allClassNames: Iterable[String] =
    classPathEntries.flatMap(_.fullyQualifiedNames)
  private[internal] def allOrphanClasses: Iterable[ClassFile] =
    classPathEntries.flatMap(_.orphanClassFiles)

  private[internal] def getScalaSig(fqcn: String): Option[ScalaSig] = {
    for {
      classPathEntry <- fqcnToClassPathEntry.get(fqcn)
      scalaSig <- classPathEntry.getScalaSig(fqcn)
    } yield scalaSig
  }

  private def getSourceFile(className: String): Option[URI] = {
    fqcnToClassPathEntry
      .get(className)
      .flatMap(_.getSourceFile(className))
  }
}

private[debugadapter] object SourceLookUpProvider {
  def apply(entries: Seq[ClassEntry], logger: Logger): SourceLookUpProvider = {
    val parrallelEntries = ParVector(entries*)
    val sourceFilesByEntry = parrallelEntries
      .flatMap(_.sourceEntries)
      .distinct
      .map(entry => entry -> SourceEntryLookUp.getAllSourceFiles(entry, logger))
      .toMap
    val allLookUps = parrallelEntries
      .map(entry => ClassEntryLookUp(entry, entry.sourceEntries.flatMap(sourceFilesByEntry.apply), logger))
      .seq
    val sourceUriToClassPathEntry = allLookUps
      .flatMap(lookup => lookup.sources.map(uri => (uri, lookup)))
      .toMap
    val fqcnToClassPathEntry = allLookUps
      .flatMap(lookup => lookup.fullyQualifiedNames.map(fqcn => (fqcn, lookup)))
      .toMap
    new SourceLookUpProvider(
      allLookUps,
      sourceUriToClassPathEntry,
      fqcnToClassPathEntry
    )
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy