206 lines
6.9 KiB
C++
206 lines
6.9 KiB
C++
module;
|
|
|
|
export module lsp.test.provider.definitions;
|
|
|
|
import std;
|
|
|
|
import lsp.test.framework;
|
|
import lsp.provider.text_document.definition;
|
|
import lsp.core.dispacther;
|
|
import lsp.manager.manager_hub;
|
|
import lsp.scheduler.async_executor;
|
|
import lsp.protocol;
|
|
import lsp.codec.facade;
|
|
import lsp.test.provider.fixtures;
|
|
|
|
export namespace lsp::test::provider
|
|
{
|
|
class DefinitionTests
|
|
{
|
|
public:
|
|
static void Register(TestRunner& runner);
|
|
|
|
private:
|
|
static TestResult TestDefinitionResolvesInDocument();
|
|
static TestResult TestDefinitionResolvesInWorkspaceIndex();
|
|
static TestResult TestDefinitionResolvesInSystemIndex();
|
|
};
|
|
}
|
|
|
|
namespace lsp::test::provider
|
|
{
|
|
namespace
|
|
{
|
|
struct ProviderEnv
|
|
{
|
|
scheduler::AsyncExecutor scheduler{ 1 };
|
|
manager::ManagerHub hub{};
|
|
core::ExecutionContext context;
|
|
|
|
ProviderEnv()
|
|
: context([](core::ServerLifecycleEvent) {}, scheduler, hub)
|
|
{
|
|
hub.Initialize();
|
|
}
|
|
};
|
|
|
|
protocol::ResponseMessage ParseResponse(const std::string& json)
|
|
{
|
|
auto parsed = codec::Deserialize<protocol::ResponseMessage>(json);
|
|
if (!parsed)
|
|
{
|
|
throw std::runtime_error("Failed to deserialize response");
|
|
}
|
|
return *parsed;
|
|
}
|
|
|
|
protocol::Position FindPosition(const std::string& content, const std::string& marker)
|
|
{
|
|
auto pos = content.find(marker);
|
|
assertTrue(pos != std::string::npos, "Marker not found in fixture");
|
|
protocol::Position result{};
|
|
result.line = 0;
|
|
result.character = 0;
|
|
for (std::size_t i = 0; i < pos; ++i)
|
|
{
|
|
if (content[i] == '\n')
|
|
{
|
|
result.line++;
|
|
result.character = 0;
|
|
}
|
|
else
|
|
{
|
|
result.character++;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void OpenDocument(manager::ManagerHub& hub, const std::string& uri, const std::string& text, int version)
|
|
{
|
|
protocol::DidOpenTextDocumentParams open_params;
|
|
open_params.textDocument.uri = uri;
|
|
open_params.textDocument.languageId = "tsl";
|
|
open_params.textDocument.version = version;
|
|
open_params.textDocument.text = text;
|
|
hub.documents().OpenDocument(open_params);
|
|
}
|
|
|
|
protocol::Location ExtractLocation(const protocol::ResponseMessage& response)
|
|
{
|
|
if (!response.result.has_value())
|
|
{
|
|
throw std::runtime_error("Expected definition result");
|
|
}
|
|
return codec::FromLSPAny.template operator()<protocol::Location>(response.result.value());
|
|
}
|
|
|
|
bool LocationMatchesLine(const protocol::Location& location, std::uint32_t line)
|
|
{
|
|
return location.range.start.line == line;
|
|
}
|
|
}
|
|
|
|
void DefinitionTests::Register(TestRunner& runner)
|
|
{
|
|
runner.addTest("definition resolves in document", TestDefinitionResolvesInDocument);
|
|
runner.addTest("definition resolves in workspace index", TestDefinitionResolvesInWorkspaceIndex);
|
|
runner.addTest("definition resolves in system index", TestDefinitionResolvesInSystemIndex);
|
|
}
|
|
|
|
TestResult DefinitionTests::TestDefinitionResolvesInDocument()
|
|
{
|
|
TestResult result{ "", true, "ok" };
|
|
|
|
ProviderEnv env;
|
|
auto path = FixturePath("main_unit.tsf");
|
|
auto content = ReadTextFile(path);
|
|
auto uri = ToUri(path);
|
|
OpenDocument(env.hub, uri, content, 1);
|
|
|
|
protocol::DefinitionParams params;
|
|
params.textDocument.uri = uri;
|
|
params.position = FindPosition(content, "UnitFunc(1);");
|
|
|
|
protocol::RequestMessage request;
|
|
request.id = "1";
|
|
request.method = "textDocument/definition";
|
|
request.params = codec::ToLSPAny(params);
|
|
|
|
::lsp::provider::text_document::Definition handler;
|
|
auto json = handler.ProvideResponse(request, env.context);
|
|
auto response = ParseResponse(json);
|
|
auto location = ExtractLocation(response);
|
|
|
|
auto def_pos = FindPosition(content, "function UnitFunc");
|
|
assertTrue(LocationMatchesLine(location, def_pos.line), "Definition should resolve in document");
|
|
return result;
|
|
}
|
|
|
|
TestResult DefinitionTests::TestDefinitionResolvesInWorkspaceIndex()
|
|
{
|
|
TestResult result{ "", true, "ok" };
|
|
|
|
ProviderEnv env;
|
|
auto workspace_root = FixturePath("workspace");
|
|
env.hub.symbols().LoadWorkspace(ToUri(workspace_root));
|
|
|
|
auto path = FixturePath("main_unit.tsf");
|
|
auto content = ReadTextFile(path);
|
|
auto uri = ToUri(path);
|
|
OpenDocument(env.hub, uri, content, 1);
|
|
|
|
protocol::DefinitionParams params;
|
|
params.textDocument.uri = uri;
|
|
params.position = FindPosition(content, "WorkspaceFunc()");
|
|
|
|
protocol::RequestMessage request;
|
|
request.id = "2";
|
|
request.method = "textDocument/definition";
|
|
request.params = codec::ToLSPAny(params);
|
|
|
|
::lsp::provider::text_document::Definition handler;
|
|
auto json = handler.ProvideResponse(request, env.context);
|
|
auto response = ParseResponse(json);
|
|
auto location = ExtractLocation(response);
|
|
|
|
auto expected = ReadTextFile(FixturePath("workspace/workspace_script.tsl"));
|
|
auto expected_pos = FindPosition(expected, "function WorkspaceFunc");
|
|
assertTrue(LocationMatchesLine(location, expected_pos.line), "Definition should resolve in workspace index");
|
|
return result;
|
|
}
|
|
|
|
TestResult DefinitionTests::TestDefinitionResolvesInSystemIndex()
|
|
{
|
|
TestResult result{ "", true, "ok" };
|
|
|
|
ProviderEnv env;
|
|
auto system_root = FixturePath("system");
|
|
env.hub.symbols().LoadSystemLibrary(system_root.string());
|
|
|
|
auto path = FixturePath("main_unit.tsf");
|
|
auto content = ReadTextFile(path);
|
|
auto uri = ToUri(path);
|
|
OpenDocument(env.hub, uri, content, 1);
|
|
|
|
protocol::DefinitionParams params;
|
|
params.textDocument.uri = uri;
|
|
params.position = FindPosition(content, "SystemUnit");
|
|
|
|
protocol::RequestMessage request;
|
|
request.id = "3";
|
|
request.method = "textDocument/definition";
|
|
request.params = codec::ToLSPAny(params);
|
|
|
|
::lsp::provider::text_document::Definition handler;
|
|
auto json = handler.ProvideResponse(request, env.context);
|
|
auto response = ParseResponse(json);
|
|
auto location = ExtractLocation(response);
|
|
|
|
auto expected = ReadTextFile(FixturePath("system/SystemUnit.tsf"));
|
|
auto expected_pos = FindPosition(expected, "unit SystemUnit");
|
|
assertTrue(LocationMatchesLine(location, expected_pos.line), "Definition should resolve in system index");
|
|
return result;
|
|
}
|
|
}
|