diff --git a/src/lib/AST/ParseJavadoc.cpp b/src/lib/AST/ParseJavadoc.cpp index 637b4fb4aa..751563c75c 100644 --- a/src/lib/AST/ParseJavadoc.cpp +++ b/src/lib/AST/ParseJavadoc.cpp @@ -988,7 +988,6 @@ visitInlineCommandComment( { MRDOCS_CHECK_OR(goodArgCount(1, *C)); std::string ref = C->getArgText(0).str(); - std::string originalRef = ref; std::string leftOver = fixReference(ref); bool const hasExtra = !leftOver.empty(); emplaceText( @@ -1140,24 +1139,131 @@ fixReference(std::string& ref) // a function, and we need to merge the next text comments // until we find a balanced ')'. bool const isFunction = contains(ref, '('); - while (std::ranges::count(ref, '(') != std::ranges::count(ref, ')')) + if (isFunction) { - ++it_; - if (it_ == end_) - { - break; - } - Comment const* c = *it_; - if (c->getCommentKind() == CommentKind::TextComment) + while (std::ranges::count(ref, '(') != std::ranges::count(ref, ')')) { - ref += static_cast(c)->getText(); + ++it_; + if (it_ == end_) + { + break; + } + Comment const* c = *it_; + if (c->getCommentKind() == CommentKind::TextComment) + { + ref += static_cast(c)->getText(); + } + else + { + break; + } } - else + if (rtrim(ref).ends_with(')')) { - break; + static constexpr std::array qualifiers = { + "const", + "volatile", + "noexcept", + "&&", + "&", + }; + auto isQualifiersOnly = [](std::string_view str) + { + // Iterate all words between spaces and check if + // they are qualifiers + std::size_t pos = 0; + while (pos < str.size()) + { + std::size_t const start = str.find_first_not_of(' ', pos); + if (start == std::string::npos) + { + break; + } + std::size_t const end = str.find_first_of(' ', start); + std::string_view word = str.substr(start, end - start); + if (std::ranges::find(qualifiers, word) == qualifiers.end()) + { + return false; + } + pos = end; + } + return true; + }; + auto isWhitespaceOnly = [](std::string_view str) + { + return str.empty() || str.find_first_not_of(' ') == std::string::npos; + }; + + // peek next comment + std::string functionContinuation; + auto originalIt = it_; + ++it_; + while ( + it_ != end_ && + (isWhitespaceOnly(functionContinuation) || + isQualifiersOnly(functionContinuation))) + { + Comment const* c = *it_; + if (c->getCommentKind() != CommentKind::TextComment) + { + break; + } + functionContinuation += static_cast(c)->getText(); + ++it_; + } + if (isWhitespaceOnly(functionContinuation)) + { + it_ = originalIt; + } + else /* if (!functionContinuation.empty()) */ + { + --it_; + std::string_view suffix = functionContinuation; + std::string_view leftover = functionContinuation; + bool foundAny = false; + std::size_t totalRemoved = 0; + while (!suffix.empty()) + { + bool found = false; + std::size_t const initialWhitespace = std::min( + suffix.find_first_not_of(" "), suffix.size()); + for (auto const& q : qualifiers) + { + if (suffix.substr(initialWhitespace).starts_with(q)) + { + std::size_t const toRemove = initialWhitespace + q.size(); + if ( + contains(idChars, q.back()) && + suffix.size() > toRemove && + contains(idChars, suffix[toRemove])) + { + // This is not a qualifier, but part of + // an identifier + continue; + } + suffix.remove_prefix(toRemove); + totalRemoved += toRemove; + found = true; + foundAny = true; + break; + } + } + if (!found) + { + break; + } + } + if (foundAny) + { + leftover = leftover.substr(0, totalRemoved); + ref += leftover; + return std::string(suffix); + } + } } } + // Clang refs can also contain invalid characters // at the end, especially punctuation. We need to // truncate the ref at the last valid identifier diff --git a/test-files/golden-tests/javadoc/copydoc/qualifiers.adoc b/test-files/golden-tests/javadoc/copydoc/qualifiers.adoc new file mode 100644 index 0000000000..d082d0ce10 --- /dev/null +++ b/test-files/golden-tests/javadoc/copydoc/qualifiers.adoc @@ -0,0 +1,423 @@ += Reference +:mrdocs: + +[#index] +== Global namespace + + +=== Types + +[cols=1] +|=== +| Name + +| <> + +|=== + +[#A] +== A + + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct A; +---- + +=== Types + +[cols=1] +|=== +| Name + +| <> + +| <> + +|=== +=== Member Functions + +[cols=2] +|=== +| Name +| Description + +| <> +| `begin` overloads + +| <> +| Return a const iterator to the beginning + +| <> +| An const rvalue reference to A + +| <> +| `ref` overloads + +| <> +| An rvalue reference to A + +|=== + + + +[#A-const_iterator] +== <>::const_iterator + + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +class const_iterator; +---- + + + + +[#A-iterator] +== <>::iterator + + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +class iterator; +---- + + + + +[#A-begin-05] +== <>::begin + + +`begin` overloads + +=== Synopses + + +Declared in `<qualifiers.cpp>` + +Returns an iterator to the beginning + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> +<>(); +---- + +[.small]#<># + +Return a const iterator to the beginning + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> +<>() const; +---- + +[.small]#<># + +=== Return Value + + +* Iterator to the first element. +* Const iterator to the first element. + +[#A-begin-06] +== <>::begin + + +Returns an iterator to the beginning + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> +begin(); +---- + +=== Description + + +Returns an iterator to the first element of the vector. + + + +=== Return Value + + +Iterator to the first element. + +[#A-begin-0c] +== <>::begin + + +Return a const iterator to the beginning + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> +begin() const; +---- + +=== Description + + +Returns a const iterator to the first element of the vector. + + + +=== Return Value + + +Const iterator to the first element. + +[#A-cbegin] +== <>::cbegin + + +Return a const iterator to the beginning + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> +cbegin() const; +---- + +=== Description + + +Returns a const iterator to the first element of the vector. + + + +=== Return Value + + +Const iterator to the first element. + +[#A-crvalue] +== <>::crvalue + + +An const rvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>&& +crvalue() const &&; +---- + +=== Return Value + + +A reference to A + +[#A-ref-0f] +== <>::ref + + +`ref` overloads + +=== Synopses + + +Declared in `<qualifiers.cpp>` + +An lvalue reference to A + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>& +<>() &; +---- + +[.small]#<># + +An rvalue reference to A + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>&& +<>() &&; +---- + +[.small]#<># + +An const lvalue reference to A + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> const& +<>() const &; +---- + +[.small]#<># + +An const rvalue reference to A + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> const&& +<>() const &&; +---- + +[.small]#<># + +=== Return Value + + +A reference to A + +[#A-ref-05] +== <>::ref + + +An lvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>& +ref() &; +---- + +=== Return Value + + +A reference to A + +[#A-ref-0e] +== <>::ref + + +An rvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>&& +ref() &&; +---- + +=== Return Value + + +A reference to A + +[#A-ref-04] +== <>::ref + + +An const lvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> const& +ref() const &; +---- + +=== Return Value + + +A reference to A + +[#A-ref-07] +== <>::ref + + +An const rvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<> const&& +ref() const &&; +---- + +=== Return Value + + +A reference to A + +[#A-rvalue] +== <>::rvalue + + +An rvalue reference to A + +=== Synopsis + + +Declared in `<qualifiers.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>&& +rvalue() &&; +---- + +=== Return Value + + +A reference to A + + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/test-files/golden-tests/javadoc/copydoc/qualifiers.cpp b/test-files/golden-tests/javadoc/copydoc/qualifiers.cpp new file mode 100644 index 0000000000..cc76a66544 --- /dev/null +++ b/test-files/golden-tests/javadoc/copydoc/qualifiers.cpp @@ -0,0 +1,58 @@ +struct A { + class iterator; + class const_iterator; + + /** Returns an iterator to the beginning + + Returns an iterator to the first element + of the vector. + + @return Iterator to the first element. + */ + iterator begin(); + + /** Return a const iterator to the beginning + + Returns a const iterator to the first element + of the vector. + + @return Const iterator to the first element. + */ + const_iterator begin() const; + + /** @copydoc begin() const + */ + const_iterator cbegin() const; + + /** An lvalue reference to A + + @return A reference to A + */ + A& ref() &; + + /** An rvalue reference to A + + @return A reference to A + */ + A&& ref() &&; + + /** An const lvalue reference to A + + @return A reference to A + */ + A const& ref() const &; + + /** An const rvalue reference to A + + @return A reference to A + */ + A const&& ref() const &&; + + /** @copydoc ref() && + */ + A&& rvalue() &&; + + /** @copydoc ref() const && + */ + A&& crvalue() const &&; +}; \ No newline at end of file diff --git a/test-files/golden-tests/javadoc/copydoc/qualifiers.html b/test-files/golden-tests/javadoc/copydoc/qualifiers.html new file mode 100644 index 0000000000..9a4d32330a --- /dev/null +++ b/test-files/golden-tests/javadoc/copydoc/qualifiers.html @@ -0,0 +1,501 @@ + + +Reference + + +
+

Reference

+
+
+

Global namespace

+
+

Types

+ + + + + + + + + + + +
Name
A
+
+
+
+

A

+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+struct A;
+
+
+
+

Types

+ + + + + + + + + + + + + +
Name
const_iterator
iterator
+

Member Functions

+ + + + + + + + + + + + + + + + + + + + +
NameDescription
begin begin overloads +
cbegin Return a const iterator to the beginning +
crvalue An const rvalue reference to A +
ref ref overloads +
rvalue An rvalue reference to A +
+ + +
+
+
+

A::const_iterator

+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+class const_iterator;
+
+
+
+ + +
+
+
+

A::iterator

+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+class iterator;
+
+
+
+ + +
+
+
+

A::begin

+
+begin overloads + + +
+
+
+

Synopses

+
+Declared in <qualifiers.cpp>
+

+ Returns an iterator to the beginning + +

+ + +
+
+iterator
+begin();
+
+
» more... + +

+ Return a const iterator to the beginning + +

+ + +
+
+const_iterator
+begin() const;
+
+
» more... + + +
+
+

Return Value

+
    +
  • Iterator to the first element.

    +
  • +
  • Const iterator to the first element.

    +
  • +
+
+
+
+
+

A::begin

+
+Returns an iterator to the beginning + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+iterator
+begin();
+
+
+
+
+

Description

+

Returns an iterator to the first element of the vector.

+ + +
+
+

Return Value

+

Iterator to the first element.

+ +
+
+
+
+

A::begin

+
+Return a const iterator to the beginning + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+const_iterator
+begin() const;
+
+
+
+
+

Description

+

Returns a const iterator to the first element of the vector.

+ + +
+
+

Return Value

+

Const iterator to the first element.

+ +
+
+
+
+

A::cbegin

+
+Return a const iterator to the beginning + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+const_iterator
+cbegin() const;
+
+
+
+
+

Description

+

Returns a const iterator to the first element of the vector.

+ + +
+
+

Return Value

+

Const iterator to the first element.

+ +
+
+
+
+

A::crvalue

+
+An const rvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A&&
+crvalue() const &&;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::ref

+
+ref overloads + + +
+
+
+

Synopses

+
+Declared in <qualifiers.cpp>
+

+ An lvalue reference to A + +

+ + +
+
+A&
+ref() &;
+
+
» more... + +

+ An rvalue reference to A + +

+ + +
+
+A&&
+ref() &&;
+
+
» more... + +

+ An const lvalue reference to A + +

+ + +
+
+A const&
+ref() const &;
+
+
» more... + +

+ An const rvalue reference to A + +

+ + +
+
+A const&&
+ref() const &&;
+
+
» more... + + +
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::ref

+
+An lvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A&
+ref() &;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::ref

+
+An rvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A&&
+ref() &&;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::ref

+
+An const lvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A const&
+ref() const &;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::ref

+
+An const rvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A const&&
+ref() const &&;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+
+
+

A::rvalue

+
+An rvalue reference to A + + +
+
+
+

Synopsis

+
+Declared in <qualifiers.cpp>
+
+
+A&&
+rvalue() &&;
+
+
+
+
+

Return Value

+

A reference to A

+ +
+
+ +
+
+

Created with MrDocs

+
+ + \ No newline at end of file diff --git a/test-files/golden-tests/javadoc/copydoc/qualifiers.xml b/test-files/golden-tests/javadoc/copydoc/qualifiers.xml new file mode 100644 index 0000000000..c7d71b32b0 --- /dev/null +++ b/test-files/golden-tests/javadoc/copydoc/qualifiers.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + Returns an iterator to the beginning + + + Returns an iterator to the first element of the vector. + + + Iterator to the first element. + + + + + + + + + + + + Return a const iterator to the beginning + + + Returns a const iterator to the first element of the vector. + + + Const iterator to the first element. + + + + + + + + + + + + Return a const iterator to the beginning + + + Returns a const iterator to the first element of the vector. + + + Const iterator to the first element. + + + + + + + + + + + + + + + An const rvalue reference to A + + + A reference to A + + + + + + + + + + + + + + An lvalue reference to A + + + A reference to A + + + + + + + + + + + + + + An rvalue reference to A + + + A reference to A + + + + + + + + + + + + + + + An const lvalue reference to A + + + A reference to A + + + + + + + + + + + + + + + An const rvalue reference to A + + + A reference to A + + + + + + + + + + + + + + An rvalue reference to A + + + A reference to A + + + + + +