diff options
-rw-r--r-- | Changelog.md | 3 | ||||
-rw-r--r-- | docs/introduction-to-smart-contracts.rst | 6 | ||||
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.cpp | 3 | ||||
-rw-r--r-- | libsolidity/interface/StandardCompiler.cpp | 6 | ||||
-rw-r--r-- | test/libsolidity/ASTJSON.cpp | 23 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 36 |
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"( |