15
15
#include " Headers.h"
16
16
#include " IncludeCleaner.h"
17
17
#include " ParsedAST.h"
18
+ #include " Protocol.h"
18
19
#include " Selection.h"
19
20
#include " SourceCode.h"
20
21
#include " clang-include-cleaner/Analysis.h"
@@ -960,42 +961,6 @@ std::optional<HoverInfo> getHoverContents(const Attr *A, ParsedAST &AST) {
960
961
return HI;
961
962
}
962
963
963
- bool isParagraphBreak (llvm::StringRef Rest) {
964
- return Rest.ltrim (" \t " ).starts_with (" \n " );
965
- }
966
-
967
- bool punctuationIndicatesLineBreak (llvm::StringRef Line) {
968
- constexpr llvm::StringLiteral Punctuation = R"txt( .:,;!?)txt" ;
969
-
970
- Line = Line.rtrim ();
971
- return !Line.empty () && Punctuation.contains (Line.back ());
972
- }
973
-
974
- bool isHardLineBreakIndicator (llvm::StringRef Rest) {
975
- // '-'/'*' md list, '@'/'\' documentation command, '>' md blockquote,
976
- // '#' headings, '`' code blocks
977
- constexpr llvm::StringLiteral LinebreakIndicators = R"txt( -*@\>#`)txt" ;
978
-
979
- Rest = Rest.ltrim (" \t " );
980
- if (Rest.empty ())
981
- return false ;
982
-
983
- if (LinebreakIndicators.contains (Rest.front ()))
984
- return true ;
985
-
986
- if (llvm::isDigit (Rest.front ())) {
987
- llvm::StringRef AfterDigit = Rest.drop_while (llvm::isDigit);
988
- if (AfterDigit.starts_with (" ." ) || AfterDigit.starts_with (" )" ))
989
- return true ;
990
- }
991
- return false ;
992
- }
993
-
994
- bool isHardLineBreakAfter (llvm::StringRef Line, llvm::StringRef Rest) {
995
- // Should we also consider whether Line is short?
996
- return punctuationIndicatesLineBreak (Line) || isHardLineBreakIndicator (Rest);
997
- }
998
-
999
964
void addLayoutInfo (const NamedDecl &ND, HoverInfo &HI) {
1000
965
if (ND.isInvalidDecl ())
1001
966
return ;
@@ -1570,6 +1535,26 @@ markup::Document HoverInfo::present() const {
1570
1535
return Output;
1571
1536
}
1572
1537
1538
+ std::string HoverInfo::present (MarkupKind Kind) const {
1539
+ if (Kind == MarkupKind::Markdown) {
1540
+ const Config &Cfg = Config::current ();
1541
+ if ((Cfg.Documentation .CommentFormat ==
1542
+ Config::CommentFormatPolicy::Markdown) ||
1543
+ (Cfg.Documentation .CommentFormat ==
1544
+ Config::CommentFormatPolicy::Doxygen))
1545
+ // If the user prefers Markdown, we use the present() method to generate
1546
+ // the Markdown output.
1547
+ return present ().asMarkdown ();
1548
+ if (Cfg.Documentation .CommentFormat ==
1549
+ Config::CommentFormatPolicy::PlainText)
1550
+ // If the user prefers plain text, we use the present() method to generate
1551
+ // the plain text output.
1552
+ return present ().asEscapedMarkdown ();
1553
+ }
1554
+
1555
+ return present ().asPlainText ();
1556
+ }
1557
+
1573
1558
// If the backtick at `Offset` starts a probable quoted range, return the range
1574
1559
// (including the quotes).
1575
1560
std::optional<llvm::StringRef> getBacktickQuoteRange (llvm::StringRef Line,
@@ -1583,9 +1568,14 @@ std::optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
1583
1568
return std::nullopt;
1584
1569
1585
1570
// The quoted string must be nonempty and usually has no leading/trailing ws.
1586
- auto Next = Line.find ( ' ` ' , Offset + 1 );
1571
+ auto Next = Line.find_first_of ( " ` \n " , Offset + 1 );
1587
1572
if (Next == llvm::StringRef::npos)
1588
1573
return std::nullopt;
1574
+
1575
+ // There should be no newline in the quoted string.
1576
+ if (Line[Next] == ' \n ' )
1577
+ return std::nullopt;
1578
+
1589
1579
llvm::StringRef Contents = Line.slice (Offset + 1 , Next);
1590
1580
if (Contents.empty () || isWhitespace (Contents.front ()) ||
1591
1581
isWhitespace (Contents.back ()))
@@ -1600,51 +1590,40 @@ std::optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
1600
1590
return Line.slice (Offset, Next + 1 );
1601
1591
}
1602
1592
1603
- void parseDocumentationLine (llvm::StringRef Line , markup::Paragraph &Out) {
1593
+ void parseDocumentationParagraph (llvm::StringRef Text , markup::Paragraph &Out) {
1604
1594
// Probably this is appendText(Line), but scan for something interesting.
1605
- for (unsigned I = 0 ; I < Line .size (); ++I) {
1606
- switch (Line [I]) {
1595
+ for (unsigned I = 0 ; I < Text .size (); ++I) {
1596
+ switch (Text [I]) {
1607
1597
case ' `' :
1608
- if (auto Range = getBacktickQuoteRange (Line , I)) {
1609
- Out.appendText (Line .substr (0 , I));
1598
+ if (auto Range = getBacktickQuoteRange (Text , I)) {
1599
+ Out.appendText (Text .substr (0 , I));
1610
1600
Out.appendCode (Range->trim (" `" ), /* Preserve=*/ true );
1611
- return parseDocumentationLine (Line .substr (I + Range->size ()), Out);
1601
+ return parseDocumentationParagraph (Text .substr (I + Range->size ()), Out);
1612
1602
}
1613
1603
break ;
1614
1604
}
1615
1605
}
1616
- Out.appendText (Line). appendSpace ( );
1606
+ Out.appendText (Text );
1617
1607
}
1618
1608
1619
1609
void parseDocumentation (llvm::StringRef Input, markup::Document &Output) {
1620
- std::vector<llvm::StringRef> ParagraphLines;
1621
- auto FlushParagraph = [&] {
1622
- if (ParagraphLines.empty ())
1623
- return ;
1624
- auto &P = Output.addParagraph ();
1625
- for (llvm::StringRef Line : ParagraphLines)
1626
- parseDocumentationLine (Line, P);
1627
- ParagraphLines.clear ();
1628
- };
1629
-
1630
- llvm::StringRef Line, Rest;
1631
- for (std::tie (Line, Rest) = Input.split (' \n ' );
1632
- !(Line.empty () && Rest.empty ());
1633
- std::tie (Line, Rest) = Rest.split (' \n ' )) {
1634
-
1635
- // After a linebreak remove spaces to avoid 4 space markdown code blocks.
1636
- // FIXME: make FlushParagraph handle this.
1637
- Line = Line.ltrim ();
1638
- if (!Line.empty ())
1639
- ParagraphLines.push_back (Line);
1640
-
1641
- if (isParagraphBreak (Rest) || isHardLineBreakAfter (Line, Rest)) {
1642
- FlushParagraph ();
1643
- }
1610
+ // A documentation string is treated as a sequence of paragraphs,
1611
+ // where the paragraphs are seperated by at least one empty line
1612
+ // (meaning 2 consecutive newline characters).
1613
+ // Possible leading empty lines (introduced by an odd number > 1 of
1614
+ // empty lines between 2 paragraphs) will be removed later in the Markup
1615
+ // renderer.
1616
+ llvm::StringRef Paragraph, Rest;
1617
+ for (std::tie (Paragraph, Rest) = Input.split (" \n\n " );
1618
+ !(Paragraph.empty () && Rest.empty ());
1619
+ std::tie (Paragraph, Rest) = Rest.split (" \n\n " )) {
1620
+
1621
+ // The Paragraph will be empty if there is an even number of newline
1622
+ // characters between two paragraphs, so we skip it.
1623
+ if (!Paragraph.empty ())
1624
+ parseDocumentationParagraph (Paragraph, Output.addParagraph ());
1644
1625
}
1645
- FlushParagraph ();
1646
1626
}
1647
-
1648
1627
llvm::raw_ostream &operator <<(llvm::raw_ostream &OS,
1649
1628
const HoverInfo::PrintedType &T) {
1650
1629
OS << T.Type ;
0 commit comments