mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-14 22:17:35 +00:00
* scala: answer Metals' build-import prompt
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.
* scala: name the build-tool choice as a gap, and test the setting
`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.
95 lines
4.2 KiB
Python
95 lines
4.2 KiB
Python
"""
|
|
Unit tests for Serena's answer to Metals' `window/showMessageRequest` prompts.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from solidlsp.language_servers.scala_language_server import (
|
|
_get_scala_settings,
|
|
choose_show_message_request_action,
|
|
)
|
|
from solidlsp.ls_config import LanguageServerId
|
|
from solidlsp.settings import SolidLSPSettings
|
|
|
|
# Metals' own prompts, with the message and action titles as its `Messages` object builds them
|
|
# (scala/meta/internal/metals/Messages.scala) and `type` as lsp4j serialises `MessageType.Info`.
|
|
IMPORT_BUILD = {
|
|
"message": "New sbt workspace detected, would you like to import the build?",
|
|
"type": 3,
|
|
"actions": [{"title": "Import build"}, {"title": "Not now"}, {"title": "Don't show again"}],
|
|
}
|
|
IMPORT_CHANGES = {
|
|
"message": "sbt build needs to be re-imported",
|
|
"type": 3,
|
|
"actions": [{"title": "Import changes"}, {"title": "Not now"}, {"title": "Don't show again"}],
|
|
}
|
|
GENERATE_BSP_AND_CONNECT = {
|
|
"message": "New sbt workspace detected, would you like connect to the Bloop build server?",
|
|
"type": 3,
|
|
"actions": [{"title": "Connect"}, {"title": "Not now"}, {"title": "Don't show again"}],
|
|
}
|
|
OLD_BLOOP_VERSION_RUNNING = {
|
|
"message": "Deprecated Bloop server is still running and is taking up resources, do you want to kill the process?",
|
|
"type": 3,
|
|
"actions": [{"title": "Yes"}, {"title": "Not now"}],
|
|
}
|
|
CHOOSE_BUILD_TOOL = {
|
|
"message": "Multiple build definitions found. Which would you like to use?",
|
|
"type": 3,
|
|
"actions": [{"title": "sbt"}, {"title": "mill"}],
|
|
}
|
|
|
|
|
|
@pytest.mark.scala
|
|
class TestChooseShowMessageRequestAction:
|
|
@pytest.mark.parametrize("params", [IMPORT_BUILD, IMPORT_CHANGES, GENERATE_BSP_AND_CONNECT])
|
|
def test_build_import_prompts_are_answered_affirmatively(self, params: dict) -> None:
|
|
chosen = choose_show_message_request_action(params)
|
|
assert chosen is not None
|
|
assert chosen["title"] in ("Import build", "Import changes", "Connect")
|
|
|
|
@pytest.mark.parametrize("params", [IMPORT_BUILD, IMPORT_CHANGES, GENERATE_BSP_AND_CONNECT])
|
|
def test_auto_import_build_can_be_turned_off(self, params: dict) -> None:
|
|
assert choose_show_message_request_action(params, auto_import_build=False) is None
|
|
|
|
def test_dont_show_again_is_never_chosen(self) -> None:
|
|
"""Metals persists that dismissal in the project's own state."""
|
|
params = {"message": "…", "actions": [{"title": "Don't show again"}, {"title": "Not now"}]}
|
|
assert choose_show_message_request_action(params) is None
|
|
|
|
def test_an_unrecognised_prompt_is_dismissed(self) -> None:
|
|
"""Answering "Yes" here would kill a process on the user's machine."""
|
|
assert choose_show_message_request_action(OLD_BLOOP_VERSION_RUNNING) is None
|
|
|
|
def test_a_prompt_with_no_actions_is_dismissed(self) -> None:
|
|
assert choose_show_message_request_action({"message": "just so you know"}) is None
|
|
assert choose_show_message_request_action({"message": "just so you know", "actions": None}) is None
|
|
|
|
def test_malformed_actions_do_not_raise(self) -> None:
|
|
params = {"message": "…", "actions": ["Import build", None, {"title": "Import build"}]}
|
|
assert choose_show_message_request_action(params) == {"title": "Import build"}
|
|
|
|
def test_choosing_between_build_tools_is_left_alone(self) -> None:
|
|
"""Naming the build tool for the user is a guess of a different order; see the comment
|
|
on BUILD_IMPORT_PROMPT_ACTIONS. A workspace with several build definitions is therefore
|
|
still not imported.
|
|
"""
|
|
assert choose_show_message_request_action(CHOOSE_BUILD_TOOL) is None
|
|
|
|
|
|
@pytest.mark.scala
|
|
class TestAutoImportBuildSetting:
|
|
"""`auto_import_build` has to reach the handler from the project configuration."""
|
|
|
|
@staticmethod
|
|
def setting(**scala_settings) -> object:
|
|
settings = SolidLSPSettings(ls_specific_settings={LanguageServerId.SCALA: scala_settings})
|
|
return _get_scala_settings(settings)["auto_import_build"]
|
|
|
|
def test_defaults_to_true(self) -> None:
|
|
assert self.setting() is True
|
|
assert _get_scala_settings(SolidLSPSettings())["auto_import_build"] is True
|
|
|
|
def test_can_be_disabled(self) -> None:
|
|
assert self.setting(auto_import_build=False) is False
|