mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #14329 from ethereum/remove-ast-output-in-error-recovery-mode
Remove AST output in error recovery mode
This commit is contained in:
commit
664baa9e6b
@ -87,15 +87,19 @@ public:
|
|||||||
static void listAccept(std::vector<T> const& _list, ASTVisitor& _visitor)
|
static void listAccept(std::vector<T> const& _list, ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
for (T const& element: _list)
|
for (T const& element: _list)
|
||||||
if (element)
|
{
|
||||||
element->accept(_visitor);
|
solAssert(element);
|
||||||
|
element->accept(_visitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
static void listAccept(std::vector<T> const& _list, ASTConstVisitor& _visitor)
|
static void listAccept(std::vector<T> const& _list, ASTConstVisitor& _visitor)
|
||||||
{
|
{
|
||||||
for (T const& element: _list)
|
for (T const& element: _list)
|
||||||
if (element)
|
{
|
||||||
element->accept(_visitor);
|
solAssert(element);
|
||||||
|
element->accept(_visitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a copy of the vector containing only the nodes which derive from T.
|
/// @returns a copy of the vector containing only the nodes which derive from T.
|
||||||
|
@ -560,7 +560,7 @@ bool ASTJsonExporter::visit(EventDefinition const& _node)
|
|||||||
std::make_pair("parameters", toJson(_node.parameterList())),
|
std::make_pair("parameters", toJson(_node.parameterList())),
|
||||||
std::make_pair("anonymous", _node.isAnonymous())
|
std::make_pair("anonymous", _node.isAnonymous())
|
||||||
};
|
};
|
||||||
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
|
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
|
||||||
_attributes.emplace_back(
|
_attributes.emplace_back(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
"eventSelector",
|
"eventSelector",
|
||||||
@ -579,7 +579,7 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node)
|
|||||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
std::make_pair("parameters", toJson(_node.parameterList()))
|
std::make_pair("parameters", toJson(_node.parameterList()))
|
||||||
};
|
};
|
||||||
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
|
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
|
||||||
_attributes.emplace_back(std::make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
|
_attributes.emplace_back(std::make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
|
||||||
|
|
||||||
setJsonNode(_node, "ErrorDefinition", std::move(_attributes));
|
setJsonNode(_node, "ErrorDefinition", std::move(_attributes));
|
||||||
|
@ -307,7 +307,6 @@ void CompilerStack::addSMTLib2Response(h256 const& _hash, std::string const& _re
|
|||||||
void CompilerStack::reset(bool _keepSettings)
|
void CompilerStack::reset(bool _keepSettings)
|
||||||
{
|
{
|
||||||
m_stackState = Empty;
|
m_stackState = Empty;
|
||||||
m_hasError = false;
|
|
||||||
m_sources.clear();
|
m_sources.clear();
|
||||||
m_smtlib2Responses.clear();
|
m_smtlib2Responses.clear();
|
||||||
m_unhandledSMTLib2Queries.clear();
|
m_unhandledSMTLib2Queries.clear();
|
||||||
@ -403,16 +402,12 @@ bool CompilerStack::parse()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_stopAfter <= Parsed)
|
|
||||||
m_stackState = Parsed;
|
|
||||||
else
|
|
||||||
m_stackState = ParsedAndImported;
|
|
||||||
if (Error::containsErrors(m_errorReporter.errors()))
|
if (Error::containsErrors(m_errorReporter.errors()))
|
||||||
m_hasError = true;
|
return false;
|
||||||
|
|
||||||
|
m_stackState = (m_stopAfter <= Parsed ? Parsed : ParsedAndImported);
|
||||||
storeContractDefinitions();
|
storeContractDefinitions();
|
||||||
|
return true;
|
||||||
return !m_hasError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerStack::importASTs(std::map<std::string, Json::Value> const& _sources)
|
void CompilerStack::importASTs(std::map<std::string, Json::Value> const& _sources)
|
||||||
@ -440,8 +435,8 @@ void CompilerStack::importASTs(std::map<std::string, Json::Value> const& _source
|
|||||||
|
|
||||||
bool CompilerStack::analyze()
|
bool CompilerStack::analyze()
|
||||||
{
|
{
|
||||||
if (m_stackState != ParsedAndImported || m_stackState >= AnalysisPerformed)
|
if (m_stackState != ParsedAndImported)
|
||||||
solThrow(CompilerError, "Must call analyze only after parsing was performed.");
|
solThrow(CompilerError, "Must call analyze only after parsing was successful.");
|
||||||
|
|
||||||
if (!resolveImports())
|
if (!resolveImports())
|
||||||
return false;
|
return false;
|
||||||
@ -628,11 +623,11 @@ bool CompilerStack::analyze()
|
|||||||
noErrors = false;
|
noErrors = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stackState = AnalysisPerformed;
|
|
||||||
if (!noErrors)
|
if (!noErrors)
|
||||||
m_hasError = true;
|
return false;
|
||||||
|
|
||||||
return !m_hasError;
|
m_stackState = AnalysisSuccessful;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompilerStack::parseAndAnalyze(State _stopAfter)
|
bool CompilerStack::parseAndAnalyze(State _stopAfter)
|
||||||
@ -642,7 +637,7 @@ bool CompilerStack::parseAndAnalyze(State _stopAfter)
|
|||||||
bool success = parse();
|
bool success = parse();
|
||||||
if (m_stackState >= m_stopAfter)
|
if (m_stackState >= m_stopAfter)
|
||||||
return success;
|
return success;
|
||||||
if (success || m_parserErrorRecovery)
|
if (success)
|
||||||
success = analyze();
|
success = analyze();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -675,16 +670,13 @@ bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) con
|
|||||||
bool CompilerStack::compile(State _stopAfter)
|
bool CompilerStack::compile(State _stopAfter)
|
||||||
{
|
{
|
||||||
m_stopAfter = _stopAfter;
|
m_stopAfter = _stopAfter;
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
if (!parseAndAnalyze(_stopAfter))
|
if (!parseAndAnalyze(_stopAfter))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_stackState >= m_stopAfter)
|
if (m_stackState >= m_stopAfter)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (m_hasError)
|
|
||||||
solThrow(CompilerError, "Called compile with errors.");
|
|
||||||
|
|
||||||
// Only compile contracts individually which have been requested.
|
// Only compile contracts individually which have been requested.
|
||||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> otherCompilers;
|
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> otherCompilers;
|
||||||
|
|
||||||
@ -763,7 +755,7 @@ std::vector<std::string> CompilerStack::contractNames() const
|
|||||||
|
|
||||||
std::string const CompilerStack::lastContractName(std::optional<std::string> const& _sourceName) const
|
std::string const CompilerStack::lastContractName(std::optional<std::string> const& _sourceName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Parsing was not successful.");
|
solThrow(CompilerError, "Parsing was not successful.");
|
||||||
// try to find some user-supplied contract
|
// try to find some user-supplied contract
|
||||||
std::string contractName;
|
std::string contractName;
|
||||||
@ -866,7 +858,7 @@ std::string const* CompilerStack::runtimeSourceMapping(std::string const& _contr
|
|||||||
|
|
||||||
std::string const CompilerStack::filesystemFriendlyName(std::string const& _contractName) const
|
std::string const CompilerStack::filesystemFriendlyName(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "No compiled contracts found.");
|
solThrow(CompilerError, "No compiled contracts found.");
|
||||||
|
|
||||||
// Look up the contract (by its fully-qualified name)
|
// Look up the contract (by its fully-qualified name)
|
||||||
@ -980,7 +972,7 @@ std::map<std::string, unsigned> CompilerStack::sourceIndices() const
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::contractABI(std::string const& _contractName) const
|
Json::Value const& CompilerStack::contractABI(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return contractABI(contract(_contractName));
|
return contractABI(contract(_contractName));
|
||||||
@ -988,7 +980,7 @@ Json::Value const& CompilerStack::contractABI(std::string const& _contractName)
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
|
Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
solAssert(_contract.contract, "");
|
solAssert(_contract.contract, "");
|
||||||
@ -998,7 +990,7 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::storageLayout(std::string const& _contractName) const
|
Json::Value const& CompilerStack::storageLayout(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return storageLayout(contract(_contractName));
|
return storageLayout(contract(_contractName));
|
||||||
@ -1006,7 +998,7 @@ Json::Value const& CompilerStack::storageLayout(std::string const& _contractName
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const
|
Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
solAssert(_contract.contract, "");
|
solAssert(_contract.contract, "");
|
||||||
@ -1016,7 +1008,7 @@ Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) const
|
Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return natspecUser(contract(_contractName));
|
return natspecUser(contract(_contractName));
|
||||||
@ -1024,7 +1016,7 @@ Json::Value const& CompilerStack::natspecUser(std::string const& _contractName)
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const
|
Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
solAssert(_contract.contract, "");
|
solAssert(_contract.contract, "");
|
||||||
@ -1034,7 +1026,7 @@ Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) const
|
Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return natspecDev(contract(_contractName));
|
return natspecDev(contract(_contractName));
|
||||||
@ -1042,7 +1034,7 @@ Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) c
|
|||||||
|
|
||||||
Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
|
Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
solAssert(_contract.contract, "");
|
solAssert(_contract.contract, "");
|
||||||
@ -1052,7 +1044,7 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
|
|||||||
|
|
||||||
Json::Value CompilerStack::interfaceSymbols(std::string const& _contractName) const
|
Json::Value CompilerStack::interfaceSymbols(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
Json::Value interfaceSymbols(Json::objectValue);
|
Json::Value interfaceSymbols(Json::objectValue);
|
||||||
@ -1082,7 +1074,7 @@ Json::Value CompilerStack::interfaceSymbols(std::string const& _contractName) co
|
|||||||
|
|
||||||
bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const
|
bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return createCBORMetadata(contract(_contractName), _forIR);
|
return createCBORMetadata(contract(_contractName), _forIR);
|
||||||
@ -1090,7 +1082,7 @@ bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR)
|
|||||||
|
|
||||||
std::string const& CompilerStack::metadata(Contract const& _contract) const
|
std::string const& CompilerStack::metadata(Contract const& _contract) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
solAssert(_contract.contract, "");
|
solAssert(_contract.contract, "");
|
||||||
@ -1120,7 +1112,7 @@ SourceUnit const& CompilerStack::ast(std::string const& _sourceName) const
|
|||||||
|
|
||||||
ContractDefinition const& CompilerStack::contractDefinition(std::string const& _contractName) const
|
ContractDefinition const& CompilerStack::contractDefinition(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
if (m_stackState < AnalysisPerformed)
|
if (m_stackState < AnalysisSuccessful)
|
||||||
solThrow(CompilerError, "Analysis was not successful.");
|
solThrow(CompilerError, "Analysis was not successful.");
|
||||||
|
|
||||||
return *contract(_contractName).contract;
|
return *contract(_contractName).contract;
|
||||||
@ -1219,15 +1211,15 @@ bool CompilerStack::resolveImports()
|
|||||||
if (sourcesSeen.count(_source))
|
if (sourcesSeen.count(_source))
|
||||||
return;
|
return;
|
||||||
sourcesSeen.insert(_source);
|
sourcesSeen.insert(_source);
|
||||||
if (_source->ast)
|
solAssert(_source->ast);
|
||||||
for (ASTPointer<ASTNode> const& node: _source->ast->nodes())
|
for (ASTPointer<ASTNode> const& node: _source->ast->nodes())
|
||||||
if (ImportDirective const* import = dynamic_cast<ImportDirective*>(node.get()))
|
if (ImportDirective const* import = dynamic_cast<ImportDirective*>(node.get()))
|
||||||
{
|
{
|
||||||
std::string const& path = *import->annotation().absolutePath;
|
std::string const& path = *import->annotation().absolutePath;
|
||||||
solAssert(m_sources.count(path), "");
|
solAssert(m_sources.count(path), "");
|
||||||
import->annotation().sourceUnit = m_sources[path].ast.get();
|
import->annotation().sourceUnit = m_sources[path].ast.get();
|
||||||
toposort(&m_sources[path]);
|
toposort(&m_sources[path]);
|
||||||
}
|
}
|
||||||
sourceOrder.push_back(_source);
|
sourceOrder.push_back(_source);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1326,8 +1318,7 @@ void CompilerStack::assembleYul(
|
|||||||
std::shared_ptr<evmasm::Assembly> _runtimeAssembly
|
std::shared_ptr<evmasm::Assembly> _runtimeAssembly
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
solAssert(m_stackState >= AnalysisSuccessful, "");
|
||||||
solAssert(!m_hasError, "");
|
|
||||||
|
|
||||||
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
||||||
|
|
||||||
@ -1400,9 +1391,7 @@ void CompilerStack::compileContract(
|
|||||||
{
|
{
|
||||||
solAssert(!m_viaIR, "");
|
solAssert(!m_viaIR, "");
|
||||||
solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation.");
|
solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation.");
|
||||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
solAssert(m_stackState >= AnalysisSuccessful, "");
|
||||||
if (m_hasError)
|
|
||||||
solThrow(CompilerError, "Called compile with errors.");
|
|
||||||
|
|
||||||
if (_otherCompilers.count(&_contract))
|
if (_otherCompilers.count(&_contract))
|
||||||
return;
|
return;
|
||||||
@ -1438,9 +1427,7 @@ void CompilerStack::compileContract(
|
|||||||
|
|
||||||
void CompilerStack::generateIR(ContractDefinition const& _contract)
|
void CompilerStack::generateIR(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
solAssert(m_stackState >= AnalysisSuccessful, "");
|
||||||
if (m_hasError)
|
|
||||||
solThrow(CompilerError, "Called generateIR with errors.");
|
|
||||||
|
|
||||||
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
||||||
if (!compiledContract.yulIR.empty())
|
if (!compiledContract.yulIR.empty())
|
||||||
@ -1502,9 +1489,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
|
void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
solAssert(m_stackState >= AnalysisSuccessful, "");
|
||||||
if (m_hasError)
|
|
||||||
solThrow(CompilerError, "Called generateEVMFromIR with errors.");
|
|
||||||
|
|
||||||
if (!_contract.canBeDeployed())
|
if (!_contract.canBeDeployed())
|
||||||
return;
|
return;
|
||||||
@ -1535,7 +1520,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
CompilerStack::Contract const& CompilerStack::contract(std::string const& _contractName) const
|
CompilerStack::Contract const& CompilerStack::contract(std::string const& _contractName) const
|
||||||
{
|
{
|
||||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
solAssert(m_stackState >= AnalysisSuccessful, "");
|
||||||
|
|
||||||
auto it = m_contracts.find(_contractName);
|
auto it = m_contracts.find(_contractName);
|
||||||
if (it != m_contracts.end())
|
if (it != m_contracts.end())
|
||||||
|
@ -86,8 +86,6 @@ class DeclarationContainer;
|
|||||||
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
|
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
|
||||||
* It holds state and can be used to either step through the compilation stages (and abort e.g.
|
* It holds state and can be used to either step through the compilation stages (and abort e.g.
|
||||||
* before compilation to bytecode) or run the whole compilation in one call.
|
* before compilation to bytecode) or run the whole compilation in one call.
|
||||||
* If error recovery is active, it is possible to progress through the stages even when
|
|
||||||
* there are errors. In any case, producing code is only possible without errors.
|
|
||||||
*/
|
*/
|
||||||
class CompilerStack: public langutil::CharStreamProvider
|
class CompilerStack: public langutil::CharStreamProvider
|
||||||
{
|
{
|
||||||
@ -101,7 +99,7 @@ public:
|
|||||||
SourcesSet,
|
SourcesSet,
|
||||||
Parsed,
|
Parsed,
|
||||||
ParsedAndImported,
|
ParsedAndImported,
|
||||||
AnalysisPerformed,
|
AnalysisSuccessful,
|
||||||
CompilationSuccessful
|
CompilationSuccessful
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -137,10 +135,6 @@ public:
|
|||||||
/// @returns the current state.
|
/// @returns the current state.
|
||||||
State state() const { return m_stackState; }
|
State state() const { return m_stackState; }
|
||||||
|
|
||||||
bool hasError() const { return m_hasError; }
|
|
||||||
|
|
||||||
bool compilationSuccessful() const { return m_stackState >= CompilationSuccessful; }
|
|
||||||
|
|
||||||
/// Resets the compiler to an empty state. Unless @a _keepSettings is set to true,
|
/// Resets the compiler to an empty state. Unless @a _keepSettings is set to true,
|
||||||
/// all settings are reset as well.
|
/// all settings are reset as well.
|
||||||
void reset(bool _keepSettings = false);
|
void reset(bool _keepSettings = false);
|
||||||
@ -520,9 +514,6 @@ private:
|
|||||||
bool m_parserErrorRecovery = false;
|
bool m_parserErrorRecovery = false;
|
||||||
State m_stackState = Empty;
|
State m_stackState = Empty;
|
||||||
CompilationSourceType m_compilationSourceType = CompilationSourceType::Solidity;
|
CompilationSourceType m_compilationSourceType = CompilationSourceType::Solidity;
|
||||||
/// Whether or not there has been an error during processing.
|
|
||||||
/// If this is true, the stack will refuse to generate code.
|
|
||||||
bool m_hasError = false;
|
|
||||||
MetadataFormat m_metadataFormat = defaultMetadataFormat();
|
MetadataFormat m_metadataFormat = defaultMetadataFormat();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1317,21 +1317,18 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool parsingSuccess = compilerStack.state() >= CompilerStack::State::Parsed;
|
bool parsingSuccess = compilerStack.state() >= CompilerStack::State::Parsed;
|
||||||
bool analysisPerformed = compilerStack.state() >= CompilerStack::State::AnalysisPerformed;
|
bool analysisSuccess = compilerStack.state() >= CompilerStack::State::AnalysisSuccessful;
|
||||||
bool compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful;
|
bool compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful;
|
||||||
|
|
||||||
if (compilerStack.hasError() && !_inputsAndSettings.parserErrorRecovery)
|
|
||||||
analysisPerformed = false;
|
|
||||||
|
|
||||||
// If analysis fails, the artifacts inside CompilerStack are potentially incomplete and must not be returned.
|
// If analysis fails, the artifacts inside CompilerStack are potentially incomplete and must not be returned.
|
||||||
// Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success.
|
// Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success.
|
||||||
bool analysisFailed = !analysisPerformed && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed;
|
bool analysisFailed = !analysisSuccess && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisSuccessful;
|
||||||
bool compilationFailed = !compilationSuccess && binariesRequested;
|
bool compilationFailed = !compilationSuccess && binariesRequested;
|
||||||
|
|
||||||
/// Inconsistent state - stop here to receive error reports from users
|
/// Inconsistent state - stop here to receive error reports from users
|
||||||
if (
|
if (
|
||||||
(compilationFailed || !analysisPerformed) &&
|
(compilationFailed || analysisFailed || !parsingSuccess) &&
|
||||||
(errors.empty() && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed)
|
errors.empty()
|
||||||
)
|
)
|
||||||
return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed.");
|
return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed.");
|
||||||
|
|
||||||
@ -1348,7 +1345,9 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
|
|
||||||
output["sources"] = Json::objectValue;
|
output["sources"] = Json::objectValue;
|
||||||
unsigned sourceIndex = 0;
|
unsigned sourceIndex = 0;
|
||||||
if (parsingSuccess && !analysisFailed && (!compilerStack.hasError() || _inputsAndSettings.parserErrorRecovery))
|
// NOTE: A case that will pass `parsingSuccess && !analysisFailed` but not `analysisSuccess` is
|
||||||
|
// stopAfter: parsing with no parsing errors.
|
||||||
|
if (parsingSuccess && !analysisFailed)
|
||||||
for (std::string const& sourceName: compilerStack.sourceNames())
|
for (std::string const& sourceName: compilerStack.sourceNames())
|
||||||
{
|
{
|
||||||
Json::Value sourceResult = Json::objectValue;
|
Json::Value sourceResult = Json::objectValue;
|
||||||
@ -1359,7 +1358,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
}
|
}
|
||||||
|
|
||||||
Json::Value contractsOutput = Json::objectValue;
|
Json::Value contractsOutput = Json::objectValue;
|
||||||
for (std::string const& contractName: analysisPerformed ? compilerStack.contractNames() : std::vector<std::string>())
|
for (std::string const& contractName: analysisSuccess ? compilerStack.contractNames() : std::vector<std::string>())
|
||||||
{
|
{
|
||||||
size_t colon = contractName.rfind(':');
|
size_t colon = contractName.rfind(':');
|
||||||
solAssert(colon != std::string::npos, "");
|
solAssert(colon != std::string::npos, "");
|
||||||
|
@ -265,7 +265,7 @@ void LanguageServer::compile()
|
|||||||
|
|
||||||
m_compilerStack.reset(false);
|
m_compilerStack.reset(false);
|
||||||
m_compilerStack.setSources(m_fileRepository.sourceUnits());
|
m_compilerStack.setSources(m_fileRepository.sourceUnits());
|
||||||
m_compilerStack.compile(CompilerStack::State::AnalysisPerformed);
|
m_compilerStack.compile(CompilerStack::State::AnalysisSuccessful);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanguageServer::compileAndUpdateDiagnostics()
|
void LanguageServer::compileAndUpdateDiagnostics()
|
||||||
@ -554,7 +554,7 @@ ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourc
|
|||||||
|
|
||||||
std::tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
std::tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
||||||
{
|
{
|
||||||
if (m_compilerStack.state() < CompilerStack::AnalysisPerformed)
|
if (m_compilerStack.state() < CompilerStack::AnalysisSuccessful)
|
||||||
return {nullptr, -1};
|
return {nullptr, -1};
|
||||||
if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
|
if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
|
||||||
return {nullptr, -1};
|
return {nullptr, -1};
|
||||||
|
@ -41,7 +41,7 @@ REPO_ROOT="$(dirname "$0")"/..
|
|||||||
cd "$REPO_ROOT" || exit 1
|
cd "$REPO_ROOT" || exit 1
|
||||||
|
|
||||||
WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" |
|
WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" |
|
||||||
grep -v "test/libsolidity/ASTJSON\|test/libsolidity/ASTRecoveryTests\|test/compilationTests/zeppelin/LICENSE\|${EXCLUDE_FILES_JOINED}" || true
|
grep -v "test/libsolidity/ASTJSON\|test/compilationTests/zeppelin/LICENSE\|${EXCLUDE_FILES_JOINED}" || true
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ "$WHITESPACE" != "" ]]
|
if [[ "$WHITESPACE" != "" ]]
|
||||||
|
@ -805,7 +805,7 @@ void CommandLineInterface::compile()
|
|||||||
formatter.printErrorInformation(*error);
|
formatter.printErrorInformation(*error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!successful && !m_options.input.errorRecovery)
|
if (!successful)
|
||||||
solThrow(CommandLineExecutionError, "");
|
solThrow(CommandLineExecutionError, "");
|
||||||
}
|
}
|
||||||
catch (CompilerError const& _exception)
|
catch (CompilerError const& _exception)
|
||||||
@ -845,52 +845,56 @@ void CommandLineInterface::handleCombinedJSON()
|
|||||||
output[g_strVersion] = frontend::VersionString;
|
output[g_strVersion] = frontend::VersionString;
|
||||||
vector<string> contracts = m_compiler->contractNames();
|
vector<string> contracts = m_compiler->contractNames();
|
||||||
|
|
||||||
|
// NOTE: The state checks here are more strict that in Standard JSON. There we allow
|
||||||
|
// requesting certain outputs even if compilation fails as long as analysis went ok.
|
||||||
|
bool compilationSuccess = m_compiler->state() >= CompilerStack::State::CompilationSuccessful;
|
||||||
|
|
||||||
if (!contracts.empty())
|
if (!contracts.empty())
|
||||||
output[g_strContracts] = Json::Value(Json::objectValue);
|
output[g_strContracts] = Json::Value(Json::objectValue);
|
||||||
for (string const& contractName: contracts)
|
for (string const& contractName: contracts)
|
||||||
{
|
{
|
||||||
Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue;
|
Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue;
|
||||||
if (m_options.compiler.combinedJsonRequests->abi)
|
if (m_options.compiler.combinedJsonRequests->abi && compilationSuccess)
|
||||||
contractData[g_strAbi] = m_compiler->contractABI(contractName);
|
contractData[g_strAbi] = m_compiler->contractABI(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->metadata)
|
if (m_options.compiler.combinedJsonRequests->metadata && compilationSuccess)
|
||||||
contractData["metadata"] = m_compiler->metadata(contractName);
|
contractData["metadata"] = m_compiler->metadata(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->binary && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->binary && compilationSuccess)
|
||||||
contractData[g_strBinary] = m_compiler->object(contractName).toHex();
|
contractData[g_strBinary] = m_compiler->object(contractName).toHex();
|
||||||
if (m_options.compiler.combinedJsonRequests->binaryRuntime && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->binaryRuntime && compilationSuccess)
|
||||||
contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex();
|
contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex();
|
||||||
if (m_options.compiler.combinedJsonRequests->opcodes && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->opcodes && compilationSuccess)
|
||||||
contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode, m_options.output.evmVersion);
|
contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode, m_options.output.evmVersion);
|
||||||
if (m_options.compiler.combinedJsonRequests->asm_ && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->asm_ && compilationSuccess)
|
||||||
contractData[g_strAsm] = m_compiler->assemblyJSON(contractName);
|
contractData[g_strAsm] = m_compiler->assemblyJSON(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->storageLayout && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->storageLayout && compilationSuccess)
|
||||||
contractData[g_strStorageLayout] = m_compiler->storageLayout(contractName);
|
contractData[g_strStorageLayout] = m_compiler->storageLayout(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->generatedSources && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->generatedSources && compilationSuccess)
|
||||||
contractData[g_strGeneratedSources] = m_compiler->generatedSources(contractName, false);
|
contractData[g_strGeneratedSources] = m_compiler->generatedSources(contractName, false);
|
||||||
if (m_options.compiler.combinedJsonRequests->generatedSourcesRuntime && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->generatedSourcesRuntime && compilationSuccess)
|
||||||
contractData[g_strGeneratedSourcesRuntime] = m_compiler->generatedSources(contractName, true);
|
contractData[g_strGeneratedSourcesRuntime] = m_compiler->generatedSources(contractName, true);
|
||||||
if (m_options.compiler.combinedJsonRequests->srcMap && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->srcMap && compilationSuccess)
|
||||||
{
|
{
|
||||||
auto map = m_compiler->sourceMapping(contractName);
|
auto map = m_compiler->sourceMapping(contractName);
|
||||||
contractData[g_strSrcMap] = map ? *map : "";
|
contractData[g_strSrcMap] = map ? *map : "";
|
||||||
}
|
}
|
||||||
if (m_options.compiler.combinedJsonRequests->srcMapRuntime && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->srcMapRuntime && compilationSuccess)
|
||||||
{
|
{
|
||||||
auto map = m_compiler->runtimeSourceMapping(contractName);
|
auto map = m_compiler->runtimeSourceMapping(contractName);
|
||||||
contractData[g_strSrcMapRuntime] = map ? *map : "";
|
contractData[g_strSrcMapRuntime] = map ? *map : "";
|
||||||
}
|
}
|
||||||
if (m_options.compiler.combinedJsonRequests->funDebug && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->funDebug && compilationSuccess)
|
||||||
contractData[g_strFunDebug] = StandardCompiler::formatFunctionDebugData(
|
contractData[g_strFunDebug] = StandardCompiler::formatFunctionDebugData(
|
||||||
m_compiler->object(contractName).functionDebugData
|
m_compiler->object(contractName).functionDebugData
|
||||||
);
|
);
|
||||||
if (m_options.compiler.combinedJsonRequests->funDebugRuntime && m_compiler->compilationSuccessful())
|
if (m_options.compiler.combinedJsonRequests->funDebugRuntime && compilationSuccess)
|
||||||
contractData[g_strFunDebugRuntime] = StandardCompiler::formatFunctionDebugData(
|
contractData[g_strFunDebugRuntime] = StandardCompiler::formatFunctionDebugData(
|
||||||
m_compiler->runtimeObject(contractName).functionDebugData
|
m_compiler->runtimeObject(contractName).functionDebugData
|
||||||
);
|
);
|
||||||
if (m_options.compiler.combinedJsonRequests->signatureHashes)
|
if (m_options.compiler.combinedJsonRequests->signatureHashes && compilationSuccess)
|
||||||
contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"];
|
contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"];
|
||||||
if (m_options.compiler.combinedJsonRequests->natspecDev)
|
if (m_options.compiler.combinedJsonRequests->natspecDev && compilationSuccess)
|
||||||
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
|
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
|
||||||
if (m_options.compiler.combinedJsonRequests->natspecUser)
|
if (m_options.compiler.combinedJsonRequests->natspecUser && compilationSuccess)
|
||||||
contractData[g_strNatspecUser] = m_compiler->natspecUser(contractName);
|
contractData[g_strNatspecUser] = m_compiler->natspecUser(contractName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,57 +1168,56 @@ void CommandLineInterface::outputCompilationResults()
|
|||||||
// do we need AST output?
|
// do we need AST output?
|
||||||
handleAst();
|
handleAst();
|
||||||
|
|
||||||
if (
|
CompilerOutputs astOutputSelection;
|
||||||
!m_compiler->compilationSuccessful() &&
|
astOutputSelection.astCompactJson = true;
|
||||||
m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful
|
if (m_options.compiler.outputs != CompilerOutputs() && m_options.compiler.outputs != astOutputSelection)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
serr() << endl << "Compilation halted after AST generation due to errors." << endl;
|
// Currently AST is the only output allowed with --stop-after parsing. For all of the others
|
||||||
return;
|
// we can safely assume that full compilation was performed and successful.
|
||||||
}
|
solAssert(m_options.output.stopAfter >= CompilerStack::State::CompilationSuccessful);
|
||||||
|
|
||||||
vector<string> contracts = m_compiler->contractNames();
|
for (string const& contract: m_compiler->contractNames())
|
||||||
for (string const& contract: contracts)
|
|
||||||
{
|
|
||||||
if (needsHumanTargetedStdout(m_options))
|
|
||||||
sout() << endl << "======= " << contract << " =======" << endl;
|
|
||||||
|
|
||||||
// do we need EVM assembly?
|
|
||||||
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
|
|
||||||
{
|
{
|
||||||
string ret;
|
if (needsHumanTargetedStdout(m_options))
|
||||||
if (m_options.compiler.outputs.asmJson)
|
sout() << endl << "======= " << contract << " =======" << endl;
|
||||||
ret = util::jsonPrint(removeNullMembers(m_compiler->assemblyJSON(contract)), m_options.formatting.json);
|
|
||||||
else
|
|
||||||
ret = m_compiler->assemblyString(contract, m_fileReader.sourceUnits());
|
|
||||||
|
|
||||||
if (!m_options.output.dir.empty())
|
// do we need EVM assembly?
|
||||||
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
|
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
|
||||||
else
|
{
|
||||||
sout() << "EVM assembly:" << endl << ret << endl;
|
string ret;
|
||||||
}
|
if (m_options.compiler.outputs.asmJson)
|
||||||
|
ret = util::jsonPrint(removeNullMembers(m_compiler->assemblyJSON(contract)), m_options.formatting.json);
|
||||||
|
else
|
||||||
|
ret = m_compiler->assemblyString(contract, m_fileReader.sourceUnits());
|
||||||
|
|
||||||
if (m_options.compiler.estimateGas)
|
if (!m_options.output.dir.empty())
|
||||||
handleGasEstimation(contract);
|
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
|
||||||
|
else
|
||||||
|
sout() << "EVM assembly:" << endl << ret << endl;
|
||||||
|
}
|
||||||
|
|
||||||
handleBytecode(contract);
|
if (m_options.compiler.estimateGas)
|
||||||
handleIR(contract);
|
handleGasEstimation(contract);
|
||||||
handleIRAst(contract);
|
|
||||||
handleIROptimized(contract);
|
handleBytecode(contract);
|
||||||
handleIROptimizedAst(contract);
|
handleIR(contract);
|
||||||
handleSignatureHashes(contract);
|
handleIRAst(contract);
|
||||||
handleMetadata(contract);
|
handleIROptimized(contract);
|
||||||
handleABI(contract);
|
handleIROptimizedAst(contract);
|
||||||
handleStorageLayout(contract);
|
handleSignatureHashes(contract);
|
||||||
handleNatspec(true, contract);
|
handleMetadata(contract);
|
||||||
handleNatspec(false, contract);
|
handleABI(contract);
|
||||||
} // end of contracts iteration
|
handleStorageLayout(contract);
|
||||||
|
handleNatspec(true, contract);
|
||||||
|
handleNatspec(false, contract);
|
||||||
|
} // end of contracts iteration
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_hasOutput)
|
if (!m_hasOutput)
|
||||||
{
|
{
|
||||||
if (!m_options.output.dir.empty())
|
if (!m_options.output.dir.empty())
|
||||||
sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl;
|
sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl;
|
||||||
else if (contracts.empty())
|
else if (m_compiler->contractNames().empty())
|
||||||
sout() << "Compiler run successful. No contracts to compile." << endl;
|
sout() << "Compiler run successful. No contracts to compile." << endl;
|
||||||
else
|
else
|
||||||
sout() << "Compiler run successful. No output generated." << endl;
|
sout() << "Compiler run successful. No output generated." << endl;
|
||||||
|
1
test/cmdlineTests/combined_json_stop_after_parsing/args
Normal file
1
test/cmdlineTests/combined_json_stop_after_parsing/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--pretty-json --json-indent 4 --stop-after parsing --combined-json abi,asm,ast,bin,bin-runtime,devdoc,function-debug,function-debug-runtime,generated-sources,generated-sources-runtime,hashes,metadata,opcodes,srcmap,srcmap-runtime,storage-layout,userdoc
|
@ -0,0 +1,4 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity *;
|
||||||
|
|
||||||
|
contract C {}
|
53
test/cmdlineTests/combined_json_stop_after_parsing/output
Normal file
53
test/cmdlineTests/combined_json_stop_after_parsing/output
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"contracts":
|
||||||
|
{
|
||||||
|
"combined_json_stop_after_parsing/input.sol:C": {}
|
||||||
|
},
|
||||||
|
"sourceList":
|
||||||
|
[
|
||||||
|
"combined_json_stop_after_parsing/input.sol"
|
||||||
|
],
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"combined_json_stop_after_parsing/input.sol":
|
||||||
|
{
|
||||||
|
"AST":
|
||||||
|
{
|
||||||
|
"absolutePath": "combined_json_stop_after_parsing/input.sol",
|
||||||
|
"id": 3,
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"nodeType": "SourceUnit",
|
||||||
|
"nodes":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"literals":
|
||||||
|
[
|
||||||
|
"solidity",
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"nodeType": "PragmaDirective",
|
||||||
|
"src": "36:18:0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abstract": false,
|
||||||
|
"baseContracts": [],
|
||||||
|
"contractDependencies": [],
|
||||||
|
"contractKind": "contract",
|
||||||
|
"id": 2,
|
||||||
|
"name": "C",
|
||||||
|
"nameLocation": "65:1:0",
|
||||||
|
"nodeType": "ContractDefinition",
|
||||||
|
"nodes": [],
|
||||||
|
"src": "56:13:0",
|
||||||
|
"usedErrors": [],
|
||||||
|
"usedEvents": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"src": "36:34:0"
|
||||||
|
},
|
||||||
|
"id": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "<VERSION REMOVED>"
|
||||||
|
}
|
@ -9,6 +9,3 @@ Warning: Recovered in Statement at ';'.
|
|||||||
|
|
|
|
||||||
6 | balances[tx.origin] = ; // missing RHS.
|
6 | balances[tx.origin] = ; // missing RHS.
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
|
|
||||||
Compilation halted after AST generation due to errors.
|
|
||||||
|
1
test/cmdlineTests/recovery_ast_constructor/exit
Normal file
1
test/cmdlineTests/recovery_ast_constructor/exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
@ -6,12 +6,7 @@ contract Error1 {
|
|||||||
balances[tx.origin] = ; // missing RHS.
|
balances[tx.origin] = ; // missing RHS.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without error recovery we stop due to the above error.
|
// This function parses properly
|
||||||
// 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) {
|
function five() public view returns(uint) {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
@ -1,188 +0,0 @@
|
|||||||
JSON AST (compact format):
|
|
||||||
|
|
||||||
|
|
||||||
======= recovery_ast_constructor/input.sol =======
|
|
||||||
{
|
|
||||||
"absolutePath": "recovery_ast_constructor/input.sol",
|
|
||||||
"exportedSymbols":
|
|
||||||
{
|
|
||||||
"Error1":
|
|
||||||
[
|
|
||||||
18
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"id": 19,
|
|
||||||
"license": "GPL-3.0",
|
|
||||||
"nodeType": "SourceUnit",
|
|
||||||
"nodes":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"literals":
|
|
||||||
[
|
|
||||||
"solidity",
|
|
||||||
">=",
|
|
||||||
"0.0",
|
|
||||||
".0"
|
|
||||||
],
|
|
||||||
"nodeType": "PragmaDirective",
|
|
||||||
"src": "36:24:0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"abstract": false,
|
|
||||||
"baseContracts": [],
|
|
||||||
"canonicalName": "Error1",
|
|
||||||
"contractDependencies": [],
|
|
||||||
"contractKind": "contract",
|
|
||||||
"fullyImplemented": true,
|
|
||||||
"id": 18,
|
|
||||||
"linearizedBaseContracts":
|
|
||||||
[
|
|
||||||
18
|
|
||||||
],
|
|
||||||
"name": "Error1",
|
|
||||||
"nameLocation": "71:6:0",
|
|
||||||
"nodeType": "ContractDefinition",
|
|
||||||
"nodes":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"body":
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"nodeType": "Block",
|
|
||||||
"src": "96:49:0",
|
|
||||||
"statements":
|
|
||||||
[
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"id": 9,
|
|
||||||
"implemented": true,
|
|
||||||
"kind": "constructor",
|
|
||||||
"modifiers": [],
|
|
||||||
"name": "",
|
|
||||||
"nameLocation": "-1:-1:-1",
|
|
||||||
"nodeType": "FunctionDefinition",
|
|
||||||
"parameters":
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"nodeType": "ParameterList",
|
|
||||||
"parameters": [],
|
|
||||||
"src": "93:2:0"
|
|
||||||
},
|
|
||||||
"returnParameters":
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"nodeType": "ParameterList",
|
|
||||||
"parameters": [],
|
|
||||||
"src": "96:0:0"
|
|
||||||
},
|
|
||||||
"scope": 18,
|
|
||||||
"src": "82:63:0",
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"virtual": false,
|
|
||||||
"visibility": "public"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"body":
|
|
||||||
{
|
|
||||||
"id": 16,
|
|
||||||
"nodeType": "Block",
|
|
||||||
"src": "440:19:0",
|
|
||||||
"statements":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"expression":
|
|
||||||
{
|
|
||||||
"hexValue": "35",
|
|
||||||
"id": 14,
|
|
||||||
"isConstant": false,
|
|
||||||
"isLValue": false,
|
|
||||||
"isPure": true,
|
|
||||||
"kind": "number",
|
|
||||||
"lValueRequested": false,
|
|
||||||
"nodeType": "Literal",
|
|
||||||
"src": "453:1:0",
|
|
||||||
"typeDescriptions":
|
|
||||||
{
|
|
||||||
"typeIdentifier": "t_rational_5_by_1",
|
|
||||||
"typeString": "int_const 5"
|
|
||||||
},
|
|
||||||
"value": "5"
|
|
||||||
},
|
|
||||||
"functionReturnParameters": 13,
|
|
||||||
"id": 15,
|
|
||||||
"nodeType": "Return",
|
|
||||||
"src": "446:8:0"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"functionSelector": "af11c34c",
|
|
||||||
"id": 17,
|
|
||||||
"implemented": true,
|
|
||||||
"kind": "function",
|
|
||||||
"modifiers": [],
|
|
||||||
"name": "five",
|
|
||||||
"nameLocation": "407:4:0",
|
|
||||||
"nodeType": "FunctionDefinition",
|
|
||||||
"parameters":
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"nodeType": "ParameterList",
|
|
||||||
"parameters": [],
|
|
||||||
"src": "411:2:0"
|
|
||||||
},
|
|
||||||
"returnParameters":
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"nodeType": "ParameterList",
|
|
||||||
"parameters":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"id": 12,
|
|
||||||
"mutability": "mutable",
|
|
||||||
"name": "",
|
|
||||||
"nameLocation": "-1:-1:-1",
|
|
||||||
"nodeType": "VariableDeclaration",
|
|
||||||
"scope": 17,
|
|
||||||
"src": "434:4:0",
|
|
||||||
"stateVariable": false,
|
|
||||||
"storageLocation": "default",
|
|
||||||
"typeDescriptions":
|
|
||||||
{
|
|
||||||
"typeIdentifier": "t_uint256",
|
|
||||||
"typeString": "uint256"
|
|
||||||
},
|
|
||||||
"typeName":
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"name": "uint",
|
|
||||||
"nodeType": "ElementaryTypeName",
|
|
||||||
"src": "434:4:0",
|
|
||||||
"typeDescriptions":
|
|
||||||
{
|
|
||||||
"typeIdentifier": "t_uint256",
|
|
||||||
"typeString": "uint256"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"visibility": "internal"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src": "433:6:0"
|
|
||||||
},
|
|
||||||
"scope": 18,
|
|
||||||
"src": "398:61:0",
|
|
||||||
"stateMutability": "view",
|
|
||||||
"virtual": false,
|
|
||||||
"visibility": "public"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"scope": 19,
|
|
||||||
"src": "62:399:0",
|
|
||||||
"usedErrors": [],
|
|
||||||
"usedEvents": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src": "36:426:0"
|
|
||||||
}
|
|
@ -3,6 +3,3 @@ Error: Expected pragma, import directive or contract/interface/library/struct/en
|
|||||||
|
|
|
|
||||||
3 | c
|
3 | c
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
|
|
||||||
Compilation halted after AST generation due to errors.
|
|
||||||
|
1
test/cmdlineTests/recovery_ast_empty_contract/exit
Normal file
1
test/cmdlineTests/recovery_ast_empty_contract/exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
@ -42,61 +42,5 @@
|
|||||||
"type": "Warning"
|
"type": "Warning"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sources":
|
"sources": {}
|
||||||
{
|
|
||||||
"A":
|
|
||||||
{
|
|
||||||
"ast":
|
|
||||||
{
|
|
||||||
"absolutePath": "A",
|
|
||||||
"exportedSymbols":
|
|
||||||
{
|
|
||||||
"Errort6":
|
|
||||||
[
|
|
||||||
3
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"id": 4,
|
|
||||||
"license": "GPL-3.0",
|
|
||||||
"nodeType": "SourceUnit",
|
|
||||||
"nodes":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"literals":
|
|
||||||
[
|
|
||||||
"solidity",
|
|
||||||
">=",
|
|
||||||
"0.0"
|
|
||||||
],
|
|
||||||
"nodeType": "PragmaDirective",
|
|
||||||
"src": "36:22:0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"abstract": false,
|
|
||||||
"baseContracts": [],
|
|
||||||
"canonicalName": "Errort6",
|
|
||||||
"contractDependencies": [],
|
|
||||||
"contractKind": "contract",
|
|
||||||
"fullyImplemented": true,
|
|
||||||
"id": 3,
|
|
||||||
"linearizedBaseContracts":
|
|
||||||
[
|
|
||||||
3
|
|
||||||
],
|
|
||||||
"name": "Errort6",
|
|
||||||
"nameLocation": "68:7:0",
|
|
||||||
"nodeType": "ContractDefinition",
|
|
||||||
"nodes": [],
|
|
||||||
"scope": 4,
|
|
||||||
"src": "59:35:0",
|
|
||||||
"usedErrors": [],
|
|
||||||
"usedEvents": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src": "36:84:0"
|
|
||||||
},
|
|
||||||
"id": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ string compilerStateToString(CompilerStack::State _state)
|
|||||||
case CompilerStack::State::SourcesSet: return "SourcesSet";
|
case CompilerStack::State::SourcesSet: return "SourcesSet";
|
||||||
case CompilerStack::State::Parsed: return "Parsed";
|
case CompilerStack::State::Parsed: return "Parsed";
|
||||||
case CompilerStack::State::ParsedAndImported: return "ParsedAndImported";
|
case CompilerStack::State::ParsedAndImported: return "ParsedAndImported";
|
||||||
case CompilerStack::State::AnalysisPerformed: return "AnalysisPerformed";
|
case CompilerStack::State::AnalysisSuccessful: return "AnalysisSuccessful";
|
||||||
case CompilerStack::State::CompilationSuccessful: return "CompilationSuccessful";
|
case CompilerStack::State::CompilationSuccessful: return "CompilationSuccessful";
|
||||||
}
|
}
|
||||||
soltestAssert(false, "Unexpected value of state parameter");
|
soltestAssert(false, "Unexpected value of state parameter");
|
||||||
@ -102,7 +102,7 @@ void ASTJSONTest::generateTestVariants(string const& _filename)
|
|||||||
|
|
||||||
const std::vector<CompilerStack::State> variantCompileStates = {
|
const std::vector<CompilerStack::State> variantCompileStates = {
|
||||||
CompilerStack::State::Parsed,
|
CompilerStack::State::Parsed,
|
||||||
CompilerStack::State::AnalysisPerformed
|
CompilerStack::State::AnalysisSuccessful,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto state: variantCompileStates)
|
for (const auto state: variantCompileStates)
|
||||||
|
@ -102,7 +102,7 @@ EdgeNames edgeNames(EdgeMap const& _edgeMap)
|
|||||||
|
|
||||||
tuple<CallGraphMap, CallGraphMap> collectGraphs(CompilerStack const& _compilerStack)
|
tuple<CallGraphMap, CallGraphMap> collectGraphs(CompilerStack const& _compilerStack)
|
||||||
{
|
{
|
||||||
soltestAssert(!_compilerStack.hasError(), "");
|
soltestAssert(_compilerStack.state() >= CompilerStack::State::AnalysisSuccessful);
|
||||||
|
|
||||||
tuple<CallGraphMap, CallGraphMap> graphs;
|
tuple<CallGraphMap, CallGraphMap> graphs;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user