forked from qt-creator/qt-creator
ClangCodeModel: Do not try to rename macros and namespaces with clangd
Unfortunately, clangd refuses to rename macros and namespaces. Fall back to our old two-stage "find + replace" approach for macros (which clangd can find just fine) and employ the built-in code model for namespaces (as they don't get indexed at all by clangd). Change-Id: I08b1088ff4de9220427e089ef0700dbf2a944081 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -508,21 +508,56 @@ void ClangdClient::closeExtraFile(const Utils::FilePath &filePath)
|
|||||||
SendDocUpdates::Ignore);
|
SendDocUpdates::Ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
void ClangdClient::findUsages(const CppEditor::CursorInEditor &cursor,
|
||||||
const std::optional<QString> &replacement,
|
const std::optional<QString> &replacement,
|
||||||
const std::function<void()> &renameCallback)
|
const std::function<void()> &renameCallback)
|
||||||
{
|
{
|
||||||
// Quick check: Are we even on anything searchable?
|
// 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);
|
const QString searchTerm = d->searchTermFromCursor(adjustedCursor);
|
||||||
if (searchTerm.isEmpty())
|
if (searchTerm.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (replacement && versionNumber() >= QVersionNumber(16)
|
if (replacement && versionNumber() >= QVersionNumber(16)
|
||||||
&& Utils::qtcEnvironmentVariable("QTC_CLANGD_RENAMING") != "0") {
|
&& Utils::qtcEnvironmentVariable("QTC_CLANGD_RENAMING") != "0") {
|
||||||
symbolSupport().renameSymbol(document, adjustedCursor, *replacement, renameCallback,
|
|
||||||
CppEditor::preferLowerCaseFileNames());
|
// If we have up-to-date highlighting data, we can prevent giving clangd
|
||||||
return;
|
// 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();
|
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) {
|
if (searchTerm != "operator" && Utils::allOf(searchTerm, [](const QChar &c) {
|
||||||
return c.isLetterOrNumber() || c == '_';
|
return c.isLetterOrNumber() || c == '_';
|
||||||
})) {
|
})) {
|
||||||
d->findUsages(document, adjustedCursor, searchTerm, replacement, renameCallback, categorize);
|
d->findUsages(cursor.textDocument(), adjustedCursor, searchTerm, replacement,
|
||||||
|
renameCallback, categorize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise get the proper spelling of the search term from clang, so we can put it into the
|
// Otherwise get the proper spelling of the search term from clang, so we can put it into the
|
||||||
// search widget.
|
// search widget.
|
||||||
const auto symbolInfoHandler = [this, doc = QPointer(document), adjustedCursor, replacement,
|
const auto symbolInfoHandler = [this, doc = QPointer(cursor.textDocument()), adjustedCursor,
|
||||||
renameCallback, categorize]
|
replacement, renameCallback, categorize]
|
||||||
(const QString &name, const QString &, const MessageId &) {
|
(const QString &name, const QString &, const MessageId &) {
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return;
|
||||||
@@ -546,7 +582,8 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
|||||||
return;
|
return;
|
||||||
d->findUsages(doc.data(), adjustedCursor, name, replacement, renameCallback, categorize);
|
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,
|
void ClangdClient::checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
||||||
|
@@ -53,7 +53,7 @@ public:
|
|||||||
void openExtraFile(const Utils::FilePath &filePath, const QString &content = {});
|
void openExtraFile(const Utils::FilePath &filePath, const QString &content = {});
|
||||||
void closeExtraFile(const Utils::FilePath &filePath);
|
void closeExtraFile(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
void findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
|
void findUsages(const CppEditor::CursorInEditor &cursor,
|
||||||
const std::optional<QString> &replacement,
|
const std::optional<QString> &replacement,
|
||||||
const std::function<void()> &renameCallback);
|
const std::function<void()> &renameCallback);
|
||||||
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
||||||
|
@@ -320,7 +320,7 @@ void ClangModelManagerSupport::globalRename(const CppEditor::CursorInEditor &cur
|
|||||||
client && client->isFullyIndexed()) {
|
client && client->isFullyIndexed()) {
|
||||||
QTC_ASSERT(client->documentOpen(cursor.textDocument()),
|
QTC_ASSERT(client->documentOpen(cursor.textDocument()),
|
||||||
client->openDocument(cursor.textDocument()));
|
client->openDocument(cursor.textDocument()));
|
||||||
client->findUsages(cursor.textDocument(), cursor.cursor(), replacement, callback);
|
client->findUsages(cursor, replacement, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CppModelManager::globalRename(cursor, replacement, callback, CppModelManager::Backend::Builtin);
|
CppModelManager::globalRename(cursor, replacement, callback, CppModelManager::Backend::Builtin);
|
||||||
@@ -332,8 +332,7 @@ void ClangModelManagerSupport::findUsages(const CppEditor::CursorInEditor &curso
|
|||||||
client && client->isFullyIndexed()) {
|
client && client->isFullyIndexed()) {
|
||||||
QTC_ASSERT(client->documentOpen(cursor.textDocument()),
|
QTC_ASSERT(client->documentOpen(cursor.textDocument()),
|
||||||
client->openDocument(cursor.textDocument()));
|
client->openDocument(cursor.textDocument()));
|
||||||
client->findUsages(cursor.textDocument(), cursor.cursor(), {}, {});
|
client->findUsages(cursor, {}, {});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CppModelManager::findUsages(cursor, CppModelManager::Backend::Builtin);
|
CppModelManager::findUsages(cursor, CppModelManager::Backend::Builtin);
|
||||||
|
@@ -294,7 +294,7 @@ void ClangdTestFindReferences::test()
|
|||||||
QVERIFY(doc);
|
QVERIFY(doc);
|
||||||
QTextCursor cursor(doc->document());
|
QTextCursor cursor(doc->document());
|
||||||
cursor.setPosition(pos);
|
cursor.setPosition(pos);
|
||||||
client()->findUsages(doc, cursor, {}, {});
|
client()->findUsages(CppEditor::CursorInEditor(cursor, doc->filePath(), nullptr, doc), {}, {});
|
||||||
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::findUsagesDone, timeOutInMs()));
|
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::findUsagesDone, timeOutInMs()));
|
||||||
|
|
||||||
QCOMPARE(m_actualResults.size(), expectedResults.size());
|
QCOMPARE(m_actualResults.size(), expectedResults.size());
|
||||||
|
Reference in New Issue
Block a user