Skip to content

Scala: answer Metals' build-import prompt - #1769

Open
merlinorg wants to merge 2 commits into
oraios:mainfrom
merlinorg:scala-answer-metals-prompts
Open

Scala: answer Metals' build-import prompt#1769
merlinorg wants to merge 2 commits into
oraios:mainfrom
merlinorg:scala-answer-metals-prompts

Conversation

@merlinorg

Copy link
Copy Markdown

Fixes #1768, where the reproduction and the source trail are.

In short: Metals asks whether to import a workspace it has not seen before, Serena registered no window/showMessageRequest handler, so the request came back MethodNotFound and no build was ever imported — leaving every cross-file query to the fallback presentation compiler. It affects any Scala project not already imported by another editor, not just monorepos.

Fix

Register the handler, following ansible_language_server.py:308 (added in #1170 for the same reason).

Answer the three prompts that lead to a build server — Import build, Import changes, Connect — and dismiss anything else with null. The allow-list is deliberate rather than "pick the first action": a prompt we do not recognise is one whose consequences we cannot judge, and Metals' others include offers to kill a Bloop process (OldBloopVersionRunning) and to open a new window (NewScalaProject). Don't show again is never chosen, since Metals persists that dismissal in the project's own state.

The one prompt on the path this does not answer is ChooseBuildTool ("Multiple build definitions found. Which would you like to use?"), whose actions are the build tools' executable names. A workspace holding more than one kind of build therefore still goes unimported; naming the build tool for someone felt like a guess of a different order, but say the word and I'll add it. The comment and the setup guide both call it out rather than implying full coverage.

Answering yes lets Metals run the project's build tool (for sbt, sbt bloopInstall), which is a real side effect on the user's machine, so ls_specific_settings.scala.auto_import_build: false declines instead and restores the previous behaviour minus the protocol error.

Testing

Nine tests (thirteen cases) in test/solidlsp/scala/test_scala_show_message_request.py, built on Metals' own prompt payloads — the affirmative cases, the opt-out and its route from ls_specific_settings, Don't show again, an unrecognised prompt, the build-tool choice, no actions, and malformed actions. No Metals needed, so they run in CI.

End-to-end on a fresh single-module sbt project with no .bloop/.bsp — before, request_references returns [] for three minutes and the log shows the MethodNotFound error; after:

references to Lib.greet: ['src/main/scala/plain/App.scala']

with the log showing time: ran 'sbt bloopInstall' in 5.54s then Connected to Build server: Bloop v2.0.17.

ruff check, ruff format --check, ty check src/serena src/solidlsp and ty check test --exclude test/resources are clean.

Docs

The Scala setup guide was written around this bug, so its Quick Start is now "start Serena and let it import", with the VS Code and manual bloopInstall routes kept below as the ways to import the build yourself. The language-support page no longer says Scala "requires some manual setup".

This does not close #839, but it removes the manual pre-import step that is part of why the end-to-end Scala suite is hard to run.

Checklist

  • This PR follows the guidelines in CONTRIBUTING.md regarding the scope of PRs.
  • For changes that add features or fix problems, I have added an entry to CHANGELOG.md, which concisely describes the change.

Prepared with the help of Claude Code; I have reviewed and tested the change and will handle review myself.

Metals asks, via window/showMessageRequest, whether to import a workspace it
has not seen before. Serena registered no handler, so the request came back
`method 'window/showMessageRequest' not handled on client` and Metals logged
"Unexpected error initializing server" and gave up. No build server, no build
target, and every cross-file query answered by the fallback presentation
compiler — which cannot see past the file it is given.

A client cannot decline the question instead: Metals' `disableShowMessageRequest`
is server-side configuration, and its no-op fallback answers "Not now", which
imports nothing either. Answering is the only route to a build.

So answer the three prompts that lead to a build server, and dismiss anything
else with `null` — a prompt we do not recognise is one whose consequences we
cannot judge, and two of Metals' others offer to kill a process and to open a
window. "Don't show again" is never chosen; Metals persists that in the
project's own state.

Since answering yes lets Metals run the project's build tool,
`ls_specific_settings.scala.auto_import_build: false` declines instead.
`Messages.ChooseBuildTool` ("Multiple build definitions found. Which would
you like to use?") offers the build tools' own executable names, and precedes
the import prompt wherever a workspace holds more than one kind of build. It
is dismissed like anything else unrecognised, so such a workspace is still
not imported — a deliberate choice, since picking one is a guess of a
different order, but one the comment and the setup guide should admit to
rather than claim every prompt on the path is answered.

Also: cover the route from `ls_specific_settings` to `auto_import_build`,
which nothing exercised, and correct the `ImportBuildChanges` message in the
fixtures, which had the notification variant's trailing full stop rather than
the request's own text.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant