-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add unsafe RawPresentationCompiler implementation #24133
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
base: main
Are you sure you want to change the base?
Conversation
…iver will now check for Thread.isInterrupted cancellation
LabelPart(": ") :: toLabelParts(tpe, pos), | ||
InlayHintKind.Type, | ||
) | ||
.addDefinition(adjustedPos.start) |
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.
It was removed out of sudden in Scala 2 presentation compiler, I believe it is no longer necessary as we're deduplicating inlay hints during add
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 it wasn't actually doing anything anymore
| | ||
|def test/*: (path : String<<java/lang/String#>>, num : Int<<scala/Int#>>, line : Int<<scala/Int#>>)*/ = | ||
| hello ++/*[Tuple1<<scala/Tuple1#>>["line"], Tuple1<<scala/Tuple1#>>[Int<<scala/Int#>>]]*/ (line = 1)/*(using refl<<scala/`<:<`.refl().>>)*//*[Tuple1<<scala/Tuple1#>>[Int<<scala/Int#>>]]*/ | ||
| hello ++/*[Tuple1<<scala/Tuple1#>>["line"], Tuple1<<scala/Tuple1#>>[Int<<scala/Int#>>]]*/ (line = 1)/*[Tuple1<<scala/Tuple1#>>[Int<<scala/Int#>>]]*//*(using refl<<scala/`<:<`.refl().>>)*/ |
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.
Caused by mtags version bump
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 good to me. (Just "Comment", since I don't feel "in the loop" enough to understand the context of these changes)
} | ||
|
||
tree match |
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.
TLDR: I think that it's fine to patch only the necessary changes for now, but this should probably be refactored (similarly as Scala 2 code) soon-ish.
The refactor in the Scala 2 PC was meant to allow for more than one "case" to be executed here. This isn't a problem yet, since scalameta/metals#7815 hasn't been ported yet. Though one could make an argument that this problem appeared before and was "hacked" my merging implementations for two inlay hint types.
The idea behind the refactor is:
- We move the logic from the branches in this match into private methods on appropriate Inlay-Hint-providing-objects.
- Afterwards, this method is simplified to a
foldLeft
through all the cases. - Every Inlay-Hint-providing-objects returns its inlay hints in separation, and we merge them together for every tree.
- Afterwards, they can be deduplicated (right now only for InferredType) – this separates generation and deduplication.
I think that a similar refactor should be done here as well, though it maybe shouldn't be part of this PR.
import org.eclipse.lsp4j as l | ||
|
||
|
||
case class RawScalaPresentationCompiler( |
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.
Could you add a comment that explains the purpose of this class?
|
||
lazy val presentationCompilerSettings = { | ||
val mtagsVersion = "1.6.2" | ||
val mtagsVersion = "1.6.2+105-e665821a-SNAPSHOT" |
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.
We cannot use a snapshot version, since now they get removed after 60 days. We need to wait for Metals release, so this will go into 3.8.1 most likely
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.
Do we have an ETA for Metals release?
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 this will be next week because of all the other stuff going on
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.
Looking at the contents, I'd try to get this in 3.8.0, still... let's try to coordinate with @WojciechMazur and perhaps we could get it in time for 3.8.0-RC1?
) | ||
lspDiag.setCode(diag.msg.errorId.errorNumber) | ||
|
||
val scalaDiagnostic = new bsp4j.ScalaDiagnostic() |
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.
Shouldn't we instead create our own diagnotic in metals and translate them to code actions as well? We wouldn't need to add bsp4j to the PC compiler.
private val forbiddenOptions = Set("-print-lines", "-print-tasty") | ||
private val forbiddenDoubleOptions = Set.empty[String] | ||
|
||
val driverSettings = |
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 seems duplicated with the Scala Presentation Compiler, shouldn't we reuse this class in the old ScalaPResentationCompiler?
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 didn't want to touch original presentation compiler for now. In the end I'll completely replace implementation of ScalaPresentationCompiler to use RawScalaPresentationCompiler as underlying impl but lets try it first.
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.
ScalaPresentationCompiler in my vision will become just a wrapper that ensures thread safety and sequential processing of messages.
class DiagnosticProvider(driver: InteractiveDriver, params: VirtualFileParams): | ||
|
||
def diagnostics(): List[lsp4j.Diagnostic] = | ||
val diags = driver.run(params.uri().nn, params.text().nn) |
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.
We should check if diagnotics are expected via params.shouldReturnDiagnostics()
I added it recently, will be available in the new metals
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.
Can you tell me the scenario in which you don't want to return diags ?
LSP always sends request after keypress in following order:
didChange -> completion -> inlayHints
It will be compiled by completion or inlay hints anyway so it doesn't matter, and getting diagnostics is a free operation in terms of computations.
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 was thinking of cases where people would want to switch between the two modes.
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.
Ok, I see it, it would be very easy to control this on lsp level though but yeah. We can add it for simplicity.
project/Build.scala
Outdated
"io.get-coursier" % "interface" % "1.0.18", | ||
"org.scalameta" % "mtags-interfaces" % mtagsVersion, | ||
"com.google.guava" % "guava" % "33.2.1-jre", | ||
"ch.epfl.scala" % "bsp4j" % "2.1.1", |
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.
We shouldn't add it for Code Actions only
RawPresentationCompiler
is a direct, unsafe way to access presentation compiler interface provided inscalameta/metals#7841
It is up to the consumer to guarantee thread safety and sequential request processing.
This solves many issues with the current
PresentationCompiler
interface but most important are:SingleThreadExecutor
created by thePresentationCompiler
. The original behavior will stay with the standardScalaPresentationCompiler
interface. (There is another PR that refactors that part),On top of that this PR implements all things that will work out of the box:
Scala3CompilerAccess
. Will be super useful e.g for Scastie which will become a consumer of this new raw API.InteractiveDriver
compilation cancellation by checking Thread.interrupted(). Future changes are required to make it work with safeScalaPresentationCompiler
andCancelTokens
. Here we can omit the cancel token support for now, because we would check forThread.interrupted()
along thecancelToken.isCancelled
anyway, and we can now easily interrupt it from e.gIO.interruptible
Those changes were adapted from my other PR's that required adjustment of
Scala3CompilerAccess
but I don't think it is ready / I'm not happy with current state of that refactor.In the future we should think of replacing the implementation of
ScalaPresentationCompiler
to useRawPresentationCompiler
as underlying impl and just call it in safe way.The implementation was tested on the actual LSP server and it works fine.