mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
AsmParser: Accept optional code snippets after the @src tags
This commit is contained in:
parent
37f681c430
commit
d78522b08b
@ -135,7 +135,8 @@ void Parser::fetchSourceLocationFromComment()
|
||||
regex_constants::ECMAScript | regex_constants::optimize
|
||||
);
|
||||
static regex const srcTagArgsRegex = regex(
|
||||
R"~~(^(-1|\d+):(-1|\d+):(-1|\d+)(?:\s+|$))~~", // index and location, e.g.: 1:234:-1
|
||||
R"~~(^(-1|\d+):(-1|\d+):(-1|\d+)(?:\s+|$))~~" // index and location, e.g.: 1:234:-1
|
||||
R"~~(("(?:[^"\\]|\\.)*"?)?)~~", // optional code snippet, e.g.: "string memory s = \"abc\";..."
|
||||
regex_constants::ECMAScript | regex_constants::optimize
|
||||
);
|
||||
|
||||
@ -164,9 +165,22 @@ void Parser::fetchSourceLocationFromComment()
|
||||
return;
|
||||
}
|
||||
|
||||
solAssert(srcTagArgsMatch.size() == 4, "");
|
||||
solAssert(srcTagArgsMatch.size() == 5, "");
|
||||
position += srcTagArgsMatch.position() + srcTagArgsMatch.length();
|
||||
|
||||
if (srcTagArgsMatch[4].matched && (
|
||||
!boost::algorithm::ends_with(srcTagArgsMatch[4].str(), "\"") ||
|
||||
boost::algorithm::ends_with(srcTagArgsMatch[4].str(), "\\\"")
|
||||
))
|
||||
{
|
||||
m_errorReporter.syntaxError(
|
||||
1544_error,
|
||||
commentLocation,
|
||||
"Invalid code snippet in source location mapping. Quote is not terminated."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
optional<int> const sourceIndex = toInt(srcTagArgsMatch[1].str());
|
||||
optional<int> const start = toInt(srcTagArgsMatch[2].str());
|
||||
optional<int> const end = toInt(srcTagArgsMatch[3].str());
|
||||
|
@ -192,6 +192,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False):
|
||||
# white list of ids which are not covered by tests
|
||||
white_ids = {
|
||||
"9804", # Tested in test/libyul/ObjectParser.cpp.
|
||||
"1544",
|
||||
"2674",
|
||||
"6367",
|
||||
"8387",
|
||||
|
@ -624,6 +624,20 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace)
|
||||
CHECK_LOCATION(result->debugData->location, "", -1, -1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_space)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222 @src 1:333:444
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
CHECK_LOCATION(result->debugData->location, "source1", 333, 444);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace)
|
||||
{
|
||||
ErrorList errorList;
|
||||
@ -656,6 +670,164 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc)
|
||||
CHECK_LOCATION(varDecl.debugData->location, "", 10, 20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"~~~(
|
||||
{
|
||||
/// @src 0:149:156 "new C(\"123\")"
|
||||
let x := 123
|
||||
|
||||
let y := /** @src 1:96:165 "contract D {..." */ 128
|
||||
}
|
||||
)~~~";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
BOOST_REQUIRE_EQUAL(result->statements.size(), 2);
|
||||
|
||||
BOOST_REQUIRE(holds_alternative<VariableDeclaration>(result->statements.at(0)));
|
||||
VariableDeclaration const& varX = get<VariableDeclaration>(result->statements.at(0));
|
||||
CHECK_LOCATION(varX.debugData->location, "source0", 149, 156);
|
||||
|
||||
BOOST_REQUIRE(holds_alternative<VariableDeclaration>(result->statements.at(1)));
|
||||
VariableDeclaration const& varY = get<VariableDeclaration>(result->statements.at(1));
|
||||
BOOST_REQUIRE(!!varY.value);
|
||||
BOOST_REQUIRE(holds_alternative<Literal>(*varY.value));
|
||||
Literal const& literal128 = get<Literal>(*varY.value);
|
||||
CHECK_LOCATION(literal128.debugData->location, "source1", 96, 165);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222 ""
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
CHECK_LOCATION(result->debugData->location, "source0", 111, 222);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_before_snippet)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222"abc" def
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result);
|
||||
BOOST_REQUIRE(errorList.size() == 1);
|
||||
BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError);
|
||||
BOOST_TEST(errorList[0]->errorId() == 8387_error);
|
||||
CHECK_LOCATION(result->debugData->location, "", -1, -1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_after_snippet)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222 "abc"def
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
CHECK_LOCATION(result->debugData->location, "source0", 111, 222);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whitespace)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222 "abc"@src 1:333:444 "abc"
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
CHECK_LOCATION(result->debugData->location, "source1", 333, 444);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_unterminated_quote)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"(
|
||||
/// @src 0:111:222 " abc @src 1:333:444
|
||||
{}
|
||||
)";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result);
|
||||
BOOST_REQUIRE(errorList.size() == 1);
|
||||
BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError);
|
||||
BOOST_TEST(errorList[0]->errorId() == 1544_error);
|
||||
CHECK_LOCATION(result->debugData->location, "", -1, -1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locations)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText = R"~~~(
|
||||
{
|
||||
/// @src 0:149:156 "new C(\"123\") /// @src 1:3:4 "
|
||||
let x := 123
|
||||
|
||||
let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128
|
||||
}
|
||||
)~~~";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
BOOST_REQUIRE_EQUAL(result->statements.size(), 2);
|
||||
|
||||
BOOST_REQUIRE(holds_alternative<VariableDeclaration>(result->statements.at(0)));
|
||||
VariableDeclaration const& varX = get<VariableDeclaration>(result->statements.at(0));
|
||||
CHECK_LOCATION(varX.debugData->location, "source0", 149, 156);
|
||||
|
||||
BOOST_REQUIRE(holds_alternative<VariableDeclaration>(result->statements.at(1)));
|
||||
VariableDeclaration const& varY = get<VariableDeclaration>(result->statements.at(1));
|
||||
BOOST_REQUIRE(!!varY.value);
|
||||
BOOST_REQUIRE(holds_alternative<Literal>(*varY.value));
|
||||
Literal const& literal128 = get<Literal>(*varY.value);
|
||||
CHECK_LOCATION(literal128.debugData->location, "source1", 96, 165);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line)
|
||||
{
|
||||
ErrorList errorList;
|
||||
ErrorReporter reporter(errorList);
|
||||
auto const sourceText =
|
||||
"{\n"
|
||||
" /// "
|
||||
R"~~(@src 1:2:3 ""@src 1:2:4 @src-1:2:5@src 1:2:6 @src 1:2:7 "" @src 1:2:8)~~"
|
||||
R"~~( X "@src 0:10:20 "new C(\"123\") /// @src 1:4:5 "" XYZ)~~"
|
||||
R"~~( @src0:20:30 "abc"@src0:2:4 @src-0:2:5@)~~"
|
||||
R"~~( @some text with random @ signs @@@ @- @** 1:6:7 "src 1:8:9")~~"
|
||||
"\n"
|
||||
" let x := 123\n"
|
||||
"}\n";
|
||||
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
|
||||
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
|
||||
BOOST_REQUIRE(!!result && errorList.size() == 0);
|
||||
BOOST_REQUIRE_EQUAL(result->statements.size(), 1);
|
||||
|
||||
BOOST_REQUIRE(holds_alternative<VariableDeclaration>(result->statements.at(0)));
|
||||
VariableDeclaration const& varX = get<VariableDeclaration>(result->statements.at(0));
|
||||
CHECK_LOCATION(varX.debugData->location, "source1", 4, 5);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // end namespaces
|
||||
|
Loading…
Reference in New Issue
Block a user