mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 22:35:43 +08:00
Pass string content to autocomplete callback (#800)
Closes #718 We pass an extra `contents` parameter to the string callback function to provide contextual information for autocomplete. Because we support both string literals and simple interpolated strings, we pass it through as a `std::string` value. This is a breaking change
This commit is contained in:
parent
be52bd91e4
commit
86494918f5
@ -89,7 +89,8 @@ struct AutocompleteResult
|
|||||||
};
|
};
|
||||||
|
|
||||||
using ModuleName = std::string;
|
using ModuleName = std::string;
|
||||||
using StringCompletionCallback = std::function<std::optional<AutocompleteEntryMap>(std::string tag, std::optional<const ClassType*> ctx)>;
|
using StringCompletionCallback =
|
||||||
|
std::function<std::optional<AutocompleteEntryMap>(std::string tag, std::optional<const ClassType*> ctx, std::optional<std::string> contents)>;
|
||||||
|
|
||||||
AutocompleteResult autocomplete(Frontend& frontend, const ModuleName& moduleName, Position position, StringCompletionCallback callback);
|
AutocompleteResult autocomplete(Frontend& frontend, const ModuleName& moduleName, Position position, StringCompletionCallback callback);
|
||||||
|
|
||||||
|
@ -1262,6 +1262,23 @@ static bool isSimpleInterpolatedString(const AstNode* node)
|
|||||||
return interpString != nullptr && interpString->expressions.size == 0;
|
return interpString != nullptr && interpString->expressions.size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::optional<std::string> getStringContents(const AstNode* node)
|
||||||
|
{
|
||||||
|
if (const AstExprConstantString* string = node->as<AstExprConstantString>())
|
||||||
|
{
|
||||||
|
return std::string(string->value.data, string->value.size);
|
||||||
|
}
|
||||||
|
else if (const AstExprInterpString* interpString = node->as<AstExprInterpString>(); interpString && interpString->expressions.size == 0)
|
||||||
|
{
|
||||||
|
LUAU_ASSERT(interpString->strings.size == 1);
|
||||||
|
return std::string(interpString->strings.data->data, interpString->strings.data->size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static std::optional<AutocompleteEntryMap> autocompleteStringParams(const SourceModule& sourceModule, const ModulePtr& module,
|
static std::optional<AutocompleteEntryMap> autocompleteStringParams(const SourceModule& sourceModule, const ModulePtr& module,
|
||||||
const std::vector<AstNode*>& nodes, Position position, StringCompletionCallback callback)
|
const std::vector<AstNode*>& nodes, Position position, StringCompletionCallback callback)
|
||||||
{
|
{
|
||||||
@ -1294,10 +1311,13 @@ static std::optional<AutocompleteEntryMap> autocompleteStringParams(const Source
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto performCallback = [&](const FunctionType* funcType) -> std::optional<AutocompleteEntryMap> {
|
std::optional<std::string> candidateString = getStringContents(nodes.back());
|
||||||
|
|
||||||
|
auto performCallback = [&](const FunctionType* funcType) -> std::optional<AutocompleteEntryMap>
|
||||||
|
{
|
||||||
for (const std::string& tag : funcType->tags)
|
for (const std::string& tag : funcType->tags)
|
||||||
{
|
{
|
||||||
if (std::optional<AutocompleteEntryMap> ret = callback(tag, getMethodContainingClass(module, candidate->func)))
|
if (std::optional<AutocompleteEntryMap> ret = callback(tag, getMethodContainingClass(module, candidate->func), candidateString))
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ LUAU_FASTFLAG(LuauSetMetatableDoesNotTimeTravel)
|
|||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
static std::optional<AutocompleteEntryMap> nullCallback(std::string tag, std::optional<const ClassType*> ptr)
|
static std::optional<AutocompleteEntryMap> nullCallback(std::string tag, std::optional<const ClassType*> ptr, std::optional<std::string> contents)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@ -36,9 +36,9 @@ struct ACFixtureImpl : BaseType
|
|||||||
return Luau::autocomplete(this->frontend, "MainModule", Position{row, column}, nullCallback);
|
return Luau::autocomplete(this->frontend, "MainModule", Position{row, column}, nullCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutocompleteResult autocomplete(char marker)
|
AutocompleteResult autocomplete(char marker, StringCompletionCallback callback = nullCallback)
|
||||||
{
|
{
|
||||||
return Luau::autocomplete(this->frontend, "MainModule", getPosition(marker), nullCallback);
|
return Luau::autocomplete(this->frontend, "MainModule", getPosition(marker), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckResult check(const std::string& source)
|
CheckResult check(const std::string& source)
|
||||||
@ -3363,4 +3363,31 @@ TEST_CASE_FIXTURE(ACFixture, "type_reduction_is_hooked_up_to_autocomplete")
|
|||||||
// CHECK("{| x: nil |}" == toString(*ty2, opts));
|
// CHECK("{| x: nil |}" == toString(*ty2, opts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(ACFixture, "string_contents_is_available_to_callback")
|
||||||
|
{
|
||||||
|
loadDefinition(R"(
|
||||||
|
declare function require(path: string): any
|
||||||
|
)");
|
||||||
|
|
||||||
|
std::optional<Binding> require = frontend.typeCheckerForAutocomplete.globalScope->linearSearchForBinding("require");
|
||||||
|
REQUIRE(require);
|
||||||
|
Luau::unfreeze(frontend.typeCheckerForAutocomplete.globalTypes);
|
||||||
|
attachTag(require->typeId, "RequireCall");
|
||||||
|
Luau::freeze(frontend.typeCheckerForAutocomplete.globalTypes);
|
||||||
|
|
||||||
|
check(R"(
|
||||||
|
local x = require("testing/@1")
|
||||||
|
)");
|
||||||
|
|
||||||
|
bool isCorrect = false;
|
||||||
|
auto ac1 = autocomplete('1',
|
||||||
|
[&isCorrect](std::string, std::optional<const ClassType*>, std::optional<std::string> contents) -> std::optional<AutocompleteEntryMap>
|
||||||
|
{
|
||||||
|
isCorrect = contents.has_value() && contents.value() == "testing/";
|
||||||
|
return std::nullopt;
|
||||||
|
});
|
||||||
|
|
||||||
|
CHECK(isCorrect);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
Loading…
Reference in New Issue
Block a user