From eb53fa5bec07f8405fb837f8b0ec426916ad7582 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 15 Nov 2022 13:12:39 -0800 Subject: [PATCH] Fix string interpolation autocomplete --- Analysis/src/AstQuery.cpp | 1 + Analysis/src/Autocomplete.cpp | 4 ---- Ast/src/Parser.cpp | 42 ++++++++++++++--------------------- tests/AstJsonEncoder.test.cpp | 2 +- tests/Autocomplete.test.cpp | 24 ++++++++++++++------ 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/Analysis/src/AstQuery.cpp b/Analysis/src/AstQuery.cpp index 75388760..c643d32e 100644 --- a/Analysis/src/AstQuery.cpp +++ b/Analysis/src/AstQuery.cpp @@ -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/AstQuery.h" +#include "Luau/Ast.h" #include "Luau/Module.h" #include "Luau/Scope.h" #include "Luau/TypeInfer.h" diff --git a/Analysis/src/Autocomplete.cpp b/Analysis/src/Autocomplete.cpp index 1edcef84..938cbf49 100644 --- a/Analysis/src/Autocomplete.cpp +++ b/Analysis/src/Autocomplete.cpp @@ -1227,11 +1227,8 @@ static bool stringPartOfInterpString(const AstNode* node, Position position) return false; } - printf("expressions.count: %ld\n", interpString->expressions.size); - for (const AstExpr* expression : interpString->expressions) { - printf("%s <= %s <= %s -- expression = %d\n", toString(expression->location.begin).c_str(), toString(position).c_str(), toString(expression->location.end).c_str(), expression->classIndex); if (expression->location.containsClosed(position)) { return false; @@ -1239,7 +1236,6 @@ static bool stringPartOfInterpString(const AstNode* node, Position position) } return true; - // return node->is(); } static std::optional autocompleteStringParams(const SourceModule& sourceModule, const ModulePtr& module, diff --git a/Ast/src/Parser.cpp b/Ast/src/Parser.cpp index 5cd8c74b..ae25727d 100644 --- a/Ast/src/Parser.cpp +++ b/Ast/src/Parser.cpp @@ -22,7 +22,7 @@ bool lua_telemetry_parsed_named_non_function_type = false; LUAU_FASTFLAGVARIABLE(LuauErrorDoubleHexPrefix, false) LUAU_DYNAMIC_FASTFLAGVARIABLE(LuaReportParseIntegerIssues, false) -LUAU_FASTFLAGVARIABLE(LuauInterpolatedStringBaseSupport, false) +LUAU_FASTFLAGVARIABLE(LuauInterpolatedStringBaseSupport, true) LUAU_FASTFLAGVARIABLE(LuauCommaParenWarnings, false) LUAU_FASTFLAGVARIABLE(LuauTableConstructorRecovery, false) @@ -2661,6 +2661,7 @@ AstExpr* Parser::parseInterpString() TempVector expressions(scratchExpr); Location startLocation = lexer.current().location; + Location endLocation; do { @@ -2668,17 +2669,16 @@ AstExpr* Parser::parseInterpString() LUAU_ASSERT(currentLexeme.type == Lexeme::InterpStringBegin || currentLexeme.type == Lexeme::InterpStringMid || currentLexeme.type == Lexeme::InterpStringEnd || currentLexeme.type == Lexeme::InterpStringSimple); - Location location = currentLexeme.location; + endLocation = currentLexeme.location; - Location startOfBrace = Location(location.end, 1); + Location startOfBrace = Location(endLocation.end, 1); scratchData.assign(currentLexeme.data, currentLexeme.length); if (!Lexer::fixupQuotedString(scratchData)) { nextLexeme(); - printf("FIXUP QUOTED STRING FAIL\n"); - return reportExprError(startLocation, {}, "Interpolated string literal contains malformed escape sequence"); + return reportExprError(Location{startLocation, endLocation}, {}, "Interpolated string literal contains malformed escape sequence"); } AstArray chars = copy(scratchData); @@ -2689,10 +2689,7 @@ AstExpr* Parser::parseInterpString() if (currentLexeme.type == Lexeme::InterpStringEnd || currentLexeme.type == Lexeme::InterpStringSimple) { - AstArray> stringsArray = copy(strings); - AstArray expressionsArray = copy(expressions); - - return allocator.alloc(startLocation, stringsArray, expressionsArray); + break; } switch (lexer.current().type) @@ -2701,20 +2698,14 @@ AstExpr* Parser::parseInterpString() case Lexeme::InterpStringEnd: { nextLexeme(); - expressions.push_back(reportExprError(location, {}, "Malformed interpolated string, expected expression inside '{}'")); - AstArray> stringsArray = copy(strings); - AstArray expressionsArray = copy(expressions); - - return allocator.alloc(startLocation, stringsArray, expressionsArray); + expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, expected expression inside '{}'")); + break; } case Lexeme::BrokenString: { nextLexeme(); - expressions.push_back(reportExprError(location, {}, "Malformed interpolated string, did you forget to add a '`'?")); - AstArray> stringsArray = copy(strings); - AstArray expressionsArray = copy(expressions); - - return allocator.alloc(startLocation, stringsArray, expressionsArray); + expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, did you forget to add a '`'?")); + break; } default: expressions.push_back(parseExpr()); @@ -2728,17 +2719,18 @@ AstExpr* Parser::parseInterpString() break; case Lexeme::BrokenInterpDoubleBrace: nextLexeme(); - printf("BROKEN INTERP DOUBLE BRACE\n"); - return reportExprError(location, {}, ERROR_INVALID_INTERP_DOUBLE_BRACE); + return reportExprError(endLocation, {}, ERROR_INVALID_INTERP_DOUBLE_BRACE); case Lexeme::BrokenString: nextLexeme(); - printf("BROKEN STRING\n"); - return reportExprError(location, {}, "Malformed interpolated string, did you forget to add a '}'?"); + return reportExprError(endLocation, {}, "Malformed interpolated string, did you forget to add a '}'?"); default: - printf("DEFAULT: %s\n", lexer.current().toString().c_str()); - return reportExprError(location, {}, "Malformed interpolated string, got %s", lexer.current().toString().c_str()); + return reportExprError(endLocation, {}, "Malformed interpolated string, got %s", lexer.current().toString().c_str()); } } while (true); + + AstArray> stringsArray = copy(strings); + AstArray expressionsArray = copy(expressions); + return allocator.alloc(Location{startLocation, endLocation}, stringsArray, expressionsArray); } AstExpr* Parser::parseNumber() diff --git a/tests/AstJsonEncoder.test.cpp b/tests/AstJsonEncoder.test.cpp index 81e74941..a14d5f59 100644 --- a/tests/AstJsonEncoder.test.cpp +++ b/tests/AstJsonEncoder.test.cpp @@ -183,7 +183,7 @@ TEST_CASE_FIXTURE(JsonEncoderFixture, "encode_AstExprInterpString") AstStat* statement = expectParseStatement("local a = `var = {x}`"); std::string_view expected = - R"({"type":"AstStatLocal","location":"0,0 - 0,18","vars":[{"luauType":null,"name":"a","type":"AstLocal","location":"0,6 - 0,7"}],"values":[{"type":"AstExprInterpString","location":"0,10 - 0,18","strings":["var = ",""],"expressions":[{"type":"AstExprGlobal","location":"0,18 - 0,19","global":"x"}]}]})"; + R"({"type":"AstStatLocal","location":"0,0 - 0,21","vars":[{"luauType":null,"name":"a","type":"AstLocal","location":"0,6 - 0,7"}],"values":[{"type":"AstExprInterpString","location":"0,10 - 0,21","strings":["var = ",""],"expressions":[{"type":"AstExprGlobal","location":"0,18 - 0,19","global":"x"}]}]})"; CHECK(toJson(statement) == expected); } diff --git a/tests/Autocomplete.test.cpp b/tests/Autocomplete.test.cpp index 4653b520..6149775d 100644 --- a/tests/Autocomplete.test.cpp +++ b/tests/Autocomplete.test.cpp @@ -2712,15 +2712,24 @@ a = if temp then even else abc@3 TEST_CASE_FIXTURE(ACFixture, "autocomplete_interpolated_string_constant") { ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true}; - printf("======= autocomplete_interpolated_string_constant =======\n"); - // check(R"(f(`@1`))"); - // auto ac = autocomplete('1'); - // CHECK(ac.entryMap.empty()); - // CHECK_EQ(ac.context, AutocompleteContext::String); + check(R"(f(`@1`))"); + auto ac = autocomplete('1'); + CHECK(ac.entryMap.empty()); + CHECK_EQ(ac.context, AutocompleteContext::String); + + check(R"(f(`@1 {"a"}`))"); + ac = autocomplete('1'); + CHECK(ac.entryMap.empty()); + CHECK_EQ(ac.context, AutocompleteContext::String); check(R"(f(`{"a"} @1`))"); - auto ac = autocomplete('1'); + ac = autocomplete('1'); + CHECK(ac.entryMap.empty()); + CHECK_EQ(ac.context, AutocompleteContext::String); + + check(R"(f(`{"a"} @1 {"b"}`))"); + ac = autocomplete('1'); CHECK(ac.entryMap.empty()); CHECK_EQ(ac.context, AutocompleteContext::String); } @@ -2745,8 +2754,9 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_interpolated_string_expression_with_c CHECK(ac.entryMap.count("table")); CHECK_EQ(ac.context, AutocompleteContext::Expression); - check(R"(f(`expression = {@1--[[ bla bla bla ]]`))"); + check(R"(f(`expression = {@1 --[[ bla bla bla ]]`))"); ac = autocomplete('1'); + CHECK(!ac.entryMap.empty()); CHECK(ac.entryMap.count("table")); CHECK_EQ(ac.context, AutocompleteContext::Expression); }