From 6b7bec980a482f1e9271b9178d961fbc59a17908 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 1 Dec 2014 17:03:04 +0100 Subject: [PATCH 01/12] Exporting Natspec documentation to a JSON interface - Adding a getDocumentation() function to solidity compiler stack so that we can obtain the natspec interface for a contract - Adding libjsoncpp as a dependency of libsolidity. This is done in a dirty way, using libjsonrpc-cpp s an intermediate dependency for the moment. Will fix soon. - Start of a test file for Natspec exporting to JSON --- solidityNatspecJSON.cpp | 77 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 solidityNatspecJSON.cpp diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp new file mode 100644 index 000000000..5918eec99 --- /dev/null +++ b/solidityNatspecJSON.cpp @@ -0,0 +1,77 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** + * @author Lefteris Karapetsas + * @date 2014 + * Unit tests for the solidity compiler JSON Interface output. + */ + +#include +#include +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class DocumentationChecker +{ +public: + void checkNatspec(std::string const& _code, std::string const& _expectedDocumentationString) + { + m_compilerStack.parse(_code); + auto generatedDocumentationString = m_compilerStack.getDocumentation(); + Json::Value generatedDocumentation; + m_reader.parse(generatedDocumentationString, generatedDocumentation); + Json::Value expectedDocumentation; + m_reader.parse(_expectedDocumentationString, expectedDocumentation); + BOOST_CHECK_MESSAGE(expectedDocumentation == generatedDocumentation, + "Expected " << _expectedDocumentationString << + "\n but got:\n" << generatedDocumentationString); + } + +private: + CompilerStack m_compilerStack; + Json::Reader m_reader; +}; + +BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker) + +BOOST_AUTO_TEST_CASE(basic_test) +{ + char const* sourceCode = "contract test {\n" + " /// Multiplies `a` by 7\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \"user\": \" Multiplies `a` by 7\"}" + "}}"; + + checkNatspec(sourceCode, natspec); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} From bbf4beab45e4e4a8b02bbf5736e8667c2667f815 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 1 Dec 2014 18:01:42 +0100 Subject: [PATCH 02/12] Using jsoncpp for exporting ABI interface from solidity - Also changing the interface JSON test to have a shorter name plus to provide meaningful error message in case of failure --- solidityJSONInterfaceTest.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/solidityJSONInterfaceTest.cpp b/solidityJSONInterfaceTest.cpp index 1a443087f..b91880130 100644 --- a/solidityJSONInterfaceTest.cpp +++ b/solidityJSONInterfaceTest.cpp @@ -34,7 +34,7 @@ namespace test class InterfaceChecker { public: - bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) + void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) { m_compilerStack.parse(_code); std::string generatedInterfaceString = m_compilerStack.getInterface(); @@ -42,15 +42,17 @@ public: m_reader.parse(generatedInterfaceString, generatedInterface); Json::Value expectedInterface; m_reader.parse(_expectedInterfaceString, expectedInterface); - return expectedInterface == generatedInterface; + BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface, + "Expected " << _expectedInterfaceString << + "\n but got:\n" << generatedInterfaceString); } - + private: CompilerStack m_compilerStack; Json::Reader m_reader; }; -BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker) +BOOST_FIXTURE_TEST_SUITE(solidityABIJSON, InterfaceChecker) BOOST_AUTO_TEST_CASE(basic_test) { @@ -76,7 +78,7 @@ BOOST_AUTO_TEST_CASE(basic_test) } ])"; - BOOST_CHECK(checkInterface(sourceCode, interface)); + checkInterface(sourceCode, interface); } BOOST_AUTO_TEST_CASE(empty_contract) @@ -86,7 +88,7 @@ BOOST_AUTO_TEST_CASE(empty_contract) char const* interface = "[]"; - BOOST_CHECK(checkInterface(sourceCode, interface)); + checkInterface(sourceCode, interface); } BOOST_AUTO_TEST_CASE(multiple_methods) @@ -95,7 +97,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) " function f(uint a) returns(uint d) { return a * 7; }\n" " function g(uint b) returns(uint e) { return b * 8; }\n" "}\n"; - + char const* interface = R"([ { "name": "f", @@ -129,7 +131,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) } ])"; - BOOST_CHECK(checkInterface(sourceCode, interface)); + checkInterface(sourceCode, interface); } BOOST_AUTO_TEST_CASE(multiple_params) @@ -160,7 +162,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) } ])"; - BOOST_CHECK(checkInterface(sourceCode, interface)); + checkInterface(sourceCode, interface); } BOOST_AUTO_TEST_CASE(multiple_methods_order) @@ -170,7 +172,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) " function f(uint a) returns(uint d) { return a * 7; }\n" " function c(uint b) returns(uint e) { return b * 8; }\n" "}\n"; - + char const* interface = R"([ { "name": "c", @@ -203,8 +205,8 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) ] } ])"; - - BOOST_CHECK(checkInterface(sourceCode, interface)); + + checkInterface(sourceCode, interface); } BOOST_AUTO_TEST_SUITE_END() From 92724ab80a713332d711fe43a5a09332d9d2d9e4 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 2 Dec 2014 10:41:18 +0100 Subject: [PATCH 03/12] More Natspec JSON export tests and better error reporting --- solidityJSONInterfaceTest.cpp | 17 +++++++- solidityNatspecJSON.cpp | 76 ++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/solidityJSONInterfaceTest.cpp b/solidityJSONInterfaceTest.cpp index b91880130..f46a3ad36 100644 --- a/solidityJSONInterfaceTest.cpp +++ b/solidityJSONInterfaceTest.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace dev { @@ -36,7 +37,19 @@ class InterfaceChecker public: void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) { - m_compilerStack.parse(_code); + try + { + m_compilerStack.parse(_code); + } + catch (const std::exception& e) + { + std::string const* extra = boost::get_error_info(e); + std::string msg = std::string("Parsing contract failed with: ") + + e.what() + std::string("\n"); + if (extra) + msg += *extra; + BOOST_FAIL(msg); + } std::string generatedInterfaceString = m_compilerStack.getInterface(); Json::Value generatedInterface; m_reader.parse(generatedInterfaceString, generatedInterface); @@ -52,7 +65,7 @@ private: Json::Reader m_reader; }; -BOOST_FIXTURE_TEST_SUITE(solidityABIJSON, InterfaceChecker) +BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, InterfaceChecker) BOOST_AUTO_TEST_CASE(basic_test) { diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 5918eec99..5a4649d2e 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace dev { @@ -36,7 +37,19 @@ class DocumentationChecker public: void checkNatspec(std::string const& _code, std::string const& _expectedDocumentationString) { - m_compilerStack.parse(_code); + try + { + m_compilerStack.parse(_code); + } + catch (const std::exception& e) + { + std::string const* extra = boost::get_error_info(e); + std::string msg = std::string("Parsing contract failed with: ") + + e.what() + std::string("\n"); + if (extra) + msg += *extra; + BOOST_FAIL(msg); + } auto generatedDocumentationString = m_compilerStack.getDocumentation(); Json::Value generatedDocumentation; m_reader.parse(generatedDocumentationString, generatedDocumentation); @@ -69,6 +82,67 @@ BOOST_AUTO_TEST_CASE(basic_test) checkNatspec(sourceCode, natspec); } +BOOST_AUTO_TEST_CASE(multiline_comment) +{ + char const* sourceCode = "contract test {\n" + " /// Multiplies `a` by 7\n" + " /// and then adds `b`\n" + " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" + " {\n" + " return (a * 7) + b;\n" + " }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul_and_add\":{ \"user\": \" Multiplies `a` by 7\n and then adds `b`\"}" + "}}"; + + checkNatspec(sourceCode, natspec); +} + +BOOST_AUTO_TEST_CASE(multiple_functions) +{ + char const* sourceCode = "contract test {\n" + " /// Multiplies `a` by 7\n" + " /// and then adds `b`\n" + " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" + " {\n" + " return (a * 7) + b;\n" + " }\n" + "\n" + " /// Divides `input` by `div`\n" + " function divide(uint input, uint div) returns(uint d)\n" + " {\n" + " return input / div;\n" + " }\n" + " /// Subtracts 3 from `input`\n" + " function sub(int input) returns(int d)\n" + " {\n" + " return input - 3;\n" + " }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul_and_add\":{ \"user\": \" Multiplies `a` by 7\n and then adds `b`\"}," + " \"divide\":{ \"user\": \" Divides `input` by `div`\"}," + " \"sub\":{ \"user\": \" Subtracts 3 from `input`\"}" + "}}"; + + checkNatspec(sourceCode, natspec); +} + +BOOST_AUTO_TEST_CASE(empty_contract) +{ + char const* sourceCode = "contract test {\n" + "}\n"; + + char const* natspec = "{\"methods\":{} }"; + + checkNatspec(sourceCode, natspec); +} + BOOST_AUTO_TEST_SUITE_END() From 8afb0256a7e30d4cd16d0c3167178300f1270124 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Wed, 3 Dec 2014 08:36:52 +0100 Subject: [PATCH 04/12] test update due to CALLCODA <-> RETURN --- stSystemOperationsTestFiller.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stSystemOperationsTestFiller.json b/stSystemOperationsTestFiller.json index e62753089..edd803641 100644 --- a/stSystemOperationsTestFiller.json +++ b/stSystemOperationsTestFiller.json @@ -12,7 +12,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28) }", + "code" : "{ (MSTORE 0 0x601080600c6000396000f30060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -46,7 +46,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 1000 4 28) }", + "code" : "{ (MSTORE 0 0x601080600c6000396000f30060003554156009570060203560003555) [[ 0 ]] (CREATE 1000 4 28) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -80,7 +80,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 0xfffffffffff 28) }", + "code" : "{ (MSTORE 0 0x601080600c6000396000f30060003554156009570060203560003555) [[ 0 ]] (CREATE 23 0xfffffffffff 28) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -114,7 +114,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 0xfffffffffff) }", + "code" : "{ (MSTORE 0 0x601080600c6000396000f30060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 0xfffffffffff) }", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { @@ -195,7 +195,7 @@ }, "945304eb96065b2a98b57a48a06ae28d285a71b5" : { "balance" : "23", - "code" : "0x6001600155603760005360026000f2", + "code" : "0x6001600155603760005360026000f3", "nonce" : "0", "storage" : { } @@ -321,7 +321,7 @@ }, "945304eb96065b2a98b57a48a06ae28d285a71b5" : { "balance" : "23", - "code" : "0x6001600155603760005360026000f2", + "code" : "0x6001600155603760005360026000f3", "nonce" : "0", "storage" : { } From 2f7b263f9bc5e6bb75d0974721ca6b90cc9001e9 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 3 Dec 2014 13:50:04 +0100 Subject: [PATCH 05/12] Separate user and dev natspec documentation - plus other small changes according to the spec --- solidityNatspecJSON.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 5a4649d2e..f729e4ff8 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -35,8 +35,11 @@ namespace test class DocumentationChecker { public: - void checkNatspec(std::string const& _code, std::string const& _expectedDocumentationString) + void checkNatspec(std::string const& _code, + std::string const& _expectedDocumentationString, + bool _userDocumentation) { + std::string generatedDocumentationString; try { m_compilerStack.parse(_code); @@ -50,7 +53,11 @@ public: msg += *extra; BOOST_FAIL(msg); } - auto generatedDocumentationString = m_compilerStack.getDocumentation(); + + if (_userDocumentation) + generatedDocumentationString = m_compilerStack.getUserDocumentation(); + else + generatedDocumentationString = m_compilerStack.getDevDocumentation(); Json::Value generatedDocumentation; m_reader.parse(generatedDocumentationString, generatedDocumentation); Json::Value expectedDocumentation; @@ -67,7 +74,7 @@ private: BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker) -BOOST_AUTO_TEST_CASE(basic_test) +BOOST_AUTO_TEST_CASE(user_basic_test) { char const* sourceCode = "contract test {\n" " /// Multiplies `a` by 7\n" @@ -76,13 +83,13 @@ BOOST_AUTO_TEST_CASE(basic_test) char const* natspec = "{" "\"methods\":{" - " \"mul\":{ \"user\": \" Multiplies `a` by 7\"}" + " \"mul\":{ \"notice\": \" Multiplies `a` by 7\"}" "}}"; - checkNatspec(sourceCode, natspec); + checkNatspec(sourceCode, natspec, true); } -BOOST_AUTO_TEST_CASE(multiline_comment) +BOOST_AUTO_TEST_CASE(user_multiline_comment) { char const* sourceCode = "contract test {\n" " /// Multiplies `a` by 7\n" @@ -95,13 +102,13 @@ BOOST_AUTO_TEST_CASE(multiline_comment) char const* natspec = "{" "\"methods\":{" - " \"mul_and_add\":{ \"user\": \" Multiplies `a` by 7\n and then adds `b`\"}" + " \"mul_and_add\":{ \"notice\": \" Multiplies `a` by 7\n and then adds `b`\"}" "}}"; - checkNatspec(sourceCode, natspec); + checkNatspec(sourceCode, natspec, true); } -BOOST_AUTO_TEST_CASE(multiple_functions) +BOOST_AUTO_TEST_CASE(user_multiple_functions) { char const* sourceCode = "contract test {\n" " /// Multiplies `a` by 7\n" @@ -125,22 +132,22 @@ BOOST_AUTO_TEST_CASE(multiple_functions) char const* natspec = "{" "\"methods\":{" - " \"mul_and_add\":{ \"user\": \" Multiplies `a` by 7\n and then adds `b`\"}," - " \"divide\":{ \"user\": \" Divides `input` by `div`\"}," - " \"sub\":{ \"user\": \" Subtracts 3 from `input`\"}" + " \"mul_and_add\":{ \"notice\": \" Multiplies `a` by 7\n and then adds `b`\"}," + " \"divide\":{ \"notice\": \" Divides `input` by `div`\"}," + " \"sub\":{ \"notice\": \" Subtracts 3 from `input`\"}" "}}"; - checkNatspec(sourceCode, natspec); + checkNatspec(sourceCode, natspec, true); } -BOOST_AUTO_TEST_CASE(empty_contract) +BOOST_AUTO_TEST_CASE(user_empty_contract) { char const* sourceCode = "contract test {\n" "}\n"; char const* natspec = "{\"methods\":{} }"; - checkNatspec(sourceCode, natspec); + checkNatspec(sourceCode, natspec, true); } From 4eefbc941ef593d7649491a5f2681ecc2a61cfbe Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 3 Dec 2014 16:40:37 +0100 Subject: [PATCH 06/12] Moving all Interface and Documentation functionality to own class - Creating the Interface Handler class which will take care of the parsing of Natspec comments and of interfacing with and outputing to JSON files. - Will also handle the ABI interface creation --- solidityJSONInterfaceTest.cpp | 2 +- solidityNatspecJSON.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/solidityJSONInterfaceTest.cpp b/solidityJSONInterfaceTest.cpp index f46a3ad36..8fe0ea653 100644 --- a/solidityJSONInterfaceTest.cpp +++ b/solidityJSONInterfaceTest.cpp @@ -50,7 +50,7 @@ public: msg += *extra; BOOST_FAIL(msg); } - std::string generatedInterfaceString = m_compilerStack.getInterface(); + std::string generatedInterfaceString = *m_compilerStack.getJsonDocumentation(ABI_INTERFACE); Json::Value generatedInterface; m_reader.parse(generatedInterfaceString, generatedInterface); Json::Value expectedInterface; diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index f729e4ff8..9e24d23ed 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -55,9 +55,9 @@ public: } if (_userDocumentation) - generatedDocumentationString = m_compilerStack.getUserDocumentation(); + generatedDocumentationString = *m_compilerStack.getJsonDocumentation(NATSPEC_USER); else - generatedDocumentationString = m_compilerStack.getDevDocumentation(); + generatedDocumentationString = *m_compilerStack.getJsonDocumentation(NATSPEC_DEV); Json::Value generatedDocumentation; m_reader.parse(generatedDocumentationString, generatedDocumentation); Json::Value expectedDocumentation; From 75d0b8e0b6371d2956308dd2d01aff565f931e0f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 4 Dec 2014 09:42:38 +0100 Subject: [PATCH 07/12] Parsing notice and dev doxytags. - Only initial work done. Still need to refine the logic and incorporate all the other types of tags. - Added/Modified some tests - Work in progress --- solidityNatspecJSON.cpp | 58 +++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 9e24d23ed..d74aa8ab9 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -77,22 +77,59 @@ BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker) BOOST_AUTO_TEST_CASE(user_basic_test) { char const* sourceCode = "contract test {\n" - " /// Multiplies `a` by 7\n" + " /// @notice Multiplies `a` by 7\n" " function mul(uint a) returns(uint d) { return a * 7; }\n" "}\n"; char const* natspec = "{" "\"methods\":{" - " \"mul\":{ \"notice\": \" Multiplies `a` by 7\"}" + " \"mul\":{ \"notice\": \"Multiplies `a` by 7\"}" "}}"; checkNatspec(sourceCode, natspec, true); } +BOOST_AUTO_TEST_CASE(dev_basic_test) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \"details\": \"Multiplies a number by 7\"}" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + +BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) +{ + char const* sourceCode = "contract test {\n" + " /// @notice Multiplies `a` by 7\n" + " /// @dev Multiplies a number by 7\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" + "}\n"; + + char const* devNatspec = "{" + "\"methods\":{" + " \"mul\":{ \"details\": \"Multiplies a number by 7\"}" + "}}"; + + char const* userNatspec = "{" + "\"methods\":{" + " \"mul\":{ \"notice\": \"Multiplies `a` by 7\"}" + "}}"; + + checkNatspec(sourceCode, devNatspec, false); + checkNatspec(sourceCode, userNatspec, true); +} + BOOST_AUTO_TEST_CASE(user_multiline_comment) { char const* sourceCode = "contract test {\n" - " /// Multiplies `a` by 7\n" + " /// @notice Multiplies `a` by 7\n" " /// and then adds `b`\n" " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" " {\n" @@ -102,7 +139,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) char const* natspec = "{" "\"methods\":{" - " \"mul_and_add\":{ \"notice\": \" Multiplies `a` by 7\n and then adds `b`\"}" + " \"mul_and_add\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}" "}}"; checkNatspec(sourceCode, natspec, true); @@ -111,19 +148,18 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) BOOST_AUTO_TEST_CASE(user_multiple_functions) { char const* sourceCode = "contract test {\n" - " /// Multiplies `a` by 7\n" - " /// and then adds `b`\n" + " /// @notice Multiplies `a` by 7 and then adds `b`\n" " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" " {\n" " return (a * 7) + b;\n" " }\n" "\n" - " /// Divides `input` by `div`\n" + " /// @notice Divides `input` by `div`\n" " function divide(uint input, uint div) returns(uint d)\n" " {\n" " return input / div;\n" " }\n" - " /// Subtracts 3 from `input`\n" + " /// @notice Subtracts 3 from `input`\n" " function sub(int input) returns(int d)\n" " {\n" " return input - 3;\n" @@ -132,9 +168,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) char const* natspec = "{" "\"methods\":{" - " \"mul_and_add\":{ \"notice\": \" Multiplies `a` by 7\n and then adds `b`\"}," - " \"divide\":{ \"notice\": \" Divides `input` by `div`\"}," - " \"sub\":{ \"notice\": \" Subtracts 3 from `input`\"}" + " \"mul_and_add\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}," + " \"divide\":{ \"notice\": \"Divides `input` by `div`\"}," + " \"sub\":{ \"notice\": \"Subtracts 3 from `input`\"}" "}}"; checkNatspec(sourceCode, natspec, true); From e3a1ef66e2ad382a5479619f4764f4a7cfda388a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 4 Dec 2014 17:19:47 +0100 Subject: [PATCH 08/12] Natspec parsing @param doctags - Plus additional work on generally parsing doctags. One important missing feature is to parse a tag midline - Adding more tests --- solidityNatspecJSON.cpp | 117 ++++++++++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 16 deletions(-) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index d74aa8ab9..5894f3b04 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -89,21 +89,6 @@ BOOST_AUTO_TEST_CASE(user_basic_test) checkNatspec(sourceCode, natspec, true); } -BOOST_AUTO_TEST_CASE(dev_basic_test) -{ - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; - - char const* natspec = "{" - "\"methods\":{" - " \"mul\":{ \"details\": \"Multiplies a number by 7\"}" - "}}"; - - checkNatspec(sourceCode, natspec, false); -} - BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) { char const* sourceCode = "contract test {\n" @@ -114,7 +99,11 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) char const* devNatspec = "{" "\"methods\":{" - " \"mul\":{ \"details\": \"Multiplies a number by 7\"}" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7\",\n" + " \"params\": {}\n" + " }\n" + " }\n" "}}"; char const* userNatspec = "{" @@ -186,6 +175,102 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) checkNatspec(sourceCode, natspec, true); } +BOOST_AUTO_TEST_CASE(dev_multiple_params) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter\n" + " /// @param second Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " }\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + +BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter starts here.\n" + " /// Since it's a really complicated parameter we need 2 lines\n" + " /// @param second Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " }\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + +BOOST_AUTO_TEST_CASE(dev_multiple_functions) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter\n" + " /// @param second Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + " \n" + " /// @dev Divides 2 numbers\n" + " /// @param input Documentation for the input parameter\n" + " /// @param div Documentation for the div parameter\n" + " function divide(uint input, uint div) returns(uint d)\n" + " {\n" + " return input / div;\n" + " }\n" + " /// @dev Subtracts 3 from `input`\n" + " /// @param input Documentation for the input parameter\n" + " function sub(int input) returns(int d)\n" + " {\n" + " return input - 3;\n" + " }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " }\n" + " },\n" + " \"divide\":{ \n" + " \"details\": \"Divides 2 numbers\",\n" + " \"params\": {\n" + " \"input\": \"Documentation for the input parameter\",\n" + " \"div\": \"Documentation for the div parameter\"\n" + " }\n" + " },\n" + " \"sub\":{ \n" + " \"details\": \"Subtracts 3 from `input`\",\n" + " \"params\": {\n" + " \"input\": \"Documentation for the input parameter\"\n" + " }\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} BOOST_AUTO_TEST_SUITE_END() From b6c8e9e011141ef82c27e9df299e7a9771069133 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 4 Dec 2014 18:12:52 +0100 Subject: [PATCH 09/12] Natspec @return tag parsing - Also omitting tags from the output JSON file if they are missing instead of providing an empty string for their value --- solidityNatspecJSON.cpp | 74 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 5894f3b04..2c4be219b 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -100,8 +100,7 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) char const* devNatspec = "{" "\"methods\":{" " \"mul\":{ \n" - " \"details\": \"Multiplies a number by 7\",\n" - " \"params\": {}\n" + " \"details\": \"Multiplies a number by 7\"\n" " }\n" " }\n" "}}"; @@ -175,6 +174,24 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) checkNatspec(sourceCode, natspec, true); } +BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) +{ + char const* sourceCode = "contract test {\n" + " function mul(uint a) returns(uint d) { return a * 7; }\n" + " function sub(int input) returns(int d)\n" + " {\n" + " return input - 3;\n" + " }\n" + "}\n"; + + char const* devNatspec = "{\"methods\":{}}"; + + char const* userNatspec = "{\"methods\":{}}"; + + checkNatspec(sourceCode, devNatspec, false); + checkNatspec(sourceCode, userNatspec, true); +} + BOOST_AUTO_TEST_CASE(dev_multiple_params) { char const* sourceCode = "contract test {\n" @@ -272,6 +289,59 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) checkNatspec(sourceCode, natspec, false); } +BOOST_AUTO_TEST_CASE(dev_return) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter starts here.\n" + " /// Since it's a really complicated parameter we need 2 lines\n" + " /// @param second Documentation for the second parameter\n" + " /// @return The result of the multiplication\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " },\n" + " \"return\": \"The result of the multiplication\"\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + +BOOST_AUTO_TEST_CASE(dev_multiline_return) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter starts here.\n" + " /// Since it's a really complicated parameter we need 2 lines\n" + " /// @param second Documentation for the second parameter\n" + " /// @return The result of the multiplication\n" + " /// and cookies with nutella\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " },\n" + " \"return\": \"The result of the multiplication and cookies with nutella\"\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + BOOST_AUTO_TEST_SUITE_END() } From 54f353da1002de55541704664ddc764c406979f3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 5 Dec 2014 02:10:54 +0100 Subject: [PATCH 10/12] Using iterators in Natspec comment parsing - Used iterators in the entirety of the InterfaceHandler natspec comment parsing pipeline - Fixed issue where @param continuing in new line would not get a space --- solidityNatspecJSON.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 2c4be219b..f2ae15c96 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) " \"mul\":{ \n" " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" " \"params\": {\n" - " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n" " \"second\": \"Documentation for the second parameter\"\n" " }\n" " }\n" @@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(dev_return) " \"mul\":{ \n" " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" " \"params\": {\n" - " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n" " \"second\": \"Documentation for the second parameter\"\n" " },\n" " \"return\": \"The result of the multiplication\"\n" @@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) " \"mul\":{ \n" " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" " \"params\": {\n" - " \"a\": \"Documentation for the first parameter starts here.Since it's a really complicated parameter we need 2 lines\",\n" + " \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n" " \"second\": \"Documentation for the second parameter\"\n" " },\n" " \"return\": \"The result of the multiplication and cookies with nutella\"\n" From 0c24dc096eac2720288967eb1c7b3c0e078d2bf1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 5 Dec 2014 12:27:18 +0100 Subject: [PATCH 11/12] Newline right after doctag is now a valid natspec entry - Plus tests for that --- solidityNatspecJSON.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index f2ae15c96..9596f2b80 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -192,6 +192,30 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) checkNatspec(sourceCode, userNatspec, true); } +BOOST_AUTO_TEST_CASE(dev_desc_after_nl) +{ + char const* sourceCode = "contract test {\n" + " /// @dev\n" + " /// Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter\n" + " /// @param second Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \" Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " }\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + BOOST_AUTO_TEST_CASE(dev_multiple_params) { char const* sourceCode = "contract test {\n" @@ -314,6 +338,33 @@ BOOST_AUTO_TEST_CASE(dev_return) checkNatspec(sourceCode, natspec, false); } +BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter starts here.\n" + " /// Since it's a really complicated parameter we need 2 lines\n" + " /// @param second Documentation for the second parameter\n" + " /// @return\n" + " /// The result of the multiplication\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + char const* natspec = "{" + "\"methods\":{" + " \"mul\":{ \n" + " \"details\": \"Multiplies a number by 7 and adds second parameter\",\n" + " \"params\": {\n" + " \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n" + " \"second\": \"Documentation for the second parameter\"\n" + " },\n" + " \"return\": \" The result of the multiplication\"\n" + " }\n" + "}}"; + + checkNatspec(sourceCode, natspec, false); +} + BOOST_AUTO_TEST_CASE(dev_multiline_return) { From 80ad71576459f0401d838aa97b62bc40607dbafb Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 5 Dec 2014 12:41:32 +0100 Subject: [PATCH 12/12] Stack compiler now correctly returns a string and not a pointer --- solidityJSONInterfaceTest.cpp | 2 +- solidityNatspecJSON.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/solidityJSONInterfaceTest.cpp b/solidityJSONInterfaceTest.cpp index 8fe0ea653..407f05d03 100644 --- a/solidityJSONInterfaceTest.cpp +++ b/solidityJSONInterfaceTest.cpp @@ -50,7 +50,7 @@ public: msg += *extra; BOOST_FAIL(msg); } - std::string generatedInterfaceString = *m_compilerStack.getJsonDocumentation(ABI_INTERFACE); + std::string generatedInterfaceString = m_compilerStack.getJsonDocumentation(ABI_INTERFACE); Json::Value generatedInterface; m_reader.parse(generatedInterfaceString, generatedInterface); Json::Value expectedInterface; diff --git a/solidityNatspecJSON.cpp b/solidityNatspecJSON.cpp index 9596f2b80..2ccedf7a2 100644 --- a/solidityNatspecJSON.cpp +++ b/solidityNatspecJSON.cpp @@ -55,9 +55,9 @@ public: } if (_userDocumentation) - generatedDocumentationString = *m_compilerStack.getJsonDocumentation(NATSPEC_USER); + generatedDocumentationString = m_compilerStack.getJsonDocumentation(NATSPEC_USER); else - generatedDocumentationString = *m_compilerStack.getJsonDocumentation(NATSPEC_DEV); + generatedDocumentationString = m_compilerStack.getJsonDocumentation(NATSPEC_DEV); Json::Value generatedDocumentation; m_reader.parse(generatedDocumentationString, generatedDocumentation); Json::Value expectedDocumentation;