@@ -312,7 +312,8 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
312312
313313 auto position = textDocument->convertPosition (params.position );
314314 auto result = Luau::autocomplete (frontend, moduleName, position,
315- [&](std::string tag, std::optional<const Luau::ClassType*> ctx) -> std::optional<Luau::AutocompleteEntryMap>
315+ [&](std::string tag, std::optional<const Luau::ClassType*> ctx,
316+ std::optional<std::string> contents) -> std::optional<Luau::AutocompleteEntryMap>
316317 {
317318 if (tag == " ClassNames" )
318319 {
@@ -372,6 +373,46 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
372373
373374 return result;
374375 }
376+ else if (tag == " Require" )
377+ {
378+ if (!contents.has_value ())
379+ return std::nullopt ;
380+
381+ try
382+ {
383+ auto contentsString = contents.value ();
384+ auto currentDirectory = rootUri.fsPath ().append (contentsString);
385+
386+ Luau::AutocompleteEntryMap result;
387+ for (const auto & dir_entry : std::filesystem::directory_iterator (currentDirectory))
388+ {
389+ if (dir_entry.is_regular_file () || dir_entry.is_directory ())
390+ {
391+ std::string fileName = dir_entry.path ().filename ().generic_string ();
392+ Luau::AutocompleteEntry entry{
393+ Luau::AutocompleteEntryKind::String, frontend.builtinTypes ->stringType , false , false , Luau::TypeCorrectKind::Correct};
394+ entry.tags .push_back (dir_entry.is_directory () ? " Directory" : " File" );
395+
396+ result.insert_or_assign (fileName, entry);
397+ }
398+ }
399+
400+ // Add in ".." support
401+ if (currentDirectory.has_parent_path ())
402+ {
403+ Luau::AutocompleteEntry dotdotEntry{
404+ Luau::AutocompleteEntryKind::String, frontend.builtinTypes ->stringType , false , false , Luau::TypeCorrectKind::Correct};
405+ dotdotEntry.tags .push_back (" Directory" );
406+ result.insert_or_assign (" .." , dotdotEntry);
407+ }
408+
409+ return result;
410+ }
411+ catch (std::exception&)
412+ {
413+ return std::nullopt ;
414+ }
415+ }
375416
376417 return std::nullopt ;
377418 });
@@ -424,6 +465,18 @@ std::vector<lsp::CompletionItem> WorkspaceFolder::completion(const lsp::Completi
424465 break ;
425466 }
426467
468+ // Special cases: Files and directory
469+ if (std::find (entry.tags .begin (), entry.tags .end (), " File" ) != entry.tags .end ())
470+ {
471+ item.kind = lsp::CompletionItemKind::File;
472+ // We shouldn't include the extension when inserting
473+ std::string insertText = name;
474+ insertText.erase (insertText.find_last_of (' .' ));
475+ item.insertText = insertText;
476+ }
477+ else if (std::find (entry.tags .begin (), entry.tags .end (), " Directory" ) != entry.tags .end ())
478+ item.kind = lsp::CompletionItemKind::Folder;
479+
427480 // Handle if name is not an identifier
428481 if (entry.kind == Luau::AutocompleteEntryKind::Property && !Luau::isIdentifier (name))
429482 {
0 commit comments