-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'StartDebugAdapter' command now accepts user's parameters (launch.json) #1466
'StartDebugAdapter' command now accepts user's parameters (launch.json) #1466
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really cool, I think this will be super useful. Left some comments, but I will also check the other PR.
metals/src/main/scala/scala/meta/internal/metals/MetalsLanguageServer.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/MetalsLanguageServer.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/MetalsLanguageServer.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/ServerCommands.scala
Outdated
Show resolved
Hide resolved
fb192c1
to
fef5e50
Compare
c751eb0
to
f57dc5a
Compare
|
metals/src/main/scala/scala/meta/internal/metals/BuildTargetClasses.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/debug/DebugServer.scala
Outdated
Show resolved
Hide resolved
metals/src/main/scala/scala/meta/internal/metals/debug/DebugServer.scala
Outdated
Show resolved
Hide resolved
Also, increasing the timeout to The underlying cause is that the BuildTargetClasses are fetched initially as a part of the indexing and |
Thank you for the review and the advice @marek1840 , will try that.
|
As for the server hanging - I am at a loss but can try to debug it if you share the exact sequence of steps (I can at least try, even if it would mean repeating them a few times to encounter this singularity ;) ). Also, a thread dump could help a great deal in finding the cause. |
basically, you open metals-vscode project in VS Code, run debug, and in newly opened code instance open a simple project with a main class with one-line |
@marek1840 I've made some reworks, and fixed flakiness of tests by including indexing build targets into |
Don't see though, why it still fails on CI, the tests are being passed now on my machine 🤔 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This branch was failing on my machine at first, but after second or third run it started passing and the error never appeared during 5-10 repetitions.
It is worth checking if the the query for build classes is issued before they are populated and whether they are populated at all.
ef8c0c7
to
5772341
Compare
for using with 'launch.json'
debug-resolve-class command removed, now debug-adapter-start uses additional parameters
+ fixed test output for 'DebugProtocolSuite', thanks to @marek1840
224c833
to
82361a8
Compare
added rebuild recovery for resolving classes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks to be shaping up nicely! I still how some comments, but overall concept and design looks good!
metals/src/main/scala/scala/meta/internal/metals/BuildTargetClasses.scala
Show resolved
Hide resolved
} { target => | ||
buildTargetClasses | ||
.classesOf(target.getId()) | ||
.testClasses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like the only difference between the 2 functions is here and two lines below. Can w reuse the code and just add maybe a function Classes => Option[T]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, I've added
private def findClassAndBuildTarget[A](
className: String,
buildTarget: Option[String],
findClassesByName: String => List[(A, b.BuildTargetIdentifier)],
classesByBuildTarget: b.BuildTargetIdentifier => Iterable[A],
getClassName: A => String
): Try[List[(A, b.BuildTarget)]]
to generalize them
|{ | ||
| mainClass: "com.foo.App", | ||
| buildTarget: "foo", | ||
| args: ["bar"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we able to also add environment variables? Also, let's add jvmOptions
to the example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the input for this Params
class is based on ScalaMainClass
params, and it does not take environment variables.
About jvmOpts -- can you propose one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marek1840 Would make sense to add them to BSP?
@alekseiAlefirov Maybe -Dfile.encoding=UTF-8
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
@@ -152,7 +152,7 @@ private[debug] object DebugProxy { | |||
endpoint: RemoteEndpoint, | |||
name: String | |||
): RemoteEndpoint = { | |||
val trace = GlobalTrace.setup(name) | |||
val trace = GlobalTrace.setupTracePrinter(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should fixed the issues with missing logs.
buildTargetClasses: BuildTargetClasses | ||
)(implicit ec: ExecutionContext): Future[A] = { | ||
Future.fromTry(f()).recoverWith { | ||
case _: ClassNotFoundException | _: BuildTargetNotFoundException => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BuildTargetNotFoundException
will not be needed here. User would need reimport the build to change them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good one, fixed
@@ -105,6 +114,85 @@ object DebugServer { | |||
} | |||
} | |||
|
|||
def resolveMainClassParams( | |||
params: DebugUnresolvedMainClassParams, | |||
buildTargetClassesFinder: BuildTargetClassesFinder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's maybe move these new methods to BuildTargetClassesFinder
with other than params
method parameters added to the constructor? Also, with client instead of showWarningMessage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure. This method takes some debug parameters to resolve them to other parameters and reports about running debug on one class, if multiple found. So it's more about debug, then about finding, which is extracted to Finder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then maybe this should not actually be an object but maybe DebugProvider
class? Start also takes a lot of parameters, which are not specific to the actual function invocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DebugProvider
class created, all code from DebugServer
object moved to it.
case _: ClassNotFoundException | _: BuildTargetNotFoundException => | ||
val allTargets = buildTargets.all.toSeq.map(_.info.getId()) | ||
for { | ||
_ <- compilations.compileTargets(allTargets) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think even if we manage to find the build target we should still run compile on it.
So, do the same, but on single target first. If that fails, compile all targets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, added narrowed recovery for ClassNotFoundInBuildTargetException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just two more comments! Sorry for being so nitpicky! 😅
} | ||
|
||
session.asJavaObject | ||
val debugSessionParamsParser = new JsonParser.Of[b.DebugSessionParams] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's maybe move those parsers to an object, no need to recreate them each time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created DebugParametersJsonParsers
with these parsers
@@ -105,6 +114,85 @@ object DebugServer { | |||
} | |||
} | |||
|
|||
def resolveMainClassParams( | |||
params: DebugUnresolvedMainClassParams, | |||
buildTargetClassesFinder: BuildTargetClassesFinder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then maybe this should not actually be an object but maybe DebugProvider
class? Start also takes a lot of parameters, which are not specific to the actual function invocation.
@tgodzik agreed on that |
@@ -122,6 +123,8 @@ class MetalsLanguageServer( | |||
private val languageClient = new DelegatingLanguageClient(NoopLanguageClient) | |||
var userConfig: UserConfiguration = UserConfiguration() | |||
val buildTargets: BuildTargets = new BuildTargets() | |||
private val buildTargetClassesFinder = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unused now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you! fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment left, but otherwise I think this is ready.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jus last comments, tested it all out and seems to work really good! Thanks for the awesome cotnribution!
params.testClass, | ||
Option(params.buildTarget) | ||
) | ||
}).map { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fail on Nil, could you handle that case?
Option(params.buildTarget) | ||
) | ||
).map { | ||
case (clazz, target) :: others => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will also fail on Nil, could you handle that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as I commented on BuildTargetClassFinder#findMainClassAndItsBuildTarget
(above method def), it either returns Success
with non-empty list, or Failure
. So it should not be the case. I wish we had a type-level solution for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solution for NonEmptyList? You have scalaz.NonEmptyList
, cats.data.NonEmptyList
, everything is already included in dependencies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, last time I checked (several months ago), cats
just got eliminated from Metals, and it was said it's better to have less dependencies. Okay, thanks, @kpbochenek !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, seems like there's no cats used in the main code, and @tgodzik recommended not to start.
^ fixed with throw NoSuchElement(Exception)
for the Nil
case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@ckipp01 This might be helpful for |
Yes! I'll have to dive into this a bit more and then that'd be awesome. Because right now if it's reliant on code-lenses, then only nvim users will benefit. |
Exactly, with this PR however we will no longer be reliant on code lenses. |
Issue: scalameta/metals-vscode#217
In this PR

debug-adapter-start
command is modified to accept more type of parameters like configuration above.Client side PR: scalameta/metals-vscode#223