mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Store docstrings in AST annotations.
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
|
||||
#include <libsolidity/parsing/DocStringParser.h>
|
||||
#include <boost/range/irange.hpp>
|
||||
#include <libsolidity/interface/Utils.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
using namespace dev::solidity;
|
||||
|
||||
|
||||
static inline string::const_iterator skipLineOrEOS(
|
||||
string::const_iterator _nlPos,
|
||||
string::const_iterator _end
|
||||
)
|
||||
{
|
||||
return (_nlPos == _end) ? _end : ++_nlPos;
|
||||
}
|
||||
|
||||
static inline string::const_iterator firstSpaceOrNl(
|
||||
string::const_iterator _pos,
|
||||
string::const_iterator _end
|
||||
)
|
||||
{
|
||||
auto spacePos = find(_pos, _end, ' ');
|
||||
auto nlPos = find(_pos, _end, '\n');
|
||||
return (spacePos < nlPos) ? spacePos : nlPos;
|
||||
}
|
||||
|
||||
bool DocStringParser::parse(string const& _docString, ErrorList& _errors)
|
||||
{
|
||||
m_errors = &_errors;
|
||||
m_errorsOccurred = false;
|
||||
m_lastTag = nullptr;
|
||||
|
||||
auto currPos = _docString.begin();
|
||||
auto end = _docString.end();
|
||||
|
||||
while (currPos != end)
|
||||
{
|
||||
auto tagPos = find(currPos, end, '@');
|
||||
auto nlPos = find(currPos, end, '\n');
|
||||
|
||||
if (tagPos != end && tagPos < nlPos)
|
||||
{
|
||||
// we found a tag
|
||||
auto tagNameEndPos = firstSpaceOrNl(tagPos, end);
|
||||
if (tagNameEndPos == end)
|
||||
{
|
||||
appendError("End of tag " + string(tagPos, tagNameEndPos) + "not found");
|
||||
break;
|
||||
}
|
||||
|
||||
currPos = parseDocTag(tagNameEndPos + 1, end, string(tagPos + 1, tagNameEndPos));
|
||||
}
|
||||
else if (!!m_lastTag) // continuation of the previous tag
|
||||
currPos = appendDocTag(currPos, end);
|
||||
else if (currPos != end)
|
||||
{
|
||||
// if it begins without a tag then consider it as @notice
|
||||
if (currPos == _docString.begin())
|
||||
{
|
||||
currPos = parseDocTag(currPos, end, "notice");
|
||||
continue;
|
||||
}
|
||||
else if (nlPos == end) //end of text
|
||||
break;
|
||||
// else skip the line if a newline was found and we get here
|
||||
currPos = nlPos + 1;
|
||||
}
|
||||
}
|
||||
return !m_errorsOccurred;
|
||||
}
|
||||
|
||||
DocStringParser::iter DocStringParser::parseDocTagLine(iter _pos, iter _end, bool _appending)
|
||||
{
|
||||
solAssert(!!m_lastTag, "");
|
||||
auto nlPos = find(_pos, _end, '\n');
|
||||
if (_appending && _pos < _end && *_pos != ' ')
|
||||
m_lastTag->content += " ";
|
||||
copy(_pos, nlPos, back_inserter(m_lastTag->content));
|
||||
return skipLineOrEOS(nlPos, _end);
|
||||
}
|
||||
|
||||
DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
||||
{
|
||||
// find param name
|
||||
auto currPos = find(_pos, _end, ' ');
|
||||
if (currPos == _end)
|
||||
{
|
||||
appendError("End of param name not found" + string(_pos, _end));
|
||||
return _end;
|
||||
}
|
||||
|
||||
auto paramName = string(_pos, currPos);
|
||||
|
||||
currPos += 1;
|
||||
auto nlPos = find(currPos, _end, '\n');
|
||||
auto paramDesc = string(currPos, nlPos);
|
||||
newTag("param");
|
||||
m_lastTag->paramName = paramName;
|
||||
m_lastTag->content = paramDesc;
|
||||
|
||||
return skipLineOrEOS(nlPos, _end);
|
||||
}
|
||||
|
||||
DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string const& _tag)
|
||||
{
|
||||
// LTODO: need to check for @(start of a tag) between here and the end of line
|
||||
// for all cases.
|
||||
if (!m_lastTag || _tag != "")
|
||||
{
|
||||
if (_tag == "param")
|
||||
return parseDocTagParam(_pos, _end);
|
||||
else
|
||||
{
|
||||
newTag(_tag);
|
||||
return parseDocTagLine(_pos, _end, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
return appendDocTag(_pos, _end);
|
||||
}
|
||||
|
||||
DocStringParser::iter DocStringParser::appendDocTag(iter _pos, iter _end)
|
||||
{
|
||||
solAssert(!!m_lastTag, "");
|
||||
return parseDocTagLine(_pos, _end, true);
|
||||
}
|
||||
|
||||
void DocStringParser::newTag(string const& _tagName)
|
||||
{
|
||||
m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second;
|
||||
}
|
||||
|
||||
void DocStringParser::appendError(string const& _description)
|
||||
{
|
||||
auto err = make_shared<Error>(Error::Type::DocstringParsingError);
|
||||
*err << errinfo_comment(_description);
|
||||
m_errors->push_back(err);
|
||||
m_errorsOccurred = true;
|
||||
}
|
||||
Reference in New Issue
Block a user