mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fixed bug when two empty NatSpec comments led to scanning past EOL
This commit is contained in:
parent
29405c223b
commit
37257548d0
@ -12,6 +12,8 @@ Compiler Features:
|
||||
Bugfixes:
|
||||
* Optimizer: Fixed a bug in BlockDeDuplicator.
|
||||
* Type Checker: Disallow assignments to storage variables of type ``mapping``.
|
||||
* NatSpec: DocString block is terminated when encountering an empty line.
|
||||
* Scanner: Fix bug when two empty NatSpec comments lead to scanning past EOL.
|
||||
|
||||
|
||||
### 0.6.8 (2020-05-14)
|
||||
|
@ -267,10 +267,13 @@ bool Scanner::skipWhitespace()
|
||||
return sourcePos() != startPosition;
|
||||
}
|
||||
|
||||
void Scanner::skipWhitespaceExceptUnicodeLinebreak()
|
||||
bool Scanner::skipWhitespaceExceptUnicodeLinebreak()
|
||||
{
|
||||
int const startPosition = sourcePos();
|
||||
while (isWhiteSpace(m_char) && !isUnicodeLinebreak())
|
||||
advance();
|
||||
// Return whether or not we skipped any characters.
|
||||
return sourcePos() != startPosition;
|
||||
}
|
||||
|
||||
Token Scanner::skipSingleLineComment()
|
||||
@ -321,7 +324,7 @@ int Scanner::scanSingleLineDocComment()
|
||||
{
|
||||
// Check if next line is also a single-line comment.
|
||||
// If any whitespaces were skipped, use source position before.
|
||||
if (!skipWhitespace())
|
||||
if (!skipWhitespaceExceptUnicodeLinebreak())
|
||||
endPosition = m_source->position();
|
||||
|
||||
if (!m_source->isPastEndOfInput(3) &&
|
||||
@ -329,8 +332,10 @@ int Scanner::scanSingleLineDocComment()
|
||||
m_source->get(1) == '/' &&
|
||||
m_source->get(2) == '/')
|
||||
{
|
||||
addCommentLiteralChar('\n');
|
||||
m_char = m_source->advanceAndGet(3);
|
||||
if (atEndOfLine())
|
||||
continue;
|
||||
addCommentLiteralChar('\n');
|
||||
}
|
||||
else
|
||||
break; // next line is not a documentation comment, we are done
|
||||
@ -389,9 +394,11 @@ Token Scanner::scanMultiLineDocComment()
|
||||
}
|
||||
else if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) != '/')
|
||||
{ // skip first '*' in subsequent lines
|
||||
m_char = m_source->advanceAndGet(1);
|
||||
if (atEndOfLine()) // ignores empty lines
|
||||
continue;
|
||||
if (charsAdded)
|
||||
addCommentLiteralChar('\n');
|
||||
m_char = m_source->advanceAndGet(2);
|
||||
addCommentLiteralChar('\n'); // corresponds to the end of previous line
|
||||
}
|
||||
else if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) == '/')
|
||||
{ // if after newline the comment ends, don't insert the newline
|
||||
|
@ -214,7 +214,7 @@ private:
|
||||
/// Skips all whitespace and @returns true if something was skipped.
|
||||
bool skipWhitespace();
|
||||
/// Skips all whitespace that are neither '\r' nor '\n'.
|
||||
void skipWhitespaceExceptUnicodeLinebreak();
|
||||
bool skipWhitespaceExceptUnicodeLinebreak();
|
||||
Token skipSingleLineComment();
|
||||
Token skipMultiLineComment();
|
||||
|
||||
|
@ -78,6 +78,81 @@ private:
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(user_empty_natspec_test)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
///
|
||||
///
|
||||
function f() public {
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
char const* natspec = R"(
|
||||
{
|
||||
"methods": {}
|
||||
}
|
||||
)";
|
||||
|
||||
checkNatspec(sourceCode, "test", natspec, true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(user_newline_break)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
///
|
||||
/// @notice hello
|
||||
|
||||
/// @notice world
|
||||
function f() public {
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
char const* natspec = R"ABCDEF(
|
||||
{
|
||||
"methods": {
|
||||
"f()":
|
||||
{
|
||||
"notice": "world"
|
||||
}
|
||||
}
|
||||
}
|
||||
)ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "test", natspec, true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(user_multiline_empty_lines)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @notice hello world
|
||||
*/
|
||||
function f() public {
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
char const* natspec = R"ABCDEF(
|
||||
{
|
||||
"methods": {
|
||||
"f()": {
|
||||
"notice": "hello world"
|
||||
}
|
||||
}
|
||||
}
|
||||
)ABCDEF";
|
||||
|
||||
checkNatspec(sourceCode, "test", natspec, true);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(user_basic_test)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
@ -361,7 +361,7 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed)
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), " Send $(value / 1000) chocolates to the user");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multiline_documentation_no_stars)
|
||||
@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_whitespace_hell)
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "Send $(value / 1000) chocolates to the user");
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), " Send $(value / 1000) chocolates to the user");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comment_before_eos)
|
||||
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
///
|
||||
///
|
||||
function vote(uint id) public {
|
||||
}
|
||||
}
|
||||
// ----
|
Loading…
Reference in New Issue
Block a user