Skip to content

Commit

Permalink
Merge branch 'main' into runtime-evaluator
Browse files Browse the repository at this point in the history
  • Loading branch information
iusildra authored May 10, 2023
2 parents 7a14386 + 241e060 commit aecbb32
Show file tree
Hide file tree
Showing 22 changed files with 311 additions and 279 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package ch.epfl.scala.debugadapter

import ch.epfl.scala.debugadapter.internal.DebugAdapter
import ch.epfl.scala.debugadapter.internal.DebugSession
import com.microsoft.java.debug.core.adapter.IProviderContext

import java.net.InetSocketAddress
import java.net.ServerSocket
Expand All @@ -15,7 +13,7 @@ import scala.util.control.NonFatal

final class DebugServer private (
debuggee: Debuggee,
context: IProviderContext,
resolver: DebugToolsResolver,
logger: Logger,
address: DebugServer.Address,
config: DebugConfig
Expand Down Expand Up @@ -49,7 +47,7 @@ final class DebugServer private (
*/
private[debugadapter] def connect(): DebugSession = {
val socket = serverSocket.accept()
val session = DebugSession(socket, debuggee, context, logger, config)
val session = DebugSession(socket, debuggee, resolver, logger, config)
lock.synchronized {
if (closedServer) {
session.close()
Expand Down Expand Up @@ -107,13 +105,12 @@ object DebugServer {
*/
def apply(
debuggee: Debuggee,
tools: DebugTools,
resolver: DebugToolsResolver,
logger: Logger,
address: Address = new Address,
config: DebugConfig = DebugConfig.default
)(implicit ec: ExecutionContext): DebugServer = {
val context = DebugAdapter.context(debuggee, tools, logger, config)
new DebugServer(debuggee, context, logger, address, config)
new DebugServer(debuggee, resolver, logger, address, config)
}

/**
Expand All @@ -131,13 +128,13 @@ object DebugServer {
*/
def start(
debuggee: Debuggee,
tools: DebugTools,
resolver: DebugToolsResolver,
logger: Logger,
autoCloseSession: Boolean = false,
gracePeriod: Duration = 5.seconds
)(implicit ec: ExecutionContext): Handler = {
val config = DebugConfig.default.copy(gracePeriod = gracePeriod, autoCloseSession = autoCloseSession)
val server = DebugServer(debuggee, tools, logger, config = config)
val server = DebugServer(debuggee, resolver, logger, config = config)
val running = server.start()
running.onComplete(_ => server.close())
new Handler(server.uri, running)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ch.epfl.scala.debugadapter.internal

import com.microsoft.java.debug.core.adapter.ICompletionsProvider
import com.microsoft.java.debug.core.protocol.Types
import com.sun.jdi.StackFrame

import java.util

object CompletionsProvider extends ICompletionsProvider {
override def codeComplete(
frame: StackFrame,
snippet: String,
line: Int,
column: Int
): util.List[Types.CompletionItem] = util.Collections.emptyList()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package ch.epfl.scala.debugadapter.internal

import ch.epfl.scala.debugadapter._
import ch.epfl.scala.debugadapter.*
import ch.epfl.scala.debugadapter.testing.TestSuiteSummary
import com.microsoft.java.debug.core.adapter.IProviderContext
import com.microsoft.java.debug.core.adapter.{ProtocolServer => DapServer}
import com.microsoft.java.debug.core.adapter.ProtocolServer
import com.microsoft.java.debug.core.protocol.Events
import com.microsoft.java.debug.core.protocol.Events.OutputEvent
import com.microsoft.java.debug.core.protocol.JsonUtils
import com.microsoft.java.debug.core.protocol.Messages.Request
import com.microsoft.java.debug.core.protocol.Messages.Response
import com.microsoft.java.debug.core.protocol.Requests._
import com.microsoft.java.debug.core.protocol.Requests.*

import java.net.InetSocketAddress
import java.net.Socket
Expand Down Expand Up @@ -38,12 +37,13 @@ import scala.util.control.NonFatal
private[debugadapter] final class DebugSession private (
socket: Socket,
debuggee: Debuggee,
context: IProviderContext,
context: ScalaProviderContext,
resolver: DebugToolsResolver,
logger: Logger,
loggingAdapter: LoggingAdapter,
config: DebugConfig
)(implicit executionContext: ExecutionContext)
extends DapServer(
extends ProtocolServer(
socket.getInputStream,
socket.getOutputStream,
context,
Expand Down Expand Up @@ -143,7 +143,16 @@ private[debugadapter] final class DebugSession private (
protected override def dispatchRequest(request: Request): Unit = {
val requestId = request.seq
request.command match {
case "attach" =>
val tools = DebugTools(debuggee, resolver, logger)
context.configure(tools)
super.dispatchRequest(request)
case "launch" =>
val launchArgs = JsonUtils.fromJson(request.arguments, classOf[LaunchArguments])
val tools =
if (launchArgs.noDebug) DebugTools.none
else DebugTools(debuggee, resolver, logger)
context.configure(tools)
// launch request is implemented by spinning up a JVM
// and sending an attach request to the java DapServer
launchedRequests.add(requestId)
Expand Down Expand Up @@ -283,13 +292,14 @@ private[debugadapter] object DebugSession {
def apply(
socket: Socket,
debuggee: Debuggee,
context: IProviderContext,
resolver: DebugToolsResolver,
logger: Logger,
config: DebugConfig
)(implicit executionContext: ExecutionContext): DebugSession = {
try {
val loggingHandler = new LoggingAdapter(logger)
new DebugSession(socket, debuggee, context, logger, loggingHandler, config)
val context = ScalaProviderContext(debuggee, logger, config)
new DebugSession(socket, debuggee, context, resolver, logger, loggingHandler, config)
} catch {
case NonFatal(cause) =>
logger.trace(cause)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
package ch.epfl.scala.debugadapter
package ch.epfl.scala.debugadapter.internal

import scala.reflect.io.File
import ch.epfl.scala.debugadapter._
import ch.epfl.scala.debugadapter.internal.ScalaExtension._
import ch.epfl.scala.debugadapter.internal.evaluator.ExpressionCompiler

final case class DebugTools(expressionCompilers: Map[ClassEntry, ExpressionCompiler], stepFilter: Option[ClassLoader])
import scala.reflect.io.File

private[debugadapter] final class DebugTools(
val expressionCompilers: Map[ClassEntry, ExpressionCompiler],
val stepFilter: Option[ClassLoader],
val sourceLookUp: SourceLookUpProvider
)

object DebugTools {

def none: DebugTools =
new DebugTools(Map.empty, None, SourceLookUpProvider.empty)

/**
* Resolve the expression compilers and the step filter of the debuggee
* Resolve the expression compilers and the step filter of the debuggee,
* Link all classes with source file in the SourceLookUpProvider
*
* At most 2 expression compilers are resolved, one for Scala 2 and one for Scala 3
* TODO if scala3Entries is not empty we should use the Scala 3 step filter
*/
def apply(debuggee: Debuggee, resolver: DebugToolsResolver, logger: Logger): DebugTools = {
val allCompilers = TimeUtils.logTime(logger, "Loaded expression compiler") {
loadExpressionCompiler(debuggee, resolver, logger)
}

val stepFilter =
if (debuggee.scalaVersion.isScala3) {
TimeUtils.logTime(logger, "Loaded step filter") {
resolver
.resolveStepFilter(debuggee.scalaVersion)
.warnFailure(logger, s"Cannot fetch step filter of Scala ${debuggee.scalaVersion}")
}
} else None

val sourceLookup =
TimeUtils.logTime(logger, "Loaded all sources and classes") {
val classEntries = debuggee.classEntries
val distinctEntries = classEntries
.groupBy(e => e.name)
.map { case (name, group) =>
if (group.size > 1) logger.warn(s"Found duplicate entry $name in debuggee ${debuggee.name}")
group.head
}
.toSeq
SourceLookUpProvider(distinctEntries, logger)
}

new DebugTools(allCompilers, stepFilter, sourceLookup)
}

/* At most 2 expression compilers are resolved, one for Scala 2 and one for Scala 3
* For both Scala 2 and Scala 3 we want to use the most recent known version:
* - the version of the main module
* - or the version of the scala-library/scala3-library in the classpath
Expand All @@ -25,10 +67,12 @@ object DebugTools {
* The scalacOptions are adapted so that:
* - both compilers can unpickle Scala 2 AND Scala 3
* - both compilers does not fail on warnings
*
* TODO if scala3Entries is not empty we should use the Scala 3 step filter
*/
def apply(debuggee: Debuggee, resolver: DebugToolsResolver, logger: Logger): DebugTools = {
private def loadExpressionCompiler(
debuggee: Debuggee,
resolver: DebugToolsResolver,
logger: Logger
): Map[ClassEntry, ExpressionCompiler] = {
val scala2Entries = debuggee.managedEntries.filter(_.isScala2)
val scala3Entries = debuggee.managedEntries.filter(_.isScala3)
val scala2Version =
Expand Down Expand Up @@ -74,15 +118,7 @@ object DebugTools {
} yield entry -> compiler
}

val allCompilers = debuggee.managedEntries.flatMap(loadExpressionCompiler).toMap
val stepFilter =
if (debuggee.scalaVersion.isScala3) {
resolver
.resolveStepFilter(debuggee.scalaVersion)
.warnFailure(logger, s"Cannot fetch step filter of Scala ${debuggee.scalaVersion}")
} else None

new DebugTools(allCompilers, stepFilter)
debuggee.managedEntries.flatMap(loadExpressionCompiler).toMap
}

private val optionsToRemove = Set("-Xfatal-warnings", "-Werror")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ch.epfl.scala.debugadapter.internal
import ch.epfl.scala.debugadapter.BuildInfo
import ch.epfl.scala.debugadapter.ClassEntry
import ch.epfl.scala.debugadapter.DebugConfig
import ch.epfl.scala.debugadapter.DebugTools
import ch.epfl.scala.debugadapter.Debuggee
import ch.epfl.scala.debugadapter.EvaluationFailed
import ch.epfl.scala.debugadapter.JavaRuntime
Expand Down Expand Up @@ -230,18 +229,17 @@ private[internal] class EvaluationProvider(
private[internal] object EvaluationProvider {
def apply(
debuggee: Debuggee,
debugTools: DebugTools,
sourceLookUp: SourceLookUpProvider,
tools: DebugTools,
logger: Logger,
config: DebugConfig
): IEvaluationProvider = {
val simpleEvaluator = new SimpleEvaluator(logger, config.testMode)
val scalaEvaluators = debugTools.expressionCompilers.view.map { case (entry, compiler) =>
val scalaEvaluators = tools.expressionCompilers.view.map { case (entry, compiler) =>
(entry, new ScalaEvaluator(entry, compiler, logger, config.testMode))
}.toMap
val messageLogger = new MessageLogger()
new EvaluationProvider(
sourceLookUp,
tools.sourceLookUp,
simpleEvaluator,
messageLogger,
scalaEvaluators,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ch.epfl.scala.debugadapter.internal

import com.microsoft.java.debug.core.adapter.HotCodeReplaceEvent
import com.microsoft.java.debug.core.adapter.IHotCodeReplaceProvider
import io.reactivex.Observable

import java.util
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer

object HotCodeReplaceProvider extends IHotCodeReplaceProvider {
override def onClassRedefined(consumer: Consumer[util.List[String]]): Unit =
()

override def redefineClasses(): CompletableFuture[util.List[String]] =
CompletableFuture.completedFuture(util.Collections.emptyList())

override def getEventHub: Observable[HotCodeReplaceEvent] =
Observable.empty()
}
Loading

0 comments on commit aecbb32

Please sign in to comment.