Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make --pretty-json work with Standard JSON output #11639

Merged
merged 1 commit into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Compiler Features:
* Yul EVM Code Transform: Do not reuse stack slots that immediately become unreachable.
* Yul EVM Code Transform: Also pop unused argument slots for functions without return variables (under the same restrictions as for functions with return variables).
* Yul Optimizer: Move function arguments and return variables to memory with the experimental Stack Limit Evader (which is not enabled by default).
* Commandline Interface: option ``--pretty-json`` works also with ``--standard--json``.


Bugfixes:
sladecek marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 2 additions & 2 deletions libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,7 @@ string StandardCompiler::compile(string const& _input) noexcept
try
{
if (!util::jsonParseStrict(_input, input, &errors))
return util::jsonCompactPrint(formatFatalError("JSONError", errors));
return util::jsonPrint(formatFatalError("JSONError", errors), m_jsonPrintingFormat);
}
catch (...)
{
Expand All @@ -1433,7 +1433,7 @@ string StandardCompiler::compile(string const& _input) noexcept

try
{
return util::jsonCompactPrint(output);
return util::jsonPrint(output, m_jsonPrintingFormat);
}
catch (...)
{
Expand Down
9 changes: 7 additions & 2 deletions libsolidity/interface/StandardCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#pragma once

#include <libsolidity/interface/CompilerStack.h>
#include <libsolutil/JSON.h>

#include <optional>
#include <utility>
Expand All @@ -46,8 +47,10 @@ class StandardCompiler
/// Creates a new StandardCompiler.
/// @param _readFile callback used to read files for import statements. Must return
/// and must not emit exceptions.
explicit StandardCompiler(ReadCallback::Callback _readFile = ReadCallback::Callback()):
m_readFile(std::move(_readFile))
explicit StandardCompiler(ReadCallback::Callback _readFile = ReadCallback::Callback(),
util::JsonFormat const& _format = {}):
m_readFile(std::move(_readFile)),
m_jsonPrintingFormat(std::move(_format))
{
}

Expand Down Expand Up @@ -91,6 +94,8 @@ class StandardCompiler
Json::Value compileYul(InputsAndSettings _inputsAndSettings);

ReadCallback::Callback m_readFile;

util::JsonFormat m_jsonPrintingFormat;
};

}
27 changes: 19 additions & 8 deletions libsolutil/JSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,29 @@ Json::Value removeNullMembers(Json::Value _json)

string jsonPrettyPrint(Json::Value const& _input)
{
static map<string, Json::Value> settings{{"indentation", " "}, {"enableYAMLCompatibility", true}};
static StreamWriterBuilder writerBuilder(settings);
string result = print(_input, writerBuilder);
boost::replace_all(result, " \n", "\n");
return result;
return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty });
}

string jsonCompactPrint(Json::Value const& _input)
{
static map<string, Json::Value> settings{{"indentation", ""}};
static StreamWriterBuilder writerBuilder(settings);
return print(_input, writerBuilder);
return jsonPrint(_input, JsonFormat{ JsonFormat::Compact });
}

string jsonPrint(Json::Value const& _input, JsonFormat const& _format)
{
map<string, Json::Value> settings;
if (_format.format == JsonFormat::Pretty)
{
settings["indentation"] = string(_format.indent, ' ');
settings["enableYAMLCompatibility"] = true;
}
else
settings["indentation"] = "";
StreamWriterBuilder writerBuilder(settings);
string result = print(_input, writerBuilder);
if (_format.format == JsonFormat::Pretty)
boost::replace_all(result, " \n", "\n");
return result;
}

bool jsonParseStrict(string const& _input, Json::Value& _json, string* _errs /* = nullptr */)
Expand Down
21 changes: 21 additions & 0 deletions libsolutil/JSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,33 @@ namespace solidity::util
/// Removes members with null value recursively from (@a _json).
Json::Value removeNullMembers(Json::Value _json);

/// JSON printing format.
struct JsonFormat
{
enum Format
{
Compact,
Pretty
};

static constexpr uint32_t defaultIndent = 2;

bool operator==(JsonFormat const& _other) const noexcept { return (format == _other.format) && (indent == _other.indent); }
bool operator!=(JsonFormat const& _other) const noexcept { return !(*this == _other); }

Format format = Compact;
uint32_t indent = defaultIndent;
};

/// Serialise the JSON object (@a _input) with indentation
std::string jsonPrettyPrint(Json::Value const& _input);

/// Serialise the JSON object (@a _input) without indentation
std::string jsonCompactPrint(Json::Value const& _input);

/// Serialise the JSON object (@a _input) using specified format (@a _format)
std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format);

/// Parse a JSON string (@a _input) with enabled strict-mode and writes resulting JSON object to (@a _json)
/// \param _input JSON input string
/// \param _json [out] resulting JSON object
Expand Down
6 changes: 2 additions & 4 deletions solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ bool CommandLineInterface::processInput()
return false;
}
}
StandardCompiler compiler(m_fileReader.reader());
StandardCompiler compiler(m_fileReader.reader(), m_options.formatting.json);
sout() << compiler.compile(std::move(input)) << endl;
return true;
}
Expand Down Expand Up @@ -771,9 +771,7 @@ void CommandLineInterface::handleCombinedJSON()
}
}

string json = m_options.formatting.prettyJson ? jsonPrettyPrint(removeNullMembers(std::move(output))) :
jsonCompactPrint(removeNullMembers(std::move(output)));

string json = jsonPrint(removeNullMembers(std::move(output)), m_options.formatting.json);
if (!m_options.output.dir.empty())
createJson("combined", json);
else
Expand Down
21 changes: 18 additions & 3 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ static string const g_strStandardJSON = "standard-json";
static string const g_strStrictAssembly = "strict-assembly";
static string const g_strSwarm = "swarm";
static string const g_strPrettyJson = "pretty-json";
static string const g_strJsonIndent = "json-indent";
static string const g_strVersion = "version";
static string const g_strIgnoreMissingFiles = "ignore-missing";
static string const g_strColor = "color";
Expand Down Expand Up @@ -281,7 +282,7 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex
assembly.targetMachine == _other.assembly.targetMachine &&
assembly.inputLanguage == _other.assembly.inputLanguage &&
linker.libraries == _other.linker.libraries &&
formatting.prettyJson == _other.formatting.prettyJson &&
formatting.json == _other.formatting.json &&
formatting.coloredOutput == _other.formatting.coloredOutput &&
formatting.withErrorIds == _other.formatting.withErrorIds &&
compiler.outputs == _other.compiler.outputs &&
Expand Down Expand Up @@ -582,7 +583,12 @@ General Information)").c_str(),
outputFormatting.add_options()
(
g_strPrettyJson.c_str(),
"Output JSON in pretty format. Currently it only works with the combined JSON output."
"Output JSON in pretty format."
)
(
g_strJsonIndent.c_str(),
po::value<uint32_t>()->value_name("N")->default_value(util::JsonFormat::defaultIndent),
"Indent pretty-printed JSON with N spaces. Enables '--pretty-json' automatically."
)
(
g_strColor.c_str(),
Expand Down Expand Up @@ -790,7 +796,16 @@ General Information)").c_str(),
m_options.output.dir = m_args.at(g_strOutputDir).as<string>();

m_options.output.overwriteFiles = (m_args.count(g_strOverwrite) > 0);
m_options.formatting.prettyJson = (m_args.count(g_strPrettyJson) > 0);

if (m_args.count(g_strPrettyJson) > 0)
{
m_options.formatting.json.format = JsonFormat::Pretty;
}
if (!m_args[g_strJsonIndent].defaulted())
{
m_options.formatting.json.format = JsonFormat::Pretty;
m_options.formatting.json.indent = m_args[g_strJsonIndent].as<uint32_t>();
}

static_assert(
sizeof(m_options.compiler.outputs) == 15 * sizeof(bool),
Expand Down
5 changes: 4 additions & 1 deletion solc/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <libsolidity/interface/ImportRemapper.h>
#include <libyul/AssemblyStack.h>
#include <liblangutil/EVMVersion.h>
#include <libsolutil/JSON.h>

#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>
Expand Down Expand Up @@ -101,6 +102,7 @@ struct CommandLineOptions
bool operator==(CommandLineOptions const& _other) const noexcept;
bool operator!=(CommandLineOptions const& _other) const noexcept { return !(*this == _other); }


struct
{
InputMode mode = InputMode::Compiler;
Expand Down Expand Up @@ -137,7 +139,7 @@ struct CommandLineOptions

struct
{
bool prettyJson = false;
util::JsonFormat json;
std::optional<bool> coloredOutput;
bool withErrorIds = false;
} formatting;
Expand Down Expand Up @@ -168,6 +170,7 @@ struct CommandLineOptions
bool initialize = false;
ModelCheckerSettings settings;
} modelChecker;

};

/// Parses the command-line arguments and produces a filled-out CommandLineOptions structure.
Expand Down
11 changes: 9 additions & 2 deletions test/cmdlineTests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,16 @@ function test_solc_behaviour()

if [[ " ${solc_args[*]} " == *" --standard-json "* ]]
then
sed -i.bak -e 's/{[^{]*Warning: This is a pre-release compiler version[^}]*},\{0,1\}//' "$stdout_path"
python3 - <<EOF
import re, sys
json = open("$stdout_path", "r").read()
json = re.sub(r"{[^{}]*Warning: This is a pre-release compiler version[^{}]*},?", "", json)
json = re.sub(r"},\s*]", "}]", json) # },] -> }]
json = re.sub(r"\"errors\":\s*\[\s*\],?\s*","",json) # Remove "errors" array if it's not empty
json = re.sub("\n\\s+\n", "\n\n", json) # Remove any leftover trailing whitespace
open("$stdout_path", "w").write(json)
EOF
sed -i.bak -E -e 's/ Consider adding \\"pragma solidity \^[0-9.]*;\\"//g' "$stdout_path"
sed -i.bak -e 's/"errors":\[\],\{0,1\}//' "$stdout_path"
sed -i.bak -E -e 's/\"opcodes\":\"[^"]+\"/\"opcodes\":\"<OPCODES REMOVED>\"/g' "$stdout_path"
sed -i.bak -E -e 's/\"sourceMap\":\"[0-9:;-]+\"/\"sourceMap\":\"<SOURCEMAP REMOVED>\"/g' "$stdout_path"

Expand Down
1 change: 1 addition & 0 deletions test/cmdlineTests/pretty_json_combined/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--combined-json abi --pretty-json --json-indent 3
3 changes: 3 additions & 0 deletions test/cmdlineTests/pretty_json_combined/input.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {}
10 changes: 10 additions & 0 deletions test/cmdlineTests/pretty_json_combined/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"contracts":
{
"pretty_json_combined/input.sol:C":
{
"abi": []
}
},
"version": "<VERSION REMOVED>"
}
1 change: 1 addition & 0 deletions test/cmdlineTests/pretty_json_indent_only/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--json-indent 7
10 changes: 10 additions & 0 deletions test/cmdlineTests/pretty_json_indent_only/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C {}"
}
}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/pretty_json_indent_only/output
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

9 changes: 9 additions & 0 deletions test/cmdlineTests/pretty_json_indent_only/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"sources":
{
"A":
{
"id": 0
}
}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/pretty_json_standard/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--pretty-json
10 changes: 10 additions & 0 deletions test/cmdlineTests/pretty_json_standard/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C {}"
}
}
}
9 changes: 9 additions & 0 deletions test/cmdlineTests/pretty_json_standard/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"sources":
{
"A":
{
"id": 0
}
}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/pretty_json_standard_indent/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--pretty-json --json-indent 7
10 changes: 10 additions & 0 deletions test/cmdlineTests/pretty_json_standard_indent/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { }"
}
}
}
9 changes: 9 additions & 0 deletions test/cmdlineTests/pretty_json_standard_indent/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"sources":
{
"A":
{
"id": 0
}
}
}
9 changes: 9 additions & 0 deletions test/cmdlineTests/pretty_json_standard_indent/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"sources":
{
"A":
{
"id": 0
}
}
}
Loading