✅ test(lsp_server): cover completion trigger cases
Add explicit coverage for empty-prefix variants, unit/member dot access, createobject quoting forms, and resolve snippet placeholders. Verified: test_provider (clang-linux-server/Release)
This commit is contained in:
parent
adec86a3aa
commit
ec2c580a8c
|
|
@ -23,21 +23,34 @@ export namespace lsp::test::provider
|
|||
|
||||
private:
|
||||
static TestResult TestClassMethodCompletion();
|
||||
static TestResult TestClassMethodEmptyPrefixCompletion();
|
||||
static TestResult TestNewCompletion();
|
||||
static TestResult TestNewEmptyPrefixCompletion();
|
||||
static TestResult TestUnitScopedNewCompletion();
|
||||
static TestResult TestCreateObjectCompletion();
|
||||
static TestResult TestCreateObjectEmptyPrefixCompletion();
|
||||
static TestResult TestCreateObjectQuotedCompletion();
|
||||
static TestResult TestCreateObjectQuotedEmptyPrefixCompletion();
|
||||
static TestResult TestCreateObjectSingleQuoteCompletion();
|
||||
static TestResult TestCreateObjectQualifiedCompletion();
|
||||
static TestResult TestCreateObjectQuotedQualifiedCompletion();
|
||||
static TestResult TestCreateObjectUnitCallQualifiedCompletion();
|
||||
static TestResult TestUnitContextCompletion();
|
||||
static TestResult TestUnitContextEmptyPrefixCompletion();
|
||||
static TestResult TestUnitMemberCompletion();
|
||||
static TestResult TestUnitMemberDotCompletion();
|
||||
static TestResult TestObjectMemberCompletion();
|
||||
static TestResult TestObjectMemberQualifiedSelfUnitCompletion();
|
||||
static TestResult TestObjectMemberQualifiedTypeCompletion();
|
||||
static TestResult TestFunctionCompletion();
|
||||
static TestResult TestKeywordCompletion();
|
||||
static TestResult TestClassContextCompletion();
|
||||
static TestResult TestClassContextEmptyPrefixCompletion();
|
||||
static TestResult TestUnitScopedNewAliasCompletion();
|
||||
static TestResult TestCompletionResolveNewSnippet();
|
||||
static TestResult TestCompletionResolveCreateObjectSnippet();
|
||||
static TestResult TestCompletionResolveCreateObjectUnquotedSnippet();
|
||||
static TestResult TestCompletionResolveCreateObjectSingleQuoteSnippet();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -150,21 +163,34 @@ namespace lsp::test::provider
|
|||
void CompletionTests::Register(TestRunner& runner)
|
||||
{
|
||||
runner.addTest("completion class(Widget).", TestClassMethodCompletion);
|
||||
runner.addTest("completion class(Widget).<empty>", TestClassMethodEmptyPrefixCompletion);
|
||||
runner.addTest("completion new Widget", TestNewCompletion);
|
||||
runner.addTest("completion new <empty>", TestNewEmptyPrefixCompletion);
|
||||
runner.addTest("completion new unit(MainUnit).Widget", TestUnitScopedNewCompletion);
|
||||
runner.addTest("completion createobject", TestCreateObjectCompletion);
|
||||
runner.addTest("completion createobject <empty>", TestCreateObjectEmptyPrefixCompletion);
|
||||
runner.addTest("completion createobject quoted", TestCreateObjectQuotedCompletion);
|
||||
runner.addTest("completion createobject quoted <empty>", TestCreateObjectQuotedEmptyPrefixCompletion);
|
||||
runner.addTest("completion createobject single quote", TestCreateObjectSingleQuoteCompletion);
|
||||
runner.addTest("completion createobject qualified", TestCreateObjectQualifiedCompletion);
|
||||
runner.addTest("completion createobject qualified quoted", TestCreateObjectQuotedQualifiedCompletion);
|
||||
runner.addTest("completion createobject qualified unit()", TestCreateObjectUnitCallQualifiedCompletion);
|
||||
runner.addTest("completion unit(", TestUnitContextCompletion);
|
||||
runner.addTest("completion unit(<empty>)", TestUnitContextEmptyPrefixCompletion);
|
||||
runner.addTest("completion unit member", TestUnitMemberCompletion);
|
||||
runner.addTest("completion unit member dot", TestUnitMemberDotCompletion);
|
||||
runner.addTest("completion object member", TestObjectMemberCompletion);
|
||||
runner.addTest("completion object member qualified self unit", TestObjectMemberQualifiedSelfUnitCompletion);
|
||||
runner.addTest("completion object member qualified type", TestObjectMemberQualifiedTypeCompletion);
|
||||
runner.addTest("completion function prefix", TestFunctionCompletion);
|
||||
runner.addTest("completion keyword prefix", TestKeywordCompletion);
|
||||
runner.addTest("completion class(", TestClassContextCompletion);
|
||||
runner.addTest("completion class(<empty>)", TestClassContextEmptyPrefixCompletion);
|
||||
runner.addTest("completion new alias", TestUnitScopedNewAliasCompletion);
|
||||
runner.addTest("completion resolve new snippet", TestCompletionResolveNewSnippet);
|
||||
runner.addTest("completion resolve createobject snippet", TestCompletionResolveCreateObjectSnippet);
|
||||
runner.addTest("completion resolve createobject unquoted snippet", TestCompletionResolveCreateObjectUnquotedSnippet);
|
||||
runner.addTest("completion resolve createobject single quote snippet", TestCompletionResolveCreateObjectSingleQuoteSnippet);
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestClassMethodCompletion()
|
||||
|
|
@ -181,6 +207,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestClassMethodEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "class(Widget).");
|
||||
assertTrue(HasLabel(items, "StaticFoo"), "class() should suggest static methods with empty prefix");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestNewCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -195,6 +235,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestNewEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "obj := new ");
|
||||
assertTrue(HasLabel(items, "Widget"), "new context should suggest classes with empty prefix");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitScopedNewCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -223,6 +277,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "aliased := createobject(");
|
||||
assertTrue(HasLabel(items, "Widget"), "createobject should suggest classes with empty prefix");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectQuotedCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -237,6 +305,39 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectQuotedEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "aliased := createobject(\"");
|
||||
assertTrue(HasLabel(items, "Widget"), "quoted createobject should suggest classes with empty prefix");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectSingleQuoteCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
ProviderEnv env;
|
||||
auto path = FixturePath("main_unit.tsf");
|
||||
auto content = ReadTextFile(path);
|
||||
|
||||
auto replacement_pos = content.find("createobject(\"Wid\");");
|
||||
assertTrue(replacement_pos != std::string::npos, "Fixture should include createobject(\"Wid\");");
|
||||
content.replace(replacement_pos, std::string_view("createobject(\"Wid\");").size(), "createobject('Wid');");
|
||||
|
||||
auto uri = ToUri(path);
|
||||
OpenDocument(env.hub, uri, content, 1);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "createobject('Wid");
|
||||
assertTrue(HasLabel(items, "Widget"), "single-quote createobject should suggest classes");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectQualifiedCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -251,6 +352,41 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectQuotedQualifiedCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "createobject(\"MainUnit.");
|
||||
assertTrue(HasLabel(items, "Widget"), "qualified quoted createobject should suggest unit classes");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCreateObjectUnitCallQualifiedCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
ProviderEnv env;
|
||||
auto path = FixturePath("main_unit.tsf");
|
||||
auto content = ReadTextFile(path);
|
||||
|
||||
auto replacement_pos = content.find("createobject(MainUnit.Wid);");
|
||||
assertTrue(replacement_pos != std::string::npos, "Fixture should include createobject(MainUnit.Wid);");
|
||||
content.replace(replacement_pos,
|
||||
std::string_view("createobject(MainUnit.Wid);").size(),
|
||||
"createobject(unit(MainUnit).Wid);");
|
||||
|
||||
auto uri = ToUri(path);
|
||||
OpenDocument(env.hub, uri, content, 1);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "createobject(unit(MainUnit).Wid");
|
||||
assertTrue(HasLabel(items, "Widget"), "unit() qualified createobject should suggest unit classes");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitContextCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -265,6 +401,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitContextEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, " unit(");
|
||||
assertTrue(HasLabel(items, "MainUnit"), "unit context should list visible units with empty prefix");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitMemberCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -279,6 +429,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitMemberDotCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "MainUnit.Uni");
|
||||
assertTrue(HasLabel(items, "UnitFunc"), "unit member dot completion should list functions");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestObjectMemberCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -293,6 +457,20 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestObjectMemberQualifiedSelfUnitCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "aliased.Fo");
|
||||
assertTrue(HasLabel(items, "Foo"), "qualified self unit type should resolve instance members");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestObjectMemberQualifiedTypeCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -351,6 +529,21 @@ namespace lsp::test::provider
|
|||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestClassContextEmptyPrefixCompletion()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "class(");
|
||||
assertTrue(HasLabel(items, "Widget"), "class context should suggest classes with static methods");
|
||||
assertFalse(HasLabel(items, "Plain"), "class context should not suggest classes without static methods");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestUnitScopedNewAliasCompletion()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
|
|
@ -390,6 +583,7 @@ namespace lsp::test::provider
|
|||
|
||||
assertTrue(resolved.insertText.has_value(), "Resolved item should have insertText");
|
||||
assertTrue(resolved.insertText.value().find("Widget(") == 0, "Resolved new snippet should start with Widget(");
|
||||
assertTrue(resolved.insertText.value().contains("${1:a}"), "Resolved new snippet should include param placeholders");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -418,7 +612,73 @@ namespace lsp::test::provider
|
|||
|
||||
assertTrue(resolved.insertText.has_value(), "Resolved item should have insertText");
|
||||
auto snippet = resolved.insertText.value();
|
||||
assertTrue(!snippet.empty() && snippet.front() == 'W', "Resolved createobject snippet should not add quote");
|
||||
assertTrue(snippet.starts_with("Widget\""), "Resolved createobject snippet should close quote but not add opening quote");
|
||||
assertTrue(snippet.contains("${1:a}"), "Resolved createobject snippet should include param placeholders");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCompletionResolveCreateObjectUnquotedSnippet()
|
||||
{
|
||||
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);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "createobject(Wid");
|
||||
auto item = FindItem(items, "Widget");
|
||||
assertTrue(item.has_value(), "Expected Widget completion");
|
||||
|
||||
protocol::RequestMessage request;
|
||||
request.id = "r3";
|
||||
request.method = "completionItem/resolve";
|
||||
request.params = codec::ToLSPAny(*item);
|
||||
|
||||
::lsp::provider::completion_item::Resolve resolver;
|
||||
auto json = resolver.ProvideResponse(request, env.context);
|
||||
auto response = ParseResponse(json);
|
||||
auto resolved = codec::FromLSPAny.template operator()<protocol::CompletionItem>(response.result.value());
|
||||
|
||||
assertTrue(resolved.insertText.has_value(), "Resolved item should have insertText");
|
||||
auto snippet = resolved.insertText.value();
|
||||
assertTrue(snippet.starts_with("\"Widget\""), "Resolved createobject snippet should add opening quote for unquoted call");
|
||||
assertTrue(snippet.contains("${1:a}"), "Resolved createobject snippet should include param placeholders");
|
||||
return result;
|
||||
}
|
||||
|
||||
TestResult CompletionTests::TestCompletionResolveCreateObjectSingleQuoteSnippet()
|
||||
{
|
||||
TestResult result{ "", true, "ok" };
|
||||
ProviderEnv env;
|
||||
auto path = FixturePath("main_unit.tsf");
|
||||
auto content = ReadTextFile(path);
|
||||
|
||||
auto replacement_pos = content.find("createobject(\"Wid\");");
|
||||
assertTrue(replacement_pos != std::string::npos, "Fixture should include createobject(\"Wid\");");
|
||||
content.replace(replacement_pos, std::string_view("createobject(\"Wid\");").size(), "createobject('Wid');");
|
||||
|
||||
auto uri = ToUri(path);
|
||||
OpenDocument(env.hub, uri, content, 1);
|
||||
|
||||
auto items = RequestCompletion(env, uri, content, "createobject('Wid");
|
||||
auto item = FindItem(items, "Widget");
|
||||
assertTrue(item.has_value(), "Expected Widget completion");
|
||||
|
||||
protocol::RequestMessage request;
|
||||
request.id = "r4";
|
||||
request.method = "completionItem/resolve";
|
||||
request.params = codec::ToLSPAny(*item);
|
||||
|
||||
::lsp::provider::completion_item::Resolve resolver;
|
||||
auto json = resolver.ProvideResponse(request, env.context);
|
||||
auto response = ParseResponse(json);
|
||||
auto resolved = codec::FromLSPAny.template operator()<protocol::CompletionItem>(response.result.value());
|
||||
|
||||
assertTrue(resolved.insertText.has_value(), "Resolved item should have insertText");
|
||||
auto snippet = resolved.insertText.value();
|
||||
assertTrue(snippet.starts_with("Widget'"), "Resolved createobject snippet should close single quote but not add opening quote");
|
||||
assertTrue(snippet.contains("${1:a}"), "Resolved createobject snippet should include param placeholders");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue