Skip to content

Commit 241e060

Browse files
authored
Merge pull request #422 from adpi2/speed-up-2
Skip configuration if noDebug in launchRequest
2 parents b156f13 + 5f5a8e1 commit 241e060

File tree

24 files changed

+314
-282
lines changed

24 files changed

+314
-282
lines changed

modules/core/src/main/scala/ch/epfl/scala/debugadapter/DebugServer.scala

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package ch.epfl.scala.debugadapter
22

3-
import ch.epfl.scala.debugadapter.internal.DebugAdapter
43
import ch.epfl.scala.debugadapter.internal.DebugSession
5-
import com.microsoft.java.debug.core.adapter.IProviderContext
64

75
import java.net.InetSocketAddress
86
import java.net.ServerSocket
@@ -15,7 +13,7 @@ import scala.util.control.NonFatal
1513

1614
final class DebugServer private (
1715
debuggee: Debuggee,
18-
context: IProviderContext,
16+
resolver: DebugToolsResolver,
1917
logger: Logger,
2018
address: DebugServer.Address,
2119
config: DebugConfig
@@ -49,7 +47,7 @@ final class DebugServer private (
4947
*/
5048
private[debugadapter] def connect(): DebugSession = {
5149
val socket = serverSocket.accept()
52-
val session = DebugSession(socket, debuggee, context, logger, config)
50+
val session = DebugSession(socket, debuggee, resolver, logger, config)
5351
lock.synchronized {
5452
if (closedServer) {
5553
session.close()
@@ -107,13 +105,12 @@ object DebugServer {
107105
*/
108106
def apply(
109107
debuggee: Debuggee,
110-
tools: DebugTools,
108+
resolver: DebugToolsResolver,
111109
logger: Logger,
112110
address: Address = new Address,
113111
config: DebugConfig = DebugConfig.default
114112
)(implicit ec: ExecutionContext): DebugServer = {
115-
val context = DebugAdapter.context(debuggee, tools, logger, config)
116-
new DebugServer(debuggee, context, logger, address, config)
113+
new DebugServer(debuggee, resolver, logger, address, config)
117114
}
118115

119116
/**
@@ -131,13 +128,13 @@ object DebugServer {
131128
*/
132129
def start(
133130
debuggee: Debuggee,
134-
tools: DebugTools,
131+
resolver: DebugToolsResolver,
135132
logger: Logger,
136133
autoCloseSession: Boolean = false,
137134
gracePeriod: Duration = 5.seconds
138135
)(implicit ec: ExecutionContext): Handler = {
139136
val config = DebugConfig.default.copy(gracePeriod = gracePeriod, autoCloseSession = autoCloseSession)
140-
val server = DebugServer(debuggee, tools, logger, config = config)
137+
val server = DebugServer(debuggee, resolver, logger, config = config)
141138
val running = server.start()
142139
running.onComplete(_ => server.close())
143140
new Handler(server.uri, running)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ch.epfl.scala.debugadapter.internal
2+
3+
import com.microsoft.java.debug.core.adapter.ICompletionsProvider
4+
import com.microsoft.java.debug.core.protocol.Types
5+
import com.sun.jdi.StackFrame
6+
7+
import java.util
8+
9+
object CompletionsProvider extends ICompletionsProvider {
10+
override def codeComplete(
11+
frame: StackFrame,
12+
snippet: String,
13+
line: Int,
14+
column: Int
15+
): util.List[Types.CompletionItem] = util.Collections.emptyList()
16+
}

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/DebugAdapter.scala

Lines changed: 0 additions & 79 deletions
This file was deleted.

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/DebugSession.scala

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package ch.epfl.scala.debugadapter.internal
22

3-
import ch.epfl.scala.debugadapter._
3+
import ch.epfl.scala.debugadapter.*
44
import ch.epfl.scala.debugadapter.testing.TestSuiteSummary
5-
import com.microsoft.java.debug.core.adapter.IProviderContext
6-
import com.microsoft.java.debug.core.adapter.{ProtocolServer => DapServer}
5+
import com.microsoft.java.debug.core.adapter.ProtocolServer
76
import com.microsoft.java.debug.core.protocol.Events
87
import com.microsoft.java.debug.core.protocol.Events.OutputEvent
98
import com.microsoft.java.debug.core.protocol.JsonUtils
109
import com.microsoft.java.debug.core.protocol.Messages.Request
1110
import com.microsoft.java.debug.core.protocol.Messages.Response
12-
import com.microsoft.java.debug.core.protocol.Requests._
11+
import com.microsoft.java.debug.core.protocol.Requests.*
1312

1413
import java.net.InetSocketAddress
1514
import java.net.Socket
@@ -38,12 +37,13 @@ import scala.util.control.NonFatal
3837
private[debugadapter] final class DebugSession private (
3938
socket: Socket,
4039
debuggee: Debuggee,
41-
context: IProviderContext,
40+
context: ScalaProviderContext,
41+
resolver: DebugToolsResolver,
4242
logger: Logger,
4343
loggingAdapter: LoggingAdapter,
4444
config: DebugConfig
4545
)(implicit executionContext: ExecutionContext)
46-
extends DapServer(
46+
extends ProtocolServer(
4747
socket.getInputStream,
4848
socket.getOutputStream,
4949
context,
@@ -143,7 +143,16 @@ private[debugadapter] final class DebugSession private (
143143
protected override def dispatchRequest(request: Request): Unit = {
144144
val requestId = request.seq
145145
request.command match {
146+
case "attach" =>
147+
val tools = DebugTools(debuggee, resolver, logger)
148+
context.configure(tools)
149+
super.dispatchRequest(request)
146150
case "launch" =>
151+
val launchArgs = JsonUtils.fromJson(request.arguments, classOf[LaunchArguments])
152+
val tools =
153+
if (launchArgs.noDebug) DebugTools.none
154+
else DebugTools(debuggee, resolver, logger)
155+
context.configure(tools)
147156
// launch request is implemented by spinning up a JVM
148157
// and sending an attach request to the java DapServer
149158
launchedRequests.add(requestId)
@@ -283,13 +292,14 @@ private[debugadapter] object DebugSession {
283292
def apply(
284293
socket: Socket,
285294
debuggee: Debuggee,
286-
context: IProviderContext,
295+
resolver: DebugToolsResolver,
287296
logger: Logger,
288297
config: DebugConfig
289298
)(implicit executionContext: ExecutionContext): DebugSession = {
290299
try {
291300
val loggingHandler = new LoggingAdapter(logger)
292-
new DebugSession(socket, debuggee, context, logger, loggingHandler, config)
301+
val context = ScalaProviderContext(debuggee, logger, config)
302+
new DebugSession(socket, debuggee, context, resolver, logger, loggingHandler, config)
293303
} catch {
294304
case NonFatal(cause) =>
295305
logger.trace(cause)

modules/core/src/main/scala/ch/epfl/scala/debugadapter/DebugTools.scala renamed to modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/DebugTools.scala

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,59 @@
1-
package ch.epfl.scala.debugadapter
1+
package ch.epfl.scala.debugadapter.internal
22

3-
import scala.reflect.io.File
3+
import ch.epfl.scala.debugadapter._
44
import ch.epfl.scala.debugadapter.internal.ScalaExtension._
55
import ch.epfl.scala.debugadapter.internal.evaluator.ExpressionCompiler
66

7-
final case class DebugTools(expressionCompilers: Map[ClassEntry, ExpressionCompiler], stepFilter: Option[ClassLoader])
7+
import scala.reflect.io.File
8+
9+
private[debugadapter] final class DebugTools(
10+
val expressionCompilers: Map[ClassEntry, ExpressionCompiler],
11+
val stepFilter: Option[ClassLoader],
12+
val sourceLookUp: SourceLookUpProvider
13+
)
814

915
object DebugTools {
1016

17+
def none: DebugTools =
18+
new DebugTools(Map.empty, None, SourceLookUpProvider.empty)
19+
1120
/**
12-
* Resolve the expression compilers and the step filter of the debuggee
21+
* Resolve the expression compilers and the step filter of the debuggee,
22+
* Link all classes with source file in the SourceLookUpProvider
1323
*
14-
* At most 2 expression compilers are resolved, one for Scala 2 and one for Scala 3
24+
* TODO if scala3Entries is not empty we should use the Scala 3 step filter
25+
*/
26+
def apply(debuggee: Debuggee, resolver: DebugToolsResolver, logger: Logger): DebugTools = {
27+
val allCompilers = TimeUtils.logTime(logger, "Loaded expression compiler") {
28+
loadExpressionCompiler(debuggee, resolver, logger)
29+
}
30+
31+
val stepFilter =
32+
if (debuggee.scalaVersion.isScala3) {
33+
TimeUtils.logTime(logger, "Loaded step filter") {
34+
resolver
35+
.resolveStepFilter(debuggee.scalaVersion)
36+
.warnFailure(logger, s"Cannot fetch step filter of Scala ${debuggee.scalaVersion}")
37+
}
38+
} else None
39+
40+
val sourceLookup =
41+
TimeUtils.logTime(logger, "Loaded all sources and classes") {
42+
val classEntries = debuggee.classEntries
43+
val distinctEntries = classEntries
44+
.groupBy(e => e.name)
45+
.map { case (name, group) =>
46+
if (group.size > 1) logger.warn(s"Found duplicate entry $name in debuggee ${debuggee.name}")
47+
group.head
48+
}
49+
.toSeq
50+
SourceLookUpProvider(distinctEntries, logger)
51+
}
52+
53+
new DebugTools(allCompilers, stepFilter, sourceLookup)
54+
}
55+
56+
/* At most 2 expression compilers are resolved, one for Scala 2 and one for Scala 3
1557
* For both Scala 2 and Scala 3 we want to use the most recent known version:
1658
* - the version of the main module
1759
* - or the version of the scala-library/scala3-library in the classpath
@@ -25,10 +67,12 @@ object DebugTools {
2567
* The scalacOptions are adapted so that:
2668
* - both compilers can unpickle Scala 2 AND Scala 3
2769
* - both compilers does not fail on warnings
28-
*
29-
* TODO if scala3Entries is not empty we should use the Scala 3 step filter
3070
*/
31-
def apply(debuggee: Debuggee, resolver: DebugToolsResolver, logger: Logger): DebugTools = {
71+
private def loadExpressionCompiler(
72+
debuggee: Debuggee,
73+
resolver: DebugToolsResolver,
74+
logger: Logger
75+
): Map[ClassEntry, ExpressionCompiler] = {
3276
val scala2Entries = debuggee.managedEntries.filter(_.isScala2)
3377
val scala3Entries = debuggee.managedEntries.filter(_.isScala3)
3478
val scala2Version =
@@ -74,15 +118,7 @@ object DebugTools {
74118
} yield entry -> compiler
75119
}
76120

77-
val allCompilers = debuggee.managedEntries.flatMap(loadExpressionCompiler).toMap
78-
val stepFilter =
79-
if (debuggee.scalaVersion.isScala3) {
80-
resolver
81-
.resolveStepFilter(debuggee.scalaVersion)
82-
.warnFailure(logger, s"Cannot fetch step filter of Scala ${debuggee.scalaVersion}")
83-
} else None
84-
85-
new DebugTools(allCompilers, stepFilter)
121+
debuggee.managedEntries.flatMap(loadExpressionCompiler).toMap
86122
}
87123

88124
private val optionsToRemove = Set("-Xfatal-warnings", "-Werror")

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/EvaluationProvider.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package ch.epfl.scala.debugadapter.internal
33
import ch.epfl.scala.debugadapter.BuildInfo
44
import ch.epfl.scala.debugadapter.ClassEntry
55
import ch.epfl.scala.debugadapter.DebugConfig
6-
import ch.epfl.scala.debugadapter.DebugTools
76
import ch.epfl.scala.debugadapter.Debuggee
87
import ch.epfl.scala.debugadapter.EvaluationFailed
98
import ch.epfl.scala.debugadapter.JavaRuntime
@@ -198,18 +197,17 @@ private[internal] class EvaluationProvider(
198197
private[internal] object EvaluationProvider {
199198
def apply(
200199
debuggee: Debuggee,
201-
debugTools: DebugTools,
202-
sourceLookUp: SourceLookUpProvider,
200+
tools: DebugTools,
203201
logger: Logger,
204202
config: DebugConfig
205203
): IEvaluationProvider = {
206204
val simpleEvaluator = new SimpleEvaluator(logger, config.testMode)
207-
val scalaEvaluators = debugTools.expressionCompilers.view.map { case (entry, compiler) =>
205+
val scalaEvaluators = tools.expressionCompilers.view.map { case (entry, compiler) =>
208206
(entry, new ScalaEvaluator(entry, compiler, logger, config.testMode))
209207
}.toMap
210208
val messageLogger = new MessageLogger()
211209
new EvaluationProvider(
212-
sourceLookUp,
210+
tools.sourceLookUp,
213211
simpleEvaluator,
214212
messageLogger,
215213
scalaEvaluators,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ch.epfl.scala.debugadapter.internal
2+
3+
import com.microsoft.java.debug.core.adapter.HotCodeReplaceEvent
4+
import com.microsoft.java.debug.core.adapter.IHotCodeReplaceProvider
5+
import io.reactivex.Observable
6+
7+
import java.util
8+
import java.util.concurrent.CompletableFuture
9+
import java.util.function.Consumer
10+
11+
object HotCodeReplaceProvider extends IHotCodeReplaceProvider {
12+
override def onClassRedefined(consumer: Consumer[util.List[String]]): Unit =
13+
()
14+
15+
override def redefineClasses(): CompletableFuture[util.List[String]] =
16+
CompletableFuture.completedFuture(util.Collections.emptyList())
17+
18+
override def getEventHub: Observable[HotCodeReplaceEvent] =
19+
Observable.empty()
20+
}

0 commit comments

Comments
 (0)