Handle formatting of parts of formatted interpolated string

This commit is contained in:
Kampfkarren 2022-11-15 13:50:52 -08:00
parent 2d94ef6f55
commit 971088a08a
3 changed files with 47 additions and 2 deletions

View file

@ -1,6 +1,7 @@
// 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/Ast.h"
#include "Luau/AstQuery.h"
#include "Luau/BuiltinDefinitions.h"
#include "Luau/Frontend.h"
@ -1238,6 +1239,12 @@ static bool stringPartOfInterpString(const AstNode* node, Position position)
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,
const std::vector<AstNode*>& nodes, Position position, StringCompletionCallback callback)
{
@ -1246,7 +1253,8 @@ static std::optional<AutocompleteEntryMap> autocompleteStringParams(const Source
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;
}
@ -1490,7 +1498,7 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
{
return {*ret, ancestry, AutocompleteContext::String};
}
else if (node->is<AstExprConstantString>() || stringPartOfInterpString(node, position))
else if (node->is<AstExprConstantString>() || isSimpleInterpolatedString(node))
{
AutocompleteEntryMap result;
@ -1516,6 +1524,13 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
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>())
return {};

View file

@ -2692,17 +2692,21 @@ AstExpr* Parser::parseInterpString()
break;
}
bool errorWhileChecking = false;
switch (lexer.current().type)
{
case Lexeme::InterpStringMid:
case Lexeme::InterpStringEnd:
{
errorWhileChecking = true;
nextLexeme();
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, expected expression inside '{}'"));
break;
}
case Lexeme::BrokenString:
{
errorWhileChecking = true;
nextLexeme();
expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, did you forget to add a '`'?"));
break;
@ -2711,6 +2715,11 @@ AstExpr* Parser::parseInterpString()
expressions.push_back(parseExpr());
}
if (errorWhileChecking)
{
break;
}
switch (lexer.current().type)
{
case Lexeme::InterpStringBegin:

View file

@ -2761,6 +2761,27 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_interpolated_string_expression_with_c
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")
{
check(R"(