1 /*
2 SPDX-FileCopyrightText: 2017 Kevin Funk <kfunk@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6
7 #include "test_refactoring.h"
8
9 #include <tests/testcore.h>
10 #include <tests/autotestshell.h>
11 #include <tests/testfile.h>
12 #include <tests/testproject.h>
13 #include <interfaces/ilanguagecontroller.h>
14
15 #include "codegen/clangrefactoring.h"
16
17 #include <language/duchain/duchainlock.h>
18 #include <language/duchain/declaration.h>
19 #include <language/interfaces/ilanguagesupport.h>
20
21 #include <QTemporaryDir>
22 #include <QLoggingCategory>
23 #include <QTest>
24
25 QTEST_MAIN(TestRefactoring)
26
27 using namespace KDevelop;
28
29 TestRefactoring::~TestRefactoring() = default;
30
initTestCase()31 void TestRefactoring::initTestCase()
32 {
33 QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false\ndefault.debug=true\nkdevelop.plugins.clang.debug=true\n"));
34
35 QVERIFY(qputenv("KDEV_CLANG_DISPLAY_DIAGS", "1"));
36
37 AutoTestShell::init({QStringLiteral("kdevclangsupport")});
38
39 auto core = TestCore::initialize();
40 delete core->projectController();
41 m_projectController = new TestProjectController(core);
42 core->setProjectController(m_projectController);
43 }
44
cleanupTestCase()45 void TestRefactoring::cleanupTestCase()
46 {
47 TestCore::shutdown();
48 }
49
testClassRename()50 void TestRefactoring::testClassRename()
51 {
52 const QString codeBefore(QStringLiteral(R"(
53 class Foo {
54 public:
55 Foo();
56 ~Foo();
57 };
58 Foo::Foo() {
59 }
60 Foo::~Foo() {
61 }
62 )"));
63
64 const QString codeAfter(QStringLiteral(R"(
65 class FooNew {
66 public:
67 FooNew();
68 ~FooNew();
69 };
70 FooNew::FooNew() {
71 }
72 FooNew::~FooNew() {
73 }
74 )"));
75
76 QTemporaryDir dir;
77 auto project = new TestProject(Path(dir.path()), this);
78 m_projectController->addProject(project);
79
80 TestFile file(codeBefore, QStringLiteral("cpp"), project, dir.path());
81 QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsAndUses));
82
83 DUChainReadLocker lock;
84
85 auto top = file.topContext();
86 QVERIFY(top);
87
88 auto declaration = top->localDeclarations().first();
89 QVERIFY(declaration);
90
91 const QString originalName = declaration->identifier().identifier().str();
92 const QString newName = QStringLiteral("FooNew");
93
94 QSharedPointer<BasicRefactoringCollector> collector(new BasicRefactoringCollector(declaration));
95
96 // TODO: Do this without GUI?
97 UsesWidget uses(declaration, collector);
98 lock.unlock();
99
100 for (int i = 0; i < 30000; i += 1000) {
101 if (collector->isReady()) {
102 break;
103 }
104 QTest::qWait(1000);
105 }
106 QVERIFY(collector->isReady());
107
108 BasicRefactoring::NameAndCollector nameAndCollector{newName, collector};
109
110 auto languages = ICore::self()->languageController()->languagesForUrl(file.url().toUrl());
111 QVERIFY(!languages.isEmpty());
112 auto clangLanguageSupport = languages.first();
113 QVERIFY(clangLanguageSupport);
114 auto clangRefactoring = qobject_cast<ClangRefactoring*>(clangLanguageSupport->refactoring());
115 QVERIFY(clangRefactoring);
116
117 clangRefactoring->renameCollectedDeclarations(nameAndCollector.collector.data(), newName, originalName);
118 QCOMPARE(file.fileContents(), codeAfter);
119
120 m_projectController->closeAllProjects();
121 }
122
123