File indexing completed on 2024-05-12 04:39:05
0001 /* 0002 SPDX-License-Identifier: LGPL-2.0-only 0003 */ 0004 0005 #include "test_astyle.h" 0006 0007 #include <QTest> 0008 #include <QDebug> 0009 #include <QStandardPaths> 0010 0011 #include "../astyle_formatter.h" 0012 #include <util/formattinghelpers.h> 0013 0014 QTEST_MAIN(TestAstyle) 0015 0016 TestAstyle::~TestAstyle() = default; 0017 0018 void TestAstyle::initTestCase() 0019 { 0020 QStandardPaths::setTestModeEnabled(true); 0021 m_formatter = std::make_unique<AStyleFormatter>(); 0022 ///TODO: probably all settings should be covered by tests 0023 /// or at least set so we can be sure about what we 0024 /// actually test... 0025 m_formatter->setSpaceIndentationNoConversion(4); 0026 } 0027 0028 void TestAstyle::renameVariable() 0029 { 0030 // think this: 0031 // int asdf = 1; 0032 // e.g. asdf was before something different and got renamed 0033 QString formattedSource = m_formatter->formatSource( 0034 QStringLiteral("asdf"), QStringLiteral("int "), QStringLiteral(" = 1;") 0035 ); 0036 qDebug() << "formatted source:" << formattedSource; 0037 QCOMPARE(formattedSource, QString("asdf")); 0038 0039 // int main() { 0040 // if(asdf){}} 0041 formattedSource = m_formatter->formatSource( 0042 QStringLiteral("asdf"), QStringLiteral("int main(){\n if("), QStringLiteral("){}}") 0043 ); 0044 qDebug() << "formatted source:" << formattedSource; 0045 QCOMPARE(formattedSource, QString("asdf")); 0046 } 0047 0048 void TestAstyle::testFuzzyMatching() 0049 { 0050 // Some formatting styles inserts "{" and "}" parens behind "ifs", or change comment styles 0051 // The actual text changes, thus it is difficult to match original and formatted text 0052 0053 QString leftContext = QStringLiteral("void b() {/*some comment*/\nif( "); 0054 QString center = QStringLiteral("a[ 0]"); 0055 QString rightContext = QStringLiteral(" ) q;\n }\n"); 0056 QString text = leftContext + center + rightContext; 0057 QString formatted = QStringLiteral("void b() {// some comment\n if( a[0] ) {\n q;\n }\n }\n"); 0058 QString extracted = KDevelop::extractFormattedTextFromContext( formatted, text, QString(), QString() ); 0059 QCOMPARE( extracted, formatted ); 0060 0061 extracted = KDevelop::extractFormattedTextFromContext( formatted, center, leftContext, rightContext ); 0062 qDebug() << "extracted" << extracted << "formatted" << formatted; 0063 QCOMPARE( extracted, QString("a[0]") ); 0064 0065 rightContext = QStringLiteral("\nvoid g() {}"); 0066 extracted = KDevelop::extractFormattedTextFromContext(formatted + rightContext, text, QString(), rightContext); 0067 QCOMPARE(extracted, formatted); 0068 } 0069 0070 void TestAstyle::testTabMatching() 0071 { 0072 // Some formatting styles inserts "{" and "}" parens behind "ifs", or change comment styles 0073 // The actual text changes, thus it is difficult to match original and formatted text 0074 0075 { 0076 // Mismatch: There is a preceding tab, but the formatter replaces the tab with spaces 0077 // The tab is matched with 2 spaces, since we set tab-width 2 0078 QString extracted = KDevelop::extractFormattedTextFromContext( 0079 QStringLiteral("class C {\n class A;\n}\n"), 0080 QStringLiteral("class A;"), QStringLiteral("class C {\n "), QStringLiteral("\n}\n"), 2 ); 0081 QCOMPARE( extracted, QString("class A;") ); 0082 0083 // Two tabs are inserted insead of 1 0084 extracted = KDevelop::extractFormattedTextFromContext( 0085 QStringLiteral("class C {\n class A;\n}\n"), 0086 QStringLiteral("class A;"), QStringLiteral("class C {\n "), QStringLiteral("\n}\n"), 2 ); 0087 QCOMPARE( extracted, QString(" class A;") ); 0088 0089 // One space is inserted behind the tab 0090 extracted = KDevelop::extractFormattedTextFromContext( 0091 QStringLiteral("class C {\n class A;\n}\n"), 0092 QStringLiteral("class A;"), QStringLiteral("class C {\n "), QStringLiteral("\n}\n"), 2 ); 0093 QCOMPARE( extracted, QString(" class A;") ); 0094 0095 // Two tabs are inserted, with 2 preceding whitespaces 0096 // Add only 1 tab 0097 extracted = KDevelop::extractFormattedTextFromContext( 0098 QStringLiteral("class C {\n class A;\n}\n"), 0099 QStringLiteral("class A;"), QStringLiteral("class C {\n "), QStringLiteral("\n}\n"), 2 ); 0100 QCOMPARE( extracted, QString(" class A;") ); 0101 0102 extracted = KDevelop::extractFormattedTextFromContext( 0103 QStringLiteral("class C {\n class A;\n}\n"), 0104 QStringLiteral("class A;"), QStringLiteral("class C {\n "), QStringLiteral("\n}\n"), 4 ); 0105 QCOMPARE( extracted, QString(" class A;") ); 0106 } 0107 { 0108 // Already correctly formatted 0109 QString leftContext = QStringLiteral("void b() {\n c = 4;\n "); 0110 QString center = QStringLiteral("a = 3;"); 0111 QString rightContext = QStringLiteral("\n b = 5;\n }\n"); 0112 QString text = leftContext + center + rightContext; 0113 QString formatted = QStringLiteral("void b() {\n c = 4;\n a = 3;\n b = 5;\n }\n"); 0114 QString extracted = KDevelop::extractFormattedTextFromContext( formatted, text, QString(), QString() ); 0115 QCOMPARE( extracted, formatted ); 0116 0117 extracted = KDevelop::extractFormattedTextFromContext( formatted, center, leftContext, rightContext ); 0118 QCOMPARE( extracted, QString("a = 3;") ); 0119 } 0120 { 0121 QString leftContext = QStringLiteral("void b() {\n c = 4;\n"); 0122 QString center = QStringLiteral("a = 3;\n"); 0123 QString rightContext = QStringLiteral("b = 5;\n }\n"); 0124 QString text = leftContext + center + rightContext; 0125 QString formatted = QStringLiteral("void b() {\n c = 4;\n a = 3;\n b = 5;\n }\n"); 0126 QString extracted = KDevelop::extractFormattedTextFromContext( formatted, text, QString(), QString() ); 0127 QCOMPARE( extracted, formatted ); 0128 0129 extracted = KDevelop::extractFormattedTextFromContext( formatted, center, leftContext, rightContext ); 0130 QCOMPARE( extracted, QString(" a = 3;\n ") ); 0131 } 0132 } 0133 0134 void TestAstyle::overrideHelper() 0135 { 0136 // think this: 0137 // virtual void asdf(); 0138 // gets included into a class 0139 0140 // test1: not indented 0141 QString formattedSource = m_formatter->formatSource( 0142 QStringLiteral("virtual void asdf();"), QStringLiteral("class asdf {\n int bar();\n"), QStringLiteral("\n};") 0143 ); 0144 qDebug() << "formatted source:" << formattedSource; 0145 QCOMPARE(formattedSource, QString(" virtual void asdf();")); 0146 0147 // test2: already indented 0148 formattedSource = m_formatter->formatSource( 0149 QStringLiteral("virtual void asdf();"), QStringLiteral("class asdf {\n int bar();\n "), QStringLiteral("\n};") 0150 ); 0151 qDebug() << "formatted source:" << formattedSource; 0152 QCOMPARE(formattedSource, QString("virtual void asdf();")); 0153 } 0154 0155 void TestAstyle::varTypeAssistant() 0156 { 0157 // think this: 0158 // asdf = 1; 0159 // and you execute the assistant to get: 0160 // int asdf = 1; 0161 0162 // test1: already indented 0163 QString formattedSource = m_formatter->formatSource( 0164 QStringLiteral("int "), QStringLiteral("int main() {\n "), QStringLiteral("asdf = 1;\n}\n") 0165 ); 0166 qDebug() << "formatted source:" << formattedSource; 0167 QCOMPARE(formattedSource, QString("int ")); 0168 0169 // test2: not yet indented 0170 formattedSource = m_formatter->formatSource( 0171 QStringLiteral("int "), QStringLiteral("int main() {\n"), QStringLiteral("asdf = 1;\n}\n") 0172 ); 0173 qDebug() << "formatted source:" << formattedSource; 0174 QCOMPARE(formattedSource, QString(" int ")); 0175 0176 } 0177 0178 void TestAstyle::testMultipleFormatters() 0179 { 0180 // just test that multiple formatters can exist at the same time 0181 auto* formatter1 = new AStyleFormatter; 0182 auto* formatter2 = new AStyleFormatter; 0183 delete formatter1; 0184 delete formatter2; 0185 } 0186 0187 void TestAstyle::testMacroFormatting() 0188 { 0189 AStyleFormatter fmt; 0190 fmt.setSpaceIndentationNoConversion(2); 0191 fmt.setPreprocessorIndent(true); 0192 QString formatted = fmt.formatSource(QStringLiteral("#define asdf\\\nfoobar\n")); 0193 QCOMPARE(formatted, QString("#define asdf\\\n foobar\n")); 0194 } 0195 0196 void TestAstyle::testContext() 0197 { 0198 auto* formatter = new AStyleFormatter; 0199 formatter->setBracketFormatMode(astyle::LINUX_MODE); 0200 formatter->setParensInsidePaddingMode(true); 0201 formatter->setBlockIndent(true); 0202 // We enable break-blocks mode, so that we can test the newline matching 0203 formatter->setBreakBlocksMode(true); 0204 formatter->setBreakClosingHeaderBlocksMode(true); 0205 formatter->setParensUnPaddingMode(true); 0206 0207 QString leftContext = QStringLiteral("int main() {\n"); 0208 QString rightContext = QStringLiteral(";\n}\n"); 0209 0210 /// Newline tests 0211 0212 QString formattedSource = formatter->formatSource( 0213 QStringLiteral(" int a;\n"), leftContext, "int b;" + rightContext ); 0214 0215 // qDebug() << formattedSource; 0216 // Adjust indentation 0217 QCOMPARE(formattedSource, QString(" int a;\n ")); 0218 0219 formattedSource = formatter->formatSource( 0220 QStringLiteral(" int a;\n"), leftContext + " ", " int b;" + rightContext ); 0221 0222 // qDebug() << formattedSource; 0223 QCOMPARE(formattedSource, QString(" int a;\n ")); 0224 0225 /// "if(a);" is interpreted as own block, so due to the "break blocks" option, 0226 /// astyle breaks these blocks with a newline in between. 0227 formattedSource = formatter->formatSource( 0228 QStringLiteral(" if(a); "), leftContext + " if(a); ", " if(a);" + rightContext ); 0229 0230 // qDebug() << formattedSource; 0231 QCOMPARE(formattedSource, QString("\n\n if( a );\n\n ")); 0232 0233 formattedSource = formatter->formatSource( 0234 QStringLiteral(" if(a); "), leftContext + " if(a);\n", " \n if(a);" + rightContext ); 0235 0236 // qDebug() << formattedSource; 0237 QCOMPARE(formattedSource, QString("\n if( a );\n")); 0238 0239 formattedSource = formatter->formatSource( 0240 QStringLiteral(" if(a)\na; "), leftContext + " if(a);\n", " \n\n if(a);" + rightContext ); 0241 0242 // qDebug() << formattedSource; 0243 // Adjust indentation, successor already partially indentend 0244 QCOMPARE(formattedSource, QString("\n if( a )\n a;")); 0245 0246 /// Whitespace tests 0247 0248 formattedSource = formatter->formatSource( 0249 QStringLiteral("int "), leftContext + " ", rightContext ); 0250 0251 // 2 whitespaces are already in the context, so add only 2 0252 // qDebug() << "formatted source:" << formattedSource; 0253 QCOMPARE(formattedSource, QString(" int ")); 0254 0255 formattedSource = formatter->formatSource( 0256 QStringLiteral("q"), leftContext + " if(", ")" + rightContext ); 0257 0258 // Padding was added around both parens 0259 QCOMPARE(formattedSource, QString(" q ")); 0260 0261 formattedSource = formatter->formatSource( 0262 QStringLiteral("q"), leftContext + " if( ", " )" + rightContext ); 0263 0264 // Padding already existed around both parens 0265 QCOMPARE(formattedSource, QString("q")); 0266 0267 formattedSource = formatter->formatSource( 0268 QStringLiteral(" q "), leftContext + " if(", " )" + rightContext ); 0269 0270 // qDebug() << formattedSource; 0271 // No padding on left, too much padding on right 0272 QCOMPARE(formattedSource, QString(" q")); 0273 0274 formattedSource = formatter->formatSource( 0275 QStringLiteral(" "), leftContext + " if(q", ")" + rightContext ); 0276 0277 // qDebug() << formattedSource; 0278 // Normalize padding: from 3 to 1 0279 QCOMPARE(formattedSource, QString(" ")); 0280 0281 formattedSource = formatter->formatSource( 0282 QString(), leftContext + " if(", "q )" + rightContext ); 0283 0284 // qDebug() << formattedSource; 0285 // Normalize padding: from 0 to 1 0286 QCOMPARE(formattedSource, QString(" ")); 0287 0288 formattedSource = formatter->formatSource( 0289 QStringLiteral(" "), leftContext + " if( ", "q )" + rightContext ); 0290 0291 // qDebug() << formattedSource; 0292 // Reduce padding as much as possible 0293 QCOMPARE(formattedSource, QString()); 0294 0295 delete formatter; 0296 } 0297 0298 void TestAstyle::testTabIndentation() 0299 { 0300 AStyleFormatter formatter; 0301 formatter.setTabIndentation(2, false); 0302 0303 const QString initial(QStringLiteral("int a() {\n return 0;\n}\n")); 0304 const QString expected(QStringLiteral("int a() {\n\treturn 0;\n}\n")); 0305 const QString formatted = formatter.formatSource(initial); 0306 QCOMPARE(formatted, expected); 0307 } 0308 0309 void TestAstyle::testForeach() 0310 { 0311 AStyleFormatter formatter; 0312 QVERIFY(formatter.predefinedStyle("KDELibs")); 0313 0314 const QString initial(QStringLiteral("int a(){QList<int> v;\n foreach(int i,v){\nreturn i;}}\n")); 0315 const QString expected(QStringLiteral("int a()\n{\n QList<int> v;\n foreach (int i, v) {\n return i;\n }\n}\n")); 0316 const QString formatted = formatter.formatSource(initial); 0317 QCOMPARE(formatted, expected); 0318 } 0319 0320 void TestAstyle::testPointerAlignment() 0321 { 0322 AStyleFormatter formatter; 0323 formatter.setPointerAlignment(astyle::PTR_ALIGN_NAME); 0324 0325 const QString initial(QStringLiteral("int* a;\nint * b;\nint *c;\nint & d;\nconst double * const e;\n")); 0326 const QString expected(QStringLiteral("int *a;\nint *b;\nint *c;\nint &d;\nconst double *const e;\n")); 0327 const QString formatted = formatter.formatSource(initial); 0328 QCOMPARE(formatted, expected); 0329 } 0330 0331 void TestAstyle::testKdeFrameworks() 0332 { 0333 AStyleFormatter formatter; 0334 QVERIFY(formatter.predefinedStyle("KDELibs")); 0335 0336 QFETCH(QString, initial); 0337 QFETCH(QString, leftContext); 0338 QFETCH(QString, rightContext); 0339 QFETCH(QString, expected); 0340 0341 const QString formatted = formatter.formatSource(initial, leftContext, rightContext); 0342 QCOMPARE(formatted, expected); 0343 } 0344 0345 void TestAstyle::testKdeFrameworks_data() 0346 { 0347 QTest::addColumn<QString>("initial"); 0348 QTest::addColumn<QString>("leftContext"); 0349 QTest::addColumn<QString>("rightContext"); 0350 QTest::addColumn<QString>("expected"); 0351 0352 const QString leftContext = QStringLiteral("int main()\n{\n"); 0353 const QString rightContext = QStringLiteral("\n}\n"); 0354 0355 QString initial = QStringLiteral("\t int a;"); 0356 QString expected = QStringLiteral(" int a;"); 0357 QTest::newRow("indentation") << initial << leftContext << rightContext << expected; 0358 0359 initial = QStringLiteral("if(1);\n while (false);\nfor(int i=0; i<1; i++);\n"); 0360 expected = QStringLiteral(" if (1);\n while (false);\n for (int i = 0; i < 1; i++);\n"); 0361 QTest::newRow("space-after-keyword") << initial << leftContext << rightContext << expected; 0362 0363 initial = QStringLiteral("int* a;\nint * b;\nint *c;\nint & d;\nconst double * const e;\n"); 0364 expected = QStringLiteral("int *a;\nint *b;\nint *c;\nint &d;\nconst double *const e;\n"); 0365 QTest::newRow("pointer-alignment") << initial << QString() << QString() << expected; 0366 0367 initial = QStringLiteral("if (true)\n{\n}\n"); 0368 expected = QStringLiteral(" if (true) {\n }\n"); 0369 QTest::newRow("brace-on-same-line") << initial << leftContext << rightContext << expected; 0370 0371 initial = QStringLiteral("void foo(void) {\n}\nclass a {\n};\nnamespace c\n{\n}\n"); 0372 expected = QStringLiteral("void foo(void)\n{\n}\nclass a\n{\n};\nnamespace c\n{\n}\n"); 0373 QTest::newRow("brace-on-new-line") << initial << QString() << QString() << expected; 0374 0375 initial = QStringLiteral("switch (myEnum)\n{\ncase Value1:\ndoSomething();}\n"); 0376 expected = QStringLiteral(" switch (myEnum) {\n case Value1:\n doSomething();\n }\n"); 0377 QTest::newRow("switch-statement") << initial << leftContext << rightContext << expected; 0378 } 0379 0380 #include "moc_test_astyle.cpp"