Skip to content

Commit 9bbeea5

Browse files
sladecekcameel
authored andcommitted
Make --pretty-json work with Standard JSON output
1 parent 7041b87 commit 9bbeea5

File tree

24 files changed

+176
-26
lines changed

24 files changed

+176
-26
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Compiler Features:
88
* Yul EVM Code Transform: Do not reuse stack slots that immediately become unreachable.
99
* Yul EVM Code Transform: Also pop unused argument slots for functions without return variables (under the same restrictions as for functions with return variables).
1010
* Yul Optimizer: Move function arguments and return variables to memory with the experimental Stack Limit Evader (which is not enabled by default).
11+
* Commandline Interface: option ``--pretty-json`` works also with ``--standard--json``.
1112

1213

1314
Bugfixes:

libsolidity/interface/StandardCompiler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,7 @@ string StandardCompiler::compile(string const& _input) noexcept
14201420
try
14211421
{
14221422
if (!util::jsonParseStrict(_input, input, &errors))
1423-
return util::jsonCompactPrint(formatFatalError("JSONError", errors));
1423+
return util::jsonPrint(formatFatalError("JSONError", errors), m_jsonPrintingFormat);
14241424
}
14251425
catch (...)
14261426
{
@@ -1433,7 +1433,7 @@ string StandardCompiler::compile(string const& _input) noexcept
14331433

14341434
try
14351435
{
1436-
return util::jsonCompactPrint(output);
1436+
return util::jsonPrint(output, m_jsonPrintingFormat);
14371437
}
14381438
catch (...)
14391439
{

libsolidity/interface/StandardCompiler.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#pragma once
2525

2626
#include <libsolidity/interface/CompilerStack.h>
27+
#include <libsolutil/JSON.h>
2728

2829
#include <optional>
2930
#include <utility>
@@ -46,8 +47,10 @@ class StandardCompiler
4647
/// Creates a new StandardCompiler.
4748
/// @param _readFile callback used to read files for import statements. Must return
4849
/// and must not emit exceptions.
49-
explicit StandardCompiler(ReadCallback::Callback _readFile = ReadCallback::Callback()):
50-
m_readFile(std::move(_readFile))
50+
explicit StandardCompiler(ReadCallback::Callback _readFile = ReadCallback::Callback(),
51+
util::JsonFormat const& _format = {}):
52+
m_readFile(std::move(_readFile)),
53+
m_jsonPrintingFormat(std::move(_format))
5154
{
5255
}
5356

@@ -91,6 +94,8 @@ class StandardCompiler
9194
Json::Value compileYul(InputsAndSettings _inputsAndSettings);
9295

9396
ReadCallback::Callback m_readFile;
97+
98+
util::JsonFormat m_jsonPrintingFormat;
9499
};
95100

96101
}

libsolutil/JSON.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,29 @@ Json::Value removeNullMembers(Json::Value _json)
115115

116116
string jsonPrettyPrint(Json::Value const& _input)
117117
{
118-
static map<string, Json::Value> settings{{"indentation", " "}, {"enableYAMLCompatibility", true}};
119-
static StreamWriterBuilder writerBuilder(settings);
120-
string result = print(_input, writerBuilder);
121-
boost::replace_all(result, " \n", "\n");
122-
return result;
118+
return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty });
123119
}
124120

125121
string jsonCompactPrint(Json::Value const& _input)
126122
{
127-
static map<string, Json::Value> settings{{"indentation", ""}};
128-
static StreamWriterBuilder writerBuilder(settings);
129-
return print(_input, writerBuilder);
123+
return jsonPrint(_input, JsonFormat{ JsonFormat::Compact });
124+
}
125+
126+
string jsonPrint(Json::Value const& _input, JsonFormat const& _format)
127+
{
128+
map<string, Json::Value> settings;
129+
if (_format.format == JsonFormat::Pretty)
130+
{
131+
settings["indentation"] = string(_format.indent, ' ');
132+
settings["enableYAMLCompatibility"] = true;
133+
}
134+
else
135+
settings["indentation"] = "";
136+
StreamWriterBuilder writerBuilder(settings);
137+
string result = print(_input, writerBuilder);
138+
if (_format.format == JsonFormat::Pretty)
139+
boost::replace_all(result, " \n", "\n");
140+
return result;
130141
}
131142

132143
bool jsonParseStrict(string const& _input, Json::Value& _json, string* _errs /* = nullptr */)

libsolutil/JSON.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,33 @@ namespace solidity::util
3333
/// Removes members with null value recursively from (@a _json).
3434
Json::Value removeNullMembers(Json::Value _json);
3535

36+
/// JSON printing format.
37+
struct JsonFormat
38+
{
39+
enum Format
40+
{
41+
Compact,
42+
Pretty
43+
};
44+
45+
static constexpr uint32_t defaultIndent = 2;
46+
47+
bool operator==(JsonFormat const& _other) const noexcept { return (format == _other.format) && (indent == _other.indent); }
48+
bool operator!=(JsonFormat const& _other) const noexcept { return !(*this == _other); }
49+
50+
Format format = Compact;
51+
uint32_t indent = defaultIndent;
52+
};
53+
3654
/// Serialise the JSON object (@a _input) with indentation
3755
std::string jsonPrettyPrint(Json::Value const& _input);
3856

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

60+
/// Serialise the JSON object (@a _input) using specified format (@a _format)
61+
std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format);
62+
4263
/// Parse a JSON string (@a _input) with enabled strict-mode and writes resulting JSON object to (@a _json)
4364
/// \param _input JSON input string
4465
/// \param _json [out] resulting JSON object

solc/CommandLineInterface.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ bool CommandLineInterface::processInput()
532532
return false;
533533
}
534534
}
535-
StandardCompiler compiler(m_fileReader.reader());
535+
StandardCompiler compiler(m_fileReader.reader(), m_options.formatting.json);
536536
sout() << compiler.compile(std::move(input)) << endl;
537537
return true;
538538
}
@@ -771,9 +771,7 @@ void CommandLineInterface::handleCombinedJSON()
771771
}
772772
}
773773

774-
string json = m_options.formatting.prettyJson ? jsonPrettyPrint(removeNullMembers(std::move(output))) :
775-
jsonCompactPrint(removeNullMembers(std::move(output)));
776-
774+
string json = jsonPrint(removeNullMembers(std::move(output)), m_options.formatting.json);
777775
if (!m_options.output.dir.empty())
778776
createJson("combined", json);
779777
else

solc/CommandLineParser.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static string const g_strStandardJSON = "standard-json";
125125
static string const g_strStrictAssembly = "strict-assembly";
126126
static string const g_strSwarm = "swarm";
127127
static string const g_strPrettyJson = "pretty-json";
128+
static string const g_strJsonIndent = "json-indent";
128129
static string const g_strVersion = "version";
129130
static string const g_strIgnoreMissingFiles = "ignore-missing";
130131
static string const g_strColor = "color";
@@ -281,7 +282,7 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex
281282
assembly.targetMachine == _other.assembly.targetMachine &&
282283
assembly.inputLanguage == _other.assembly.inputLanguage &&
283284
linker.libraries == _other.linker.libraries &&
284-
formatting.prettyJson == _other.formatting.prettyJson &&
285+
formatting.json == _other.formatting.json &&
285286
formatting.coloredOutput == _other.formatting.coloredOutput &&
286287
formatting.withErrorIds == _other.formatting.withErrorIds &&
287288
compiler.outputs == _other.compiler.outputs &&
@@ -582,7 +583,12 @@ General Information)").c_str(),
582583
outputFormatting.add_options()
583584
(
584585
g_strPrettyJson.c_str(),
585-
"Output JSON in pretty format. Currently it only works with the combined JSON output."
586+
"Output JSON in pretty format."
587+
)
588+
(
589+
g_strJsonIndent.c_str(),
590+
po::value<uint32_t>()->value_name("N")->default_value(util::JsonFormat::defaultIndent),
591+
"Indent pretty-printed JSON with N spaces. Enables '--pretty-json' automatically."
586592
)
587593
(
588594
g_strColor.c_str(),
@@ -790,7 +796,16 @@ General Information)").c_str(),
790796
m_options.output.dir = m_args.at(g_strOutputDir).as<string>();
791797

792798
m_options.output.overwriteFiles = (m_args.count(g_strOverwrite) > 0);
793-
m_options.formatting.prettyJson = (m_args.count(g_strPrettyJson) > 0);
799+
800+
if (m_args.count(g_strPrettyJson) > 0)
801+
{
802+
m_options.formatting.json.format = JsonFormat::Pretty;
803+
}
804+
if (!m_args[g_strJsonIndent].defaulted())
805+
{
806+
m_options.formatting.json.format = JsonFormat::Pretty;
807+
m_options.formatting.json.indent = m_args[g_strJsonIndent].as<uint32_t>();
808+
}
794809

795810
static_assert(
796811
sizeof(m_options.compiler.outputs) == 15 * sizeof(bool),

solc/CommandLineParser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <libsolidity/interface/ImportRemapper.h>
2727
#include <libyul/AssemblyStack.h>
2828
#include <liblangutil/EVMVersion.h>
29+
#include <libsolutil/JSON.h>
2930

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

105+
104106
struct
105107
{
106108
InputMode mode = InputMode::Compiler;
@@ -137,7 +139,7 @@ struct CommandLineOptions
137139

138140
struct
139141
{
140-
bool prettyJson = false;
142+
util::JsonFormat json;
141143
std::optional<bool> coloredOutput;
142144
bool withErrorIds = false;
143145
} formatting;
@@ -168,6 +170,7 @@ struct CommandLineOptions
168170
bool initialize = false;
169171
ModelCheckerSettings settings;
170172
} modelChecker;
173+
171174
};
172175

173176
/// Parses the command-line arguments and produces a filled-out CommandLineOptions structure.

test/cmdlineTests.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,16 @@ function test_solc_behaviour()
141141

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--combined-json abi --pretty-json --json-indent 3

0 commit comments

Comments
 (0)