Provide secondary source location for error messages in standard json.

This commit is contained in:
chriseth 2019-07-03 14:21:09 +02:00
parent b837705259
commit d3e542d32c
6 changed files with 65 additions and 14 deletions

View File

@ -11,6 +11,7 @@ Compiler Features:
* eWasm: Highly experimental eWasm output using ``--ewasm`` in the commandline interface or output selection of ``ewasm.wast`` in standard-json. * eWasm: Highly experimental eWasm output using ``--ewasm`` in the commandline interface or output selection of ``ewasm.wast`` in standard-json.
* Metadata: Update the swarm hash, changes ``bzzr0`` to ``bzzr1`` and urls to use ``bzz-raw://``. * Metadata: Update the swarm hash, changes ``bzzr0`` to ``bzzr1`` and urls to use ``bzz-raw://``.
* Standard JSON Interface: Compile only selected sources and contracts. * Standard JSON Interface: Compile only selected sources and contracts.
* Standard JSON Interface: Provide secondary error locations (e.g. the source position of other conflicting declarations).

View File

@ -314,6 +314,15 @@ Output Description
"start": 0, "start": 0,
"end": 100 "end": 100
], ],
// Optional: Further locations (e.g. places of conflicting declarations)
"secondarySourceLocations": [
{
"file": "sourceFile.sol",
"start": 64,
"end": 92,
"message": "Other declaration is here:"
}
],
// Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc. // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
// See below for complete list of types. // See below for complete list of types.
"type": "TypeError", "type": "TypeError",

View File

@ -40,7 +40,8 @@ using namespace langutil;
using namespace dev::solidity; using namespace dev::solidity;
using namespace yul; using namespace yul;
namespace { namespace
{
Json::Value formatError( Json::Value formatError(
bool _warning, bool _warning,
@ -48,7 +49,8 @@ Json::Value formatError(
string const& _component, string const& _component,
string const& _message, string const& _message,
string const& _formattedMessage = "", string const& _formattedMessage = "",
Json::Value const& _sourceLocation = Json::Value() Json::Value const& _sourceLocation = Json::Value(),
Json::Value const& _secondarySourceLocation = Json::Value()
) )
{ {
Json::Value error = Json::objectValue; Json::Value error = Json::objectValue;
@ -59,6 +61,8 @@ Json::Value formatError(
error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message; error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message;
if (_sourceLocation.isObject()) if (_sourceLocation.isObject())
error["sourceLocation"] = _sourceLocation; error["sourceLocation"] = _sourceLocation;
if (_secondarySourceLocation.isArray())
error["secondarySourceLocations"] = _secondarySourceLocation;
return error; return error;
} }
@ -70,6 +74,34 @@ Json::Value formatFatalError(string const& _type, string const& _message)
return output; return output;
} }
Json::Value formatSourceLocation(SourceLocation const* location)
{
Json::Value sourceLocation;
if (location && location->source && !location->source->name().empty())
{
sourceLocation["file"] = location->source->name();
sourceLocation["start"] = location->start;
sourceLocation["end"] = location->end;
}
return sourceLocation;
}
Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _secondaryLocation)
{
if (!_secondaryLocation)
return {};
Json::Value secondarySourceLocation = Json::arrayValue;
for (auto const& location: _secondaryLocation->infos)
{
Json::Value msg = formatSourceLocation(&location.second);
msg["message"] = location.first;
secondarySourceLocation.append(msg);
}
return secondarySourceLocation;
}
Json::Value formatErrorWithException( Json::Value formatErrorWithException(
Exception const& _exception, Exception const& _exception,
bool const& _warning, bool const& _warning,
@ -81,23 +113,20 @@ Json::Value formatErrorWithException(
string message; string message;
string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(_exception, _type); string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(_exception, _type);
// NOTE: the below is partially a copy from SourceReferenceFormatter
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
if (string const* description = boost::get_error_info<errinfo_comment>(_exception)) if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
message = ((_message.length() > 0) ? (_message + ":") : "") + *description; message = ((_message.length() > 0) ? (_message + ":") : "") + *description;
else else
message = _message; message = _message;
Json::Value sourceLocation; return formatError(
if (location && location->source && location->source->name() != "") _warning,
{ _type,
sourceLocation["file"] = location->source->name(); _component,
sourceLocation["start"] = location->start; message,
sourceLocation["end"] = location->end; formattedMessage,
} formatSourceLocation(boost::get_error_info<errinfo_sourceLocation>(_exception)),
formatSecondarySourceLocation(boost::get_error_info<errinfo_secondarySourceLocation>(_exception))
return formatError(_warning, _type, _component, message, formattedMessage, sourceLocation); );
} }
map<string, set<string>> requestedContractNames(Json::Value const& _outputSelection) map<string, set<string>> requestedContractNames(Json::Value const& _outputSelection)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,10 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract A { constructor(uint) public {} } contract B is A(2) { } contract C is A(3) {} contract D is B, C {}"
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"A:1:112: DeclarationError: Base constructor arguments given twice.\npragma solidity >=0.0; contract A { constructor(uint) public {} } contract B is A(2) { } contract C is A(3) {} contract D is B, C {}\n ^-------------------^\nA:1:81: First constructor call is here: \npragma solidity >=0.0; contract A { constructor(uint) public {} } contract B is A(2) { } contract C is A(3) {} contract D is B, C {}\n ^--^\nA:1:104: Second constructor call is here: \npragma solidity >=0.0; contract A { constructor(uint) public {} } contract B is A(2) { } contract C is A(3) {} contract D is B, C {}\n ^--^\n","message":"Base constructor arguments given twice.","secondarySourceLocations":[{"end":84,"file":"A","message":"First constructor call is here: ","start":80},{"end":107,"file":"A","message":"Second constructor call is here: ","start":103}],"severity":"error","sourceLocation":{"end":132,"file":"A","start":111},"type":"DeclarationError"}],"sources":{}}