🐛 fix(core): enforce strict LSP lifecycle
This commit is contained in:
@@ -56,6 +56,10 @@ if(BUILD_TESTS)
|
||||
COMMAND ${PYTHON3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_cli_startup.py
|
||||
--server $<TARGET_FILE:tsl-server>)
|
||||
add_test(NAME test_core_server
|
||||
COMMAND ${PYTHON3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_core_server.py
|
||||
--server $<TARGET_FILE:test_provider>)
|
||||
else()
|
||||
message(WARNING "python3 not found; skipping test_lsp_json and test_cli_startup registration")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import select
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def frame(message: dict) -> bytes:
|
||||
body = json.dumps(message, separators=(",", ":")).encode("utf-8")
|
||||
return f"Content-Length: {len(body)}\r\n\r\n".encode("ascii") + body
|
||||
|
||||
|
||||
def read_messages(data: bytes) -> list[dict]:
|
||||
messages = []
|
||||
offset = 0
|
||||
while offset < len(data):
|
||||
header_end = data.find(b"\r\n\r\n", offset)
|
||||
if header_end < 0:
|
||||
raise RuntimeError("Incomplete LSP response header")
|
||||
|
||||
header = data[offset:header_end].decode("ascii")
|
||||
fields = dict(line.split(": ", 1) for line in header.split("\r\n"))
|
||||
length = int(fields["Content-Length"])
|
||||
body_start = header_end + 4
|
||||
body_end = body_start + length
|
||||
if body_end > len(data):
|
||||
raise RuntimeError("Incomplete LSP response body")
|
||||
|
||||
messages.append(json.loads(data[body_start:body_end].decode("utf-8")))
|
||||
offset = body_end
|
||||
return messages
|
||||
|
||||
|
||||
def response_by_id(data: bytes, request_id: int | str) -> dict:
|
||||
return next(message for message in read_messages(data)
|
||||
if message.get("id") == request_id)
|
||||
|
||||
|
||||
def run_raw(server: Path, payload: bytes) -> subprocess.CompletedProcess[bytes]:
|
||||
return subprocess.run(
|
||||
[str(server), "--core-server-fixture"],
|
||||
input=payload,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=5,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
def run_batch(server: Path, messages: list[dict]) -> subprocess.CompletedProcess[bytes]:
|
||||
return run_raw(server, b"".join(frame(message) for message in messages))
|
||||
|
||||
|
||||
class LspClient:
|
||||
def __init__(self, server: Path) -> None:
|
||||
self.proc = subprocess.Popen(
|
||||
[str(server), "--core-server-fixture"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
self.buffer = b""
|
||||
|
||||
def send(self, message: dict) -> None:
|
||||
if self.proc.stdin is None:
|
||||
raise RuntimeError("Fixture stdin is unavailable")
|
||||
self.proc.stdin.write(frame(message))
|
||||
self.proc.stdin.flush()
|
||||
|
||||
def read(self, timeout: float = 1.0) -> dict:
|
||||
if self.proc.stdout is None:
|
||||
raise RuntimeError("Fixture stdout is unavailable")
|
||||
|
||||
deadline = time.monotonic() + timeout
|
||||
while True:
|
||||
header_end = self.buffer.find(b"\r\n\r\n")
|
||||
if header_end >= 0:
|
||||
header = self.buffer[:header_end].decode("ascii")
|
||||
fields = dict(line.split(": ", 1)
|
||||
for line in header.split("\r\n"))
|
||||
length = int(fields["Content-Length"])
|
||||
body_start = header_end + 4
|
||||
body_end = body_start + length
|
||||
if len(self.buffer) >= body_end:
|
||||
body = self.buffer[body_start:body_end]
|
||||
self.buffer = self.buffer[body_end:]
|
||||
return json.loads(body.decode("utf-8"))
|
||||
|
||||
remaining = deadline - time.monotonic()
|
||||
if remaining <= 0:
|
||||
raise TimeoutError("Timed out waiting for LSP response")
|
||||
|
||||
ready, _, _ = select.select(
|
||||
[self.proc.stdout.fileno()], [], [], remaining)
|
||||
if not ready:
|
||||
continue
|
||||
|
||||
chunk = os.read(self.proc.stdout.fileno(), 4096)
|
||||
if not chunk:
|
||||
raise RuntimeError("Fixture closed stdout before a response")
|
||||
self.buffer += chunk
|
||||
|
||||
def close_input(self) -> int:
|
||||
if self.proc.stdin is not None:
|
||||
self.proc.stdin.close()
|
||||
return self.proc.wait(timeout=5)
|
||||
|
||||
def kill(self) -> None:
|
||||
if self.proc.poll() is None:
|
||||
self.proc.kill()
|
||||
self.proc.wait(timeout=5)
|
||||
|
||||
|
||||
def assert_lifecycle(server: Path) -> None:
|
||||
before_init = run_batch(server, [
|
||||
{"jsonrpc": "2.0", "id": 1, "method": "shutdown"},
|
||||
{"jsonrpc": "2.0", "method": "exit"},
|
||||
])
|
||||
if before_init.returncode != 1:
|
||||
raise RuntimeError("shutdown before initialize should exit with code 1")
|
||||
if response_by_id(before_init.stdout, 1)["error"]["code"] != -32002:
|
||||
raise RuntimeError("shutdown before initialize should return ServerNotInitialized")
|
||||
|
||||
repeated = run_batch(server, [
|
||||
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}},
|
||||
{"jsonrpc": "2.0", "id": 2, "method": "initialize", "params": {}},
|
||||
{"jsonrpc": "2.0", "id": 3, "method": "shutdown"},
|
||||
{"jsonrpc": "2.0", "method": "exit"},
|
||||
])
|
||||
if repeated.returncode != 0:
|
||||
raise RuntimeError("shutdown followed by exit should return code 0")
|
||||
if response_by_id(repeated.stdout, 2)["error"]["code"] != -32600:
|
||||
raise RuntimeError("repeated initialize should return InvalidRequest")
|
||||
if response_by_id(repeated.stdout, 3).get("result", "missing") is not None:
|
||||
raise RuntimeError("shutdown should return a null result")
|
||||
|
||||
direct_exit = run_batch(
|
||||
server, [{"jsonrpc": "2.0", "method": "exit"}])
|
||||
if direct_exit.returncode != 1:
|
||||
raise RuntimeError("exit before shutdown should return code 1")
|
||||
|
||||
client = LspClient(server)
|
||||
try:
|
||||
client.send({
|
||||
"jsonrpc": "2.0",
|
||||
"id": 11,
|
||||
"method": "initialize",
|
||||
"params": {},
|
||||
})
|
||||
if client.read().get("id") != 11:
|
||||
raise RuntimeError("missing initialize response")
|
||||
|
||||
client.send({"jsonrpc": "2.0", "id": 12, "method": "shutdown"})
|
||||
if client.read().get("result", "missing") is not None:
|
||||
raise RuntimeError("shutdown should return a null result")
|
||||
|
||||
time.sleep(0.1)
|
||||
if client.proc.poll() is not None:
|
||||
raise RuntimeError("server exited before receiving exit notification")
|
||||
|
||||
client.send({"jsonrpc": "2.0", "method": "exit"})
|
||||
if client.close_input() != 0:
|
||||
raise RuntimeError("orderly lifecycle should return code 0")
|
||||
finally:
|
||||
client.kill()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--server", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
assert_lifecycle(args.server)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -20,6 +20,7 @@ set(SOURCES
|
||||
main.cc
|
||||
test_main.cppm
|
||||
../test_lsp_any/test_framework.cppm
|
||||
core_server_fixture.cppm
|
||||
fixtures.cppm
|
||||
completion_test.cppm
|
||||
json_flow_test.cppm
|
||||
@@ -49,6 +50,7 @@ target_sources(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/test_main.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../test_lsp_any/test_framework.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/core_server_fixture.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fixtures.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/completion_test.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json_flow_test.cppm
|
||||
@@ -62,10 +64,14 @@ target_sources(
|
||||
../../src/bridge/spdlog.cppm
|
||||
../../src/bridge/taskflow.cppm
|
||||
../../src/bridge/tree_sitter.cppm
|
||||
../../src/bridge/win32_stdio.cppm
|
||||
../../src/utils/args_parser.cppm
|
||||
../../src/utils/string.cppm
|
||||
../../src/utils/text_coordinates.cppm
|
||||
../../src/core/dispatcher.cppm
|
||||
../../src/core/server.cppm
|
||||
../../src/scheduler/async_executor.cppm
|
||||
../../src/manager/bootstrap.cppm
|
||||
../../src/manager/event_bus.cppm
|
||||
../../src/manager/events.cppm
|
||||
../../src/manager/detail/text_document.cppm
|
||||
@@ -140,9 +146,6 @@ target_sources(
|
||||
../../src/provider/completion_item/resolve.cppm
|
||||
../../src/provider/initialize/initialize.cppm
|
||||
../../src/provider/initialized/initialized.cppm
|
||||
../../src/provider/shutdown/shutdown.cppm
|
||||
../../src/provider/exit/exit.cppm
|
||||
../../src/provider/cancel_request/cancel_request.cppm
|
||||
../../src/provider/trace/set_trace.cppm
|
||||
../../src/provider/client/register_capability.cppm
|
||||
../../src/provider/client/unregister_capability.cppm
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace lsp::test::provider
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
module;
|
||||
|
||||
export module lsp.test.provider.core_server_fixture;
|
||||
|
||||
import spdlog;
|
||||
import std;
|
||||
|
||||
import lsp.codec.facade;
|
||||
import lsp.core.server;
|
||||
import lsp.protocol;
|
||||
import lsp.provider.base.interface;
|
||||
|
||||
export namespace lsp::test::provider
|
||||
{
|
||||
int RunCoreServerFixture();
|
||||
}
|
||||
|
||||
namespace lsp::test::provider
|
||||
{
|
||||
class FixtureInitialize final : public core::IRequestProvider
|
||||
{
|
||||
public:
|
||||
std::string GetMethod() const override
|
||||
{
|
||||
return "initialize";
|
||||
}
|
||||
|
||||
std::string GetProviderName() const override
|
||||
{
|
||||
return "FixtureInitialize";
|
||||
}
|
||||
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request,
|
||||
core::ExecutionContext&) override
|
||||
{
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = protocol::LSPAny(protocol::LSPObject{});
|
||||
return codec::Serialize(response).value();
|
||||
}
|
||||
};
|
||||
|
||||
int RunCoreServerFixture()
|
||||
{
|
||||
spdlog::set_level(spdlog::level::off);
|
||||
core::LspServer server(
|
||||
std::cin,
|
||||
std::cout,
|
||||
[](core::RequestDispatcher& dispatcher) {
|
||||
dispatcher.RegisterRequestProvider(std::make_shared<FixtureInitialize>());
|
||||
},
|
||||
2,
|
||||
"");
|
||||
return server.Run();
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace lsp::test::provider
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace lsp::test::provider
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
@@ -207,4 +207,3 @@ namespace lsp::test::provider
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace lsp::test::provider
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
|
||||
@@ -51,13 +51,11 @@ namespace lsp::test::provider
|
||||
{
|
||||
scheduler::async_executor::AsyncExecutor scheduler{ 1 };
|
||||
manager::ManagerHub hub{};
|
||||
core::RequestDispatcher dispatcher{};
|
||||
core::RequestDispatcher dispatcher{ scheduler, hub };
|
||||
|
||||
ProviderEnv()
|
||||
{
|
||||
hub.Initialize();
|
||||
dispatcher.SetRequestScheduler(&scheduler);
|
||||
dispatcher.SetManagerHub(&hub);
|
||||
provider::RegisterAllProviders(dispatcher);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -77,10 +77,7 @@ import lsp.provider.workspace.will_delete_files;
|
||||
import lsp.provider.workspace.will_rename_files;
|
||||
import lsp.provider.workspace_symbol.resolve;
|
||||
import lsp.provider.text_document.publish_diagnostics;
|
||||
import lsp.provider.shutdown.shutdown;
|
||||
import lsp.provider.cancel_request.cancel_request;
|
||||
import lsp.provider.trace.set_trace;
|
||||
import lsp.provider.exit.exit;
|
||||
import lsp.core.dispatcher;
|
||||
import lsp.manager.manager_hub;
|
||||
import lsp.manager.symbol;
|
||||
@@ -160,13 +157,8 @@ export namespace lsp::test::provider
|
||||
static TestResult TestExecuteCommandProvider();
|
||||
static TestResult TestWillFileOperationsProviders();
|
||||
static TestResult TestWorkspaceSymbolResolveProvider();
|
||||
static TestResult TestShutdownProvider();
|
||||
static TestResult TestCancelRequestProvider();
|
||||
static TestResult TestSetTraceProvider();
|
||||
static TestResult TestExitProvider();
|
||||
};
|
||||
|
||||
int RunExitProviderChild();
|
||||
}
|
||||
|
||||
namespace lsp::test::provider
|
||||
@@ -175,13 +167,12 @@ namespace lsp::test::provider
|
||||
{
|
||||
struct ProviderEnv
|
||||
{
|
||||
std::vector<core::ServerLifecycleEvent> events;
|
||||
scheduler::async_executor::AsyncExecutor scheduler{ 1 };
|
||||
manager::ManagerHub hub{};
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([this](core::ServerLifecycleEvent event) { events.push_back(event); }, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
@@ -365,10 +356,7 @@ namespace lsp::test::provider
|
||||
runner.addTest("workspace executeCommand provider", TestExecuteCommandProvider);
|
||||
runner.addTest("workspace will file operations providers", TestWillFileOperationsProviders);
|
||||
runner.addTest("workspaceSymbol/resolve provider", TestWorkspaceSymbolResolveProvider);
|
||||
runner.addTest("shutdown provider", TestShutdownProvider);
|
||||
runner.addTest("cancel request provider", TestCancelRequestProvider);
|
||||
runner.addTest("setTrace provider", TestSetTraceProvider);
|
||||
runner.addTest("exit provider", TestExitProvider);
|
||||
}
|
||||
|
||||
TestResult ProviderMiscTests::TestInitializeProvider()
|
||||
@@ -434,8 +422,6 @@ namespace lsp::test::provider
|
||||
});
|
||||
assertTrue(found_workspace, "Workspace symbols should be indexed");
|
||||
|
||||
assertTrue(!env.events.empty(), "Initialize should emit lifecycle event");
|
||||
assertTrue(env.events.back() == core::ServerLifecycleEvent::kInitialized, "Initialize should emit initialized");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2233,7 +2219,6 @@ namespace lsp::test::provider
|
||||
const auto& stored_obj = stored.Get<protocol::LSPObject>();
|
||||
assertTrue(stored_obj.contains("tsl"), "stored settings should include tsl section");
|
||||
|
||||
assertTrue(env.events.empty(), "didChangeConfiguration should not trigger lifecycle events");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2761,7 +2746,6 @@ namespace lsp::test::provider
|
||||
provider.HandleNotification(notification, env.context);
|
||||
}
|
||||
|
||||
assertTrue(env.events.empty(), "window message notifications should not trigger lifecycle events");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2781,7 +2765,6 @@ namespace lsp::test::provider
|
||||
::lsp::provider::telemetry::Event provider;
|
||||
provider.HandleNotification(notification, env.context);
|
||||
|
||||
assertTrue(env.events.empty(), "telemetry/event should not trigger lifecycle events");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2816,7 +2799,6 @@ namespace lsp::test::provider
|
||||
::lsp::provider::text_document::PublishDiagnostics provider;
|
||||
provider.HandleNotification(notification, env.context);
|
||||
|
||||
assertTrue(env.events.empty(), "publishDiagnostics should not trigger lifecycle events");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3396,63 +3378,6 @@ namespace lsp::test::provider
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult ProviderMiscTests::TestShutdownProvider()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
ProviderEnv env;
|
||||
|
||||
auto path = FixturePath("rename_case.tsl");
|
||||
auto content = ReadTextFile(path);
|
||||
auto uri = ToUri(path);
|
||||
OpenDocument(env.hub, uri, content, 1);
|
||||
|
||||
protocol::RequestMessage request;
|
||||
request.id = "shutdown";
|
||||
request.method = "shutdown";
|
||||
|
||||
::lsp::provider::Shutdown provider;
|
||||
auto json = provider.ProvideResponse(request, env.context);
|
||||
auto response = ParseResponse(json);
|
||||
assertTrue(!response.error.has_value(), "Shutdown should not return error");
|
||||
assertTrue(env.events.size() >= 1, "Shutdown should emit lifecycle event");
|
||||
assertTrue(env.events.back() == core::ServerLifecycleEvent::kShuttingDown, "Shutdown should emit shutting down");
|
||||
assertFalse(env.hub.documents().GetContent(uri).has_value(), "Shutdown should clear documents");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult ProviderMiscTests::TestCancelRequestProvider()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
ProviderEnv env;
|
||||
|
||||
std::atomic<bool> started{ false };
|
||||
env.scheduler.Submit("cancel_me", [&started](std::stop_token) -> std::optional<std::string> {
|
||||
started.store(true);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
return std::string("done");
|
||||
});
|
||||
|
||||
while (!started.load())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
protocol::CancelParams params;
|
||||
params.id = std::string("cancel_me");
|
||||
protocol::NotificationMessage notification;
|
||||
notification.method = "$/cancelRequest";
|
||||
notification.params = codec::ToLSPAny(params);
|
||||
|
||||
::lsp::provider::CancelRequest provider;
|
||||
provider.HandleNotification(notification, env.context);
|
||||
env.scheduler.WaitAll();
|
||||
|
||||
auto stats = env.scheduler.GetStatistics();
|
||||
assertEqual(std::size_t(1), static_cast<std::size_t>(stats.cancelled),
|
||||
"CancelRequest should mark task cancelled");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult ProviderMiscTests::TestSetTraceProvider()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
@@ -3484,24 +3409,4 @@ namespace lsp::test::provider
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult ProviderMiscTests::TestExitProvider()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
auto exe = ExecutablePath();
|
||||
assertTrue(!exe.empty(), "ExecutablePath should be set");
|
||||
std::string command = "\"" + exe + "\" --exit-provider";
|
||||
int code = std::system(command.c_str());
|
||||
assertEqual(0, code, "Exit should return code 0");
|
||||
return result;
|
||||
}
|
||||
|
||||
int RunExitProviderChild()
|
||||
{
|
||||
ProviderEnv env;
|
||||
::lsp::provider::Exit provider;
|
||||
protocol::NotificationMessage notification;
|
||||
notification.method = "exit";
|
||||
provider.HandleNotification(notification, env.context);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,16 +12,13 @@ import lsp.manager.manager_hub;
|
||||
import lsp.scheduler.async_executor;
|
||||
import lsp.test.provider.fixtures;
|
||||
|
||||
import lsp.provider.cancel_request.cancel_request;
|
||||
import lsp.provider.code_action.resolve;
|
||||
import lsp.provider.code_lens.resolve;
|
||||
import lsp.provider.completion_item.resolve;
|
||||
import lsp.provider.document_link.resolve;
|
||||
import lsp.provider.exit.exit;
|
||||
import lsp.provider.initialize.initialize;
|
||||
import lsp.provider.initialized.initialized;
|
||||
import lsp.provider.inlay_hint.resolve;
|
||||
import lsp.provider.shutdown.shutdown;
|
||||
import lsp.provider.trace.set_trace;
|
||||
import lsp.provider.call_hierarchy.incoming_calls;
|
||||
import lsp.provider.call_hierarchy.outgoing_calls;
|
||||
@@ -118,7 +115,7 @@ namespace lsp::test::provider
|
||||
core::ExecutionContext context;
|
||||
|
||||
ProviderEnv()
|
||||
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
||||
: context(scheduler, hub)
|
||||
{
|
||||
hub.Initialize();
|
||||
}
|
||||
@@ -174,7 +171,6 @@ namespace lsp::test::provider
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
||||
CheckProviderMetadata<provider::Initialize>("initialize", "Initialize");
|
||||
CheckProviderMetadata<provider::Shutdown>("shutdown", "Shutdown");
|
||||
CheckProviderMetadata<provider::completion_item::Resolve>("completionItem/resolve", "CompletionItemResolve");
|
||||
CheckProviderMetadata<provider::text_document::Completion>("textDocument/completion", "TextDocumentCompletion");
|
||||
CheckProviderMetadata<provider::text_document::Definition>("textDocument/definition", "TextDocumentDefinition");
|
||||
@@ -273,8 +269,6 @@ namespace lsp::test::provider
|
||||
CheckProviderMetadata<provider::workspace::DidDeleteFiles>("workspace/didDeleteFiles", "WorkspaceDidDeleteFiles");
|
||||
CheckProviderMetadata<provider::workspace::DidRenameFiles>("workspace/didRenameFiles", "WorkspaceDidRenameFiles");
|
||||
CheckProviderMetadata<provider::Initialized>("initialized", "Initialized");
|
||||
CheckProviderMetadata<provider::Exit>("exit", "Exit");
|
||||
CheckProviderMetadata<provider::CancelRequest>("$/cancelRequest", "CancelRequest");
|
||||
CheckProviderMetadata<provider::SetTrace>("$/setTrace", "SetTrace");
|
||||
CheckProviderMetadata<provider::text_document::DidOpen>("textDocument/didOpen", "TextDocumentDidOpen");
|
||||
CheckProviderMetadata<provider::text_document::DidChange>("textDocument/didChange", "TextDocumentDidChange");
|
||||
@@ -287,7 +281,6 @@ namespace lsp::test::provider
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
||||
CheckRequestResponse<provider::Shutdown>();
|
||||
CheckRequestResponse<provider::completion_item::Resolve>();
|
||||
CheckRequestResponse<provider::text_document::Completion>();
|
||||
CheckRequestResponse<provider::text_document::Definition>();
|
||||
@@ -357,7 +350,6 @@ namespace lsp::test::provider
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
||||
CheckNotificationHandler<provider::Initialized>(std::nullopt);
|
||||
CheckNotificationHandler<provider::Exit>(std::nullopt);
|
||||
CheckNotificationHandler<provider::workspace::DidChangeConfiguration>(std::nullopt);
|
||||
CheckNotificationHandler<provider::workspace::DidChangeWatchedFiles>(std::nullopt);
|
||||
CheckNotificationHandler<provider::workspace::DidChangeWorkspaceFolders>(std::nullopt);
|
||||
|
||||
@@ -6,6 +6,7 @@ import std;
|
||||
|
||||
import lsp.test.framework;
|
||||
import lsp.test.provider.completion;
|
||||
import lsp.test.provider.core_server_fixture;
|
||||
import lsp.test.provider.definitions;
|
||||
import lsp.test.provider.interpreter;
|
||||
import lsp.test.provider.json_flow;
|
||||
@@ -26,9 +27,9 @@ export int Run(int argc, char** argv)
|
||||
{
|
||||
std::string_view arg(argv[i]);
|
||||
|
||||
if (arg == "--exit-provider")
|
||||
if (arg == "--core-server-fixture")
|
||||
{
|
||||
return lsp::test::provider::RunExitProviderChild();
|
||||
return lsp::test::provider::RunCoreServerFixture();
|
||||
}
|
||||
|
||||
constexpr std::string_view kInterpreterPrefix = "--interpreter=";
|
||||
|
||||
Reference in New Issue
Block a user