Browse Source

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
cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
5fe1133583
  1. 90
      libsolidity/InterfaceHandler.cpp
  2. 8
      libsolidity/InterfaceHandler.h
  3. 58
      test/solidityNatspecJSON.cpp

90
libsolidity/InterfaceHandler.cpp

@ -9,6 +9,7 @@ namespace solidity {
InterfaceHandler::InterfaceHandler() InterfaceHandler::InterfaceHandler()
{ {
m_lastTag = DOCTAG_NONE;
} }
std::unique_ptr<std::string> InterfaceHandler::getDocumentation(std::shared_ptr<ContractDefinition> _contractDef, std::unique_ptr<std::string> InterfaceHandler::getDocumentation(std::shared_ptr<ContractDefinition> _contractDef,
@ -71,7 +72,9 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(std::shared_
auto strPtr = f->getDocumentation(); auto strPtr = f->getDocumentation();
if (strPtr) if (strPtr)
{ {
user["notice"] = Json::Value(*strPtr); m_notice.clear();
parseDocString(*strPtr);
user["notice"] = Json::Value(m_notice);
methods[f->getName()] = user; methods[f->getName()] = user;
} }
} }
@ -94,7 +97,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(std::shared_p
m_dev.clear(); m_dev.clear();
parseDocString(*strPtr); parseDocString(*strPtr);
method["dev"] = Json::Value(m_dev); method["details"] = Json::Value(m_dev);
methods[f->getName()] = method; methods[f->getName()] = method;
} }
} }
@ -106,26 +109,55 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(std::shared_p
/* -- private -- */ /* -- private -- */
size_t InterfaceHandler::parseDocTag(std::string const& _string, std::string const& _tag, size_t _pos) size_t InterfaceHandler::parseDocTag(std::string const& _string, std::string const& _tag, size_t _pos)
{ {
//TODO: This is pretty naive at the moment. e.g. need to check for
// '@' between _pos and \n, remove redundancy e.t.c.
size_t nlPos = _pos; size_t nlPos = _pos;
if (_tag == "dev") if (m_lastTag == DOCTAG_NONE || _tag != "")
{
nlPos = _string.find("\n", _pos);
m_dev += _string.substr(_pos,
nlPos == std::string::npos ?
_string.length() :
nlPos - _pos);
}
else if (_tag == "notice")
{ {
nlPos = _string.find("\n", _pos); if (_tag == "dev")
m_notice += _string.substr(_pos, {
nlPos == std::string::npos ? nlPos = _string.find("\n", _pos);
_string.length() : m_dev += _string.substr(_pos,
nlPos - _pos); nlPos == std::string::npos ?
_string.length() :
nlPos - _pos);
m_lastTag = DOCTAG_DEV;
}
else if (_tag == "notice")
{
nlPos = _string.find("\n", _pos);
m_notice += _string.substr(_pos,
nlPos == std::string::npos ?
_string.length() :
nlPos - _pos);
m_lastTag = DOCTAG_NOTICE;
}
else
{
//TODO: Some form of warning
}
} }
else else
{ {
//TODO: Some form of warning switch(m_lastTag)
{
case DOCTAG_DEV:
nlPos = _string.find("\n", _pos);
m_dev += _string.substr(_pos,
nlPos == std::string::npos ?
_string.length() :
nlPos - _pos);
break;
case DOCTAG_NOTICE:
nlPos = _string.find("\n", _pos);
m_notice += _string.substr(_pos,
nlPos == std::string::npos ?
_string.length() :
nlPos - _pos);
break;
default:
break;
}
} }
return nlPos; return nlPos;
@ -134,16 +166,28 @@ size_t InterfaceHandler::parseDocTag(std::string const& _string, std::string con
void InterfaceHandler::parseDocString(std::string const& _string, size_t _startPos) void InterfaceHandler::parseDocString(std::string const& _string, size_t _startPos)
{ {
size_t pos2; size_t pos2;
size_t newPos = _startPos;
size_t pos1 = _string.find("@", _startPos); size_t pos1 = _string.find("@", _startPos);
if (pos1 == std::string::npos) if (pos1 != std::string::npos)
return; // no doxytags found {
// we found a tag
pos2 = _string.find(" ", pos1);
if (pos2 == std::string::npos)
{
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("End of tag not found"));
return; //no end of tag found
}
pos2 = _string.find(" ", pos1); newPos = parseDocTag(_string, _string.substr(pos1 + 1, pos2 - pos1 - 1), pos2 + 1);
if (pos2 == std::string::npos) }
return; //no end of tag found else
{
newPos = parseDocTag(_string, "", _startPos + 1);
}
size_t newPos = parseDocTag(_string, _string.substr(pos1 + 1, pos2 - pos1), pos2); if (newPos == std::string::npos)
return; // EOS
parseDocString(_string, newPos); parseDocString(_string, newPos);
} }

8
libsolidity/InterfaceHandler.h

@ -37,6 +37,13 @@ namespace solidity {
class ContractDefinition; class ContractDefinition;
enum documentationType: unsigned short; enum documentationType: unsigned short;
enum docTagType
{
DOCTAG_NONE = 0,
DOCTAG_DEV,
DOCTAG_NOTICE,
};
class InterfaceHandler class InterfaceHandler
{ {
public: public:
@ -73,6 +80,7 @@ private:
Json::StyledWriter m_writer; Json::StyledWriter m_writer;
// internal state // internal state
enum docTagType m_lastTag;
std::string m_notice; std::string m_notice;
std::string m_dev; std::string m_dev;
}; };

58
test/solidityNatspecJSON.cpp

@ -77,22 +77,59 @@ BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker)
BOOST_AUTO_TEST_CASE(user_basic_test) BOOST_AUTO_TEST_CASE(user_basic_test)
{ {
char const* sourceCode = "contract test {\n" 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" " function mul(uint a) returns(uint d) { return a * 7; }\n"
"}\n"; "}\n";
char const* natspec = "{" char const* natspec = "{"
"\"methods\":{" "\"methods\":{"
" \"mul\":{ \"notice\": \" Multiplies `a` by 7\"}" " \"mul\":{ \"notice\": \"Multiplies `a` by 7\"}"
"}}"; "}}";
checkNatspec(sourceCode, natspec, true); 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) BOOST_AUTO_TEST_CASE(user_multiline_comment)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" /// Multiplies `a` by 7\n" " /// @notice Multiplies `a` by 7\n"
" /// and then adds `b`\n" " /// and then adds `b`\n"
" function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n"
" {\n" " {\n"
@ -102,7 +139,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment)
char const* natspec = "{" char const* natspec = "{"
"\"methods\":{" "\"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); checkNatspec(sourceCode, natspec, true);
@ -111,19 +148,18 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment)
BOOST_AUTO_TEST_CASE(user_multiple_functions) BOOST_AUTO_TEST_CASE(user_multiple_functions)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" /// Multiplies `a` by 7\n" " /// @notice Multiplies `a` by 7 and then adds `b`\n"
" /// and then adds `b`\n"
" function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n"
" {\n" " {\n"
" return (a * 7) + b;\n" " return (a * 7) + b;\n"
" }\n" " }\n"
"\n" "\n"
" /// Divides `input` by `div`\n" " /// @notice Divides `input` by `div`\n"
" function divide(uint input, uint div) returns(uint d)\n" " function divide(uint input, uint div) returns(uint d)\n"
" {\n" " {\n"
" return input / div;\n" " return input / div;\n"
" }\n" " }\n"
" /// Subtracts 3 from `input`\n" " /// @notice Subtracts 3 from `input`\n"
" function sub(int input) returns(int d)\n" " function sub(int input) returns(int d)\n"
" {\n" " {\n"
" return input - 3;\n" " return input - 3;\n"
@ -132,9 +168,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions)
char const* natspec = "{" char const* natspec = "{"
"\"methods\":{" "\"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`\"},"
" \"divide\":{ \"notice\": \" Divides `input` by `div`\"}," " \"divide\":{ \"notice\": \"Divides `input` by `div`\"},"
" \"sub\":{ \"notice\": \" Subtracts 3 from `input`\"}" " \"sub\":{ \"notice\": \"Subtracts 3 from `input`\"}"
"}}"; "}}";
checkNatspec(sourceCode, natspec, true); checkNatspec(sourceCode, natspec, true);

Loading…
Cancel
Save