Changeset View
Changeset View
Standalone View
Standalone View
plugins/clang/tests/test_codecompletion.cpp
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Line(s) | |||||
106 | 106 | | |||
107 | struct NoopTestFunction | 107 | struct NoopTestFunction | ||
108 | { | 108 | { | ||
109 | void operator()(const ClangCodeCompletionItemTester& /*tester*/) const | 109 | void operator()(const ClangCodeCompletionItemTester& /*tester*/) const | ||
110 | { | 110 | { | ||
111 | } | 111 | } | ||
112 | }; | 112 | }; | ||
113 | 113 | | |||
114 | QString textForDocument(const QUrl& url, const KTextEditor::Cursor& position) | ||||
115 | { | ||||
116 | bool close = false; | ||||
117 | | ||||
118 | auto* doc = ICore::self()->documentController()->documentForUrl(url); | ||||
119 | if (!doc) { | ||||
120 | doc = ICore::self()->documentController()->openDocument(url); | ||||
kfunk: `Q_ASSERT(doc);` to be sure? | |||||
121 | close = true; | ||||
122 | } | ||||
123 | | ||||
124 | auto text = doc->textDocument()->text({{0, 0}, position}); | ||||
125 | | ||||
126 | if (close) { | ||||
127 | doc->close(IDocument::Discard); | ||||
128 | } | ||||
129 | | ||||
130 | return text; | ||||
131 | } | ||||
132 | | ||||
133 | QExplicitlySharedDataPointer<ClangCodeCompletionContext> createContext(const ReferencedTopDUContext& top, | ||||
134 | const ParseSessionData::Ptr& sessionData, | ||||
135 | const KTextEditor::Cursor position, | ||||
136 | const QString& code = {}) | ||||
137 | { | ||||
138 | const auto url = top->url().toUrl(); | ||||
139 | const auto text = code.isEmpty() ? textForDocument(url, position) : code; | ||||
140 | return QExplicitlySharedDataPointer<ClangCodeCompletionContext>{ | ||||
141 | new ClangCodeCompletionContext(DUContextPointer(top), sessionData, url, position, text)}; | ||||
142 | } | ||||
143 | | ||||
114 | template<typename CustomTestFunction = NoopTestFunction> | 144 | template<typename CustomTestFunction = NoopTestFunction> | ||
115 | void executeCompletionTest(const ReferencedTopDUContext& top, const CompletionItems& expectedCompletionItems, | 145 | void executeCompletionTest(const ReferencedTopDUContext& top, const CompletionItems& expectedCompletionItems, | ||
116 | const ClangCodeCompletionContext::ContextFilters& filters = NoMacroOrBuiltin, | 146 | const ClangCodeCompletionContext::ContextFilters& filters = NoMacroOrBuiltin, | ||
117 | CustomTestFunction customTestFunction = {}) | 147 | CustomTestFunction customTestFunction = {}) | ||
118 | { | 148 | { | ||
119 | DUChainReadLocker lock; | 149 | DUChainReadLocker lock; | ||
120 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 150 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
121 | QVERIFY(sessionData); | 151 | QVERIFY(sessionData); | ||
122 | lock.unlock(); | 152 | lock.unlock(); | ||
123 | QString text; | | |||
124 | if (auto doc = ICore::self()->documentController()->documentForUrl(top->url().toUrl())) { | | |||
125 | text = doc->textDocument()->text({{0, 0}, expectedCompletionItems.position}); | | |||
126 | } | | |||
127 | // TODO: We should not need to pass 'session' to the context, should just use the base class ctor | 153 | // TODO: We should not need to pass 'session' to the context, should just use the base class ctor | ||
128 | auto context = new ClangCodeCompletionContext(DUContextPointer(top), sessionData, top->url().toUrl(), expectedCompletionItems.position, text); | 154 | auto context = createContext(top, sessionData, expectedCompletionItems.position); | ||
129 | context->setFilters(filters); | 155 | context->setFilters(filters); | ||
130 | lock.lock(); | 156 | lock.lock(); | ||
131 | 157 | | |||
132 | auto tester = ClangCodeCompletionItemTester(QExplicitlySharedDataPointer<ClangCodeCompletionContext>(context)); | 158 | auto tester = ClangCodeCompletionItemTester(context); | ||
133 | 159 | | |||
134 | int previousMatchQuality = 10; | 160 | int previousMatchQuality = 10; | ||
135 | for(const auto& declarationName : expectedCompletionItems.declarationItems){ | 161 | for(const auto& declarationName : expectedCompletionItems.declarationItems){ | ||
136 | const auto declarationItem = tester.findItem(declarationName); | 162 | const auto declarationItem = tester.findItem(declarationName); | ||
137 | QVERIFY(declarationItem); | 163 | QVERIFY(declarationItem); | ||
138 | QVERIFY(declarationItem->declaration()); | 164 | QVERIFY(declarationItem->declaration()); | ||
139 | 165 | | |||
140 | auto matchQuality = tester.itemData(declarationItem, KTextEditor::CodeCompletionModel::Name, KTextEditor::CodeCompletionModel::MatchQuality).toInt(); | 166 | auto matchQuality = tester.itemData(declarationItem, KTextEditor::CodeCompletionModel::Name, KTextEditor::CodeCompletionModel::MatchQuality).toInt(); | ||
Show All 34 Lines | 200 | { | |||
175 | TestFile file(code, QStringLiteral("cpp")); | 201 | TestFile file(code, QStringLiteral("cpp")); | ||
176 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | 202 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | ||
177 | DUChainReadLocker lock; | 203 | DUChainReadLocker lock; | ||
178 | auto top = file.topContext(); | 204 | auto top = file.topContext(); | ||
179 | QVERIFY(top); | 205 | QVERIFY(top); | ||
180 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 206 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
181 | QVERIFY(sessionData); | 207 | QVERIFY(sessionData); | ||
182 | 208 | | |||
183 | DUContextPointer topPtr(top); | | |||
184 | | ||||
185 | // don't hold DUChain lock when constructing ClangCodeCompletionContext | 209 | // don't hold DUChain lock when constructing ClangCodeCompletionContext | ||
186 | lock.unlock(); | 210 | lock.unlock(); | ||
187 | 211 | | |||
188 | auto context = new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), expectedCompletionItems.position, QString()); | 212 | auto context = createContext(top, sessionData, expectedCompletionItems.position); | ||
189 | context->setFilters(filters); | 213 | context->setFilters(filters); | ||
190 | 214 | | |||
191 | lock.lock(); | 215 | lock.lock(); | ||
192 | auto tester = ClangCodeCompletionItemTester(QExplicitlySharedDataPointer<ClangCodeCompletionContext>(context)); | 216 | auto tester = ClangCodeCompletionItemTester(context); | ||
193 | 217 | | |||
194 | for(const auto& declaration : expectedCompletionItems.completions){ | 218 | for(const auto& declaration : expectedCompletionItems.completions){ | ||
195 | const auto declarationItem = tester.findItem(declaration.name); | 219 | const auto declarationItem = tester.findItem(declaration.name); | ||
196 | QVERIFY(declarationItem); | 220 | QVERIFY(declarationItem); | ||
197 | QVERIFY(declarationItem->declaration()); | 221 | QVERIFY(declarationItem->declaration()); | ||
198 | 222 | | |||
199 | auto matchQuality = tester.itemData(declarationItem, KTextEditor::CodeCompletionModel::Name, KTextEditor::CodeCompletionModel::MatchQuality).toInt(); | 223 | auto matchQuality = tester.itemData(declarationItem, KTextEditor::CodeCompletionModel::Name, KTextEditor::CodeCompletionModel::MatchQuality).toInt(); | ||
200 | auto inheritanceDepth = declarationItem->inheritanceDepth(); | 224 | auto inheritanceDepth = declarationItem->inheritanceDepth(); | ||
Show All 19 Lines | 235 | { | |||
220 | 244 | | |||
221 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | 245 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | ||
222 | DUChainReadLocker lock; | 246 | DUChainReadLocker lock; | ||
223 | auto top = file.topContext(); | 247 | auto top = file.topContext(); | ||
224 | QVERIFY(top); | 248 | QVERIFY(top); | ||
225 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 249 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
226 | QVERIFY(sessionData); | 250 | QVERIFY(sessionData); | ||
227 | 251 | | |||
228 | DUContextPointer topPtr(top); | | |||
229 | | ||||
230 | lock.unlock(); | 252 | lock.unlock(); | ||
231 | 253 | | |||
232 | QExplicitlySharedDataPointer<ClangCodeCompletionContext> context( | 254 | auto context = createContext(top, sessionData, expectedCompletionItems.position, code); | ||
233 | new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), | | |||
234 | expectedCompletionItems.position, code)); | | |||
235 | 255 | | |||
236 | QApplication::processEvents(); | 256 | QApplication::processEvents(); | ||
237 | document->close(KDevelop::IDocument::Silent); | 257 | document->close(KDevelop::IDocument::Silent); | ||
238 | 258 | | |||
239 | // The previous ClangCodeCompletionContext call should replace member access. | 259 | // The previous ClangCodeCompletionContext call should replace member access. | ||
240 | // That triggers an update request in the duchain which we are not interested in, | 260 | // That triggers an update request in the duchain which we are not interested in, | ||
241 | // so let's stop that request. | 261 | // so let's stop that request. | ||
242 | ICore::self()->languageController()->backgroundParser()->removeDocument(file.url()); | 262 | ICore::self()->languageController()->backgroundParser()->removeDocument(file.url()); | ||
243 | 263 | | |||
244 | context = new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), | 264 | context = createContext(top, sessionData, expectedCompletionItems.position); | ||
245 | expectedCompletionItems.position, QString()); | | |||
246 | context->setFilters(filters); | 265 | context->setFilters(filters); | ||
247 | lock.lock(); | 266 | lock.lock(); | ||
248 | auto tester = ClangCodeCompletionItemTester(context); | 267 | auto tester = ClangCodeCompletionItemTester(context); | ||
249 | 268 | | |||
250 | tester.names.sort(); | 269 | tester.names.sort(); | ||
251 | QCOMPARE(tester.names, expectedCompletionItems.completions); | 270 | QCOMPARE(tester.names, expectedCompletionItems.completions); | ||
252 | } | 271 | } | ||
253 | 272 | | |||
▲ Show 20 Lines • Show All 732 Lines • ▼ Show 20 Line(s) | 1004 | { | |||
986 | TestFile file(QStringLiteral("void f(); int f(int); void f(int, double){\n "), QStringLiteral("cpp")); | 1005 | TestFile file(QStringLiteral("void f(); int f(int); void f(int, double){\n "), QStringLiteral("cpp")); | ||
987 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | 1006 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | ||
988 | DUChainReadLocker lock; | 1007 | DUChainReadLocker lock; | ||
989 | auto top = file.topContext(); | 1008 | auto top = file.topContext(); | ||
990 | QVERIFY(top); | 1009 | QVERIFY(top); | ||
991 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 1010 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
992 | QVERIFY(sessionData); | 1011 | QVERIFY(sessionData); | ||
993 | 1012 | | |||
994 | DUContextPointer topPtr(top); | | |||
995 | lock.unlock(); | 1013 | lock.unlock(); | ||
996 | 1014 | | |||
997 | const auto context = new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), {1, 0}, QString()); | 1015 | const auto context = createContext(top, sessionData, {1, 0}); | ||
998 | context->setFilters(NoMacroOrBuiltin); | 1016 | context->setFilters(NoMacroOrBuiltin); | ||
999 | lock.lock(); | 1017 | lock.lock(); | ||
1000 | const auto tester = ClangCodeCompletionItemTester(QExplicitlySharedDataPointer<ClangCodeCompletionContext>(context)); | 1018 | const auto tester = ClangCodeCompletionItemTester(context); | ||
1001 | QCOMPARE(tester.items.size(), 3); | 1019 | QCOMPARE(tester.items.size(), 3); | ||
1002 | for (const auto& item : tester.items) { | 1020 | for (const auto& item : tester.items) { | ||
1003 | auto function = item->declaration()->type<FunctionType>(); | 1021 | auto function = item->declaration()->type<FunctionType>(); | ||
1004 | const QString display = item->declaration()->identifier().toString() + function->partToString(FunctionType::SignatureArguments); | 1022 | const QString display = item->declaration()->identifier().toString() + function->partToString(FunctionType::SignatureArguments); | ||
1005 | const QString itemDisplay = tester.itemData(item).toString() + tester.itemData(item, KTextEditor:: CodeCompletionModel::Arguments).toString(); | 1023 | const QString itemDisplay = tester.itemData(item).toString() + tester.itemData(item, KTextEditor:: CodeCompletionModel::Arguments).toString(); | ||
1006 | QCOMPARE(display, itemDisplay); | 1024 | QCOMPARE(display, itemDisplay); | ||
1007 | } | 1025 | } | ||
1008 | 1026 | | |||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Line(s) | 1092 | { | |||
1075 | TestFile file(QStringLiteral("int var; \nvoid test(int var) {int tmp =\n }"), QStringLiteral("cpp")); | 1093 | TestFile file(QStringLiteral("int var; \nvoid test(int var) {int tmp =\n }"), QStringLiteral("cpp")); | ||
1076 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | 1094 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | ||
1077 | DUChainReadLocker lock; | 1095 | DUChainReadLocker lock; | ||
1078 | auto top = file.topContext(); | 1096 | auto top = file.topContext(); | ||
1079 | QVERIFY(top); | 1097 | QVERIFY(top); | ||
1080 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 1098 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
1081 | QVERIFY(sessionData); | 1099 | QVERIFY(sessionData); | ||
1082 | 1100 | | |||
1083 | DUContextPointer topPtr(top); | | |||
1084 | lock.unlock(); | 1101 | lock.unlock(); | ||
1085 | 1102 | | |||
1086 | const auto context = new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), {2, 0}, QString()); | 1103 | const auto context = createContext(top, sessionData, {2, 0}); | ||
1087 | context->setFilters(NoMacroOrBuiltin); | 1104 | context->setFilters(NoMacroOrBuiltin); | ||
1088 | lock.lock(); | 1105 | lock.lock(); | ||
1089 | const auto tester = ClangCodeCompletionItemTester(QExplicitlySharedDataPointer<ClangCodeCompletionContext>(context)); | 1106 | const auto tester = ClangCodeCompletionItemTester(context); | ||
1090 | 1107 | | |||
1091 | QCOMPARE(tester.items.size(), 4); | 1108 | QCOMPARE(tester.items.size(), 4); | ||
1092 | auto item = tester.findItem(QStringLiteral("var")); | 1109 | auto item = tester.findItem(QStringLiteral("var")); | ||
1093 | VERIFY(item); | 1110 | VERIFY(item); | ||
1094 | QCOMPARE(item->declaration()->range().start, CursorInRevision(1, 14)); | 1111 | QCOMPARE(item->declaration()->range().start, CursorInRevision(1, 14)); | ||
1095 | } | 1112 | } | ||
1096 | 1113 | | |||
1097 | void TestCodeCompletion::testArgumentHintCompletion() | 1114 | void TestCodeCompletion::testArgumentHintCompletion() | ||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | 1176 | #endif | |||
1161 | TestFile file(QStringLiteral("void f(int i, int j = 0, double k =1){\nf( "), QStringLiteral("cpp")); | 1178 | TestFile file(QStringLiteral("void f(int i, int j = 0, double k =1){\nf( "), QStringLiteral("cpp")); | ||
1162 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | 1179 | QVERIFY(file.parseAndWait(TopDUContext::AllDeclarationsContextsUsesAndAST)); | ||
1163 | DUChainReadLocker lock; | 1180 | DUChainReadLocker lock; | ||
1164 | auto top = file.topContext(); | 1181 | auto top = file.topContext(); | ||
1165 | QVERIFY(top); | 1182 | QVERIFY(top); | ||
1166 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | 1183 | const ParseSessionData::Ptr sessionData(dynamic_cast<ParseSessionData*>(top->ast().data())); | ||
1167 | QVERIFY(sessionData); | 1184 | QVERIFY(sessionData); | ||
1168 | 1185 | | |||
1169 | DUContextPointer topPtr(top); | | |||
1170 | lock.unlock(); | 1186 | lock.unlock(); | ||
1171 | 1187 | | |||
1172 | const auto context = new ClangCodeCompletionContext(topPtr, sessionData, file.url().toUrl(), {1, 2}, QString()); | 1188 | const auto context = createContext(top, sessionData, {1, 2}); | ||
1173 | context->setFilters(NoMacroOrBuiltin); | 1189 | context->setFilters(NoMacroOrBuiltin); | ||
1174 | lock.lock(); | 1190 | lock.lock(); | ||
1175 | const auto tester = ClangCodeCompletionItemTester(QExplicitlySharedDataPointer<ClangCodeCompletionContext>(context)); | 1191 | const auto tester = ClangCodeCompletionItemTester(context); | ||
1176 | QExplicitlySharedDataPointer<KDevelop::CompletionTreeItem> f; | 1192 | QExplicitlySharedDataPointer<KDevelop::CompletionTreeItem> f; | ||
1177 | 1193 | | |||
1178 | for (const auto& item : tester.items) { | 1194 | for (const auto& item : tester.items) { | ||
1179 | if (item->argumentHintDepth() == 1) { | 1195 | if (item->argumentHintDepth() == 1) { | ||
1180 | f = item; | 1196 | f = item; | ||
1181 | break; | 1197 | break; | ||
1182 | } | 1198 | } | ||
1183 | } | 1199 | } | ||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |
Q_ASSERT(doc); to be sure?