Skip to content

Commit 9cc7268

Browse files
Prioritise autocompletion of common services and instance properties (#291)
* Prioritise autocompletion of common services * Update common services * Update for instances * Update changelog * Fix prioritised suggestions
1 parent b1e9ef2 commit 9cc7268

File tree

3 files changed

+77
-10
lines changed

3 files changed

+77
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
99
### Changed
1010

1111
- Sync to upstream Luau 0.563
12+
- Prioritised common services and Instance properties/methods in autocomplete so that they show up first
1213

1314
### Fixed
1415

src/LuauExt.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,13 @@ Luau::LoadDefinitionFileResult registerDefinitions(Luau::TypeChecker& typeChecke
470470
if (Luau::isPrim(*it, Luau::PrimitiveType::String))
471471
Luau::attachMagicFunction(part, magicFunctionInstanceNew);
472472

473+
// Mark `game:GetService()` with a tag so we can prioritise services when autocompleting
474+
if (auto serviceProviderType = typeChecker.globalScope->lookupType("ServiceProvider"))
475+
if (auto* ctv = Luau::getMutable<Luau::ClassType>(serviceProviderType->type))
476+
// :GetService is an intersection of function types, so we assign a tag on the first intersection
477+
if (auto* itv = Luau::getMutable<Luau::IntersectionType>(ctv->props["GetService"].type); itv && itv->parts.size() > 0)
478+
Luau::attachTag(itv->parts[0], "PrioritiseCommonServices");
479+
473480
// Move Enums over as imported type bindings
474481
std::unordered_map<Luau::Name, Luau::TypeFun> enumTypes{};
475482
for (auto it = typeChecker.globalScope->exportedTypeBindings.begin(); it != typeChecker.globalScope->exportedTypeBindings.end();)

src/operations/Completion.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,51 @@
1111
/// Note that sort text is lexicographically
1212
namespace SortText
1313
{
14-
static constexpr const char* TableProperties = "0";
15-
static constexpr const char* CorrectTypeKind = "1";
16-
static constexpr const char* CorrectFunctionResult = "2";
17-
static constexpr const char* Default = "3";
18-
static constexpr const char* WrongIndexType = "4";
19-
static constexpr const char* MetatableIndex = "5";
20-
static constexpr const char* AutoImports = "6";
21-
static constexpr const char* Keywords = "7";
14+
static constexpr const char* PrioritisedSuggestion = "0";
15+
static constexpr const char* TableProperties = "1";
16+
static constexpr const char* CorrectTypeKind = "2";
17+
static constexpr const char* CorrectFunctionResult = "3";
18+
static constexpr const char* Default = "4";
19+
static constexpr const char* WrongIndexType = "5";
20+
static constexpr const char* MetatableIndex = "6";
21+
static constexpr const char* AutoImports = "7";
22+
static constexpr const char* Keywords = "8";
2223
} // namespace SortText
2324

25+
static constexpr const char* COMMON_SERVICES[] = {
26+
"Players",
27+
"ReplicatedStorage",
28+
"ServerStorage",
29+
"MessagingService",
30+
"TeleportService",
31+
"HttpService",
32+
"CollectionService",
33+
"DataStoreService",
34+
"ContextActionService",
35+
"UserInputService",
36+
"Teams",
37+
"Chat",
38+
"TextService",
39+
"TextChatService",
40+
"GamepadService",
41+
"VoiceChatService",
42+
};
43+
44+
static constexpr const char* COMMON_INSTANCE_PROPERTIES[] = {
45+
"Parent",
46+
"Name",
47+
// Methods
48+
"FindFirstChild",
49+
"IsA",
50+
"Destroy",
51+
"GetAttribute",
52+
"GetChildren",
53+
"GetDescendants",
54+
"WaitForChild",
55+
"Clone",
56+
"SetAttribute",
57+
};
58+
2459
void WorkspaceFolder::endAutocompletion(const lsp::CompletionParams& params)
2560
{
2661
auto moduleName = fileResolver.getModuleName(params.textDocument.uri);
@@ -310,6 +345,8 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
310345
if (!textDocument)
311346
throw JsonRpcException(lsp::ErrorCode::RequestFailed, "No managed text document for " + params.textDocument.uri.toString());
312347

348+
bool isGetService = false;
349+
313350
auto position = textDocument->convertPosition(params.position);
314351
auto result = Luau::autocomplete(frontend, moduleName, position,
315352
[&](const std::string& tag, std::optional<const Luau::ClassType*> ctx,
@@ -413,6 +450,12 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
413450
return std::nullopt;
414451
}
415452
}
453+
else if (tag == "PrioritiseCommonServices")
454+
{
455+
// We are autocompleting a `game:GetService("$1")` call, so we set a flag to
456+
// highlight this so that we can prioritise common services first in the list
457+
isGetService = true;
458+
}
416459

417460
return std::nullopt;
418461
});
@@ -438,19 +481,35 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
438481
if (documentationString)
439482
item.documentation = {lsp::MarkupKind::Markdown, documentationString.value()};
440483

484+
if (entry.wrongIndexType)
485+
item.sortText = SortText::WrongIndexType;
441486
if (entry.typeCorrect == Luau::TypeCorrectKind::Correct)
442487
item.sortText = SortText::CorrectTypeKind;
443488
else if (entry.typeCorrect == Luau::TypeCorrectKind::CorrectFunctionResult)
444489
item.sortText = SortText::CorrectFunctionResult;
445490
else if (entry.kind == Luau::AutocompleteEntryKind::Property && types::isMetamethod(name))
446491
item.sortText = SortText::MetatableIndex;
447-
else if (entry.wrongIndexType)
448-
item.sortText = SortText::WrongIndexType;
449492
else if (entry.kind == Luau::AutocompleteEntryKind::Property)
450493
item.sortText = SortText::TableProperties;
451494
else if (entry.kind == Luau::AutocompleteEntryKind::Keyword)
452495
item.sortText = SortText::Keywords;
453496

497+
// If its a `game:GetSerivce("$1")` call, then prioritise common services
498+
if (isGetService)
499+
{
500+
if (auto it = std::find(std::begin(COMMON_SERVICES), std::end(COMMON_SERVICES), name); it != std::end(COMMON_SERVICES))
501+
item.sortText = SortText::PrioritisedSuggestion;
502+
}
503+
// If calling a property on an Instance, then prioritise these properties
504+
if (auto instanceType = frontend.typeCheckerForAutocomplete.globalScope->lookupType("Instance");
505+
instanceType && Luau::get<Luau::ClassType>(instanceType->type) && entry.containingClass &&
506+
Luau::isSubclass(entry.containingClass.value(), Luau::get<Luau::ClassType>(instanceType->type)) && !entry.wrongIndexType)
507+
{
508+
if (auto it = std::find(std::begin(COMMON_INSTANCE_PROPERTIES), std::end(COMMON_INSTANCE_PROPERTIES), name);
509+
it != std::end(COMMON_INSTANCE_PROPERTIES))
510+
item.sortText = SortText::PrioritisedSuggestion;
511+
}
512+
454513
switch (entry.kind)
455514
{
456515
case Luau::AutocompleteEntryKind::Property:

0 commit comments

Comments
 (0)