Remove parser error recovery mode

This commit is contained in:
Kamil Śliwak
2023-08-22 12:00:11 +02:00
parent c96db51013
commit 9adbced98e
44 changed files with 142 additions and 585 deletions
-1
View File
@@ -71,7 +71,6 @@ Testsuite const g_interactiveTestsuites[] = {
{"Yul Syntax", "libyul", "yulSyntaxTests", false, false, &yul::test::SyntaxTest::create},
{"EVM Code Transform", "libyul", "evmCodeTransform", false, false, &yul::test::EVMCodeTransformTest::create, {"nooptions"}},
{"Syntax", "libsolidity", "syntaxTests", false, false, &SyntaxTest::create},
{"Error Recovery", "libsolidity", "errorRecoveryTests", false, false, &SyntaxTest::createErrorRecovery},
{"Semantic", "libsolidity", "semanticTests", false, true, &SemanticTest::create},
{"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create},
{"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create},
@@ -1 +0,0 @@
--error-recovery --ast-compact-json --pretty-json --hashes
@@ -1,11 +0,0 @@
Error: Expected primary expression.
--> recovery_ast_constructor/input.sol:6:27:
|
6 | balances[tx.origin] = ; // missing RHS.
| ^
Warning: Recovered in Statement at ';'.
--> recovery_ast_constructor/input.sol:6:27:
|
6 | balances[tx.origin] = ; // missing RHS.
| ^
@@ -1 +0,0 @@
1
@@ -1,13 +0,0 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0.0;
contract Error1 {
constructor() {
balances[tx.origin] = ; // missing RHS.
}
// This function parses properly
function five() public view returns(uint) {
return 5;
}
}
@@ -1 +0,0 @@
--error-recovery
@@ -1,5 +0,0 @@
Error: Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition.
--> recovery_ast_empty_contract/input.sol:3:1:
|
3 | c
| ^
@@ -1 +0,0 @@
1
@@ -1,3 +0,0 @@
// SPDX-License-Identifier: GPL-3.0
pragma 0.5.11;
c
@@ -1,18 +0,0 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }"
}
},
"settings":
{
"parserErrorRecovery": true,
"outputSelection":
{
"*": { "": ["ast"] }
}
}
}
@@ -1,46 +0,0 @@
{
"errors":
[
{
"component": "general",
"errorCode": "3546",
"formattedMessage": "ParserError: Expected type name
--> A:2:58:
|
2 | pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
| ^
",
"message": "Expected type name",
"severity": "error",
"sourceLocation":
{
"end": 94,
"file": "A",
"start": 93
},
"type": "ParserError"
},
{
"component": "general",
"errorCode": "3796",
"formattedMessage": "Warning: Recovered in ContractDefinition at '}'.
--> A:2:84:
|
2 | pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
| ^
",
"message": "Recovered in ContractDefinition at '}'.",
"severity": "warning",
"sourceLocation":
{
"end": 120,
"file": "A",
"start": 119
},
"type": "Warning"
}
],
"sources": {}
}
+1 -4
View File
@@ -47,15 +47,12 @@ AnalysisFramework::parseAnalyseAndReturnError(
string const& _source,
bool _reportWarnings,
bool _insertLicenseAndVersionPragma,
bool _allowMultipleErrors,
bool _allowRecoveryErrors
bool _allowMultipleErrors
)
{
compiler().reset();
compiler().setSources({{"", _insertLicenseAndVersionPragma ? withPreamble(_source) : _source}});
compiler().setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
compiler().setParserErrorRecovery(_allowRecoveryErrors);
_allowMultipleErrors = _allowMultipleErrors || _allowRecoveryErrors;
if (!compiler().parse())
{
BOOST_FAIL("Parsing contract failed in analysis test suite:" + formatErrors(compiler().errors()));
+1 -2
View File
@@ -48,8 +48,7 @@ protected:
std::string const& _source,
bool _reportWarnings = false,
bool _insertLicenseAndVersionPragma = true,
bool _allowMultipleErrors = false,
bool _allowRecoveryErrors = false
bool _allowMultipleErrors = false
);
virtual ~AnalysisFramework() = default;
+4 -5
View File
@@ -39,14 +39,13 @@ namespace solidity::frontend::test
namespace
{
ASTPointer<ContractDefinition> parseText(std::string const& _source, ErrorList& _errors, bool errorRecovery = false)
ASTPointer<ContractDefinition> parseText(std::string const& _source, ErrorList& _errors)
{
ErrorReporter errorReporter(_errors);
auto charStream = CharStream(_source, "");
ASTPointer<SourceUnit> sourceUnit = Parser(
errorReporter,
solidity::test::CommonOptions::get().evmVersion(),
errorRecovery
solidity::test::CommonOptions::get().evmVersion()
).parse(charStream);
if (!sourceUnit)
return ASTPointer<ContractDefinition>();
@@ -78,12 +77,12 @@ bool successParse(std::string const& _source)
return true;
}
Error getError(std::string const& _source, bool errorRecovery = false)
Error getError(std::string const& _source)
{
ErrorList errors;
try
{
parseText(_source, errors, errorRecovery);
parseText(_source, errors);
}
catch (FatalError const& /*_exception*/)
{
-37
View File
@@ -282,43 +282,6 @@ BOOST_AUTO_TEST_CASE(smoke_test)
BOOST_CHECK(containsAtMostWarnings(result));
}
BOOST_AUTO_TEST_CASE(error_recovery_field)
{
auto input = R"(
{
"language": "Solidity",
"settings": {
"parserErrorRecovery": "1"
},
"sources": {
"empty": {
"content": ""
}
}
}
)";
Json::Value result = compile(input);
BOOST_CHECK(containsError(result, "JSONError", "\"settings.parserErrorRecovery\" must be a Boolean."));
input = R"(
{
"language": "Solidity",
"settings": {
"parserErrorRecovery": true
},
"sources": {
"empty": {
"content": ""
}
}
}
)";
result = compile(input);
BOOST_CHECK(containsAtMostWarnings(result));
}
BOOST_AUTO_TEST_CASE(optimizer_enabled_not_boolean)
{
char const* input = R"(
+1 -3
View File
@@ -38,10 +38,9 @@ using namespace solidity::frontend::test;
using namespace boost::unit_test;
namespace fs = boost::filesystem;
SyntaxTest::SyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion, bool _parserErrorRecovery): CommonSyntaxTest(_filename, _evmVersion)
SyntaxTest::SyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion): CommonSyntaxTest(_filename, _evmVersion)
{
m_optimiseYul = m_reader.boolSetting("optimize-yul", true);
m_parserErrorRecovery = _parserErrorRecovery;
}
void SyntaxTest::setupCompiler()
@@ -49,7 +48,6 @@ void SyntaxTest::setupCompiler()
compiler().reset();
compiler().setSources(withPreamble(m_sources.sources));
compiler().setEVMVersion(m_evmVersion);
compiler().setParserErrorRecovery(m_parserErrorRecovery);
compiler().setOptimiserSettings(
m_optimiseYul ?
OptimiserSettings::full() :
+2 -7
View File
@@ -39,13 +39,9 @@ class SyntaxTest: public AnalysisFramework, public solidity::test::CommonSyntaxT
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion, false);
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion);
}
static std::unique_ptr<TestCase> createErrorRecovery(Config const& _config)
{
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion, true);
}
SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion, bool _parserErrorRecovery = false);
SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
protected:
virtual void setupCompiler();
@@ -53,7 +49,6 @@ protected:
virtual void filterObtainedErrors();
bool m_optimiseYul = true;
bool m_parserErrorRecovery = false;
};
}
@@ -1,20 +0,0 @@
pragma solidity >=0.0.0;
contract Error1 {
constructor() {
balances[tx.origin] = ; // missing RHS.
}
// Without error recovery we stop due to the above error.
// Error recovery however recovers at the above ';'
// There should be an AST for the above, albeit with error
// nodes.
// This function parses properly and should give AST info.
function five() public view returns(uint) {
return 5;
}
}
// ----
// ParserError 6933: (88-89): Expected primary expression.
// Warning 3347: (88-89): Recovered in Statement at ';'.
@@ -1,6 +0,0 @@
contract Errort6 {
using foo for ; // missing type name
}
// ----
// ParserError 3546: (36-37): Expected type name
// Warning 3796: (59-60): Recovered in ContractDefinition at '}'.
@@ -1,15 +0,0 @@
pragma solidity >=0.0.0;
// Example to show why deleting the token at the
// is bad when error recovery is in effect. Here, ")" is missing
// and there is a ";" instead. That causes us to
// not be able to synchronize to ';'. Advance again and
// '}' is deleted and then we can't synchronize the contract.
// There should be an an AST created this contract (with errors).
contract Error2 {
mapping (address => uint balances; // missing ) before "balances"
}
// ----
// ParserError 6635: (425-426): Expected ')' but got ';'
// ParserError 6635: (425-426): Expected identifier but got ';'
// ParserError 6635: (458-459): Expected ';' but got '}'
@@ -1,23 +0,0 @@
// Example which where scanning hits EOS, so we reset.
// Here we recover in the contractDefinition.
// There should be an an AST created this contract (with errors).
contract Error2 {
mapping (address => uint balances) // missing ;
}
// There is no error in this contract
contract SendCoin {
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfer(msg.sender, receiver, amount);
return true;
}
}
// ----
// ParserError 6635: (235-236): Expected identifier but got '}'
// ParserError 6635: (276-284): Expected ';' but got 'contract'
// ParserError 9182: (276-284): Function, variable, struct or modifier declaration expected.
// Warning 3796: (572-573): Recovered in ContractDefinition at '}'.
// ParserError 7858: (574-575): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition.
@@ -1,11 +0,0 @@
pragma solidity >=0.0.0;
contract Error3 {
constructor() {
balances[tx.origin] = ; // missing RHS.
}
}
// ----
// ParserError 6933: (88-89): Expected primary expression.
// Warning 3347: (88-89): Recovered in Statement at ';'.
@@ -1,29 +0,0 @@
// An example with multiple errors.
// Most are caught by inserting an expected token.
// However some us S C Johnson recovery to
// skip over tokens.
pragma solidity >=0.0.0;
contract Error4 {
constructor() {
balances[tx.origin] = 1 2; // missing operator
}
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount // Missing ";"
balances[receiver] += amount // Another missing ";"
emit Transfer(msg.sender // truncated line
return true;
}
}
// ----
// ParserError 6635: (242-243): Expected ';' but got 'Number'
// ParserError 6635: (464-472): Expected ';' but got identifier
// ParserError 6635: (522-526): Expected ';' but got 'emit'
// ParserError 6635: (570-576): Expected ',' but got 'return'
// ParserError 6933: (570-576): Expected primary expression.
// Warning 3796: (581-582): Recovered in Statement at ';'.
@@ -1,10 +0,0 @@
pragma solidity >=0.0.0;
contract Error7 {
constructor() {
a =
// ----
// ParserError 6933: (76-76): Expected primary expression.
// ParserError 1957: (76-76): In Statement, ';'is expected; got end of source instead.
// ParserError 1957: (76-76): In Block, '}'is expected; got end of source instead.
// ParserError 1957: (76-76): In ContractDefinition, '}'is expected; got end of source instead.
@@ -1,3 +0,0 @@
pragma solidity ^99.99.0;
// ----
// SyntaxError 3997: (0-25): Source file requires different compiler version (current compiler is ....
@@ -1,6 +0,0 @@
pragma solidity ^99.99.0;
this is surely invalid
// ----
// ParserError 6635: (31-33): Expected identifier but got 'is'
// ParserError 6635: (34-40): Expected ';' but got identifier
// ParserError 6635: (49-49): Expected ';' but got end of source
@@ -1,7 +0,0 @@
pragma solidity ^99.99.0;
contract C {
uint ;
}
// ----
// ParserError 6635: (48-49): Expected identifier but got ';'
// ParserError 6635: (50-51): Expected ';' but got '}'
@@ -1,7 +0,0 @@
pragma solidity ^99.99.0;
contract C {
function f() {}
}
// ----
// SyntaxError 3997: (0-25): Source file requires different compiler version (current compiler is ....
// SyntaxError 4937: (43-58): No visibility specified. Did you intend to add "public"?
-4
View File
@@ -33,10 +33,6 @@ public:
{
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion);
}
static std::unique_ptr<TestCase> createErrorRecovery(Config const& _config)
{
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion);
}
SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
~SyntaxTest() override {}
protected:
-3
View File
@@ -116,7 +116,6 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
"--include-path=/home/user/include",
"--allow-paths=/tmp,/home,project,../contracts",
"--ignore-missing",
"--error-recovery",
"--output-dir=/tmp/out",
"--overwrite",
"--evm-version=spuriousDragon",
@@ -177,7 +176,6 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
expectedOptions.input.allowedDirectories = {"/tmp", "/home", "project", "../contracts", "c", "/usr/lib"};
expectedOptions.input.ignoreMissingFiles = true;
expectedOptions.input.errorRecovery = (inputMode == InputMode::Compiler);
expectedOptions.output.dir = "/tmp/out";
expectedOptions.output.overwriteFiles = true;
expectedOptions.output.evmVersion = EVMVersion::spuriousDragon();
@@ -405,7 +403,6 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
{
map<string, vector<string>> invalidOptionInputModeCombinations = {
// TODO: This should eventually contain all options.
{"--error-recovery", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}},
{"--experimental-via-ir", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}},
{"--via-ir", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}},
{"--metadata-literal", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}},