Skip to content

Commit

Permalink
Refactor for new solver (#783)
Browse files Browse the repository at this point in the history
* Fix type registration with solver v2

* fix review

* fix waitforchild magic function

* review fix

* Sync to Luau master, enable Luau fixes

* fix fflags for test suite

* requested changes

* revert inlay hints changes to split off

* latest luau

* fix flags

* sync

* Fix doctest integration with IDE

* Revert sync to 0.651

---------

Co-authored-by: JohnnyMorganz <[email protected]>
  • Loading branch information
checkraisefold and JohnnyMorganz authored Nov 9, 2024
1 parent 7b47ec4 commit cba7d65
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 91 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ jobs:
cmake ..
cmake --build . --target Luau.LanguageServer.Test -j 3
- name: Run Tests
- name: Run Tests (Old Solver)
run: ${{ matrix.test-path }}

- name: Run Tests (New Solver)
run: ${{ matrix.test-path }} --new-solver

types_smoketest:
name: Types Smoketest
runs-on: ubuntu-20.04
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/build
.vscode/settings.json
/.vs
out/
.cache
.idea
.DS_Store
Expand Down
18 changes: 11 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Sync to upstream Luau 0.650

### Fixed

- Fixed autocompletion, type registration, hover types/documentation, and some crashes for cases where the new solver is enabled

## [1.34.0] - 2024-10-27

### Changed
Expand Down Expand Up @@ -117,7 +121,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed

- Sync to upstream Luau 0.632
- Language clients are recommended to send configuration during intializationOptions (see https://github.com/JohnnyMorganz/luau-lsp/blob/main/editors/README.md for details)
- Language clients are recommended to send configuration during intializationOptions (see <https://github.com/JohnnyMorganz/luau-lsp/blob/main/editors/README.md> for details)
- Removed need for postponing requests whilst waiting for platform configuration (relies on clients sending config in intializationOptions)

### Fixed
Expand Down Expand Up @@ -150,7 +154,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed

- Sync to upstream Luau 0.631
- An indexed expression will no longer show an inlay hint if the index matches the parameter name (i.e., `call(other.value)` won't add `value: ` inlay hint) ([#618](https://github.com/JohnnyMorganz/luau-lsp/issues/618))
- An indexed expression will no longer show an inlay hint if the index matches the parameter name (i.e., `call(other.value)` won't add `value:` inlay hint) ([#618](https://github.com/JohnnyMorganz/luau-lsp/issues/618))
- Studio Plugin will now perform Gzip compression on sent requests

### Fixed
Expand Down Expand Up @@ -182,7 +186,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Sync to upstream Luau 0.625
- Improved memory usage of document and workspace diagnostics by no longer storing type graphs
- Rewritten the Luau grammar syntax: https://github.com/JohnnyMorganz/Luau.tmLanguage
- Rewritten the Luau grammar syntax: <https://github.com/JohnnyMorganz/Luau.tmLanguage>

### Fixed

Expand Down Expand Up @@ -604,7 +608,7 @@ local DATA = {

--- Doc comment
type Contents = {
...
...
}
```

Expand Down Expand Up @@ -763,7 +767,7 @@ local y = tbl.data -- Should give "This is some special information"
- Provide autocomplete for class names in `Instance:IsA("ClassName")` and errors when ClassName is unknown
- Provide autocomplete for properties in `Instance:GetPropertyChangedSignal("Property")` and errors when Property is unknown
- Provide autocomplete for enums in `EnumItem:IsA("enum")` and errors when Enum is unknown
- Added support for moonwave-style documentation comments! Currently only supports comments attached to functions directly. See https://eryn.io/moonwave for how to write doc comments
- Added support for moonwave-style documentation comments! Currently only supports comments attached to functions directly. See <https://eryn.io/moonwave> for how to write doc comments
- Added command line flag `--ignore=GLOB` to `luau-lsp analyze` allowing you to provide glob patterns to ignore diagnostics, similar to `luau-lsp.ignoreGlobs`. Repeat the flag multiple times for multiple patterns

### Changed
Expand Down Expand Up @@ -981,7 +985,7 @@ local y = tbl.data -- Should give "This is some special information"
- Fixed regression where diagnostics are not cleared when you close an ignored file
- Fixed errors sometimes occuring when you index `script`/`workspace`/`game` for children
- Fixed internal error caused by `:Clone()` calls when called on an expression which isn't an Lvalue (e.g., `inst:FindFirstChild(name):Clone()`)
- Fixed bug where `_: ` would not be removed as the name of function arguments. `function foo(_: number, _: number)` will now show as `function foo(number, number)`
- Fixed bug where `_:` would not be removed as the name of function arguments. `function foo(_: number, _: number)` will now show as `function foo(number, number)`
- Fixed analyze mode not exiting with a non-zero exit code when there are errors
- Fixed excessive whitespace in document symbols for expr-named function defintions
- Fixed hover for global functions and local variables
Expand Down Expand Up @@ -1147,7 +1151,7 @@ local y = tbl.data -- Should give "This is some special information"

- Hover over definitions will now try to give more expressive types
- `self` will now no longer show up in hover/signature help if it has already been implicitly provided
- `_: ` will no longer show up in hover/signature help for unnamed function parameters
- `_:` will no longer show up in hover/signature help for unnamed function parameters

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion luau
Submodule luau updated from a251bc to 26b230
18 changes: 11 additions & 7 deletions src/AnalyzeCli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <vector>

LUAU_FASTFLAG(DebugLuauTimeTracing)
LUAU_FASTFLAG(LuauSolverV2)

enum class ReportFormat
{
Expand Down Expand Up @@ -174,7 +175,7 @@ int startAnalyze(const argparse::ArgumentParser& program)
if (std::filesystem::is_directory(path))
{
for (std::filesystem::recursive_directory_iterator next(path, std::filesystem::directory_options::skip_permission_denied), end;
next != end; ++next)
next != end; ++next)
{
try
{
Expand Down Expand Up @@ -307,8 +308,9 @@ int startAnalyze(const argparse::ArgumentParser& program)

Luau::Frontend frontend(&fileResolver, &fileResolver, frontendOptions);

Luau::registerBuiltinGlobals(frontend, frontend.globals, /* typeCheckForAutocomplete = */ false);
Luau::registerBuiltinGlobals(frontend, frontend.globalsForAutocomplete, /* typeCheckForAutocomplete = */ true);
Luau::registerBuiltinGlobals(frontend, frontend.globals);
if (!FFlag::LuauSolverV2)
Luau::registerBuiltinGlobals(frontend, frontend.globalsForAutocomplete);

for (auto& definitionsPath : definitionsPaths)
{
Expand All @@ -325,7 +327,7 @@ int startAnalyze(const argparse::ArgumentParser& program)
return 1;
}

auto loadResult = types::registerDefinitions(frontend, frontend.globals, *definitionsContents, /* typeCheckForAutocomplete = */ false);
auto loadResult = types::registerDefinitions(frontend, frontend.globals, *definitionsContents);
if (!loadResult.success)
{
fprintf(stderr, "Failed to load definitions\n");
Expand Down Expand Up @@ -359,8 +361,9 @@ int startAnalyze(const argparse::ArgumentParser& program)
{
robloxPlatform->updateSourceNodeMap(sourceMapContents.value());

robloxPlatform->handleSourcemapUpdate(
frontend, frontend.globals, !program.is_used("--no-strict-dm-types") && client.configuration.diagnostics.strictDatamodelTypes);
bool expressiveTypes =
(program.is_used("--no-strict-dm-types") && client.configuration.diagnostics.strictDatamodelTypes) || FFlag::LuauSolverV2;
robloxPlatform->handleSourcemapUpdate(frontend, frontend.globals, expressiveTypes);
}
}
else
Expand All @@ -371,7 +374,8 @@ int startAnalyze(const argparse::ArgumentParser& program)
}

Luau::freeze(frontend.globals.globalTypes);
Luau::freeze(frontend.globalsForAutocomplete.globalTypes);
if (!FFlag::LuauSolverV2)
Luau::freeze(frontend.globalsForAutocomplete.globalTypes);

int failed = 0;

Expand Down
7 changes: 4 additions & 3 deletions src/LuauExt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <optional>
#include <utility>

#include "Luau/Type.h"
#include "Platform/LSPPlatform.hpp"
#include "Luau/BuiltinDefinitions.h"
#include "Luau/ToString.h"
Expand Down Expand Up @@ -51,11 +53,10 @@ std::optional<nlohmann::json> parseDefinitionsFileMetadata(const std::string& de
return std::nullopt;
}

Luau::LoadDefinitionFileResult registerDefinitions(
Luau::Frontend& frontend, Luau::GlobalTypes& globals, const std::string& definitions, bool typeCheckForAutocomplete)
Luau::LoadDefinitionFileResult registerDefinitions(Luau::Frontend& frontend, Luau::GlobalTypes& globals, const std::string& definitions)
{
// TODO: packageName shouldn't just be "@roblox"
return frontend.loadDefinitionFile(globals, globals.globalScope, definitions, "@roblox", /* captureComments = */ false, typeCheckForAutocomplete);
return frontend.loadDefinitionFile(globals, globals.globalScope, definitions, "@roblox", /* captureComments = */ false);
}

using NameOrExpr = std::variant<std::string, Luau::AstExpr*>;
Expand Down
16 changes: 10 additions & 6 deletions src/Workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,12 @@ void WorkspaceFolder::registerTypes()
{
LUAU_TIMETRACE_SCOPE("WorkspaceFolder::initialize", "LSP");
client->sendTrace("workspace initialization: registering Luau globals");
Luau::registerBuiltinGlobals(frontend, frontend.globals, /* typeCheckForAutocomplete = */ false);
Luau::registerBuiltinGlobals(frontend, frontend.globalsForAutocomplete, /* typeCheckForAutocomplete = */ true);
Luau::registerBuiltinGlobals(frontend, frontend.globals);
if (!FFlag::LuauSolverV2)
Luau::registerBuiltinGlobals(frontend, frontend.globalsForAutocomplete);

Luau::attachTag(Luau::getGlobalBinding(frontend.globalsForAutocomplete, "require"), "Require");
auto& tagRegisterGlobals = FFlag::LuauSolverV2 ? frontend.globals : frontend.globalsForAutocomplete;
Luau::attachTag(Luau::getGlobalBinding(tagRegisterGlobals, "require"), "Require");

if (client->definitionsFiles.empty())
client->sendLogMessage(lsp::MessageType::Warning, "No definitions file provided by client");
Expand All @@ -314,8 +316,9 @@ void WorkspaceFolder::registerTypes()
client->sendTrace("workspace initialization: parsing definitions file metadata COMPLETED", json(definitionsFileMetadata).dump());

client->sendTrace("workspace initialization: registering types definition");
auto result = types::registerDefinitions(frontend, frontend.globals, *definitionsContents, /* typeCheckForAutocomplete = */ false);
types::registerDefinitions(frontend, frontend.globalsForAutocomplete, *definitionsContents, /* typeCheckForAutocomplete = */ true);
auto result = types::registerDefinitions(frontend, frontend.globals, *definitionsContents);
if (!FFlag::LuauSolverV2)
types::registerDefinitions(frontend, frontend.globalsForAutocomplete, *definitionsContents);
client->sendTrace("workspace initialization: registering types definition COMPLETED");

client->sendTrace("workspace: applying platform mutations on definitions");
Expand Down Expand Up @@ -347,7 +350,8 @@ void WorkspaceFolder::registerTypes()
}
}
Luau::freeze(frontend.globals.globalTypes);
Luau::freeze(frontend.globalsForAutocomplete.globalTypes);
if (!FFlag::LuauSolverV2)
Luau::freeze(frontend.globalsForAutocomplete.globalTypes);
}

void WorkspaceFolder::setupWithConfiguration(const ClientConfiguration& configuration)
Expand Down
3 changes: 1 addition & 2 deletions src/include/LSP/LuauExt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ bool isMetamethod(const Luau::Name& name);

std::optional<nlohmann::json> parseDefinitionsFileMetadata(const std::string& definitions);

Luau::LoadDefinitionFileResult registerDefinitions(
Luau::Frontend& frontend, Luau::GlobalTypes& globals, const std::string& definitions, bool typeCheckForAutocomplete = false);
Luau::LoadDefinitionFileResult registerDefinitions(Luau::Frontend& frontend, Luau::GlobalTypes& globals, const std::string& definitions);

using NameOrExpr = std::variant<std::string, Luau::AstExpr*>;

Expand Down
11 changes: 7 additions & 4 deletions src/operations/Completion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "LSP/LuauExt.hpp"
#include "LSP/DocumentationParser.hpp"

LUAU_FASTFLAG(LuauSolverV2)

void WorkspaceFolder::endAutocompletion(const lsp::CompletionParams& params)
{
auto moduleName = fileResolver.getModuleName(params.textDocument.uri);
Expand Down Expand Up @@ -256,8 +258,8 @@ static const char* sortText(const Luau::Frontend& frontend, const std::string& n
return SortText::AutoImports;

// If the entry is `loadstring`, deprioritise it
if (auto it = frontend.globalsForAutocomplete.globalScope->bindings.find(Luau::AstName("loadstring"));
it != frontend.globalsForAutocomplete.globalScope->bindings.end())
auto& completionGlobals = FFlag::LuauSolverV2 ? frontend.globals : frontend.globalsForAutocomplete;
if (auto it = completionGlobals.globalScope->bindings.find(Luau::AstName("loadstring")); it != completionGlobals.globalScope->bindings.end())
{
if (entry.type == it->second.typeId)
return SortText::Deprioritized;
Expand Down Expand Up @@ -371,10 +373,11 @@ std::optional<std::string> WorkspaceFolder::getDocumentationForAutocompleteEntry
if (parentTy)
{
// parentTy might be an intersected type, find the actual base ttv
if (auto propInformation = lookupProp(*parentTy, name))
auto followedTy = Luau::follow(*parentTy);
if (auto propInformation = lookupProp(followedTy, name))
definitionModuleName = Luau::getDefinitionModuleName(propInformation->first);
else
definitionModuleName = Luau::getDefinitionModuleName(*parentTy);
definitionModuleName = Luau::getDefinitionModuleName(followedTy);
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/platform/roblox/RobloxCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "LSP/Completion.hpp"
#include "LSP/Workspace.hpp"

LUAU_FASTFLAG(LuauSolverV2)

static constexpr const char* COMMON_SERVICES[] = {
"Players",
"ReplicatedStorage",
Expand Down Expand Up @@ -254,7 +256,8 @@ const char* RobloxPlatform::handleSortText(
return SortText::PrioritisedSuggestion;

// If calling a property on ServiceProvider, then prioritise these properties
if (auto dataModelType = frontend.globalsForAutocomplete.globalScope->lookupType("ServiceProvider");
auto& completionGlobals = FFlag::LuauSolverV2 ? frontend.globals : frontend.globalsForAutocomplete;
if (auto dataModelType = completionGlobals.globalScope->lookupType("ServiceProvider");
dataModelType && Luau::get<Luau::ClassType>(dataModelType->type) && entry.containingClass &&
Luau::isSubclass(entry.containingClass.value(), Luau::get<Luau::ClassType>(dataModelType->type)) && !entry.wrongIndexType)
{
Expand All @@ -264,9 +267,9 @@ const char* RobloxPlatform::handleSortText(
}

// If calling a property on an Instance, then prioritise these properties
else if (auto instanceType = frontend.globalsForAutocomplete.globalScope->lookupType("Instance");
instanceType && Luau::get<Luau::ClassType>(instanceType->type) && entry.containingClass &&
Luau::isSubclass(entry.containingClass.value(), Luau::get<Luau::ClassType>(instanceType->type)) && !entry.wrongIndexType)
else if (auto instanceType = completionGlobals.globalScope->lookupType("Instance");
instanceType && Luau::get<Luau::ClassType>(instanceType->type) && entry.containingClass &&
Luau::isSubclass(entry.containingClass.value(), Luau::get<Luau::ClassType>(instanceType->type)) && !entry.wrongIndexType)
{
if (auto it = std::find(std::begin(COMMON_INSTANCE_PROPERTIES), std::end(COMMON_INSTANCE_PROPERTIES), name);
it != std::end(COMMON_INSTANCE_PROPERTIES))
Expand Down
Loading

0 comments on commit cba7d65

Please sign in to comment.