mirror of
https://github.com/luau-lang/luau.git
synced 2025-05-04 10:33:46 +01:00
Handle formatting of parts of formatted interpolated string
This commit is contained in:
parent
2d94ef6f55
commit
971088a08a
3 changed files with 47 additions and 2 deletions
|
@ -1,6 +1,7 @@
|
||||||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||||
#include "Luau/Autocomplete.h"
|
#include "Luau/Autocomplete.h"
|
||||||
|
|
||||||
|
#include "Luau/Ast.h"
|
||||||
#include "Luau/AstQuery.h"
|
#include "Luau/AstQuery.h"
|
||||||
#include "Luau/BuiltinDefinitions.h"
|
#include "Luau/BuiltinDefinitions.h"
|
||||||
#include "Luau/Frontend.h"
|
#include "Luau/Frontend.h"
|
||||||
|
@ -1238,6 +1239,12 @@ static bool stringPartOfInterpString(const AstNode* node, Position position)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isSimpleInterpolatedString(const AstNode* node)
|
||||||
|
{
|
||||||
|
const AstExprInterpString* interpString = node->as<AstExprInterpString>();
|
||||||
|
return interpString != nullptr && interpString->expressions.size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -1246,7 +1253,8 @@ static std::optional<AutocompleteEntryMap> autocompleteStringParams(const Source
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nodes.back()->is<AstExprConstantString>() && !stringPartOfInterpString(nodes.back(), position) && !nodes.back()->is<AstExprError>())
|
if (!nodes.back()->is<AstExprConstantString>() && !isSimpleInterpolatedString(nodes.back()) && !nodes.back()->is<AstExprInterpString>() &&
|
||||||
|
!nodes.back()->is<AstExprError>())
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -1490,7 +1498,7 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
|
||||||
{
|
{
|
||||||
return {*ret, ancestry, AutocompleteContext::String};
|
return {*ret, ancestry, AutocompleteContext::String};
|
||||||
}
|
}
|
||||||
else if (node->is<AstExprConstantString>() || stringPartOfInterpString(node, position))
|
else if (node->is<AstExprConstantString>() || isSimpleInterpolatedString(node))
|
||||||
{
|
{
|
||||||
AutocompleteEntryMap result;
|
AutocompleteEntryMap result;
|
||||||
|
|
||||||
|
@ -1516,6 +1524,13 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
|
||||||
|
|
||||||
return {result, ancestry, AutocompleteContext::String};
|
return {result, ancestry, AutocompleteContext::String};
|
||||||
}
|
}
|
||||||
|
else if (stringPartOfInterpString(node, position))
|
||||||
|
{
|
||||||
|
// We're not a simple interpolated string, we're something like `a{"b"}@1`, and we
|
||||||
|
// can't know what to format to
|
||||||
|
AutocompleteEntryMap map;
|
||||||
|
return {map, ancestry, AutocompleteContext::String};
|
||||||
|
}
|
||||||
|
|
||||||
if (node->is<AstExprConstantNumber>())
|
if (node->is<AstExprConstantNumber>())
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -2692,17 +2692,21 @@ AstExpr* Parser::parseInterpString()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool errorWhileChecking = false;
|
||||||
|
|
||||||
switch (lexer.current().type)
|
switch (lexer.current().type)
|
||||||
{
|
{
|
||||||
case Lexeme::InterpStringMid:
|
case Lexeme::InterpStringMid:
|
||||||
case Lexeme::InterpStringEnd:
|
case Lexeme::InterpStringEnd:
|
||||||
{
|
{
|
||||||
|
errorWhileChecking = true;
|
||||||
nextLexeme();
|
nextLexeme();
|
||||||
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, expected expression inside '{}'"));
|
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, expected expression inside '{}'"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lexeme::BrokenString:
|
case Lexeme::BrokenString:
|
||||||
{
|
{
|
||||||
|
errorWhileChecking = true;
|
||||||
nextLexeme();
|
nextLexeme();
|
||||||
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, did you forget to add a '`'?"));
|
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, did you forget to add a '`'?"));
|
||||||
break;
|
break;
|
||||||
|
@ -2711,6 +2715,11 @@ AstExpr* Parser::parseInterpString()
|
||||||
expressions.push_back(parseExpr());
|
expressions.push_back(parseExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errorWhileChecking)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (lexer.current().type)
|
switch (lexer.current().type)
|
||||||
{
|
{
|
||||||
case Lexeme::InterpStringBegin:
|
case Lexeme::InterpStringBegin:
|
||||||
|
|
|
@ -2761,6 +2761,27 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_interpolated_string_expression_with_c
|
||||||
CHECK_EQ(ac.context, AutocompleteContext::Expression);
|
CHECK_EQ(ac.context, AutocompleteContext::Expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(ACFixture, "autocomplete_interpolated_string_as_singleton")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true};
|
||||||
|
|
||||||
|
check(R"(
|
||||||
|
--!strict
|
||||||
|
local function f(a: "cat" | "dog") end
|
||||||
|
|
||||||
|
f(`@1`)
|
||||||
|
f(`uhhh{'try'}@2`)
|
||||||
|
)");
|
||||||
|
|
||||||
|
auto ac = autocomplete('1');
|
||||||
|
CHECK(ac.entryMap.count("cat"));
|
||||||
|
CHECK_EQ(ac.context, AutocompleteContext::String);
|
||||||
|
|
||||||
|
ac = autocomplete('2');
|
||||||
|
CHECK(ac.entryMap.empty());
|
||||||
|
CHECK_EQ(ac.context, AutocompleteContext::String);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(ACFixture, "autocomplete_explicit_type_pack")
|
TEST_CASE_FIXTURE(ACFixture, "autocomplete_explicit_type_pack")
|
||||||
{
|
{
|
||||||
check(R"(
|
check(R"(
|
||||||
|
|
Loading…
Add table
Reference in a new issue