Changeset View
Changeset View
Standalone View
Standalone View
plugins/clang/codecompletion/completionhelper.cpp
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 43 | { | |||
---|---|---|---|---|---|
45 | QStringList templateTypes; | 45 | QStringList templateTypes; | ||
46 | QMap<QString, QString> templateTypeMap; | 46 | QMap<QString, QString> templateTypeMap; | ||
47 | }; | 47 | }; | ||
48 | 48 | | |||
49 | struct ImplementsInfo | 49 | struct ImplementsInfo | ||
50 | { | 50 | { | ||
51 | CXCursor origin; | 51 | CXCursor origin; | ||
52 | CXCursor top; | 52 | CXCursor top; | ||
53 | FunctionImplementsList* prototypes; | | |||
54 | QVector<CXCursor> originScope; | 53 | QVector<CXCursor> originScope; | ||
55 | QVector<CXFile> fileFilter; | 54 | QVector<CXFile> fileFilter; | ||
56 | int depth; | 55 | int depth; | ||
57 | QString templatePrefix; | 56 | QString templatePrefix; | ||
57 | QVector<CXCursor>& qualifiedNamespaces; | ||||
58 | struct PendingFunctions | ||||
59 | { | ||||
60 | CXCursor cursor; | ||||
61 | QString templatePrefix; | ||||
62 | }; | ||||
63 | QVector<PendingFunctions>& pendingFunctions; | ||||
58 | }; | 64 | }; | ||
59 | 65 | | |||
60 | QStringList templateParams(CXCursor cursor); | 66 | QStringList templateParams(CXCursor cursor); | ||
61 | 67 | | |||
62 | CXChildVisitResult templateParamsHelper(CXCursor cursor, CXCursor /*parent*/, CXClientData data) | 68 | CXChildVisitResult templateParamsHelper(CXCursor cursor, CXCursor /*parent*/, CXClientData data) | ||
63 | { | 69 | { | ||
64 | CXCursorKind kind = clang_getCursorKind(cursor); | 70 | CXCursorKind kind = clang_getCursorKind(cursor); | ||
65 | auto& params = *static_cast<QStringList*>(data); | 71 | auto& params = *static_cast<QStringList*>(data); | ||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Line(s) | 272 | if (kind == CXCursor_ClassTemplate || kind == CXCursor_ClassTemplatePartialSpecialization) { | |||
267 | //If we're at a template, we need to construct the template<typename T1, typename T2> | 273 | //If we're at a template, we need to construct the template<typename T1, typename T2> | ||
268 | //which goes at the front of the prototype | 274 | //which goes at the front of the prototype | ||
269 | const QStringList templateTypes = templateParams(kind == CXCursor_ClassTemplate ? cursor : clang_getSpecializedCursorTemplate(cursor)); | 275 | const QStringList templateTypes = templateParams(kind == CXCursor_ClassTemplate ? cursor : clang_getSpecializedCursorTemplate(cursor)); | ||
270 | 276 | | |||
271 | templatePrefix = QLatin1String("template<") + templateTypes.join(QStringLiteral(", ")) + QLatin1String("> "); | 277 | templatePrefix = QLatin1String("template<") + templateTypes.join(QStringLiteral(", ")) + QLatin1String("> "); | ||
272 | } | 278 | } | ||
273 | } | 279 | } | ||
274 | 280 | | |||
275 | ImplementsInfo info{data->origin, data->top, data->prototypes, data->originScope, | 281 | ImplementsInfo info{data->origin, data->top, data->originScope, | ||
276 | data->fileFilter, | 282 | data->fileFilter, | ||
277 | data->depth + 1, | 283 | data->depth + 1, | ||
278 | data->templatePrefix + templatePrefix}; | 284 | data->templatePrefix + templatePrefix, | ||
285 | data->qualifiedNamespaces, | ||||
286 | data->pendingFunctions}; | ||||
279 | clang_visitChildren(cursor, declVisitor, &info); | 287 | clang_visitChildren(cursor, declVisitor, &info); | ||
280 | 288 | | |||
281 | return CXChildVisit_Continue; | 289 | return CXChildVisit_Continue; | ||
282 | } | 290 | } | ||
283 | 291 | | |||
284 | if (data->depth < data->originScope.count()) { | 292 | if (data->depth < data->originScope.count()) { | ||
285 | return CXChildVisit_Continue; | 293 | return CXChildVisit_Continue; | ||
286 | } | 294 | } | ||
287 | 295 | | |||
296 | if (kind == CXCursor_UsingDirective) { | ||||
297 | data->qualifiedNamespaces.append(clang_getCursorDefinition(cursor)); | ||||
298 | return CXChildVisit_Continue; | ||||
299 | } | ||||
300 | | ||||
288 | //If the current cursor is not a function or if it is already defined, there's nothing to do here | 301 | //If the current cursor is not a function or if it is already defined, there's nothing to do here | ||
289 | if (!CursorKindTraits::isFunction(clang_getCursorKind(cursor)) || | 302 | if (!CursorKindTraits::isFunction(clang_getCursorKind(cursor)) || | ||
290 | !clang_equalCursors(clang_getNullCursor(), clang_getCursorDefinition(cursor))) | 303 | !clang_equalCursors(clang_getNullCursor(), clang_getCursorDefinition(cursor))) | ||
291 | { | 304 | { | ||
292 | return CXChildVisit_Continue; | 305 | return CXChildVisit_Continue; | ||
293 | } | 306 | } | ||
294 | 307 | | |||
295 | // don't try to implement pure virtual functions | 308 | // don't try to implement pure virtual functions | ||
Show All 18 Lines | |||||
314 | } | 327 | } | ||
315 | 328 | | |||
316 | QString templatePrefix; | 329 | QString templatePrefix; | ||
317 | if (kind == CXCursor_FunctionTemplate) { | 330 | if (kind == CXCursor_FunctionTemplate) { | ||
318 | const QStringList templateTypes = templateParams(cursor); | 331 | const QStringList templateTypes = templateParams(cursor); | ||
319 | templatePrefix = QLatin1String("template<") + templateTypes.join(QStringLiteral(", ")) + QLatin1String("> "); | 332 | templatePrefix = QLatin1String("template<") + templateTypes.join(QStringLiteral(", ")) + QLatin1String("> "); | ||
320 | } | 333 | } | ||
321 | 334 | | |||
322 | const auto scope = ClangUtils::getScope(cursor, data->origin); | 335 | data->pendingFunctions.append({cursor, data->templatePrefix + templatePrefix}); | ||
336 | | ||||
337 | return CXChildVisit_Continue; | ||||
338 | } | ||||
339 | | ||||
340 | void processImplements(const ImplementsInfo& info, FunctionImplementsList& implements) | ||||
341 | { | ||||
342 | for (const auto& pendingFunction : info.pendingFunctions) { | ||||
343 | const CXCursor cursor = pendingFunction.cursor; | ||||
344 | const CXCursorKind kind = clang_getCursorKind(cursor); | ||||
345 | | ||||
346 | const auto scope = ClangUtils::getScope(cursor, info.origin, info.qualifiedNamespaces); | ||||
323 | QString signature = ClangUtils::getCursorSignature(cursor, scope); | 347 | QString signature = ClangUtils::getCursorSignature(cursor, scope); | ||
324 | 348 | | |||
325 | QString returnType, rest; | 349 | QString returnType, rest; | ||
326 | if (kind != CXCursor_Constructor && kind != CXCursor_Destructor) { | 350 | if (kind != CXCursor_Constructor && kind != CXCursor_Destructor) { | ||
327 | int spaceIndex = signature.indexOf(QLatin1Char(' ')); | 351 | int spaceIndex = signature.indexOf(QLatin1Char(' ')); | ||
328 | returnType = signature.left(spaceIndex); | 352 | returnType = signature.left(spaceIndex); | ||
329 | rest = signature.mid(spaceIndex + 1); | 353 | rest = signature.mid(spaceIndex + 1); | ||
330 | } else { | 354 | } else { | ||
331 | rest = signature; | 355 | rest = signature; | ||
332 | } | 356 | } | ||
333 | 357 | | |||
334 | //TODO Add support for pure virtual functions | 358 | //TODO Add support for pure virtual functions | ||
335 | 359 | | |||
336 | ReferencedTopDUContext top; | 360 | ReferencedTopDUContext top; | ||
337 | { | 361 | { | ||
362 | CXFile file = nullptr; | ||||
363 | auto location = clang_getCursorLocation(cursor); | ||||
364 | clang_getFileLocation(location, &file, nullptr, nullptr, nullptr); | ||||
365 | | ||||
338 | DUChainReadLocker lock; | 366 | DUChainReadLocker lock; | ||
339 | top = DUChain::self()->chainForDocument(ClangString(clang_getFileName(file)).toIndexed()); | 367 | top = DUChain::self()->chainForDocument(ClangString(clang_getFileName(file)).toIndexed()); | ||
340 | } | 368 | } | ||
341 | DeclarationPointer declaration = ClangHelpers::findDeclaration(clang_getCursorLocation(cursor), QualifiedIdentifier(), top); | 369 | DeclarationPointer declaration = ClangHelpers::findDeclaration(clang_getCursorLocation(cursor), QualifiedIdentifier(), top); | ||
342 | data->prototypes->append(FuncImplementInfo{kind == CXCursor_Constructor, kind == CXCursor_Destructor, | 370 | implements.append(FuncImplementInfo{kind == CXCursor_Constructor, kind == CXCursor_Destructor, | ||
343 | data->templatePrefix + templatePrefix, returnType, rest, declaration}); | 371 | pendingFunction.templatePrefix, returnType, rest, declaration}); | ||
344 | 372 | } | |||
345 | return CXChildVisit_Continue; | | |||
346 | } | 373 | } | ||
347 | 374 | | |||
348 | } | 375 | } | ||
349 | 376 | | |||
350 | bool FuncOverrideInfo::operator==(const FuncOverrideInfo& rhs) const | 377 | bool FuncOverrideInfo::operator==(const FuncOverrideInfo& rhs) const | ||
351 | { | 378 | { | ||
352 | return std::make_tuple(returnType, name, params, isConst) | 379 | return std::make_tuple(returnType, name, params, isConst) | ||
353 | == std::make_tuple(rhs.returnType, rhs.name, rhs.params, rhs.isConst); | 380 | == std::make_tuple(rhs.returnType, rhs.name, rhs.params, rhs.isConst); | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 410 | clang_equalCursors(topCursor, currentCursor)) { | |||
398 | const auto& buddies = DocumentFinderHelpers::potentialBuddies(url); | 425 | const auto& buddies = DocumentFinderHelpers::potentialBuddies(url); | ||
399 | for (const auto& buddy : buddies) { | 426 | for (const auto& buddy : buddies) { | ||
400 | auto buddyFile = clang_getFile(unit, qPrintable(buddy.toLocalFile())); | 427 | auto buddyFile = clang_getFile(unit, qPrintable(buddy.toLocalFile())); | ||
401 | if (buddyFile) { | 428 | if (buddyFile) { | ||
402 | fileFilter << buddyFile; | 429 | fileFilter << buddyFile; | ||
403 | } | 430 | } | ||
404 | } | 431 | } | ||
405 | 432 | | |||
406 | ImplementsInfo info{currentCursor, topCursor, &m_implements, scopes, fileFilter, 0, QString()}; | 433 | QVector<CXCursor> qualifiedNamespaces; | ||
434 | QVector<ImplementsInfo::PendingFunctions> pendingFunctions; | ||||
435 | ImplementsInfo info{currentCursor, topCursor, scopes, fileFilter, 0, QString(), qualifiedNamespaces, pendingFunctions}; | ||||
407 | clang_visitChildren(topCursor, declVisitor, &info); | 436 | clang_visitChildren(topCursor, declVisitor, &info); | ||
437 | processImplements(info, m_implements); | ||||
408 | } | 438 | } | ||
409 | } | 439 | } | ||
410 | 440 | | |||
411 | FunctionOverrideList CompletionHelper::overrides() const | 441 | FunctionOverrideList CompletionHelper::overrides() const | ||
412 | { | 442 | { | ||
413 | return m_overrides; | 443 | return m_overrides; | ||
414 | } | 444 | } | ||
415 | 445 | | |||
416 | FunctionImplementsList CompletionHelper::implements() const | 446 | FunctionImplementsList CompletionHelper::implements() const | ||
417 | { | 447 | { | ||
418 | return m_implements; | 448 | return m_implements; | ||
419 | } | 449 | } |