| 542 | } |
| 543 | |
| 544 | QWidget* ContextBrowserPlugin::navigationWidgetForPosition(KTextEditor::View* view, KTextEditor::Cursor position, |
| 545 | KTextEditor::Range& itemRange) |
| 546 | { |
| 547 | QUrl viewUrl = view->document()->url(); |
| 548 | const auto languages = ICore::self()->languageController()->languagesForUrl(viewUrl); |
| 549 | |
| 550 | DUChainReadLocker lock(DUChain::lock()); |
| 551 | |
| 552 | for (const auto language : languages) { |
| 553 | auto widget = language->specialLanguageObjectNavigationWidget(viewUrl, position); |
| 554 | auto navigationWidget = qobject_cast<AbstractNavigationWidget*>(widget.first); |
| 555 | if (navigationWidget) { |
| 556 | itemRange = widget.second; |
| 557 | return navigationWidget; |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | // Find problems under the cursor (first pass) |
| 562 | TopDUContext* topContext = DUChainUtils::standardContextForUrl(view->document()->url()); |
| 563 | QVector<KDevelop::IProblem::Ptr> problems; |
| 564 | if (topContext) { |
| 565 | problems = findProblemsUnderCursor(topContext, position, itemRange); |
| 566 | } |
| 567 | |
| 568 | // Find decl (declaration) under the cursor |
| 569 | const auto itemUnderCursor = DUChainUtils::itemUnderCursor(viewUrl, position); |
| 570 | auto declUnderCursor = itemUnderCursor.declaration; |
| 571 | Declaration* decl = DUChainUtils::declarationForDefinition(declUnderCursor); |
| 572 | if (decl && decl->kind() == Declaration::Alias) { |
| 573 | auto* alias = dynamic_cast<AliasDeclaration*>(decl); |
| 574 | Q_ASSERT(alias); |
| 575 | decl = alias->aliasedDeclaration().declaration(); |
| 576 | } |
| 577 | |
| 578 | // Return nullptr if the found problems / decl are already being shown in the tool tip currently. |
| 579 | if (m_currentToolTip && |
| 580 | problems == m_currentToolTipProblems && |
| 581 | IndexedDeclaration(decl) == m_currentToolTipDeclaration) { |
| 582 | return nullptr; |
| 583 | } |
| 584 | |
| 585 | // Create a widget for problems, if any have been found. |
| 586 | AbstractNavigationWidget* problemWidget = nullptr; |
| 587 | if (!problems.isEmpty()) { |
| 588 | problemWidget = new AbstractNavigationWidget; |
| 589 | auto context = new ProblemNavigationContext(problems); |
| 590 | context->setTopContext(TopDUContextPointer(topContext)); |
| 591 | problemWidget->setContext(NavigationContextPointer(context)); |
| 592 | } |
| 593 | |
| 594 | // Let the context create a widget for decl, if there is one. |
| 595 | // Note that createNavigationWidget() might also return nullptr for a valid decl however. |
| 596 | AbstractNavigationWidget* declWidget = nullptr; |
| 597 | if (decl) { |
| 598 | if (itemRange.isValid()) { |
| 599 | itemRange.expandToRange(itemUnderCursor.range); |
| 600 | } else { |
| 601 | itemRange = itemUnderCursor.range; |
nothing calls this directly
no test coverage detected