aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md3
-rw-r--r--docs/introduction-to-smart-contracts.rst6
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp3
-rw-r--r--libsolidity/interface/StandardCompiler.cpp6
-rw-r--r--test/libsolidity/ASTJSON.cpp23
-rw-r--r--test/libsolidity/StandardCompiler.cpp36
6 files changed, 72 insertions, 5 deletions
diff --git a/Changelog.md b/Changelog.md
index d4e91c26..de0b742e 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -6,7 +6,8 @@ Features:
Bugfixes:
-
+ * JSON-AST: Add "documentation" property to function, event and modifier definition.
+ * Standard JSON: catch errors properly when invalid "sources" are passed
### 0.4.20 (2018-02-14)
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index 6425dcaa..c297a8ad 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -118,9 +118,11 @@ that is publicly accessible. The ``address`` type is a 160-bit value
that does not allow any arithmetic operations. It is suitable for
storing addresses of contracts or keypairs belonging to external
persons. The keyword ``public`` automatically generates a function that
-allows you to access the current value of the state variable.
+allows you to access the current value of the state variable
+from outside of the contract.
Without this keyword, other contracts have no way to access the variable.
-The function will look something like this::
+The code of the function generated by the compiler is roughly equivalent
+to the following::
function minter() returns (address) { return minter; }
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index 51249f20..cd9f7eca 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -324,6 +324,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
+ make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
// FIXME: remove with next breaking release
make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() <= StateMutability::View),
make_pair("payable", _node.isPayable()),
@@ -365,6 +366,7 @@ bool ASTJsonConverter::visit(ModifierDefinition const& _node)
{
setJsonNode(_node, "ModifierDefinition", {
make_pair("name", _node.name()),
+ make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("body", toJson(_node.body()))
@@ -386,6 +388,7 @@ bool ASTJsonConverter::visit(EventDefinition const& _node)
m_inEvent = true;
setJsonNode(_node, "EventDefinition", {
make_pair("name", _node.name()),
+ make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("anonymous", _node.isAnonymous())
});
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 04f5bd25..84dedfb8 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -236,7 +236,11 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
return formatFatalError("JSONError", "Only \"Solidity\" is supported as a language.");
Json::Value const& sources = _input["sources"];
- if (!sources)
+
+ if (!sources.isObject() && !sources.isNull())
+ return formatFatalError("JSONError", "\"sources\" is not a JSON object.");
+
+ if (sources.empty())
return formatFatalError("JSONError", "No input sources specified.");
Json::Value errors = Json::arrayValue;
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp
index 31165922..a165f7a9 100644
--- a/test/libsolidity/ASTJSON.cpp
+++ b/test/libsolidity/ASTJSON.cpp
@@ -237,16 +237,31 @@ BOOST_AUTO_TEST_CASE(documentation)
" and has a line-breaking comment.*/"
"contract C {}"
);
+ c.addSource("c",
+ "contract C {"
+ " /** Some comment on Evt.*/ event Evt();"
+ " /** Some comment on mod.*/ modifier mod() { _; }"
+ " /** Some comment on fn.*/ function fn() public {}"
+ "}"
+ );
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 0;
sourceIndices["b"] = 1;
+ sourceIndices["c"] = 2;
Json::Value astJsonA = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value documentationA = astJsonA["children"][0]["attributes"]["documentation"];
BOOST_CHECK_EQUAL(documentationA, "This contract is empty");
Json::Value astJsonB = ASTJsonConverter(true, sourceIndices).toJson(c.ast("b"));
Json::Value documentationB = astJsonB["children"][0]["attributes"]["documentation"];
BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment.");
+ Json::Value astJsonC = ASTJsonConverter(true, sourceIndices).toJson(c.ast("c"));
+ Json::Value documentationC0 = astJsonC["children"][0]["children"][0]["attributes"]["documentation"];
+ Json::Value documentationC1 = astJsonC["children"][0]["children"][1]["attributes"]["documentation"];
+ Json::Value documentationC2 = astJsonC["children"][0]["children"][2]["attributes"]["documentation"];
+ BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt.");
+ BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod.");
+ BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn.");
//same tests for non-legacy mode
astJsonA = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a"));
documentationA = astJsonA["nodes"][0]["documentation"];
@@ -254,7 +269,13 @@ BOOST_AUTO_TEST_CASE(documentation)
astJsonB = ASTJsonConverter(false, sourceIndices).toJson(c.ast("b"));
documentationB = astJsonB["nodes"][0]["documentation"];
BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment.");
-
+ astJsonC = ASTJsonConverter(false, sourceIndices).toJson(c.ast("c"));
+ documentationC0 = astJsonC["nodes"][0]["nodes"][0]["documentation"];
+ documentationC1 = astJsonC["nodes"][0]["nodes"][1]["documentation"];
+ documentationC2 = astJsonC["nodes"][0]["nodes"][2]["documentation"];
+ BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt.");
+ BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod.");
+ BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn.");
}
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index e48624e5..8da536d8 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -154,6 +154,42 @@ BOOST_AUTO_TEST_CASE(no_sources)
BOOST_CHECK(containsError(result, "JSONError", "No input sources specified."));
}
+BOOST_AUTO_TEST_CASE(no_sources_empty_object)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "sources": {}
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "No input sources specified."));
+}
+
+BOOST_AUTO_TEST_CASE(no_sources_empty_array)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "sources": []
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object."));
+}
+
+BOOST_AUTO_TEST_CASE(sources_is_array)
+{
+ char const* input = R"(
+ {
+ "language": "Solidity",
+ "sources": ["aa", "bb"]
+ }
+ )";
+ Json::Value result = compile(input);
+ BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object."));
+}
+
BOOST_AUTO_TEST_CASE(smoke_test)
{
char const* input = R"(