diff options
author | Lefteris Karapetsas <lefteris@refu.co> | 2014-12-05 00:19:47 +0800 |
---|---|---|
committer | Lefteris Karapetsas <lefteris@refu.co> | 2014-12-05 00:19:47 +0800 |
commit | 05964375f888e8b8a3ccf5bc01d9cfff8fd00566 (patch) | |
tree | a210bf1abee81bf7193a26414f6e5ae635d03eed /InterfaceHandler.cpp | |
parent | 3e803b40e1b22daf8e3ac45593aec6798d365ccb (diff) | |
download | dexon-solidity-05964375f888e8b8a3ccf5bc01d9cfff8fd00566.tar.gz dexon-solidity-05964375f888e8b8a3ccf5bc01d9cfff8fd00566.tar.zst dexon-solidity-05964375f888e8b8a3ccf5bc01d9cfff8fd00566.zip |
Natspec parsing @param doctags
- Plus additional work on generally parsing doctags.
One important missing feature is to parse a tag midline
- Adding more tests
Diffstat (limited to 'InterfaceHandler.cpp')
-rw-r--r-- | InterfaceHandler.cpp | 158 |
1 files changed, 115 insertions, 43 deletions
diff --git a/InterfaceHandler.cpp b/InterfaceHandler.cpp index e7da5e6d..222711e6 100644 --- a/InterfaceHandler.cpp +++ b/InterfaceHandler.cpp @@ -1,3 +1,4 @@ + #include <libsolidity/InterfaceHandler.h> #include <libsolidity/AST.h> #include <libsolidity/CompilerStack.h> @@ -72,7 +73,7 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(std::shared_ auto strPtr = f->getDocumentation(); if (strPtr) { - m_notice.clear(); + resetUser(); parseDocString(*strPtr); user["notice"] = Json::Value(m_notice); methods[f->getName()] = user; @@ -94,10 +95,16 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(std::shared_p auto strPtr = f->getDocumentation(); if (strPtr) { - m_dev.clear(); + resetDev(); parseDocString(*strPtr); method["details"] = Json::Value(m_dev); + Json::Value params(Json::objectValue); + for (auto const& pair: m_params) + { + params[pair.first] = pair.second; + } + method["params"] = params; methods[f->getName()] = method; } } @@ -107,86 +114,151 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(std::shared_p } /* -- private -- */ +void InterfaceHandler::resetUser() +{ + m_notice.clear(); +} + +void InterfaceHandler::resetDev() +{ + m_dev.clear(); + m_params.clear(); +} + +size_t skipLineOrEOS(std::string const& _string, size_t _nlPos) +{ + return (_nlPos == std::string::npos) ? _string.length() : _nlPos + 1; +} + +size_t InterfaceHandler::parseDocTagLine(std::string const& _string, + std::string& _tagString, + size_t _pos, + enum docTagType _tagType) +{ + size_t nlPos = _string.find("\n", _pos); + _tagString += _string.substr(_pos, + nlPos == std::string::npos ? + _string.length() : + nlPos - _pos); + m_lastTag = _tagType; + return skipLineOrEOS(_string, nlPos); +} + +size_t InterfaceHandler::parseDocTagParam(std::string const& _string, size_t _startPos) +{ + // find param name + size_t currPos = _string.find(" ", _startPos); + if (currPos == std::string::npos) + { + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("End of param name not found")); + return currPos; //no end of tag found + } + + auto paramName = _string.substr(_startPos, currPos - _startPos); + + currPos += 1; + size_t nlPos = _string.find("\n", currPos); + auto paramDesc = _string.substr(currPos, + nlPos == std::string::npos ? + _string.length() : + nlPos - currPos); + + m_params.push_back(std::make_pair(paramName, paramDesc)); + + m_lastTag = DOCTAG_PARAM; + return skipLineOrEOS(_string, nlPos); +} + +size_t InterfaceHandler::appendDocTagParam(std::string const& _string, size_t _startPos) +{ + // Should never be called with an empty vector + assert(!m_params.empty()); + + auto pair = m_params.back(); + size_t nlPos = _string.find("\n", _startPos); + pair.second += _string.substr(_startPos, + nlPos == std::string::npos ? + _string.length() : + nlPos - _startPos); + + m_params.at(m_params.size() - 1) = pair; + + return skipLineOrEOS(_string, nlPos); +} + 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. + //TODO: need to check for @(start of a tag) between here and the end of line + // for all cases size_t nlPos = _pos; if (m_lastTag == DOCTAG_NONE || _tag != "") { if (_tag == "dev") - { - nlPos = _string.find("\n", _pos); - m_dev += _string.substr(_pos, - nlPos == std::string::npos ? - _string.length() : - nlPos - _pos); - m_lastTag = DOCTAG_DEV; - } + nlPos = parseDocTagLine(_string, m_dev, _pos, 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; - } + nlPos = parseDocTagLine(_string, m_notice, _pos, DOCTAG_NOTICE); + else if (_tag == "param") + nlPos = parseDocTagParam(_string, _pos); else { //TODO: Some form of warning } } else + appendDocTag(_string, _pos); + + return nlPos; +} + +size_t InterfaceHandler::appendDocTag(std::string const& _string, size_t _startPos) +{ + size_t newPos = _startPos; + switch(m_lastTag) { - switch(m_lastTag) - { case DOCTAG_DEV: - nlPos = _string.find("\n", _pos); - m_dev += _string.substr(_pos, - nlPos == std::string::npos ? - _string.length() : - nlPos - _pos); + m_dev += " "; + newPos = parseDocTagLine(_string, m_dev, _startPos, DOCTAG_DEV); break; case DOCTAG_NOTICE: - nlPos = _string.find("\n", _pos); - m_notice += _string.substr(_pos, - nlPos == std::string::npos ? - _string.length() : - nlPos - _pos); + m_notice += " "; + newPos = parseDocTagLine(_string, m_notice, _startPos, DOCTAG_NOTICE); + break; + case DOCTAG_PARAM: + newPos = appendDocTagParam(_string, _startPos); break; default: break; } - } - - return nlPos; + return newPos; } void InterfaceHandler::parseDocString(std::string const& _string, size_t _startPos) { size_t pos2; size_t newPos = _startPos; - size_t pos1 = _string.find("@", _startPos); + size_t tagPos = _string.find("@", _startPos); + size_t nlPos = _string.find("\n", _startPos); - if (pos1 != std::string::npos) + if (tagPos != std::string::npos && tagPos < nlPos) { // we found a tag - pos2 = _string.find(" ", pos1); + pos2 = _string.find(" ", tagPos); if (pos2 == std::string::npos) { BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("End of tag not found")); return; //no end of tag found } - newPos = parseDocTag(_string, _string.substr(pos1 + 1, pos2 - pos1 - 1), pos2 + 1); + newPos = parseDocTag(_string, _string.substr(tagPos + 1, pos2 - tagPos - 1), pos2 + 1); } - else + else if (m_lastTag != DOCTAG_NONE) // continuation of the previous tag + newPos = appendDocTag(_string, _startPos + 1); + else // skip the line if a newline was found { - newPos = parseDocTag(_string, "", _startPos + 1); + if (newPos != std::string::npos) + newPos = nlPos + 1; } - - if (newPos == std::string::npos) + if (newPos == std::string::npos || newPos == _string.length()) return; // EOS parseDocString(_string, newPos); } |