Skip to content

Conversation

rochala
Copy link
Contributor

@rochala rochala commented Oct 3, 2025

RawPresentationCompiler is a direct, unsafe way to access presentation compiler interface provided in
scalameta/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:

  • We now have control where and how each presentation compiler method is run. Before it was always run on a SingleThreadExecutor created by the PresentationCompiler. The original behavior will stay with the standard ScalaPresentationCompiler interface. (There is another PR that refactors that part),
  • If there was bug in scheduler all versions were affected,

On top of that this PR implements all things that will work out of the box:

  • Diagnostic provider - trivial implementation, previously not possible to LIFO task used by 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 safe ScalaPresentationCompiler and CancelTokens. Here we can omit the cancel token support for now, because we would check for Thread.interrupted() along the cancelToken.isCancelled anyway, and we can now easily interrupt it from e.g IO.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 use RawPresentationCompiler as underlying impl and just call it in safe way.

The implementation was tested on the actual LSP server and it works fine.

…iver will now check for Thread.isInterrupted cancellation
LabelPart(": ") :: toLabelParts(tpe, pos),
InlayHintKind.Type,
)
.addDefinition(adjustedPos.start)
Copy link
Contributor Author

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

|
|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().>>)*/
Copy link
Contributor Author

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

Copy link
Member

@KacperFKorban KacperFKorban left a 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
Copy link
Member

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(
Copy link
Member

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants