diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 1ae8adc616c..7b2fc5353e2 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -508,21 +508,56 @@ void ClangdClient::closeExtraFile(const Utils::FilePath &filePath) SendDocUpdates::Ignore); } -void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor, +void ClangdClient::findUsages(const CppEditor::CursorInEditor &cursor, const std::optional &replacement, const std::function &renameCallback) { // Quick check: Are we even on anything searchable? - const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document); + const QTextCursor adjustedCursor = d->adjustedCursor(cursor.cursor(), cursor.textDocument()); const QString searchTerm = d->searchTermFromCursor(adjustedCursor); if (searchTerm.isEmpty()) return; if (replacement && versionNumber() >= QVersionNumber(16) - && Utils::qtcEnvironmentVariable("QTC_CLANGD_RENAMING") != "0") { - symbolSupport().renameSymbol(document, adjustedCursor, *replacement, renameCallback, - CppEditor::preferLowerCaseFileNames()); - return; + && Utils::qtcEnvironmentVariable("QTC_CLANGD_RENAMING") != "0") { + + // If we have up-to-date highlighting data, we can prevent giving clangd + // macros or namespaces to rename, which it can't cope with. + // TODO: Fix this upstream for macros; see https://github.com/clangd/clangd/issues/729. + bool useClangdForRenaming = true; + const auto highlightingData = d->highlightingData.constFind(cursor.textDocument()); + if (highlightingData != d->highlightingData.end() + && highlightingData->previousTokens.second == documentVersion(cursor.filePath())) { + const auto candidate = std::lower_bound( + highlightingData->previousTokens.first.cbegin(), + highlightingData->previousTokens.first.cend(), + cursor.cursor().position(), + [&cursor](const ExpandedSemanticToken &token, int pos) { + const int startPos = Utils::Text::positionInText( + cursor.textDocument()->document(), token.line, token.column); + return startPos + token.length < pos; + }); + if (candidate != highlightingData->previousTokens.first.cend()) { + const int startPos = Utils::Text::positionInText( + cursor.textDocument()->document(), candidate->line, candidate->column); + if (startPos <= cursor.cursor().position()) { + if (candidate->type == "namespace") { + CppEditor::CppModelManager::globalRename( + cursor, *replacement, renameCallback, + CppEditor::CppModelManager::Backend::Builtin); + return; + } + if (candidate->type == "macro") + useClangdForRenaming = false; + } + } + } + + if (useClangdForRenaming) { + symbolSupport().renameSymbol(cursor.textDocument(), adjustedCursor, *replacement, + renameCallback, CppEditor::preferLowerCaseFileNames()); + return; + } } const bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences(); @@ -531,14 +566,15 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor, if (searchTerm != "operator" && Utils::allOf(searchTerm, [](const QChar &c) { return c.isLetterOrNumber() || c == '_'; })) { - d->findUsages(document, adjustedCursor, searchTerm, replacement, renameCallback, categorize); + d->findUsages(cursor.textDocument(), adjustedCursor, searchTerm, replacement, + renameCallback, categorize); return; } // Otherwise get the proper spelling of the search term from clang, so we can put it into the // search widget. - const auto symbolInfoHandler = [this, doc = QPointer(document), adjustedCursor, replacement, - renameCallback, categorize] + const auto symbolInfoHandler = [this, doc = QPointer(cursor.textDocument()), adjustedCursor, + replacement, renameCallback, categorize] (const QString &name, const QString &, const MessageId &) { if (!doc) return; @@ -546,7 +582,8 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor, return; d->findUsages(doc.data(), adjustedCursor, name, replacement, renameCallback, categorize); }; - requestSymbolInfo(document->filePath(), Range(adjustedCursor).start(), symbolInfoHandler); + requestSymbolInfo(cursor.textDocument()->filePath(), Range(adjustedCursor).start(), + symbolInfoHandler); } void ClangdClient::checkUnused(const Utils::Link &link, Core::SearchResult *search, diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 772920b2776..67416d73795 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -53,7 +53,7 @@ public: void openExtraFile(const Utils::FilePath &filePath, const QString &content = {}); void closeExtraFile(const Utils::FilePath &filePath); - void findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor, + void findUsages(const CppEditor::CursorInEditor &cursor, const std::optional &replacement, const std::function &renameCallback); void checkUnused(const Utils::Link &link, Core::SearchResult *search, diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 5cc123ac911..248e97349fa 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -320,7 +320,7 @@ void ClangModelManagerSupport::globalRename(const CppEditor::CursorInEditor &cur client && client->isFullyIndexed()) { QTC_ASSERT(client->documentOpen(cursor.textDocument()), client->openDocument(cursor.textDocument())); - client->findUsages(cursor.textDocument(), cursor.cursor(), replacement, callback); + client->findUsages(cursor, replacement, callback); return; } CppModelManager::globalRename(cursor, replacement, callback, CppModelManager::Backend::Builtin); @@ -332,8 +332,7 @@ void ClangModelManagerSupport::findUsages(const CppEditor::CursorInEditor &curso client && client->isFullyIndexed()) { QTC_ASSERT(client->documentOpen(cursor.textDocument()), client->openDocument(cursor.textDocument())); - client->findUsages(cursor.textDocument(), cursor.cursor(), {}, {}); - + client->findUsages(cursor, {}, {}); return; } CppModelManager::findUsages(cursor, CppModelManager::Backend::Builtin); diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index b5103d3552d..c60a45f1df2 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -294,7 +294,7 @@ void ClangdTestFindReferences::test() QVERIFY(doc); QTextCursor cursor(doc->document()); cursor.setPosition(pos); - client()->findUsages(doc, cursor, {}, {}); + client()->findUsages(CppEditor::CursorInEditor(cursor, doc->filePath(), nullptr, doc), {}, {}); QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::findUsagesDone, timeOutInMs())); QCOMPARE(m_actualResults.size(), expectedResults.size());