mirror of
https://github.com/luau-lang/luau.git
synced 2025-04-02 01:40:54 +01:00
Hello all! Another week, another Luau release! # Change to `lua_setuserdatametatable` This release fixes #1710: `lua_setuserdatametatable` is being changed so that it _only_ operates on the top of the stack: the `idx` parameter is being removed. Prior to this, `lua_setuserdatametable` would set the metatable of the value in the stack at `idx`, but _always_ pop the top of the stack. The old behavior is available in this release as `lua_setuserdatametatable_DEPRECATED`. # General This release exposes a generalized implementation of require-by-string's autocomplete logic. `FileResolver` can now be optionally constructed with a `RequireSuggester`, which provides an interface for converting a given module to a `RequireNode`. Consumers of this new API implement a `RequireNode` to define how modules are represented in their embedded context, and the new API manages the logic specific to require-by-string, including providing suggestions for require aliases. This enhancement moves toward integrating require-by-string's semantics into the language itself, rather than merely providing a specification for community members to implement themselves. # New Type Solver * Fixed a source of potential `Luau::follow detected a Type cycle` internal compiler exceptions when assigning a global to itself. * Fixed an issue whereby `*no-refine*` (a type which should not be visible at the end of type checking) was not being properly elided, causing inference of class-like tables to become unreadable / induce crashes in autocomplete. * Fixed a case of incomplete constraint solving when performing basic math in a loop # Fragment Autocomplete * Fixed several crashes related to not properly filling in scope information for the fragments * Fixed a source of memory corruption by isolating the return type of a fragment when it is type checked. * Improved performance by opting not to clone persistent types for the fragment (e.g.: built in types) # Internal Contributors Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Talha Pathan <tpathan@roblox.com> Co-authored-by: Varun Saini <vsaini@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Varun Saini <61795485+vrn-sn@users.noreply.github.com> Co-authored-by: Alexander Youngblood <ayoungblood@roblox.com> Co-authored-by: Menarul Alam <malam@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Vighnesh <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com>
172 lines
4.8 KiB
C++
172 lines
4.8 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#pragma once
|
|
|
|
#include "Luau/Ast.h"
|
|
#include "Luau/Parser.h"
|
|
#include "Luau/AutocompleteTypes.h"
|
|
#include "Luau/DenseHash.h"
|
|
#include "Luau/Module.h"
|
|
#include "Luau/Frontend.h"
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
namespace Luau
|
|
{
|
|
struct FrontendOptions;
|
|
|
|
enum class FragmentAutocompleteWaypoint
|
|
{
|
|
ParseFragmentEnd,
|
|
CloneModuleStart,
|
|
CloneModuleEnd,
|
|
DfgBuildEnd,
|
|
CloneAndSquashScopeStart,
|
|
CloneAndSquashScopeEnd,
|
|
ConstraintSolverStart,
|
|
ConstraintSolverEnd,
|
|
TypecheckFragmentEnd,
|
|
AutocompleteEnd,
|
|
COUNT,
|
|
};
|
|
|
|
class IFragmentAutocompleteReporter
|
|
{
|
|
public:
|
|
virtual void reportWaypoint(FragmentAutocompleteWaypoint) = 0;
|
|
virtual void reportFragmentString(std::string_view) = 0;
|
|
};
|
|
|
|
enum class FragmentTypeCheckStatus
|
|
{
|
|
SkipAutocomplete,
|
|
Success,
|
|
};
|
|
|
|
struct FragmentAutocompleteAncestryResult
|
|
{
|
|
DenseHashMap<AstName, AstLocal*> localMap{AstName()};
|
|
std::vector<AstLocal*> localStack;
|
|
std::vector<AstNode*> ancestry;
|
|
AstStat* nearestStatement = nullptr;
|
|
};
|
|
|
|
struct FragmentParseResult
|
|
{
|
|
std::string fragmentToParse;
|
|
AstStatBlock* root = nullptr;
|
|
std::vector<AstNode*> ancestry;
|
|
AstStat* nearestStatement = nullptr;
|
|
std::vector<Comment> commentLocations;
|
|
std::unique_ptr<Allocator> alloc = std::make_unique<Allocator>();
|
|
};
|
|
|
|
struct FragmentTypeCheckResult
|
|
{
|
|
ModulePtr incrementalModule = nullptr;
|
|
ScopePtr freshScope;
|
|
std::vector<AstNode*> ancestry;
|
|
};
|
|
|
|
struct FragmentAutocompleteResult
|
|
{
|
|
ModulePtr incrementalModule;
|
|
Scope* freshScope;
|
|
TypeArena arenaForAutocomplete;
|
|
AutocompleteResult acResults;
|
|
};
|
|
|
|
FragmentAutocompleteAncestryResult findAncestryForFragmentParse(AstStatBlock* root, const Position& cursorPos);
|
|
|
|
std::optional<FragmentParseResult> parseFragment(
|
|
AstStatBlock* root,
|
|
AstNameTable* names,
|
|
std::string_view src,
|
|
const Position& cursorPos,
|
|
std::optional<Position> fragmentEndPosition
|
|
);
|
|
|
|
std::pair<FragmentTypeCheckStatus, FragmentTypeCheckResult> typecheckFragment(
|
|
Frontend& frontend,
|
|
const ModuleName& moduleName,
|
|
const Position& cursorPos,
|
|
std::optional<FrontendOptions> opts,
|
|
std::string_view src,
|
|
std::optional<Position> fragmentEndPosition,
|
|
IFragmentAutocompleteReporter* reporter = nullptr
|
|
);
|
|
|
|
FragmentAutocompleteResult fragmentAutocomplete(
|
|
Frontend& frontend,
|
|
std::string_view src,
|
|
const ModuleName& moduleName,
|
|
Position cursorPosition,
|
|
std::optional<FrontendOptions> opts,
|
|
StringCompletionCallback callback,
|
|
std::optional<Position> fragmentEndPosition = std::nullopt,
|
|
IFragmentAutocompleteReporter* reporter = nullptr
|
|
);
|
|
|
|
enum class FragmentAutocompleteStatus
|
|
{
|
|
Success,
|
|
FragmentTypeCheckFail,
|
|
InternalIce
|
|
};
|
|
|
|
struct FragmentAutocompleteStatusResult
|
|
{
|
|
FragmentAutocompleteStatus status;
|
|
std::optional<FragmentAutocompleteResult> result;
|
|
};
|
|
|
|
struct FragmentContext
|
|
{
|
|
std::string_view newSrc;
|
|
const ParseResult& freshParse;
|
|
std::optional<FrontendOptions> opts;
|
|
std::optional<Position> DEPRECATED_fragmentEndPosition;
|
|
IFragmentAutocompleteReporter* reporter = nullptr;
|
|
};
|
|
|
|
/**
|
|
* @brief Attempts to compute autocomplete suggestions from the fragment context.
|
|
*
|
|
* This function computes autocomplete suggestions using outdated frontend typechecking data
|
|
* by patching the fragment context of the new script source content.
|
|
*
|
|
* @param frontend The Luau Frontend data structure, which may contain outdated typechecking data.
|
|
*
|
|
* @param moduleName The name of the target module, specifying which script the caller wants to request autocomplete for.
|
|
*
|
|
* @param cursorPosition The position in the script where the caller wants to trigger autocomplete.
|
|
*
|
|
* @param context The fragment context that this API will use to patch the outdated typechecking data.
|
|
*
|
|
* @param stringCompletionCB A callback function that provides autocomplete suggestions for string contexts.
|
|
*
|
|
* @return
|
|
* The status indicating whether `fragmentAutocomplete` ran successfully or failed, along with the reason for failure.
|
|
* Also includes autocomplete suggestions if the status is successful.
|
|
*
|
|
* @usage
|
|
* FragmentAutocompleteStatusResult acStatusResult;
|
|
* if (shouldFragmentAC)
|
|
* acStatusResult = Luau::tryFragmentAutocomplete(...);
|
|
*
|
|
* if (acStatusResult.status != Successful)
|
|
* {
|
|
* frontend.check(moduleName, options);
|
|
* acStatusResult.acResult = Luau::autocomplete(...);
|
|
* }
|
|
* return convertResultWithContext(acStatusResult.acResult);
|
|
*/
|
|
FragmentAutocompleteStatusResult tryFragmentAutocomplete(
|
|
Frontend& frontend,
|
|
const ModuleName& moduleName,
|
|
Position cursorPosition,
|
|
FragmentContext context,
|
|
StringCompletionCallback stringCompletionCB
|
|
);
|
|
|
|
} // namespace Luau
|