File indexing completed on 2024-05-19 04:39:58

0001 /*
0002     SPDX-FileCopyrightText: 2019 Bernd Buschinski <b.buschinski@gmail.com>
0003     SPDX-FileCopyrightText: 2023 Igor Kushnir <igorkuo@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "test_formattinghelpers.h"
0009 
0010 #include "formattinghelpers.h"
0011 
0012 #include <QString>
0013 #include <QTest>
0014 #include <QStandardPaths>
0015 
0016 QTEST_MAIN(TestFormattingHelpers)
0017 
0018 using namespace KDevelop;
0019 
0020 void TestFormattingHelpers::initTestCase()
0021 {
0022     QStandardPaths::setTestModeEnabled(true);
0023 }
0024 
0025 void TestFormattingHelpers::testFuzzyMatching()
0026 {
0027     QFETCH(QString, formattedMergedText);
0028     QFETCH(QString, selectedText);
0029     QFETCH(QString, leftContext);
0030     QFETCH(QString, rightContext);
0031     QFETCH(QString, expectedOutput);
0032 
0033     QString output = extractFormattedTextFromContext(formattedMergedText, selectedText, leftContext, rightContext);
0034 
0035     QCOMPARE(output, expectedOutput);
0036 }
0037 
0038 void TestFormattingHelpers::testFuzzyMatching_data()
0039 {
0040     QTest::addColumn<QString>("formattedMergedText");
0041     QTest::addColumn<QString>("selectedText");
0042     QTest::addColumn<QString>("leftContext");
0043     QTest::addColumn<QString>("rightContext");
0044     QTest::addColumn<QString>("expectedOutput");
0045 
0046     QString selectedText = QStringLiteral("void bar() {\nint x;\n}");
0047     QString expectedOutput = QStringLiteral("void bar() {\n    int x;\n}");
0048 
0049     QTest::newRow("left-indentation-fixed")
0050         << QStringLiteral("void foo() {\n    int i;\n    int j;\n}\n\nvoid bar() {\n    int x;\n}")
0051         << selectedText
0052         << QStringLiteral("void foo() {\nint i;\n\n\nint j;\n}\n\n")
0053         << QStringLiteral("")
0054         << expectedOutput;
0055 
0056     QTest::newRow("right-indentation-fixed")
0057         << QStringLiteral("void bar() {\n    int x;\n}\n\nvoid foo() {\n    int i;\n    int j;\n}")
0058         << selectedText
0059         << QStringLiteral("")
0060         << QStringLiteral("\n\nvoid foo() {\nint i;\n\n\nint j;\n}")
0061         << expectedOutput;
0062 
0063     // clang-format can break long comments into multiple lines, adding new "//".
0064     // For the sake of readability, the comments in the test are actually not very long.
0065     QTest::newRow("left-comment-break-fixed")
0066         << QStringLiteral("void foo() {\n    // very\n    // long\n}\n\nvoid bar() {\n    int x;\n}")
0067         << selectedText
0068         << QStringLiteral("void foo() {\n// very long\n}\n\n")
0069         << QStringLiteral("")
0070         << expectedOutput;
0071 
0072     QTest::newRow("right-comment-break-fixed")
0073         << QStringLiteral("void bar() {\n    int x;\n}\n\nvoid foo() {\n    // very\n    // long\n}")
0074         << selectedText
0075         << QStringLiteral("")
0076         << QStringLiteral("\n\nvoid foo() {\n// very long\n}")
0077         << expectedOutput;
0078 
0079     QTest::newRow("left-multilinecomment-break-fixed")
0080         << QStringLiteral("void foo() {\n    /* very\n    * long */\n}\n\nvoid bar() {\n    int x;\n}")
0081         << selectedText
0082         << QStringLiteral("void foo() {\n/* very long */\n}\n\n")
0083         << QStringLiteral("")
0084         << expectedOutput;
0085 
0086     QTest::newRow("right-multilinecomment-break-fixed")
0087         << QStringLiteral("void bar() {\n    int x;\n}\n\nvoid foo() {\n    /* very\n    * long */\n}")
0088         << selectedText
0089         << QStringLiteral("")
0090         << QStringLiteral("\n\nvoid foo() {\n/* very long */\n}")
0091         << expectedOutput;
0092 
0093     // clang-format can break long macros and add (or remove) "\"
0094     QTest::newRow("left-macro-break-removed")
0095         << QStringLiteral("#define foo(a,b) a = b\n\nvoid bar() {\n    int x;\n}")
0096         << selectedText
0097         << QStringLiteral("#define foo(a,b) \\    a = b\n\n")
0098         << QStringLiteral("")
0099         << expectedOutput;
0100 
0101     QTest::newRow("right-macro-break-removed")
0102         << QStringLiteral("void bar() {\n    int x;\n}\n\n#define foo(a,b) a = b")
0103         << selectedText
0104         << QStringLiteral("")
0105         << QStringLiteral("\n\n#define foo(a,b) \\    a = b")
0106         << expectedOutput;
0107 
0108     QTest::newRow("left-macro-break-added")
0109         << QStringLiteral("#define foo(a,b) \\ a = b\n\nvoid bar() {\n    int x;\n}")
0110         << selectedText
0111         << QStringLiteral("#define foo(a,b) a = b\n\n")
0112         << QStringLiteral("")
0113         << expectedOutput;
0114 
0115     QTest::newRow("right-macro-break-added")
0116         << QStringLiteral("void bar() {\n    int x;\n}\n\n#define foo(a,b) \\ a = b")
0117         << selectedText
0118         << QStringLiteral("")
0119         << QStringLiteral("\n\n#define foo(a,b) a = b")
0120         << expectedOutput;
0121 
0122     // clang-format can break long strings into multiple small strings, adding new quotation mark.
0123     // For the sake of readability, the strings in the test are actually not very long.
0124     QTest::newRow("left-string-break-fixed")
0125         << QStringLiteral("void foo() {\n    string a = \"very \"\n    \"long\";\n}\n\nvoid bar() {\n    int x;\n}")
0126         << selectedText
0127         << QStringLiteral("void foo() {\nstring a = \"very long\";\n}\n\n")
0128         << QStringLiteral("")
0129         << expectedOutput;
0130 
0131     QTest::newRow("right-string-break-fixed")
0132         << QStringLiteral("void bar() {\n    int x;\n}\n\nvoid foo() {\n    string a = \"very \"\n    \"long\";\n}")
0133         << selectedText
0134         << QStringLiteral("")
0135         << QStringLiteral("\n\nvoid foo() {\nstring a = \"very long\";\n}")
0136         << expectedOutput;
0137 
0138     QString formattedMergedText;
0139     QString leftContext;
0140     QString rightContext;
0141     const auto addNewRow = [&](const char* dataTag) {
0142         QTest::newRow(dataTag) << formattedMergedText << selectedText << leftContext << rightContext << expectedOutput;
0143     };
0144 
0145     // The following 3 test data rows contain adapted code samples from https://bugs.kde.org/show_bug.cgi?id=365437
0146     // In all these tests an inserted brace is at the left-context-text boundary. extractFormattedTextFromContext()
0147     // gives up formatting, prints a warning and returns selectedText. Ideally it would figure out that the brace
0148     // belongs to the left context and return formatted selectedText (without the redundant brace complained about in
0149     // the bug report of course). But this ideal requires non-trivial implementation and could even worsen a good enough
0150     // existing formatting, because whitespace at context-text boundaries depends on whether braces are present.
0151 
0152     leftContext = R"(
0153     if (param) {
0154         if (string.isEmpty())
0155             )";
0156     selectedText = "stat";
0157     rightContext = R"( = true;
0158         else
0159             stat = false;
0160     }
0161 )";
0162     formattedMergedText = R"(
0163     if ( param ) {
0164         if ( string.isEmpty() ) {
0165             stat = true;
0166         } else {
0167             stat = false;
0168         }
0169     }
0170 )";
0171     expectedOutput = selectedText;
0172     addNewRow("insert-braces-around-renamed-variable");
0173 
0174     leftContext = R"(
0175     if (condition)
0176         value = 5;
0177     else
0178         value = -1;
0179     )";
0180     selectedText = "global_renamed_member";
0181     rightContext = " += value;";
0182     formattedMergedText = R"(
0183     if ( condition ) {
0184         value = 5;
0185     } else {
0186         value = -1;
0187     }
0188     global_renamed_member += value;)";
0189     expectedOutput = selectedText;
0190     addNewRow("insert-braces-before-renamed-variable");
0191 
0192     leftContext = R"(
0193             if (condition2) {
0194                 if (! condition3)
0195                     one_line_of_code;
0196 
0197 //              one_line_of_code;
0198             }
0199             else {
0200                 if (condition4)
0201                     one_line_of_code;
0202             })";
0203     selectedText = R"(
0204             some_more_code;)";
0205     rightContext = QString();
0206     formattedMergedText = R"(
0207     if ( condition2 ) {
0208         if ( ! condition3 ) {
0209             one_line_of_code;
0210         }
0211 
0212 //              one_line_of_code;
0213     } else {
0214         if ( condition4 ) {
0215             one_line_of_code;
0216         }
0217     }
0218     some_more_code;)";
0219     expectedOutput = selectedText;
0220     addNewRow("insert-braces-before-final-closing-brace-in-left-context");
0221 
0222     leftContext = R"(
0223     if (x)
0224     {
0225         ++z;
0226     }
0227     )";
0228     selectedText = "//comment";
0229     rightContext = "\n";
0230     formattedMergedText = R"(
0231     if (x)
0232         ++z;
0233     // comment
0234 )";
0235     expectedOutput = "// comment";
0236     addNewRow("remove-braces-in-prefix-before-comment-in-text");
0237 
0238     for (auto* str : {&selectedText, &formattedMergedText, &expectedOutput}) {
0239         str->replace("comment", "}");
0240     }
0241     addNewRow("remove-braces-in-prefix-before-commented-out-closing-brace-in-text");
0242 
0243     leftContext = R"(
0244     if (x)
0245     {)";
0246     selectedText = R"(
0247         //c
0248         ;)";
0249     rightContext = "\n}";
0250     formattedMergedText = R"(
0251     if (x)
0252         // c
0253         ;)";
0254     expectedOutput = R"(
0255         // c
0256         ;)";
0257     addNewRow("remove-braces-around-comment-text");
0258 
0259     for (auto* str : {&selectedText, &formattedMergedText, &expectedOutput}) {
0260         str->replace('c', '}');
0261     }
0262     addNewRow("remove-braces-around-commented-out-closing-brace-text");
0263 
0264     for (auto* str : {&selectedText, &formattedMergedText, &expectedOutput}) {
0265         str->replace('}', '{');
0266     }
0267     addNewRow("remove-braces-around-commented-out-opening-brace-text");
0268 
0269     leftContext = "    \"A very very looooooooooooooong";
0270     selectedText = " string this is. Even ";
0271     rightContext = "longer now.\"\n";
0272     formattedMergedText = "    \"A very very looooooooooooooong string this is. \"\n    \"Even longer now.\"\n";
0273     expectedOutput = " string this is. \"\n    \"Even ";
0274     addNewRow("insert-double-quotes-within-text");
0275 
0276     formattedMergedText = "    \"A very very \"\n    \"looooooooooooooong string this is. Even longer now.\"\n";
0277     expectedOutput = selectedText;
0278     addNewRow("insert-double-quotes-in-left-context");
0279 
0280     formattedMergedText = "    \"A very very looooooooooooooong string this is. Even longer\"\n    \" now.\"\n";
0281     addNewRow("insert-double-quotes-in-right-context");
0282 
0283     // In the following 5 test data rows, an inserted pair of double quotes is at a context-text boundary.
0284     // extractFormattedTextFromContext() gives up formatting, prints a warning and returns selectedText
0285     // in order to reduce the risk of breaking whitespace changes within string literals.
0286 
0287     formattedMergedText = "    \"A very very looooooooooooooong\"\n    \" string this is. Even longer now.\"\n";
0288     expectedOutput = selectedText;
0289     addNewRow("insert-double-quotes-just-before-text");
0290 
0291     formattedMergedText = "    \"A very very looooooooooooooong \"\n    \"string this is. Even longer now.\"\n";
0292     addNewRow("insert-double-quotes-after-initial-space-in-text");
0293 
0294     formattedMergedText = "    \"A very very looooooooooooooong string this is. Even \"\n    \"longer now.\"\n";
0295     addNewRow("insert-double-quotes-just-after-text");
0296 
0297     selectedText.chop(1);
0298     rightContext.push_front(' ');
0299     expectedOutput = selectedText;
0300     addNewRow("insert-double-quotes-after-space-just-after-text");
0301 
0302     leftContext.push_back(' ');
0303     selectedText.remove(0, 1);
0304     formattedMergedText = "    \"A very very looooooooooooooong\"\n    \" string this is. Even longer now.\"\n";
0305     expectedOutput = selectedText;
0306     addNewRow("insert-double-quotes-before-space-just-before-text");
0307 
0308     leftContext = "\"this is ";
0309     selectedText = "a\"\n\" rather ";
0310     rightContext = "short string\"";
0311     formattedMergedText = "\"this is a rather short string\"";
0312     expectedOutput = "a rather ";
0313     addNewRow("remove-double-quotes-from-text");
0314 
0315     leftContext = "\"this \"\n\"is ";
0316     selectedText = "a rather ";
0317     addNewRow("remove-double-quotes-from-left-context");
0318 
0319     leftContext = "\"this is ";
0320     rightContext = "short \"\n\"string\"";
0321     addNewRow("remove-double-quotes-from-right-context");
0322 
0323     // In the following 5 test data rows, a removed pair of double quotes is at a context-text boundary.
0324     // extractFormattedTextFromContext() gives up formatting, prints a warning and returns selectedText
0325     // in order to reduce the risk of breaking whitespace changes within string literals.
0326 
0327     rightContext = "\"\n\"short string\"";
0328     addNewRow("remove-double-quotes-just-before-right-context");
0329 
0330     selectedText = "a rather\"\n\" ";
0331     rightContext = "short string\"";
0332     expectedOutput = selectedText;
0333     addNewRow("remove-double-quotes-before-final-space-in-text");
0334 
0335     selectedText = "\"\n\"a rather ";
0336     expectedOutput = selectedText;
0337     addNewRow("remove-double-quotes-at-the-beginning-of-text");
0338 
0339     leftContext = "\"this is \"\n\"";
0340     selectedText = "a rather ";
0341     expectedOutput = selectedText;
0342     addNewRow("remove-double-quotes-at-the-end-of-left-context");
0343 
0344     leftContext = "\"this is\"\n\" ";
0345     addNewRow("remove-double-quotes-before-final-space-in-left-context");
0346 
0347     leftContext = "auto textData = [&text]";
0348     selectedText = "(){return text.constData();};";
0349     rightContext = QString();
0350     formattedMergedText = R"(auto textData = [&text] {
0351     return text.constData();
0352 };)";
0353     expectedOutput = formattedMergedText.mid(leftContext.size());
0354     addNewRow("remove-empty-lambda-parens-at-text-beginning");
0355 
0356     selectedText.remove(0, 2);
0357     formattedMergedText = R"(auto textData = [&text]() {
0358     return text.constData();
0359 };)";
0360     expectedOutput = formattedMergedText.mid(leftContext.size());
0361     addNewRow("insert-empty-lambda-parens-at-text-beginning");
0362 
0363     leftContext = R"(
0364     if (good) {
0365         auto msg = prepare();
0366         send(m);)";
0367     selectedText = R"(
0368     } else if (other) {
0369         play();
0370     } else
0371         cancel();
0372 )";
0373     rightContext = QString();
0374     formattedMergedText = R"(
0375     if (good) {
0376         auto msg = prepare();
0377         send(m);
0378     } else {
0379         if (other)
0380             play();
0381         else
0382             cancel();
0383     }
0384 )";
0385     expectedOutput = R"(
0386     } else {
0387         if (other)
0388             play();
0389         else
0390             cancel();
0391     }
0392 )";
0393     addNewRow("insert-then-remove-brace-in-text");
0394 
0395     leftContext = "int tryClose() {";
0396     selectedText = R"(
0397     if (x) {if (y) { close();  }
0398 })";
0399     rightContext = "return 0;}\n\n ";
0400     formattedMergedText = R"(
0401 int tryClose()
0402 {
0403     if (x)
0404         if (y)
0405             close();
0406     return 0;
0407 })";
0408     expectedOutput = R"(
0409     if (x)
0410         if (y)
0411             close();
0412     )";
0413     addNewRow("remove-2-brace-pairs");
0414 
0415     leftContext = "void tryClose() {";
0416     selectedText = R"(
0417     if (x) {if (y) { close();  }
0418 })";
0419     rightContext = "}\n\n ";
0420     formattedMergedText = R"(
0421 void tryClose()
0422 {
0423     if (x)
0424         if (y)
0425             close();
0426 })";
0427     expectedOutput = R"(
0428     if (x)
0429         if (y)
0430             close();
0431 )";
0432     addNewRow("remove-2-brace-pairs-single-closing-brace-in-right-context");
0433 
0434     // All test data rows below contain invalid and bogus formatting. Their purpose is to test
0435     // the behavior of extractFormattedTextFromContext() in corner cases and to increase test coverage.
0436 
0437     leftContext = "int t = 5;  ";
0438     selectedText = "\nauto å=3;";
0439     rightContext = QString();
0440     formattedMergedText = "int t = 5;\nauto a=3;";
0441     expectedOutput = selectedText;
0442     addNewRow("replace-non-ascii-with-ascii-character");
0443 
0444     formattedMergedText = "int u = 5;\nauto å=3;";
0445     addNewRow("replace-non-fuzzy-character");
0446 
0447     formattedMergedText = "int t = {};\nauto å=3;";
0448     addNewRow("replace-non-fuzzy-with-fuzzy-character");
0449 
0450     rightContext = '\\';
0451     formattedMergedText = "int t = 5;\nauto å=3; _";
0452     addNewRow("replace-fuzzy-with-non-fuzzy-character");
0453 
0454     formattedMergedText = "int t = 5;\nauto å=3; _\\";
0455     addNewRow("insert-non-fuzzy-character-at-right-context-beginning");
0456 
0457     rightContext = "X\\";
0458     formattedMergedText = "int t = 5;\nauto å=3; X_\\";
0459     addNewRow("insert-non-fuzzy-before-fuzzy-character");
0460 
0461     formattedMergedText = "int t = 5;\nauto å=3;\\";
0462     addNewRow("remove-non-fuzzy-character");
0463 
0464     rightContext = QString();
0465     formattedMergedText = "// \"\"\n  int t = 5;\nauto å=3;\n";
0466     expectedOutput = "\nauto å=3;\n";
0467     addNewRow("insert-fuzzy-characters-before-left-context");
0468 
0469     leftContext = "std::cout << \";\n";
0470     selectedText = "pin();";
0471     formattedMergedText = "std::cout << \"\";\n" + selectedText + '\n';
0472     expectedOutput = selectedText;
0473     addNewRow("insert-double-quote-in-left-context-empty-right-context");
0474 
0475     rightContext = "clear();\n";
0476     formattedMergedText += rightContext;
0477     addNewRow("insert-double-quote-in-left-context");
0478 
0479     formattedMergedText += '"';
0480     expectedOutput += '\n';
0481     addNewRow("insert-double-quote-in-left-and-right-context");
0482 
0483     {
0484         auto prevSelectedText = selectedText;
0485         selectedText += "  std::string str=\"sample string\";";
0486         formattedMergedText.replace(prevSelectedText, prevSelectedText + "\nstd::string str=\"sample\" \" string\";");
0487     }
0488     expectedOutput = selectedText;
0489     addNewRow("insert-double-quote-in-left-and-right-context-and-double-quotes-in-text");
0490 
0491     formattedMergedText.replace("\" \" string\";", " strin\"g;");
0492     expectedOutput = "pin();\nstd::string str=\"sample strin\"g;\n";
0493     addNewRow("insert-double-quote-in-left-and-right-context-and-move-double-quote-in-text");
0494 
0495     leftContext = ' ';
0496     selectedText = " s ";
0497     rightContext = ' ';
0498     formattedMergedText = "s\"\"";
0499     expectedOutput = selectedText;
0500     addNewRow("insert-double-quotes-at-text-end");
0501 
0502     rightContext = QString();
0503     expectedOutput = formattedMergedText;
0504     addNewRow("insert-double-quotes-at-text-end-empty-right-context");
0505 
0506     selectedText += '\\';
0507     formattedMergedText += '\\';
0508     expectedOutput = formattedMergedText;
0509     addNewRow("insert-double-quotes-before-a-fuzzy-character-at-text-end-empty-right-context");
0510 
0511     rightContext = '\n';
0512     expectedOutput = selectedText;
0513     addNewRow("insert-double-quotes-before-a-fuzzy-character-at-text-end");
0514 
0515     selectedText += '\\';
0516     formattedMergedText += '\\';
0517     expectedOutput = formattedMergedText;
0518     addNewRow("insert-double-quotes-before-2-fuzzy-characters-at-text-end");
0519 
0520     formattedMergedText.insert(formattedMergedText.size() - 3, "\n ");
0521     expectedOutput = selectedText;
0522     addNewRow("insert-double-quoted-whitespace-before-2-fuzzy-characters-at-text-end");
0523 
0524     selectedText.replace(selectedText.size() - 1, 1, "{}");
0525     formattedMergedText.replace(formattedMergedText.size() - 1, 1, "{}");
0526     expectedOutput = formattedMergedText;
0527     addNewRow("insert-double-quotes-before-3-fuzzy-characters-at-text-end");
0528 
0529     selectedText.insert(selectedText.size() - 3, '*');
0530     addNewRow("replace-asterisk-with-double-quotes-before-3-fuzzy-characters-at-text-end");
0531 
0532     selectedText.insert(selectedText.size() - 3, '*');
0533     addNewRow("replace-2-asterisks-with-double-quotes-before-3-fuzzy-characters-at-text-end");
0534 
0535     selectedText[selectedText.size() - 5] = '(';
0536     selectedText[selectedText.size() - 4] = ')';
0537     addNewRow("replace-parens-with-double-quotes-before-3-fuzzy-characters-at-text-end");
0538 
0539     selectedText[selectedText.size() - 5] = ')';
0540     expectedOutput = selectedText;
0541     addNewRow("replace-2-closing-parens-with-double-quotes");
0542 
0543     leftContext = ' ';
0544     selectedText = " s ";
0545     rightContext = ' ';
0546     formattedMergedText = "\"\"s";
0547     expectedOutput = selectedText;
0548     addNewRow("insert-double-quotes-at-text-beginning");
0549 
0550     leftContext = QString();
0551     expectedOutput = formattedMergedText;
0552     addNewRow("insert-double-quotes-at-text-beginning-empty-left-context");
0553 
0554     leftContext.swap(selectedText);
0555     expectedOutput = QString();
0556     addNewRow("insert-double-quotes-at-left-context-beginning-empty-text");
0557 
0558     selectedText = ' ';
0559     addNewRow("insert-double-quotes-at-left-context-beginning");
0560 
0561     selectedText = QString();
0562     formattedMergedText = "s\"\"";
0563     addNewRow("insert-double-quotes-at-left-context-end-empty-text");
0564 
0565     leftContext = '\n';
0566     selectedText = "\"X";
0567     rightContext = QString();
0568     formattedMergedText = "\n*X\n";
0569     expectedOutput = selectedText;
0570     addNewRow("replace-double-quote-with-asterisk-at-text-beginning");
0571 
0572     selectedText.back() = '\\';
0573     formattedMergedText.replace('X', '\\');
0574     expectedOutput = selectedText;
0575     addNewRow("replace-double-quote-with-asterisk-at-all-fuzzy-text-beginning");
0576 
0577     selectedText = "{}X";
0578     formattedMergedText = "\"{}X\n";
0579     expectedOutput = selectedText;
0580     addNewRow("insert-double-quote-before-fuzzy-characters-at-text-beginning");
0581 
0582     leftContext = 'L';
0583     rightContext = 'R';
0584     selectedText.push_front('a');
0585     formattedMergedText = "\"La\"\"{}X R\"";
0586     expectedOutput = selectedText;
0587     addNewRow("insert-double-quotes-in-contexts-and-in-text");
0588 
0589     leftContext = ' ';
0590     selectedText = "XY";
0591     rightContext = 'r';
0592     formattedMergedText = "X Y r";
0593     expectedOutput = "X Y ";
0594     addNewRow("insert-spaces-within-and-after-text");
0595 
0596     formattedMergedText[1] = '"';
0597     expectedOutput = selectedText;
0598     addNewRow("insert-a-double-quote-in-text");
0599 
0600     formattedMergedText[1] = '(';
0601     addNewRow("insert-a-paren-in-text");
0602 
0603     formattedMergedText = "X(()Y r";
0604     addNewRow("insert-odd-number-of-parens-in-text");
0605 
0606     formattedMergedText = "*X Y /r/";
0607     expectedOutput = "*X Y /";
0608     addNewRow("insert-3-fuzzy-characters");
0609 
0610     formattedMergedText.push_front('/');
0611     expectedOutput = selectedText;
0612     addNewRow("start-comment-before-text");
0613 
0614     formattedMergedText = "/*/X Y /r/";
0615     addNewRow("start-comment-and-insert-slash-before-text");
0616 
0617     formattedMergedText.insert(2, '*');
0618     expectedOutput = "/**/X Y /";
0619     addNewRow("insert-comment-before-text");
0620 
0621     formattedMergedText = "*//*XYr";
0622     expectedOutput = selectedText;
0623     addNewRow("insert-inverted-comment-before-text");
0624 
0625     rightContext = QString();
0626     formattedMergedText = "XY*";
0627     expectedOutput = formattedMergedText;
0628     addNewRow("insert-asterisk-at-text-and-string-end");
0629 
0630     leftContext = "abc";
0631     selectedText = 'b';
0632     formattedMergedText = "ab";
0633     expectedOutput = selectedText;
0634     addNewRow("formatted-text-a-substring-of-left-context");
0635 
0636     formattedMergedText.push_back('/');
0637     addNewRow("formatted-text-a-substring-of-left-context-except-for-fuzzy-character-at-end");
0638 }
0639 
0640 #include "moc_test_formattinghelpers.cpp"