brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.5 KiB · 676f7df Raw
737 lines · cpp
1//===-- SymbolDocumentationTests.cpp --------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "SymbolDocumentation.h"9 10#include "support/Markup.h"11#include "clang/Basic/CommentOptions.h"12#include "llvm/ADT/StringRef.h"13#include "gtest/gtest.h"14 15namespace clang {16namespace clangd {17 18TEST(SymbolDocumentation, DetailedDocToMarkup) {19 20  CommentOptions CommentOpts;21 22  struct Case {23    llvm::StringRef Documentation;24    llvm::StringRef ExpectedRenderEscapedMarkdown;25    llvm::StringRef ExpectedRenderMarkdown;26    llvm::StringRef ExpectedRenderPlainText;27  } Cases[] = {28      {29          "brief\n\nfoo bar",30          "foo bar",31          "foo bar",32          "foo bar",33      },34      {35          "brief\n\nfoo\nbar\n",36          "foo\nbar",37          "foo\nbar",38          "foo bar",39      },40      {41          "brief\n\nfoo\n\nbar\n",42          "foo\n\nbar",43          "foo\n\nbar",44          "foo\n\nbar",45      },46      {47          "brief\n\nfoo \\p bar baz",48          "foo `bar` baz",49          "foo `bar` baz",50          "foo bar baz",51      },52      {53          "brief\n\nfoo \\e bar baz",54          "foo \\*bar\\* baz",55          "foo *bar* baz",56          "foo *bar* baz",57      },58      {59          "brief\n\nfoo \\b bar baz",60          "foo \\*\\*bar\\*\\* baz",61          "foo **bar** baz",62          "foo **bar** baz",63      },64      {65          "brief\n\nfoo \\ref bar baz",66          "foo \\*\\*\\\\ref\\*\\* `bar` baz",67          "foo **\\ref** `bar` baz",68          "foo **\\ref** bar baz",69      },70      {71          "brief\n\nfoo @ref bar baz",72          "foo \\*\\*@ref\\*\\* `bar` baz",73          "foo **@ref** `bar` baz",74          "foo **@ref** bar baz",75      },76      {77          "\\brief this is a \\n\nbrief description",78          "",79          "",80          "",81      },82      {83          "brief\n\n\\throw exception foo",84          "\\*\\*\\\\throw\\*\\* `exception` foo",85          "**\\throw** `exception` foo",86          "**\\throw** exception foo",87      },88      {89          R"(\brief this is a brief description90 91\li item 192\li item 293\arg item 3)",94          R"(- item 195 96- item 297 98- item 3)",99          R"(- item 1100 101- item 2102 103- item 3)",104          R"(- item 1105 106- item 2107 108- item 3)",109      },110      {111          "brief\n\n\\defgroup mygroup this is a group\nthis is not a group "112          "description",113          "\\*\\*@defgroup\\*\\* `mygroup this is a group`\n\nthis is not a "114          "group "115          "description",116          "**@defgroup** `mygroup this is a group`\n\nthis is not a group "117          "description",118          "**@defgroup** `mygroup this is a group`\n\nthis is not a group "119          "description",120      },121      {122          R"(brief123 124\verbatim125this is a126verbatim block containing127some verbatim text128\endverbatim)",129          R"(\*\*@verbatim\*\*130 131```132this is a133verbatim block containing134some verbatim text135```136 137\*\*@endverbatim\*\*)",138          R"(**@verbatim**139 140```141this is a142verbatim block containing143some verbatim text144```145 146**@endverbatim**)",147          R"(**@verbatim**148 149this is a150verbatim block containing151some verbatim text152 153**@endverbatim**)",154      },155      {156          "brief\n\n@param foo this is a parameter\n@param bar this is another "157          "parameter",158          "",159          "",160          "",161      },162      {163          R"(@brief brief docs164 165@param foo this is a parameter166 167\brief another brief?168 169\details these are details170 171More description172documentation)",173          R"(\*\*\\brief\*\* another brief?174 175these are details176 177More description178documentation)",179          R"(**\brief** another brief?180 181these are details182 183More description184documentation)",185          R"(**\brief** another brief?186 187these are details188 189More description documentation)",190      },191      {192          R"(brief193 194<b>this is a bold text</b>195normal text<i>this is an italic text</i>196<code>this is a code block</code>)",197          R"(\<b>this is a bold text\</b>198normal text\<i>this is an italic text\</i>  199\<code>this is a code block\</code>)",200          R"(\<b>this is a bold text\</b>201normal text\<i>this is an italic text\</i>  202\<code>this is a code block\</code>)",203          "<b>this is a bold text</b> normal text<i>this is an italic text</i> "204          "<code>this is a code block</code>",205      },206      {"brief\n\n@note This is a note",207       R"(\*\*Note:\*\*  208This is a note)",209       R"(**Note:**  210This is a note)",211       R"(**Note:**212This is a note)"},213      {R"(brief214 215Paragraph 1216@note This is a note217 218Paragraph 2)",219       R"(Paragraph 1220 221\*\*Note:\*\*  222This is a note223 224Paragraph 2)",225       R"(Paragraph 1226 227**Note:**  228This is a note229 230Paragraph 2)",231       R"(Paragraph 1232 233**Note:**234This is a note235 236Paragraph 2)"},237      {"brief\n\n@warning This is a warning",238       R"(\*\*Warning:\*\*  239This is a warning)",240       R"(**Warning:**  241This is a warning)",242       R"(**Warning:**243This is a warning)"},244      {R"(brief245 246Paragraph 1247@warning This is a warning248 249Paragraph 2)",250       R"(Paragraph 1251 252\*\*Warning:\*\*  253This is a warning254 255Paragraph 2)",256       R"(Paragraph 1257 258**Warning:**  259This is a warning260 261Paragraph 2)",262       R"(Paragraph 1263 264**Warning:**265This is a warning266 267Paragraph 2)"},268      {R"(@note this is not treated as brief269 270@brief this is the brief271 272Another paragraph)",273       R"(\*\*Note:\*\*  274this is not treated as brief275 276Another paragraph)",277       R"(**Note:**  278this is not treated as brief279 280Another paragraph)",281       R"(**Note:**282this is not treated as brief283 284Another paragraph)"},285      {R"(286@brief Some brief287)",288       "", "", ""},289      {R"(290Some brief291)",292       "", "", ""},293  };294  for (const auto &C : Cases) {295    markup::Document Doc;296    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);297 298    SymbolDoc.detailedDocToMarkup(Doc);299 300    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);301    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);302    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);303  }304}305 306TEST(SymbolDocumentation, RetvalCommand) {307 308  CommentOptions CommentOpts;309 310  struct Case {311    llvm::StringRef Documentation;312    llvm::StringRef ExpectedRenderEscapedMarkdown;313    llvm::StringRef ExpectedRenderMarkdown;314    llvm::StringRef ExpectedRenderPlainText;315  } Cases[] = {316      {"@retval", "", "", ""},317      {R"(@retval MyReturnVal318@retval MyOtherReturnVal)",319       R"(- `MyReturnVal`320- `MyOtherReturnVal`)",321       R"(- `MyReturnVal`322- `MyOtherReturnVal`)",323       R"(- MyReturnVal324- MyOtherReturnVal)"},325      {R"(@retval MyReturnVal if foo326@retval MyOtherReturnVal if bar)",327       R"(- `MyReturnVal` - if foo328- `MyOtherReturnVal` - if bar)",329       R"(- `MyReturnVal` - if foo330- `MyOtherReturnVal` - if bar)",331       R"(- MyReturnVal - if foo332- MyOtherReturnVal - if bar)"},333  };334  for (const auto &C : Cases) {335    markup::Document Doc;336    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);337 338    SymbolDoc.retvalsToMarkup(Doc);339 340    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);341    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);342    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);343  }344}345 346TEST(SymbolDocumentation, DoxygenCodeBlocks) {347  CommentOptions CommentOpts;348 349  struct Case {350    llvm::StringRef Documentation;351    llvm::StringRef ExpectedRenderEscapedMarkdown;352    llvm::StringRef ExpectedRenderMarkdown;353    llvm::StringRef ExpectedRenderPlainText;354  } Cases[] = {355      {R"(@code356int code() { return 0; }357@endcode358@code{.cpp}359int code_lang() { return 0; }360@endcode361@code{.c++}362int code_lang_plus() { return 0; }363@endcode364@code{.py}365class A:366    pass367@endcode368@code{nolang}369class B:370    pass371@endcode)",372       R"(```373int code() { return 0; }374```375 376```cpp377int code_lang() { return 0; }378```379 380```c++381int code_lang_plus() { return 0; }382```383 384```py385class A:386    pass387```388 389```nolang390class B:391    pass392```)",393       R"(```394int code() { return 0; }395```396 397```cpp398int code_lang() { return 0; }399```400 401```c++402int code_lang_plus() { return 0; }403```404 405```py406class A:407    pass408```409 410```nolang411class B:412    pass413```)",414       R"(int code() { return 0; }415 416int code_lang() { return 0; }417 418int code_lang_plus() { return 0; }419 420class A:421    pass422 423class B:424    pass)"},425  };426  for (const auto &C : Cases) {427    markup::Document Doc;428    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);429 430    SymbolDoc.detailedDocToMarkup(Doc);431 432    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);433    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);434    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);435  }436}437 438TEST(SymbolDocumentation, MarkdownCodeBlocks) {439  CommentOptions CommentOpts;440 441  struct Case {442    llvm::StringRef Documentation;443    llvm::StringRef ExpectedRenderEscapedMarkdown;444    llvm::StringRef ExpectedRenderMarkdown;445    llvm::StringRef ExpectedRenderPlainText;446  } Cases[] = {447      {R"(```448int backticks() { return 0; }449```450```cpp451int backticks_lang() { return 0; }452```453```c++454int backticks_lang_plus() { return 0; }455```456~~~457int tilde() { return 0; }458~~~459~~~~~~~~~~~~~~~~~~~~~~~~460int tilde_many() { return 0; }461~~~~~~~~~~~~~~~~~~~~~~~~462~~~~~~~~~~~~~~~~~~~~~~~~{.c++}463int tilde_many_lang() { return 0; }464~~~~~~~~~~~~~~~~~~~~~~~~465```py466class A:467    pass468```469```python470class B:471    pass472```473~~~{.python}474class C:475    pass476~~~477)",478       R"(```479int backticks() { return 0; }480```481 482```cpp483int backticks_lang() { return 0; }484```485 486```c++487int backticks_lang_plus() { return 0; }488```489 490```491int tilde() { return 0; }492```493 494```495int tilde_many() { return 0; }496```497 498```c++499int tilde_many_lang() { return 0; }500```501 502```py503class A:504    pass505```506 507```python508class B:509    pass510```511 512```python513class C:514    pass515```)",516       R"(```517int backticks() { return 0; }518```519 520```cpp521int backticks_lang() { return 0; }522```523 524```c++525int backticks_lang_plus() { return 0; }526```527 528```529int tilde() { return 0; }530```531 532```533int tilde_many() { return 0; }534```535 536```c++537int tilde_many_lang() { return 0; }538```539 540```py541class A:542    pass543```544 545```python546class B:547    pass548```549 550```python551class C:552    pass553```)",554       R"(int backticks() { return 0; }555 556int backticks_lang() { return 0; }557 558int backticks_lang_plus() { return 0; }559 560int tilde() { return 0; }561 562int tilde_many() { return 0; }563 564int tilde_many_lang() { return 0; }565 566class A:567    pass568 569class B:570    pass571 572class C:573    pass)"},574      {R"(```575// this code block is missing end backticks576 577)",578       R"(```579// this code block is missing end backticks580```)",581       R"(```582// this code block is missing end backticks583```)",584       R"(// this code block is missing end backticks)"},585  };586  for (const auto &C : Cases) {587    markup::Document Doc;588    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);589 590    SymbolDoc.detailedDocToMarkup(Doc);591 592    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);593    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);594    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);595  }596}597 598TEST(SymbolDocumentation, MarkdownCodeBlocksSeparation) {599  CommentOptions CommentOpts;600 601  struct Case {602    llvm::StringRef Documentation;603    llvm::StringRef ExpectedRenderEscapedMarkdown;604    llvm::StringRef ExpectedRenderMarkdown;605    llvm::StringRef ExpectedRenderPlainText;606  } Cases[] = {607      {R"(@note Show that code blocks are correctly separated608```609/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.610 611/// With preprocessing, the code block is correctly separated from the @note paragraph.612/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.613int function() { return 0; }614```)",615       R"(\*\*Note:\*\*  616Show that code blocks are correctly separated617 618```619/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.620 621/// With preprocessing, the code block is correctly separated from the @note paragraph.622/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.623int function() { return 0; }624```)",625       R"(**Note:**  626Show that code blocks are correctly separated627 628```629/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.630 631/// With preprocessing, the code block is correctly separated from the @note paragraph.632/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.633int function() { return 0; }634```)",635       R"(**Note:**636Show that code blocks are correctly separated637 638/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.639 640/// With preprocessing, the code block is correctly separated from the @note paragraph.641/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.642int function() { return 0; })"},643      {R"(@note Show that code blocks are correctly separated644~~~~~~~~~645/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.646 647/// With preprocessing, the code block is correctly separated from the @note paragraph.648/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.649int function() { return 0; }650~~~~~~~~~)",651       R"(\*\*Note:\*\*  652Show that code blocks are correctly separated653 654```655/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.656 657/// With preprocessing, the code block is correctly separated from the @note paragraph.658/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.659int function() { return 0; }660```)",661       R"(**Note:**  662Show that code blocks are correctly separated663 664```665/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.666 667/// With preprocessing, the code block is correctly separated from the @note paragraph.668/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.669int function() { return 0; }670```)",671       R"(**Note:**672Show that code blocks are correctly separated673 674/// Without the markdown preprocessing, this line and the line above would be part of the @note paragraph.675 676/// With preprocessing, the code block is correctly separated from the @note paragraph.677/// Also note that without preprocessing, all doxygen commands inside code blocks, like @p would be incorrectly interpreted.678int function() { return 0; })"},679  };680  for (const auto &C : Cases) {681    markup::Document Doc;682    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);683 684    SymbolDoc.detailedDocToMarkup(Doc);685 686    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);687    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);688    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);689  }690}691 692TEST(SymbolDocumentation, MarkdownCodeSpans) {693  CommentOptions CommentOpts;694 695  struct Case {696    llvm::StringRef Documentation;697    llvm::StringRef ExpectedRenderEscapedMarkdown;698    llvm::StringRef ExpectedRenderMarkdown;699    llvm::StringRef ExpectedRenderPlainText;700  } Cases[] = {701      {R"(`this is a code span with @p and \c inside`)",702       R"(\`this is a code span with @p and \\c inside\`)",703       R"(`this is a code span with @p and \c inside`)",704       R"(`this is a code span with @p and \c inside`)"},705      {R"(<escaped> `<not-escaped>`)", R"(\<escaped> \`\<not-escaped>\`)",706       R"(\<escaped> `<not-escaped>`)", R"(<escaped> `<not-escaped>`)"},707      {R"(<escaped> \`<escaped> doxygen commands not parsed @p, \c, @note, \warning \`)",708       R"(\<escaped> \\\`\<escaped> doxygen commands not parsed @p, \\c, @note, \\warning \\\`)",709       R"(\<escaped> \`\<escaped> doxygen commands not parsed @p, \c, @note, \warning \`)",710       R"(<escaped> \`<escaped> doxygen commands not parsed @p, \c, @note, \warning \`)"},711      {R"(`multi712line713\c span`)",714       R"(\`multi715line  716\\c span\`)",717       R"(`multi718line  719\c span`)",720       R"(`multi line721\c span`)"},722  };723  for (const auto &C : Cases) {724    markup::Document Doc;725    SymbolDocCommentVisitor SymbolDoc(C.Documentation, CommentOpts);726 727    SymbolDoc.briefToMarkup(Doc.addParagraph());728 729    EXPECT_EQ(Doc.asPlainText(), C.ExpectedRenderPlainText);730    EXPECT_EQ(Doc.asMarkdown(), C.ExpectedRenderMarkdown);731    EXPECT_EQ(Doc.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);732  }733}734 735} // namespace clangd736} // namespace clang737