Skip to content

Commit 4fa3041

Browse files
committed
Add support for .config.luau
1 parent 1beb955 commit 4fa3041

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111
- The server now accepts DataModel information from the Studio Plugin even when there is no sourcemap present ([#1216](https://github.com/JohnnyMorganz/luau-lsp/pull/1216))
1212
- Added `luau-lsp.completion.imports.includedServices` and `luau-lsp.completion.imports.excludedServices` to configure what services show up during auto-importing. If non-empty, only the services listed in `includedServices` will show up. None of the services listed in `excludedServices` will ever show up.
1313
- Added support for inline documentation comments in global type definition files (relies on name being provided in settings, see below) ([#271](https://github.com/JohnnyMorganz/luau-lsp/issues/271))
14+
- Support processing `.config.luau` file as per [Luau-syntax configuration files RFC](https://rfcs.luau.org/config-luauconfig.html)
1415

1516
### Changed
1617

src/WorkspaceFileResolver.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <unordered_map>
33
#include <iostream>
44
#include "Luau/Ast.h"
5+
#include "Luau/LuauConfig.h"
56
#include "LSP/WorkspaceFileResolver.hpp"
67
#include "LSP/Utils.hpp"
78

@@ -129,6 +130,18 @@ std::optional<std::string> WorkspaceFileResolver::parseConfig(const Uri& configP
129130
return Luau::parseConfig(contents, result, opts);
130131
}
131132

133+
std::optional<std::string> WorkspaceFileResolver::parseLuauConfig(const Uri& configPath, const std::string& contents, Luau::Config& result)
134+
{
135+
LUAU_ASSERT(configPath.parent());
136+
137+
Luau::ConfigOptions::AliasOptions aliasOpts;
138+
aliasOpts.configLocation = configPath.parent()->fsPath();
139+
aliasOpts.overwriteAliases = true;
140+
141+
// TODO: support interrupt callbacks based on TypeCheckLimits
142+
return Luau::extractLuauConfig(contents, result, aliasOpts, Luau::InterruptCallbacks{});
143+
}
144+
132145
const Luau::Config& WorkspaceFileResolver::readConfigRec(const Uri& uri) const
133146
{
134147
auto it = configCache.find(uri);
@@ -140,8 +153,33 @@ const Luau::Config& WorkspaceFileResolver::readConfigRec(const Uri& uri) const
140153
result = readConfigRec(*parent);
141154

142155
auto configPath = uri.resolvePath(Luau::kConfigName);
156+
auto luauConfigPath = uri.resolvePath(Luau::kLuauConfigName);
143157
auto robloxRcPath = uri.resolvePath(".robloxrc");
144158

159+
if (std::optional<std::string> contents = Luau::FileUtils::readFile(luauConfigPath.fsPath()))
160+
{
161+
std::optional<std::string> error = parseLuauConfig(configPath, *contents, result);
162+
if (error)
163+
{
164+
if (client)
165+
{
166+
lsp::Diagnostic diagnostic{{{0, 0}, {0, 0}}};
167+
diagnostic.message = *error;
168+
diagnostic.severity = lsp::DiagnosticSeverity::Error;
169+
diagnostic.source = "Luau";
170+
client->publishDiagnostics({configPath, std::nullopt, {diagnostic}});
171+
}
172+
else
173+
// TODO: this should never be reached anymore
174+
std::cerr << configPath.toString() << ": " << *error;
175+
}
176+
else
177+
{
178+
if (client)
179+
// Clear errors presented for file
180+
client->publishDiagnostics({configPath, std::nullopt, {}});
181+
}
182+
}
145183
if (std::optional<std::string> contents = Luau::FileUtils::readFile(configPath.fsPath()))
146184
{
147185
std::optional<std::string> error = parseConfig(configPath, *contents, result);

src/include/LSP/WorkspaceFileResolver.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct WorkspaceFileResolver
9696

9797
// Create a WorkspaceFileResolver with a specific default configuration
9898
explicit WorkspaceFileResolver(Luau::Config defaultConfig)
99-
: defaultConfig(std::move(defaultConfig)){};
99+
: defaultConfig(std::move(defaultConfig)) {};
100100

101101
/// The file is managed by the client, so FS will be out of date
102102
const TextDocument* getTextDocument(const lsp::DocumentUri& uri) const;
@@ -116,6 +116,7 @@ struct WorkspaceFileResolver
116116
void clearConfigCache();
117117

118118
static std::optional<std::string> parseConfig(const Uri& configPath, const std::string& contents, Luau::Config& result, bool compat = false);
119+
static std::optional<std::string> parseLuauConfig(const Uri& configPath, const std::string& contents, Luau::Config& result);
119120

120121
private:
121122
const Luau::Config& readConfigRec(const Uri& path) const;

tests/WorkspaceFileResolver.test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,4 +434,24 @@ TEST_CASE_FIXTURE(Fixture, "resolve_toml_modules")
434434
CHECK_EQ(source->source, "--!strict\nreturn {[\"value\"] = 1;}");
435435
}
436436

437+
TEST_CASE_FIXTURE(Fixture, "support_config_luau")
438+
{
439+
TempDir t("file_resolver_supports_config_luau");
440+
auto fooPath = t.touch_child("project/code/foo.luau");
441+
auto luaurcPath = t.write_child("project/.config.luau", R"(
442+
return {
443+
luau = {
444+
aliases = {
445+
test = "test"
446+
}
447+
}
448+
}
449+
)");
450+
451+
auto fooConfig = workspace.fileResolver.getConfig(workspace.fileResolver.getModuleName(Uri::file(fooPath)));
452+
453+
CHECK_EQ(fooConfig.aliases.size(), 1);
454+
CHECK(fooConfig.aliases.find("test"));
455+
}
456+
437457
TEST_SUITE_END();

0 commit comments

Comments
 (0)