diff options
author | Rhett Aultman <roadriverrail@gmail.com> | 2017-05-11 21:26:35 +0800 |
---|---|---|
committer | Rhett Aultman <roadriverrail@gmail.com> | 2017-05-30 22:28:31 +0800 |
commit | 89b60ffbd4c2dde26fa5e9f1d750729b5c89373e (patch) | |
tree | a4c464d4d40baaa260f071c1028f347bd287e44d /libsolidity/interface | |
parent | 0066a08aa8f6c469cde7947ec50ca662a32123a0 (diff) | |
download | dexon-solidity-89b60ffbd4c2dde26fa5e9f1d750729b5c89373e.tar.gz dexon-solidity-89b60ffbd4c2dde26fa5e9f1d750729b5c89373e.tar.zst dexon-solidity-89b60ffbd4c2dde26fa5e9f1d750729b5c89373e.zip |
Refactor error reporting
This commit introduces ErrorReporter, a utility class which consolidates
all of the error logging functionality into a common set of functions.
It also replaces all direct interactions with an ErrorList with calls to
an ErrorReporter.
This commit resolves issue #2209
Diffstat (limited to 'libsolidity/interface')
-rw-r--r-- | libsolidity/interface/AssemblyStack.cpp | 8 | ||||
-rw-r--r-- | libsolidity/interface/AssemblyStack.h | 5 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 48 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 14 | ||||
-rw-r--r-- | libsolidity/interface/ErrorReporter.cpp | 186 | ||||
-rw-r--r-- | libsolidity/interface/ErrorReporter.h | 106 |
6 files changed, 328 insertions, 39 deletions
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index c4bd63c4..b027ac3c 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -45,13 +45,13 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string { m_analysisSuccessful = false; m_scanner = make_shared<Scanner>(CharStream(_source), _sourceName); - m_parserResult = assembly::Parser(m_errors, m_language == Language::JULIA).parse(m_scanner); - if (!m_errors.empty()) + m_parserResult = assembly::Parser(m_errorReporter, m_language == Language::JULIA).parse(m_scanner); + if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); - assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errors); + assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter); m_analysisSuccessful = analyzer.analyze(*m_parserResult); return m_analysisSuccessful; } @@ -66,7 +66,7 @@ eth::LinkerObject AssemblyStack::assemble(Machine _machine) { case Machine::EVM: { - auto assembly = assembly::CodeGenerator(m_errors).assemble(*m_parserResult, *m_analysisInfo); + auto assembly = assembly::CodeGenerator(m_errorReporter).assemble(*m_parserResult, *m_analysisInfo); return assembly.assemble(); } case Machine::EVM15: diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index 40662ac3..62a5134a 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -21,8 +21,8 @@ #pragma once -#include <libsolidity/interface/Exceptions.h> #include <libsolidity/inlineasm/AsmAnalysisInfo.h> +#include <libsolidity/interface/ErrorReporter.h> #include <libevmasm/LinkerObject.h> #include <string> @@ -50,7 +50,7 @@ public: enum class Machine { EVM, EVM15, eWasm }; explicit AssemblyStack(Language _language = Language::Assembly): - m_language(_language) + m_language(_language), m_errorReporter(m_errors) {} /// @returns the scanner used during parsing @@ -79,6 +79,7 @@ private: std::shared_ptr<assembly::Block> m_parserResult; std::shared_ptr<assembly::AsmAnalysisInfo> m_analysisInfo; ErrorList m_errors; + ErrorReporter m_errorReporter; }; } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 328df91f..44220402 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -57,9 +57,6 @@ using namespace std; using namespace dev; using namespace dev::solidity; -CompilerStack::CompilerStack(ReadFile::Callback const& _readFile): - m_readFile(_readFile) {} - void CompilerStack::setRemappings(vector<string> const& _remappings) { vector<Remapping> remappings; @@ -96,7 +93,7 @@ void CompilerStack::reset(bool _keepSources) m_scopes.clear(); m_sourceOrder.clear(); m_contracts.clear(); - m_errors.clear(); + m_errorReporter.clear(); m_stackState = Empty; } @@ -121,15 +118,11 @@ bool CompilerStack::parse() //reset if(m_stackState != SourcesSet) return false; - m_errors.clear(); + m_errorReporter.clear(); ASTNode::resetID(); if (SemVerVersion{string(VersionString)}.isPrerelease()) - { - auto err = make_shared<Error>(Error::Type::Warning); - *err << errinfo_comment("This is a pre-release compiler version, please do not use it in production."); - m_errors.push_back(err); - } + m_errorReporter.warning("This is a pre-release compiler version, please do not use it in production."); vector<string> sourcesToParse; for (auto const& s: m_sources) @@ -139,9 +132,9 @@ bool CompilerStack::parse() string const& path = sourcesToParse[i]; Source& source = m_sources[path]; source.scanner->reset(); - source.ast = Parser(m_errors).parse(source.scanner); + source.ast = Parser(m_errorReporter).parse(source.scanner); if (!source.ast) - solAssert(!Error::containsOnlyWarnings(m_errors), "Parser returned null but did not report error."); + solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error."); else { source.ast->annotation().path = path; @@ -154,7 +147,7 @@ bool CompilerStack::parse() } } } - if (Error::containsOnlyWarnings(m_errors)) + if (Error::containsOnlyWarnings(m_errorReporter.errors())) { m_stackState = ParsingSuccessful; return true; @@ -170,18 +163,18 @@ bool CompilerStack::analyze() resolveImports(); bool noErrors = true; - SyntaxChecker syntaxChecker(m_errors); + SyntaxChecker syntaxChecker(m_errorReporter); for (Source const* source: m_sourceOrder) if (!syntaxChecker.checkSyntax(*source->ast)) noErrors = false; - DocStringAnalyser docStringAnalyser(m_errors); + DocStringAnalyser docStringAnalyser(m_errorReporter); for (Source const* source: m_sourceOrder) if (!docStringAnalyser.analyseDocStrings(*source->ast)) noErrors = false; m_globalContext = make_shared<GlobalContext>(); - NameAndTypeResolver resolver(m_globalContext->declarations(), m_scopes, m_errors); + NameAndTypeResolver resolver(m_globalContext->declarations(), m_scopes, m_errorReporter); for (Source const* source: m_sourceOrder) if (!resolver.registerDeclarations(*source->ast)) return false; @@ -217,7 +210,7 @@ bool CompilerStack::analyze() { m_globalContext->setCurrentContract(*contract); resolver.updateDeclaration(*m_globalContext->currentThis()); - TypeChecker typeChecker(m_errors); + TypeChecker typeChecker(m_errorReporter); if (typeChecker.checkTypeRequirements(*contract)) { contract->setDevDocumentation(Natspec::devDocumentation(*contract)); @@ -237,7 +230,7 @@ bool CompilerStack::analyze() if (noErrors) { - PostTypeChecker postTypeChecker(m_errors); + PostTypeChecker postTypeChecker(m_errorReporter); for (Source const* source: m_sourceOrder) if (!postTypeChecker.check(*source->ast)) noErrors = false; @@ -245,7 +238,7 @@ bool CompilerStack::analyze() if (noErrors) { - StaticAnalyzer staticAnalyzer(m_errors); + StaticAnalyzer staticAnalyzer(m_errorReporter); for (Source const* source: m_sourceOrder) if (!staticAnalyzer.analyze(*source->ast)) noErrors = false; @@ -323,11 +316,11 @@ void CompilerStack::link() } } -bool CompilerStack::prepareFormalAnalysis(ErrorList* _errors) +bool CompilerStack::prepareFormalAnalysis(ErrorReporter* _errorReporter) { - if (!_errors) - _errors = &m_errors; - Why3Translator translator(*_errors); + if (!_errorReporter) + _errorReporter = &m_errorReporter; + Why3Translator translator(*_errorReporter); for (Source const* source: m_sourceOrder) if (!translator.process(*source->ast)) return false; @@ -582,11 +575,10 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string newSources[importPath] = result.contentsOrErrorMessage; else { - auto err = make_shared<Error>(Error::Type::ParserError); - *err << - errinfo_sourceLocation(import->location()) << - errinfo_comment("Source \"" + importPath + "\" not found: " + result.contentsOrErrorMessage); - m_errors.push_back(std::move(err)); + m_errorReporter.parserError( + import->location(), + string("Source \"" + importPath + "\" not found: " + result.contentsOrErrorMessage) + ); continue; } } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 84d15d70..76d36c7b 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -35,7 +35,7 @@ #include <libdevcore/FixedHash.h> #include <libevmasm/SourceLocation.h> #include <libevmasm/LinkerObject.h> -#include <libsolidity/interface/Exceptions.h> +#include <libsolidity/interface/ErrorReporter.h> #include <libsolidity/interface/ReadFile.h> namespace dev @@ -80,7 +80,10 @@ public: /// Creates a new compiler stack. /// @param _readFile callback to used to read files for import statements. Must return /// and must not emit exceptions. - explicit CompilerStack(ReadFile::Callback const& _readFile = ReadFile::Callback()); + explicit CompilerStack(ReadFile::Callback const& _readFile = ReadFile::Callback()): + m_readFile(_readFile), + m_errorList(), + m_errorReporter(m_errorList) {} /// Sets path remappings in the format "context:prefix=target" void setRemappings(std::vector<std::string> const& _remappings); @@ -130,7 +133,7 @@ public: /// Tries to translate all source files into a language suitable for formal analysis. /// @param _errors list to store errors - defaults to the internal error list. /// @returns false on error. - bool prepareFormalAnalysis(ErrorList* _errors = nullptr); + bool prepareFormalAnalysis(ErrorReporter* _errorReporter = nullptr); std::string const& formalTranslation() const { return m_formalTranslation; } /// @returns the assembled object for a contract. @@ -207,7 +210,7 @@ public: std::tuple<int, int, int, int> positionFromSourceLocation(SourceLocation const& _sourceLocation) const; /// @returns the list of errors that occured during parsing and type checking. - ErrorList const& errors() const { return m_errors; } + ErrorList const& errors() { return m_errorReporter.errors(); } private: /** @@ -289,7 +292,8 @@ private: std::vector<Source const*> m_sourceOrder; std::map<std::string const, Contract> m_contracts; std::string m_formalTranslation; - ErrorList m_errors; + ErrorList m_errorList; + ErrorReporter m_errorReporter; bool m_metadataLiteralSources = false; State m_stackState = Empty; }; diff --git a/libsolidity/interface/ErrorReporter.cpp b/libsolidity/interface/ErrorReporter.cpp new file mode 100644 index 00000000..2cbb952c --- /dev/null +++ b/libsolidity/interface/ErrorReporter.cpp @@ -0,0 +1,186 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @author Rhett <roadriverrail@gmail.com> + * @date 2017 + * Error helper class. + */ + +#include <libsolidity/interface/ErrorReporter.h> +#include <libsolidity/ast/AST.h> +#include <memory> + +using namespace std; +using namespace dev; +using namespace dev::solidity; + +ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter) +{ + if (&_errorReporter == this) + return *this; + m_errorList = _errorReporter.m_errorList; + return *this; +} + + +void ErrorReporter::warning(string const& _description) +{ + error(Error::Type::Warning, SourceLocation(), _description); +} + +void ErrorReporter::warning(SourceLocation const& _location, string const& _description) +{ + error(Error::Type::Warning, _location, _description); +} + +void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, string const& _description) +{ + auto err = make_shared<Error>(_type); + *err << + errinfo_sourceLocation(_location) << + errinfo_comment(_description); + + m_errorList.push_back(err); +} + +void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) +{ + auto err = make_shared<Error>(_type); + *err << + errinfo_sourceLocation(_location) << + errinfo_secondarySourceLocation(_secondaryLocation) << + errinfo_comment(_description); + + m_errorList.push_back(err); +} + + +void ErrorReporter::fatalError(Error::Type _type, SourceLocation const& _location, string const& _description) +{ + error(_type, _location, _description); + BOOST_THROW_EXCEPTION(FatalError()); +} + +ErrorList const& ErrorReporter::errors() const +{ + return m_errorList; +} + +void ErrorReporter::clear() +{ + m_errorList.clear(); +} + +void ErrorReporter::declarationError(SourceLocation const& _location, SecondarySourceLocation const&_secondaryLocation, string const& _description) +{ + error( + Error::Type::DeclarationError, + _location, + _secondaryLocation, + _description + ); +} + +void ErrorReporter::declarationError(SourceLocation const& _location, string const& _description) +{ + error( + Error::Type::DeclarationError, + _location, + _description + ); +} + +void ErrorReporter::fatalDeclarationError(SourceLocation const& _location, std::string const& _description) +{ + fatalError( + Error::Type::DeclarationError, + _location, + _description); +} + +void ErrorReporter::parserError(SourceLocation const& _location, string const& _description) +{ + error( + Error::Type::ParserError, + _location, + _description + ); +} + +void ErrorReporter::fatalParserError(SourceLocation const& _location, string const& _description) +{ + fatalError( + Error::Type::ParserError, + _location, + _description + ); +} + +void ErrorReporter::syntaxError(SourceLocation const& _location, string const& _description) +{ + error( + Error::Type::SyntaxError, + _location, + _description + ); +} + +void ErrorReporter::typeError(SourceLocation const& _location, string const& _description) +{ + error( + Error::Type::TypeError, + _location, + _description + ); +} + + +void ErrorReporter::fatalTypeError(SourceLocation const& _location, string const& _description) +{ + fatalError(Error::Type::TypeError, + _location, + _description + ); +} + +void ErrorReporter::docstringParsingError(string const& _description) +{ + error( + Error::Type::DocstringParsingError, + SourceLocation(), + _description + ); +} + +void ErrorReporter::why3TranslatorError(ASTNode const& _location, std::string const& _description) +{ + error( + Error::Type::Why3TranslatorError, + _location.location(), + _description + ); +} + +void ErrorReporter::fatalWhy3TranslatorError(ASTNode const& _location, std::string const& _description) +{ + fatalError( + Error::Type::Why3TranslatorError, + _location.location(), + _description + ); +} + diff --git a/libsolidity/interface/ErrorReporter.h b/libsolidity/interface/ErrorReporter.h new file mode 100644 index 00000000..83324446 --- /dev/null +++ b/libsolidity/interface/ErrorReporter.h @@ -0,0 +1,106 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @author Rhett <roadriverrail@gmail.com> + * @date 2017 + * Error reporting helper class. + */ + +#pragma once + +#include <libsolidity/interface/Exceptions.h> +#include <libevmasm/SourceLocation.h> + +namespace dev +{ +namespace solidity +{ + +class ASTNode; + +class ErrorReporter +{ +public: + + ErrorReporter(ErrorList& _errors): + m_errorList(_errors) { } + + ErrorReporter& operator=(ErrorReporter const& _errorReporter); + + void warning(std::string const& _description = std::string()); + + void warning( + SourceLocation const& _location = SourceLocation(), + std::string const& _description = std::string() + ); + + void error( + Error::Type _type, + SourceLocation const& _location = SourceLocation(), + std::string const& _description = std::string() + ); + + void declarationError( + SourceLocation const& _location, + SecondarySourceLocation const& _secondaryLocation = SecondarySourceLocation(), + std::string const& _description = std::string() + ); + + void declarationError( + SourceLocation const& _location, + std::string const& _description = std::string() + ); + + void fatalDeclarationError(SourceLocation const& _location, std::string const& _description); + + void parserError(SourceLocation const& _location, std::string const& _description); + + void fatalParserError(SourceLocation const& _location, std::string const& _description); + + void syntaxError(SourceLocation const& _location, std::string const& _description); + + void typeError(SourceLocation const& _location, std::string const& _description); + + void fatalTypeError(SourceLocation const& _location, std::string const& _description); + + void docstringParsingError(std::string const& _location); + + void why3TranslatorError(ASTNode const& _location, std::string const& _description); + + void fatalWhy3TranslatorError(ASTNode const& _location, std::string const& _description); + + ErrorList const& errors() const; + + void clear(); + +private: + void error(Error::Type _type, + SourceLocation const& _location, + SecondarySourceLocation const& _secondaryLocation, + std::string const& _description = std::string()); + + void fatalError(Error::Type _type, + SourceLocation const& _location = SourceLocation(), + std::string const& _description = std::string()); + + ErrorList& m_errorList; +}; + + +} +} + |