mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1451 from LefterisJP/fix_build
Accept any kind of whitespace after natspec tags
This commit is contained in:
commit
636e480156
@ -14,6 +14,7 @@ Bugfixes:
|
|||||||
* Code generator: Allow recursive structs.
|
* Code generator: Allow recursive structs.
|
||||||
* Inline assembly: Disallow variables named like opcodes.
|
* Inline assembly: Disallow variables named like opcodes.
|
||||||
* Type checker: Allow multiple events of the same name (but with different arities or argument types)
|
* Type checker: Allow multiple events of the same name (but with different arities or argument types)
|
||||||
|
* Natspec parser: Fix error with ``@param`` parsing and whitespace.
|
||||||
|
|
||||||
### 0.4.8 (2017-01-13)
|
### 0.4.8 (2017-01-13)
|
||||||
|
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
|
|
||||||
#include <libsolidity/parsing/DocStringParser.h>
|
#include <libsolidity/parsing/DocStringParser.h>
|
||||||
#include <boost/range/irange.hpp>
|
|
||||||
#include <libsolidity/interface/Utils.h>
|
#include <libsolidity/interface/Utils.h>
|
||||||
|
|
||||||
|
#include <boost/range/irange.hpp>
|
||||||
|
#include <boost/range/algorithm.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
using namespace dev::solidity;
|
using namespace dev::solidity;
|
||||||
|
|
||||||
|
|
||||||
static inline string::const_iterator skipLineOrEOS(
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
string::const_iterator skipLineOrEOS(
|
||||||
string::const_iterator _nlPos,
|
string::const_iterator _nlPos,
|
||||||
string::const_iterator _end
|
string::const_iterator _end
|
||||||
)
|
)
|
||||||
@ -16,14 +21,34 @@ static inline string::const_iterator skipLineOrEOS(
|
|||||||
return (_nlPos == _end) ? _end : ++_nlPos;
|
return (_nlPos == _end) ? _end : ++_nlPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline string::const_iterator firstSpaceOrNl(
|
string::const_iterator firstSpaceOrTab(
|
||||||
string::const_iterator _pos,
|
string::const_iterator _pos,
|
||||||
string::const_iterator _end
|
string::const_iterator _end
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto spacePos = find(_pos, _end, ' ');
|
return boost::range::find_first_of(make_pair(_pos, _end), " \t");
|
||||||
auto nlPos = find(_pos, _end, '\n');
|
}
|
||||||
return (spacePos < nlPos) ? spacePos : nlPos;
|
|
||||||
|
string::const_iterator firstWhitespaceOrNewline(
|
||||||
|
string::const_iterator _pos,
|
||||||
|
string::const_iterator _end
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boost::range::find_first_of(make_pair(_pos, _end), " \t\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string::const_iterator skipWhitespace(
|
||||||
|
string::const_iterator _pos,
|
||||||
|
string::const_iterator _end
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto currPos = _pos;
|
||||||
|
while (currPos != _end && (*currPos == ' ' || *currPos == '\t'))
|
||||||
|
currPos += 1;
|
||||||
|
return currPos;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocStringParser::parse(string const& _docString, ErrorList& _errors)
|
bool DocStringParser::parse(string const& _docString, ErrorList& _errors)
|
||||||
@ -43,7 +68,7 @@ bool DocStringParser::parse(string const& _docString, ErrorList& _errors)
|
|||||||
if (tagPos != end && tagPos < nlPos)
|
if (tagPos != end && tagPos < nlPos)
|
||||||
{
|
{
|
||||||
// we found a tag
|
// we found a tag
|
||||||
auto tagNameEndPos = firstSpaceOrNl(tagPos, end);
|
auto tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
|
||||||
if (tagNameEndPos == end)
|
if (tagNameEndPos == end)
|
||||||
{
|
{
|
||||||
appendError("End of tag " + string(tagPos, tagNameEndPos) + "not found");
|
appendError("End of tag " + string(tagPos, tagNameEndPos) + "not found");
|
||||||
@ -75,27 +100,40 @@ DocStringParser::iter DocStringParser::parseDocTagLine(iter _pos, iter _end, boo
|
|||||||
{
|
{
|
||||||
solAssert(!!m_lastTag, "");
|
solAssert(!!m_lastTag, "");
|
||||||
auto nlPos = find(_pos, _end, '\n');
|
auto nlPos = find(_pos, _end, '\n');
|
||||||
if (_appending && _pos < _end && *_pos != ' ')
|
if (_appending && _pos < _end && *_pos != ' ' && *_pos != '\t')
|
||||||
m_lastTag->content += " ";
|
m_lastTag->content += " ";
|
||||||
|
else if (!_appending)
|
||||||
|
_pos = skipWhitespace(_pos, _end);
|
||||||
copy(_pos, nlPos, back_inserter(m_lastTag->content));
|
copy(_pos, nlPos, back_inserter(m_lastTag->content));
|
||||||
return skipLineOrEOS(nlPos, _end);
|
return skipLineOrEOS(nlPos, _end);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
||||||
{
|
{
|
||||||
// find param name
|
// find param name start
|
||||||
auto currPos = find(_pos, _end, ' ');
|
auto nameStartPos = skipWhitespace(_pos, _end);
|
||||||
if (currPos == _end)
|
if (nameStartPos == _end)
|
||||||
{
|
{
|
||||||
appendError("End of param name not found" + string(_pos, _end));
|
appendError("No param name given");
|
||||||
|
return _end;
|
||||||
|
}
|
||||||
|
auto nameEndPos = firstSpaceOrTab(nameStartPos, _end);
|
||||||
|
if (nameEndPos == _end)
|
||||||
|
{
|
||||||
|
appendError("End of param name not found: " + string(nameStartPos, _end));
|
||||||
|
return _end;
|
||||||
|
}
|
||||||
|
auto paramName = string(nameStartPos, nameEndPos);
|
||||||
|
|
||||||
|
auto descStartPos = skipWhitespace(nameEndPos, _end);
|
||||||
|
if (descStartPos == _end)
|
||||||
|
{
|
||||||
|
appendError("No description given for param " + paramName);
|
||||||
return _end;
|
return _end;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto paramName = string(_pos, currPos);
|
auto nlPos = find(descStartPos, _end, '\n');
|
||||||
|
auto paramDesc = string(descStartPos, nlPos);
|
||||||
currPos += 1;
|
|
||||||
auto nlPos = find(currPos, _end, '\n');
|
|
||||||
auto paramDesc = string(currPos, nlPos);
|
|
||||||
newTag("param");
|
newTag("param");
|
||||||
m_lastTag->paramName = paramName;
|
m_lastTag->paramName = paramName;
|
||||||
m_lastTag->content = paramDesc;
|
m_lastTag->content = paramDesc;
|
||||||
|
@ -56,7 +56,7 @@ public:
|
|||||||
m_reader.parse(_expectedDocumentationString, expectedDocumentation);
|
m_reader.parse(_expectedDocumentationString, expectedDocumentation);
|
||||||
BOOST_CHECK_MESSAGE(
|
BOOST_CHECK_MESSAGE(
|
||||||
expectedDocumentation == generatedDocumentation,
|
expectedDocumentation == generatedDocumentation,
|
||||||
"Expected " << expectedDocumentation.toStyledString() <<
|
"Expected:\n" << expectedDocumentation.toStyledString() <<
|
||||||
"\n but got:\n" << generatedDocumentation.toStyledString()
|
"\n but got:\n" << generatedDocumentation.toStyledString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
|
|||||||
char const* natspec = "{"
|
char const* natspec = "{"
|
||||||
"\"methods\":{"
|
"\"methods\":{"
|
||||||
" \"mul(uint256,uint256)\":{ \n"
|
" \"mul(uint256,uint256)\":{ \n"
|
||||||
" \"details\": \" Multiplies a number by 7 and adds second parameter\",\n"
|
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
|
||||||
" \"params\": {\n"
|
" \"params\": {\n"
|
||||||
" \"a\": \"Documentation for the first parameter\",\n"
|
" \"a\": \"Documentation for the first parameter\",\n"
|
||||||
" \"second\": \"Documentation for the second parameter\"\n"
|
" \"second\": \"Documentation for the second parameter\"\n"
|
||||||
@ -251,6 +251,29 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params)
|
|||||||
checkNatspec(sourceCode, natspec, false);
|
checkNatspec(sourceCode, natspec, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace)
|
||||||
|
{
|
||||||
|
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(uint256,uint256)\":{ \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)
|
BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -379,7 +402,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
|
|||||||
" \"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"
|
" \"second\": \"Documentation for the second parameter\"\n"
|
||||||
" },\n"
|
" },\n"
|
||||||
" \"return\": \" The result of the multiplication\"\n"
|
" \"return\": \"The result of the multiplication\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}}";
|
"}}";
|
||||||
|
|
||||||
@ -612,6 +635,48 @@ BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param)
|
|||||||
expectNatspecError(sourceCode);
|
expectNatspecError(sourceCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(dev_documenting_no_paramname)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
/// @dev Multiplies a number by 7 and adds second parameter
|
||||||
|
/// @param a Documentation for the first parameter
|
||||||
|
/// @param
|
||||||
|
function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
expectNatspecError(sourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(dev_documenting_no_paramname_end)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
/// @dev Multiplies a number by 7 and adds second parameter
|
||||||
|
/// @param a Documentation for the first parameter
|
||||||
|
/// @param se
|
||||||
|
function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
expectNatspecError(sourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(dev_documenting_no_param_description)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
/// @dev Multiplies a number by 7 and adds second parameter
|
||||||
|
/// @param a Documentation for the first parameter
|
||||||
|
/// @param second
|
||||||
|
function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
expectNatspecError(sourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user