Add error IDs to console output

This commit is contained in:
a3d4 2020-06-04 03:19:47 +02:00
parent b17915a6ba
commit 51e64fe0b1
17 changed files with 77 additions and 31 deletions

View File

@ -5,7 +5,7 @@ Language Features:
Compiler Features: Compiler Features:
* Yul: Raise warning for switch statements that only have a default and no other cases. * Yul: Raise warning for switch statements that only have a default and no other cases.
* Add error codes to JSON output. * Output compilation error codes.
Bugfixes: Bugfixes:

View File

@ -38,7 +38,15 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(util::Except
for (auto const& info: secondaryLocation->infos) for (auto const& info: secondaryLocation->infos)
secondary.emplace_back(extract(&info.second, info.first)); secondary.emplace_back(extract(&info.second, info.first));
return Message{std::move(primary), _category, std::move(secondary)}; return Message{std::move(primary), _category, std::move(secondary), nullopt};
}
SourceReferenceExtractor::Message SourceReferenceExtractor::extract(Error const& _error)
{
string category = (_error.type() == Error::Type::Warning) ? "Warning" : "Error";
Message message = extract(_error, category);
message.errorId = _error.errorId();
return message;
} }
SourceReference SourceReferenceExtractor::extract(SourceLocation const* _location, std::string message) SourceReference SourceReferenceExtractor::extract(SourceLocation const* _location, std::string message)

View File

@ -16,16 +16,14 @@
*/ */
#pragma once #pragma once
#include <liblangutil/Exceptions.h>
#include <iosfwd> #include <iosfwd>
#include <optional>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
namespace solidity::util
{
struct Exception;
}
namespace solidity::langutil namespace solidity::langutil
{ {
@ -58,8 +56,6 @@ struct SourceReference
} }
}; };
struct SourceLocation;
namespace SourceReferenceExtractor namespace SourceReferenceExtractor
{ {
struct Message struct Message
@ -67,9 +63,11 @@ namespace SourceReferenceExtractor
SourceReference primary; SourceReference primary;
std::string category; // "Error", "Warning", ... std::string category; // "Error", "Warning", ...
std::vector<SourceReference> secondary; std::vector<SourceReference> secondary;
std::optional<ErrorId> errorId;
}; };
Message extract(util::Exception const& _exception, std::string _category); Message extract(util::Exception const& _exception, std::string _category);
Message extract(Error const& _error);
SourceReference extract(SourceLocation const* _location, std::string message = ""); SourceReference extract(SourceLocation const* _location, std::string message = "");
} }

View File

@ -80,10 +80,7 @@ void SourceReferenceFormatter::printExceptionInformation(util::Exception const&
void SourceReferenceFormatter::printErrorInformation(Error const& _error) void SourceReferenceFormatter::printErrorInformation(Error const& _error)
{ {
printExceptionInformation( printExceptionInformation(SourceReferenceExtractor::extract(_error));
_error,
(_error.type() == Error::Type::Warning) ? "Warning" : "Error"
);
} }
void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg) void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)

View File

@ -151,6 +151,8 @@ void SourceReferenceFormatterHuman::printExceptionInformation(SourceReferenceExt
{ {
// exception header line // exception header line
errorColored() << _msg.category; errorColored() << _msg.category;
if (m_withErrorIds && _msg.errorId.has_value())
errorColored() << " (" << _msg.errorId.value().error << ")";
messageColored() << ": " << _msg.primary.message << '\n'; messageColored() << ": " << _msg.primary.message << '\n';
printSourceLocation(_msg.primary); printSourceLocation(_msg.primary);

View File

@ -29,22 +29,14 @@
#include <sstream> #include <sstream>
#include <functional> #include <functional>
namespace solidity::util
{
struct Exception; // forward
}
namespace solidity::langutil namespace solidity::langutil
{ {
struct SourceLocation;
struct SourceReference;
class SourceReferenceFormatterHuman: public SourceReferenceFormatter class SourceReferenceFormatterHuman: public SourceReferenceFormatter
{ {
public: public:
SourceReferenceFormatterHuman(std::ostream& _stream, bool colored): SourceReferenceFormatterHuman(std::ostream& _stream, bool _colored, bool _withErrorIds):
SourceReferenceFormatter{_stream}, m_colored{colored} SourceReferenceFormatter{_stream}, m_colored{_colored}, m_withErrorIds(_withErrorIds)
{} {}
void printSourceLocation(SourceReference const& _ref) override; void printSourceLocation(SourceReference const& _ref) override;
@ -54,12 +46,13 @@ public:
static std::string formatExceptionInformation( static std::string formatExceptionInformation(
util::Exception const& _exception, util::Exception const& _exception,
std::string const& _name, std::string const& _name,
bool colored = false bool _colored = false,
bool _withErrorIds = false
) )
{ {
std::ostringstream errorOutput; std::ostringstream errorOutput;
SourceReferenceFormatterHuman formatter(errorOutput, colored); SourceReferenceFormatterHuman formatter(errorOutput, _colored, _withErrorIds);
formatter.printExceptionInformation(_exception, _name); formatter.printExceptionInformation(_exception, _name);
return errorOutput.str(); return errorOutput.str();
} }
@ -75,6 +68,7 @@ private:
private: private:
bool m_colored; bool m_colored;
bool m_withErrorIds;
}; };
} }

View File

@ -177,6 +177,7 @@ static string const g_strVersion = "version";
static string const g_strIgnoreMissingFiles = "ignore-missing"; static string const g_strIgnoreMissingFiles = "ignore-missing";
static string const g_strColor = "color"; static string const g_strColor = "color";
static string const g_strNoColor = "no-color"; static string const g_strNoColor = "no-color";
static string const g_strErrorIds = "error-codes";
static string const g_strOldReporter = "old-reporter"; static string const g_strOldReporter = "old-reporter";
static string const g_argAbi = g_strAbi; static string const g_argAbi = g_strAbi;
@ -222,6 +223,7 @@ static string const g_stdinFileName = g_stdinFileNameStr;
static string const g_argIgnoreMissingFiles = g_strIgnoreMissingFiles; static string const g_argIgnoreMissingFiles = g_strIgnoreMissingFiles;
static string const g_argColor = g_strColor; static string const g_argColor = g_strColor;
static string const g_argNoColor = g_strNoColor; static string const g_argNoColor = g_strNoColor;
static string const g_argErrorIds = g_strErrorIds;
static string const g_argOldReporter = g_strOldReporter; static string const g_argOldReporter = g_strOldReporter;
/// Possible arguments to for --combined-json /// Possible arguments to for --combined-json
@ -876,6 +878,10 @@ General Information)").c_str(),
g_argNoColor.c_str(), g_argNoColor.c_str(),
"Explicitly disable colored output, disabling terminal auto-detection." "Explicitly disable colored output, disabling terminal auto-detection."
) )
(
g_argErrorIds.c_str(),
"Output error codes."
)
( (
g_argOldReporter.c_str(), g_argOldReporter.c_str(),
"Enables old diagnostics reporter (legacy option, will be removed)." "Enables old diagnostics reporter (legacy option, will be removed)."
@ -989,6 +995,8 @@ General Information)").c_str(),
m_coloredOutput = !m_args.count(g_argNoColor) && (isatty(STDERR_FILENO) || m_args.count(g_argColor)); m_coloredOutput = !m_args.count(g_argNoColor) && (isatty(STDERR_FILENO) || m_args.count(g_argColor));
m_withErrorIds = m_args.count(g_argErrorIds);
if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1)) if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1))
{ {
sout() << desc; sout() << desc;
@ -1294,7 +1302,7 @@ bool CommandLineInterface::processInput()
if (m_args.count(g_argOldReporter)) if (m_args.count(g_argOldReporter))
formatter = make_unique<SourceReferenceFormatter>(serr(false)); formatter = make_unique<SourceReferenceFormatter>(serr(false));
else else
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput); formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput, m_withErrorIds);
try try
{ {
@ -1732,7 +1740,7 @@ bool CommandLineInterface::assemble(
if (m_args.count(g_argOldReporter)) if (m_args.count(g_argOldReporter))
formatter = make_unique<SourceReferenceFormatter>(serr(false)); formatter = make_unique<SourceReferenceFormatter>(serr(false));
else else
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput); formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput, m_withErrorIds);
for (auto const& error: stack.errors()) for (auto const& error: stack.errors())
{ {

View File

@ -131,6 +131,8 @@ private:
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS; CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
/// Whether or not to colorize diagnostics output. /// Whether or not to colorize diagnostics output.
bool m_coloredOutput = true; bool m_coloredOutput = true;
/// Whether or not to output error IDs.
bool m_withErrorIds = false;
}; };
} }

View File

@ -121,6 +121,7 @@ function test_solc_behaviour()
rm "$stdout_path.bak" rm "$stdout_path.bak"
else else
sed -i.bak -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path" sed -i.bak -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e '/^Warning (3805): This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1AUXDATA REMOVED/' "$stdout_path" sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1AUXDATA REMOVED/' "$stdout_path"
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path" sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
# Remove trailing empty lines. Needs a line break to make OSX sed happy. # Remove trailing empty lines. Needs a line break to make OSX sed happy.

View File

@ -0,0 +1 @@
--error-codes

View File

@ -0,0 +1,26 @@
Error (4937): No visibility specified. Did you intend to add "public"?
--> error_codes/input.sol:4:5:
|
4 | function f() {
| ^ (Relevant source part starts here and spans across multiple lines).
Warning (3420): Source file does not specify required compiler version!
--> error_codes/input.sol
Error (4247): Expression has to be an lvalue.
--> error_codes/input.sol:5:9:
|
5 | 2=0;
| ^
Error (7407): Type int_const 0 is not implicitly convertible to expected type int_const 2.
--> error_codes/input.sol:5:11:
|
5 | 2=0;
| ^
Error (2614): Indexed expression has to be a type, mapping or array (is literal_string "")
--> error_codes/input.sol:6:9:
|
6 | ""[2];
| ^^

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0
contract C {
function f() {
2=0;
""[2];
}
}

View File

@ -134,7 +134,7 @@ TestCase::TestResult ASTJSONTest::run(ostream& _stream, string const& _linePrefi
c.analyze(); c.analyze();
else else
{ {
SourceReferenceFormatterHuman formatter(_stream, _formatted); SourceReferenceFormatterHuman formatter(_stream, _formatted, false);
for (auto const& error: c.errors()) for (auto const& error: c.errors())
formatter.printErrorInformation(*error); formatter.printErrorInformation(*error);
return TestResult::FatalError; return TestResult::FatalError;

View File

@ -118,7 +118,7 @@ TestCase::TestResult GasTest::run(ostream& _stream, string const& _linePrefix, b
if (!compiler().parseAndAnalyze() || !compiler().compile()) if (!compiler().parseAndAnalyze() || !compiler().compile())
{ {
SourceReferenceFormatterHuman formatter(_stream, _formatted); SourceReferenceFormatterHuman formatter(_stream, _formatted, false);
for (auto const& error: compiler().errors()) for (auto const& error: compiler().errors())
formatter.printErrorInformation(*error); formatter.printErrorInformation(*error);
return TestResult::FatalError; return TestResult::FatalError;

View File

@ -390,7 +390,7 @@ void SourceUpgrade::applyChange(
void SourceUpgrade::printErrors() const void SourceUpgrade::printErrors() const
{ {
auto formatter = make_unique<langutil::SourceReferenceFormatterHuman>(cout, true); auto formatter = make_unique<langutil::SourceReferenceFormatterHuman>(cout, true, false);
for (auto const& error: m_compiler->errors()) for (auto const& error: m_compiler->errors())
if (error->type() != langutil::Error::Type::Warning) if (error->type() != langutil::Error::Type::Warning)

View File

@ -36,7 +36,7 @@ void UpgradeChange::apply()
void UpgradeChange::log(bool const _shorten) const void UpgradeChange::log(bool const _shorten) const
{ {
stringstream os; stringstream os;
SourceReferenceFormatterHuman formatter{os, true}; SourceReferenceFormatterHuman formatter{os, true, false};
string start = to_string(m_location.start); string start = to_string(m_location.start);
string end = to_string(m_location.end); string end = to_string(m_location.end);