forked from qt-creator/qt-creator
Designer: Update C++ code model on an object name change in designer
We try to locate the old symbol name in the generated ui header and rename the symbol in the background. Task-number: QTCREATORBUG-1179 Change-Id: Iaf68e3922cd728cbc87d0dc97125e34b8bdaa6be Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -292,7 +292,7 @@ public:
|
|||||||
|
|
||||||
void findUsages(TextDocument *document, const QTextCursor &cursor,
|
void findUsages(TextDocument *document, const QTextCursor &cursor,
|
||||||
const QString &searchTerm, const std::optional<QString> &replacement,
|
const QString &searchTerm, const std::optional<QString> &replacement,
|
||||||
bool categorize);
|
const std::function<void()> &callback, bool categorize);
|
||||||
|
|
||||||
void handleDeclDefSwitchReplies();
|
void handleDeclDefSwitchReplies();
|
||||||
|
|
||||||
@@ -509,7 +509,8 @@ void ClangdClient::closeExtraFile(const Utils::FilePath &filePath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
||||||
const std::optional<QString> &replacement)
|
const std::optional<QString> &replacement,
|
||||||
|
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, document);
|
||||||
@@ -519,7 +520,7 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
|||||||
|
|
||||||
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,
|
symbolSupport().renameSymbol(document, adjustedCursor, *replacement, renameCallback,
|
||||||
CppEditor::preferLowerCaseFileNames());
|
CppEditor::preferLowerCaseFileNames());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -530,19 +531,20 @@ 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, categorize);
|
d->findUsages(document, 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, categorize]
|
const auto symbolInfoHandler = [this, doc = QPointer(document), adjustedCursor, replacement,
|
||||||
|
renameCallback, categorize]
|
||||||
(const QString &name, const QString &, const MessageId &) {
|
(const QString &name, const QString &, const MessageId &) {
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return;
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
return;
|
return;
|
||||||
d->findUsages(doc.data(), adjustedCursor, name, replacement, categorize);
|
d->findUsages(doc.data(), adjustedCursor, name, replacement, renameCallback, categorize);
|
||||||
};
|
};
|
||||||
requestSymbolInfo(document->filePath(), Range(adjustedCursor).start(), symbolInfoHandler);
|
requestSymbolInfo(document->filePath(), Range(adjustedCursor).start(), symbolInfoHandler);
|
||||||
}
|
}
|
||||||
@@ -704,10 +706,11 @@ CppEditor::ClangdSettings::Data ClangdClient::settingsData() const { return d->s
|
|||||||
|
|
||||||
void ClangdClient::Private::findUsages(TextDocument *document,
|
void ClangdClient::Private::findUsages(TextDocument *document,
|
||||||
const QTextCursor &cursor, const QString &searchTerm,
|
const QTextCursor &cursor, const QString &searchTerm,
|
||||||
const std::optional<QString> &replacement, bool categorize)
|
const std::optional<QString> &replacement, const std::function<void()> &renameCallback,
|
||||||
|
bool categorize)
|
||||||
{
|
{
|
||||||
const auto findRefs = new ClangdFindReferences(q, document, cursor, searchTerm, replacement,
|
const auto findRefs = new ClangdFindReferences(q, document, cursor, searchTerm, replacement,
|
||||||
categorize);
|
renameCallback, categorize);
|
||||||
if (isTesting) {
|
if (isTesting) {
|
||||||
connect(findRefs, &ClangdFindReferences::foundReferences,
|
connect(findRefs, &ClangdFindReferences::foundReferences,
|
||||||
q, &ClangdClient::foundReferences);
|
q, &ClangdClient::foundReferences);
|
||||||
|
@@ -54,7 +54,8 @@ public:
|
|||||||
void closeExtraFile(const Utils::FilePath &filePath);
|
void closeExtraFile(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
void findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
|
void findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
|
||||||
const std::optional<QString> &replacement);
|
const std::optional<QString> &replacement,
|
||||||
|
const std::function<void()> &renameCallback);
|
||||||
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
||||||
const Utils::LinkHandler &callback);
|
const Utils::LinkHandler &callback);
|
||||||
void followSymbol(TextEditor::TextDocument *document,
|
void followSymbol(TextEditor::TextDocument *document,
|
||||||
|
@@ -109,7 +109,8 @@ public:
|
|||||||
|
|
||||||
ClangdFindReferences::ClangdFindReferences(ClangdClient *client, TextDocument *document,
|
ClangdFindReferences::ClangdFindReferences(ClangdClient *client, TextDocument *document,
|
||||||
const QTextCursor &cursor, const QString &searchTerm,
|
const QTextCursor &cursor, const QString &searchTerm,
|
||||||
const std::optional<QString> &replacement, bool categorize)
|
const std::optional<QString> &replacement, const std::function<void()> &callback,
|
||||||
|
bool categorize)
|
||||||
: QObject(client), d(new ClangdFindReferences::Private(this))
|
: QObject(client), d(new ClangdFindReferences::Private(this))
|
||||||
{
|
{
|
||||||
d->categorize = categorize;
|
d->categorize = categorize;
|
||||||
@@ -130,6 +131,7 @@ ClangdFindReferences::ClangdFindReferences(ClangdClient *client, TextDocument *d
|
|||||||
replacement ? SearchResultWindow::SearchAndReplace : SearchResultWindow::SearchOnly,
|
replacement ? SearchResultWindow::SearchAndReplace : SearchResultWindow::SearchOnly,
|
||||||
SearchResultWindow::PreserveCaseDisabled,
|
SearchResultWindow::PreserveCaseDisabled,
|
||||||
"CppEditor");
|
"CppEditor");
|
||||||
|
d->search->makeNonInteractive(callback);
|
||||||
if (categorize)
|
if (categorize)
|
||||||
d->search->setFilter(new CppSearchResultFilter);
|
d->search->setFilter(new CppSearchResultFilter);
|
||||||
if (d->replacementData) {
|
if (d->replacementData) {
|
||||||
@@ -150,6 +152,7 @@ ClangdFindReferences::ClangdFindReferences(ClangdClient *client, TextDocument *d
|
|||||||
connect(d->search, &SearchResult::activated, [](const SearchResultItem& item) {
|
connect(d->search, &SearchResult::activated, [](const SearchResultItem& item) {
|
||||||
EditorManager::openEditorAtSearchResult(item);
|
EditorManager::openEditorAtSearchResult(item);
|
||||||
});
|
});
|
||||||
|
if (d->search->isInteractive())
|
||||||
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||||
|
|
||||||
const std::optional<MessageId> requestId = client->symbolSupport().findUsages(
|
const std::optional<MessageId> requestId = client->symbolSupport().findUsages(
|
||||||
|
@@ -27,7 +27,9 @@ class ClangdFindReferences : public QObject
|
|||||||
public:
|
public:
|
||||||
ClangdFindReferences(ClangdClient *client, TextEditor::TextDocument *document,
|
ClangdFindReferences(ClangdClient *client, TextEditor::TextDocument *document,
|
||||||
const QTextCursor &cursor, const QString &searchTerm,
|
const QTextCursor &cursor, const QString &searchTerm,
|
||||||
const std::optional<QString> &replacement, bool categorize);
|
const std::optional<QString> &replacement,
|
||||||
|
const std::function<void()> &callback,
|
||||||
|
bool categorize);
|
||||||
ClangdFindReferences(ClangdClient *client, const Utils::Link &link, Core::SearchResult *search,
|
ClangdFindReferences(ClangdClient *client, const Utils::Link &link, Core::SearchResult *search,
|
||||||
const Utils::LinkHandler &callback);
|
const Utils::LinkHandler &callback);
|
||||||
~ClangdFindReferences();
|
~ClangdFindReferences();
|
||||||
|
@@ -313,16 +313,17 @@ void ClangModelManagerSupport::startLocalRenaming(const CppEditor::CursorInEdito
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClangModelManagerSupport::globalRename(const CppEditor::CursorInEditor &cursor,
|
void ClangModelManagerSupport::globalRename(const CppEditor::CursorInEditor &cursor,
|
||||||
const QString &replacement)
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback)
|
||||||
{
|
{
|
||||||
if (ClangdClient * const client = clientForFile(cursor.filePath());
|
if (ClangdClient * const client = clientForFile(cursor.filePath());
|
||||||
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);
|
client->findUsages(cursor.textDocument(), cursor.cursor(), replacement, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CppModelManager::globalRename(cursor, replacement, CppModelManager::Backend::Builtin);
|
CppModelManager::globalRename(cursor, replacement, callback, CppModelManager::Backend::Builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangModelManagerSupport::findUsages(const CppEditor::CursorInEditor &cursor) const
|
void ClangModelManagerSupport::findUsages(const CppEditor::CursorInEditor &cursor) const
|
||||||
@@ -331,7 +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.textDocument(), cursor.cursor(), {}, {});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,8 @@ private:
|
|||||||
void startLocalRenaming(const CppEditor::CursorInEditor &data,
|
void startLocalRenaming(const CppEditor::CursorInEditor &data,
|
||||||
const CppEditor::ProjectPart *projectPart,
|
const CppEditor::ProjectPart *projectPart,
|
||||||
CppEditor::RenameCallback &&renameSymbolsCallback) override;
|
CppEditor::RenameCallback &&renameSymbolsCallback) override;
|
||||||
void globalRename(const CppEditor::CursorInEditor &cursor, const QString &replacement) override;
|
void globalRename(const CppEditor::CursorInEditor &cursor, const QString &replacement,
|
||||||
|
const std::function<void()> &callback) override;
|
||||||
void findUsages(const CppEditor::CursorInEditor &cursor) const override;
|
void findUsages(const CppEditor::CursorInEditor &cursor) const override;
|
||||||
void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
|
void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
|
||||||
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
||||||
|
@@ -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(doc, cursor, {}, {});
|
||||||
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::findUsagesDone, timeOutInMs()));
|
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::findUsagesDone, timeOutInMs()));
|
||||||
|
|
||||||
QCOMPARE(m_actualResults.size(), expectedResults.size());
|
QCOMPARE(m_actualResults.size(), expectedResults.size());
|
||||||
|
@@ -1401,4 +1401,11 @@ void CMakeBuildSystem::runGenerator(Id id)
|
|||||||
proc->start();
|
proc->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompiler *CMakeBuildSystem::extraCompilerForSource(const Utils::FilePath &source)
|
||||||
|
{
|
||||||
|
return Utils::findOrDefault(m_extraCompilers, [source](ExtraCompiler *ec) {
|
||||||
|
return ec->source() == source;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // CMakeProjectManager::Internal
|
} // CMakeProjectManager::Internal
|
||||||
|
@@ -122,6 +122,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QList<QPair<Utils::Id, QString>> generators() const override;
|
QList<QPair<Utils::Id, QString>> generators() const override;
|
||||||
void runGenerator(Utils::Id id) override;
|
void runGenerator(Utils::Id id) override;
|
||||||
|
ProjectExplorer::ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source) override;
|
||||||
|
|
||||||
enum ForceEnabledChanged { False, True };
|
enum ForceEnabledChanged { False, True };
|
||||||
void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
|
void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
|
||||||
|
@@ -468,12 +468,16 @@ void SearchResultWidget::handleReplaceButton()
|
|||||||
{
|
{
|
||||||
// check if button is actually enabled, because this is also triggered
|
// check if button is actually enabled, because this is also triggered
|
||||||
// by pressing return in replace line edit
|
// by pressing return in replace line edit
|
||||||
if (m_replaceButton->isEnabled()) {
|
if (m_replaceButton->isEnabled())
|
||||||
|
doReplace();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchResultWidget::doReplace()
|
||||||
|
{
|
||||||
m_infoBar.clear();
|
m_infoBar.clear();
|
||||||
setShowReplaceUI(false);
|
setShowReplaceUI(false);
|
||||||
emit replaceButtonClicked(m_replaceTextEdit->text(), checkedItems(),
|
emit replaceButtonClicked(m_replaceTextEdit->text(), checkedItems(),
|
||||||
m_preserveCaseSupported && m_preserveCaseCheck->isChecked());
|
m_preserveCaseSupported && m_preserveCaseCheck->isChecked());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultWidget::cancel()
|
void SearchResultWidget::cancel()
|
||||||
|
@@ -39,6 +39,7 @@ public:
|
|||||||
|
|
||||||
void setSupportsReplace(bool replaceSupported, const QString &group);
|
void setSupportsReplace(bool replaceSupported, const QString &group);
|
||||||
bool supportsReplace() const;
|
bool supportsReplace() const;
|
||||||
|
void triggerReplace() { doReplace(); }
|
||||||
|
|
||||||
void setTextToReplace(const QString &textToReplace);
|
void setTextToReplace(const QString &textToReplace);
|
||||||
QString textToReplace() const;
|
QString textToReplace() const;
|
||||||
@@ -91,6 +92,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
void handleJumpToSearchResult(const SearchResultItem &item);
|
void handleJumpToSearchResult(const SearchResultItem &item);
|
||||||
void handleReplaceButton();
|
void handleReplaceButton();
|
||||||
|
void doReplace();
|
||||||
void cancel();
|
void cancel();
|
||||||
void searchAgain();
|
void searchAgain();
|
||||||
|
|
||||||
|
@@ -850,6 +850,12 @@ void SearchResult::setFilter(SearchResultFilter *filter)
|
|||||||
void SearchResult::finishSearch(bool canceled, const QString &reason)
|
void SearchResult::finishSearch(bool canceled, const QString &reason)
|
||||||
{
|
{
|
||||||
m_widget->finishSearch(canceled, reason);
|
m_widget->finishSearch(canceled, reason);
|
||||||
|
if (m_finishedHandler) {
|
||||||
|
if (!canceled)
|
||||||
|
m_widget->triggerReplace();
|
||||||
|
m_finishedHandler();
|
||||||
|
m_finishedHandler = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -893,6 +899,13 @@ void SearchResult::popup()
|
|||||||
m_widget->sendRequestPopup();
|
m_widget->sendRequestPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::SearchResult::makeNonInteractive(const std::function<void ()> &callback)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(callback, return);
|
||||||
|
m_widget->setEnabled(false);
|
||||||
|
m_finishedHandler = callback;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
#include "searchresultwindow.moc"
|
#include "searchresultwindow.moc"
|
||||||
|
@@ -12,6 +12,8 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QFont;
|
class QFont;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -53,6 +55,8 @@ public:
|
|||||||
void setSearchAgainSupported(bool supported);
|
void setSearchAgainSupported(bool supported);
|
||||||
QWidget *additionalReplaceWidget() const;
|
QWidget *additionalReplaceWidget() const;
|
||||||
void setAdditionalReplaceWidget(QWidget *widget);
|
void setAdditionalReplaceWidget(QWidget *widget);
|
||||||
|
void makeNonInteractive(const std::function<void()> &callback);
|
||||||
|
bool isInteractive() const { return !m_finishedHandler; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void addResult(const SearchResultItem &item);
|
void addResult(const SearchResultItem &item);
|
||||||
@@ -83,6 +87,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
Internal::SearchResultWidget *m_widget;
|
Internal::SearchResultWidget *m_widget;
|
||||||
QVariant m_userData;
|
QVariant m_userData;
|
||||||
|
std::function<void()> m_finishedHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CORE_EXPORT SearchResultWindow : public IOutputPane
|
class CORE_EXPORT SearchResultWindow : public IOutputPane
|
||||||
|
@@ -142,7 +142,8 @@ void BuiltinModelManagerSupport::startLocalRenaming(const CursorInEditor &data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BuiltinModelManagerSupport::globalRename(const CursorInEditor &data,
|
void BuiltinModelManagerSupport::globalRename(const CursorInEditor &data,
|
||||||
const QString &replacement)
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback)
|
||||||
{
|
{
|
||||||
CppModelManager *modelManager = CppModelManager::instance();
|
CppModelManager *modelManager = CppModelManager::instance();
|
||||||
if (!modelManager)
|
if (!modelManager)
|
||||||
@@ -161,7 +162,7 @@ void BuiltinModelManagerSupport::globalRename(const CursorInEditor &data,
|
|||||||
Internal::CanonicalSymbol cs(info.doc, info.snapshot);
|
Internal::CanonicalSymbol cs(info.doc, info.snapshot);
|
||||||
CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
|
CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
|
||||||
if (canonicalSymbol)
|
if (canonicalSymbol)
|
||||||
modelManager->renameUsages(canonicalSymbol, cs.context(), replacement);
|
modelManager->renameUsages(canonicalSymbol, cs.context(), replacement, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,7 +38,8 @@ private:
|
|||||||
void startLocalRenaming(const CursorInEditor &data,
|
void startLocalRenaming(const CursorInEditor &data,
|
||||||
const ProjectPart *projectPart,
|
const ProjectPart *projectPart,
|
||||||
RenameCallback &&renameSymbolsCallback) override;
|
RenameCallback &&renameSymbolsCallback) override;
|
||||||
void globalRename(const CursorInEditor &data, const QString &replacement) override;
|
void globalRename(const CursorInEditor &data, const QString &replacement,
|
||||||
|
const std::function<void()> &callback) override;
|
||||||
void findUsages(const CursorInEditor &data) const override;
|
void findUsages(const CursorInEditor &data) const override;
|
||||||
void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
|
void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) override;
|
||||||
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
void checkUnused(const Utils::Link &link, Core::SearchResult *search,
|
||||||
|
@@ -619,6 +619,16 @@ void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor curso
|
|||||||
d->m_modelManager->globalRename(cursorInEditor, replacement);
|
d->m_modelManager->globalRename(cursorInEditor, replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppEditorWidget::renameUsages(const Utils::FilePath &filePath, const QString &replacement,
|
||||||
|
QTextCursor cursor, const std::function<void ()> &callback)
|
||||||
|
{
|
||||||
|
if (cursor.isNull())
|
||||||
|
cursor = textCursor();
|
||||||
|
CursorInEditor cursorInEditor{cursor, filePath, this, textDocument()};
|
||||||
|
QPointer<CppEditorWidget> cppEditorWidget = this;
|
||||||
|
d->m_modelManager->globalRename(cursorInEditor, replacement, callback);
|
||||||
|
}
|
||||||
|
|
||||||
bool CppEditorWidget::selectBlockUp()
|
bool CppEditorWidget::selectBlockUp()
|
||||||
{
|
{
|
||||||
if (!behaviorSettings().m_smartSelectionChanging)
|
if (!behaviorSettings().m_smartSelectionChanging)
|
||||||
@@ -1160,7 +1170,7 @@ void CppEditorWidget::updateSemanticInfo()
|
|||||||
void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo,
|
void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo,
|
||||||
bool updateUseSelectionSynchronously)
|
bool updateUseSelectionSynchronously)
|
||||||
{
|
{
|
||||||
if (semanticInfo.revision != documentRevision())
|
if (semanticInfo.revision < documentRevision())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->m_lastSemanticInfo = semanticInfo;
|
d->m_lastSemanticInfo = semanticInfo;
|
||||||
|
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
class IAssistProposal;
|
class IAssistProposal;
|
||||||
class IAssistProvider;
|
class IAssistProvider;
|
||||||
@@ -61,6 +63,10 @@ public:
|
|||||||
void findUsages(QTextCursor cursor);
|
void findUsages(QTextCursor cursor);
|
||||||
void renameUsages(const QString &replacement = QString(),
|
void renameUsages(const QString &replacement = QString(),
|
||||||
QTextCursor cursor = QTextCursor());
|
QTextCursor cursor = QTextCursor());
|
||||||
|
void renameUsages(const Utils::FilePath &filePath,
|
||||||
|
const QString &replacement = QString(),
|
||||||
|
QTextCursor cursor = QTextCursor(),
|
||||||
|
const std::function<void()> &callback = {});
|
||||||
void renameSymbolUnderCursor() override;
|
void renameSymbolUnderCursor() override;
|
||||||
|
|
||||||
bool selectBlockUp() override;
|
bool selectBlockUp() override;
|
||||||
|
@@ -368,12 +368,13 @@ static void find_helper(QFutureInterface<CPlusPlus::Usage> &future,
|
|||||||
void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
||||||
const CPlusPlus::LookupContext &context)
|
const CPlusPlus::LookupContext &context)
|
||||||
{
|
{
|
||||||
findUsages(symbol, context, QString(), false);
|
findUsages(symbol, context, QString(), {}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
||||||
const CPlusPlus::LookupContext &context,
|
const CPlusPlus::LookupContext &context,
|
||||||
const QString &replacement,
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback,
|
||||||
bool replace)
|
bool replace)
|
||||||
{
|
{
|
||||||
CPlusPlus::Overview overview;
|
CPlusPlus::Overview overview;
|
||||||
@@ -385,6 +386,8 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
|||||||
SearchResultWindow::PreserveCaseDisabled,
|
SearchResultWindow::PreserveCaseDisabled,
|
||||||
QLatin1String("CppEditor"));
|
QLatin1String("CppEditor"));
|
||||||
search->setTextToReplace(replacement);
|
search->setTextToReplace(replacement);
|
||||||
|
if (callback)
|
||||||
|
search->makeNonInteractive(callback);
|
||||||
if (codeModelSettings()->categorizeFindReferences())
|
if (codeModelSettings()->categorizeFindReferences())
|
||||||
search->setFilter(new CppSearchResultFilter);
|
search->setFilter(new CppSearchResultFilter);
|
||||||
setupSearch(search);
|
setupSearch(search);
|
||||||
@@ -408,12 +411,13 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
|
|||||||
|
|
||||||
void CppFindReferences::renameUsages(CPlusPlus::Symbol *symbol,
|
void CppFindReferences::renameUsages(CPlusPlus::Symbol *symbol,
|
||||||
const CPlusPlus::LookupContext &context,
|
const CPlusPlus::LookupContext &context,
|
||||||
const QString &replacement)
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback)
|
||||||
{
|
{
|
||||||
if (const CPlusPlus::Identifier *id = symbol->identifier()) {
|
if (const CPlusPlus::Identifier *id = symbol->identifier()) {
|
||||||
const QString textToReplace = replacement.isEmpty()
|
const QString textToReplace = replacement.isEmpty()
|
||||||
? QString::fromUtf8(id->chars(), id->size()) : replacement;
|
? QString::fromUtf8(id->chars(), id->size()) : replacement;
|
||||||
findUsages(symbol, context, textToReplace, true);
|
findUsages(symbol, context, textToReplace, callback, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +433,7 @@ void CppFindReferences::findAll_helper(SearchResult *search, CPlusPlus::Symbol *
|
|||||||
Core::EditorManager::openEditorAtSearchResult(item);
|
Core::EditorManager::openEditorAtSearchResult(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (search->isInteractive())
|
||||||
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||||
const WorkingCopy workingCopy = m_modelManager->workingCopy();
|
const WorkingCopy workingCopy = m_modelManager->workingCopy();
|
||||||
QFuture<CPlusPlus::Usage> result;
|
QFuture<CPlusPlus::Usage> result;
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QTimer)
|
QT_FORWARD_DECLARE_CLASS(QTimer)
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
@@ -65,7 +67,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
|
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
|
||||||
void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
||||||
const QString &replacement = QString());
|
const QString &replacement = QString(),
|
||||||
|
const std::function<void()> &callback = {});
|
||||||
|
|
||||||
void findMacroUses(const CPlusPlus::Macro ¯o);
|
void findMacroUses(const CPlusPlus::Macro ¯o);
|
||||||
void renameMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement = QString());
|
void renameMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement = QString());
|
||||||
@@ -80,7 +83,8 @@ private:
|
|||||||
void searchAgain(Core::SearchResult *search);
|
void searchAgain(Core::SearchResult *search);
|
||||||
|
|
||||||
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
||||||
const QString &replacement, bool replace);
|
const QString &replacement, const std::function<void ()> &callback,
|
||||||
|
bool replace);
|
||||||
void findMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement,
|
void findMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement,
|
||||||
bool replace);
|
bool replace);
|
||||||
void findAll_helper(Core::SearchResult *search, CPlusPlus::Symbol *symbol,
|
void findAll_helper(Core::SearchResult *search, CPlusPlus::Symbol *symbol,
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "abstracteditorsupport.h"
|
#include "abstracteditorsupport.h"
|
||||||
#include "baseeditordocumentprocessor.h"
|
#include "baseeditordocumentprocessor.h"
|
||||||
#include "compileroptionsbuilder.h"
|
#include "compileroptionsbuilder.h"
|
||||||
|
#include "cppcanonicalsymbol.h"
|
||||||
#include "cppcodemodelinspectordumper.h"
|
#include "cppcodemodelinspectordumper.h"
|
||||||
#include "cppcodemodelsettings.h"
|
#include "cppcodemodelsettings.h"
|
||||||
#include "cppcurrentdocumentfilter.h"
|
#include "cppcurrentdocumentfilter.h"
|
||||||
@@ -325,9 +326,9 @@ void CppModelManager::startLocalRenaming(const CursorInEditor &data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CppModelManager::globalRename(const CursorInEditor &data, const QString &replacement,
|
void CppModelManager::globalRename(const CursorInEditor &data, const QString &replacement,
|
||||||
Backend backend)
|
const std::function<void()> &callback, Backend backend)
|
||||||
{
|
{
|
||||||
instance()->modelManagerSupport(backend)->globalRename(data, replacement);
|
instance()->modelManagerSupport(backend)->globalRename(data, replacement, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppModelManager::findUsages(const CursorInEditor &data, Backend backend)
|
void CppModelManager::findUsages(const CursorInEditor &data, Backend backend)
|
||||||
@@ -1170,10 +1171,21 @@ void CppModelManager::findUsages(Symbol *symbol, const LookupContext &context)
|
|||||||
|
|
||||||
void CppModelManager::renameUsages(Symbol *symbol,
|
void CppModelManager::renameUsages(Symbol *symbol,
|
||||||
const LookupContext &context,
|
const LookupContext &context,
|
||||||
const QString &replacement)
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback)
|
||||||
{
|
{
|
||||||
if (symbol->identifier())
|
if (symbol->identifier())
|
||||||
d->m_findReferences->renameUsages(symbol, context, replacement);
|
d->m_findReferences->renameUsages(symbol, context, replacement, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppModelManager::renameUsages(const Document::Ptr &doc, const QTextCursor &cursor,
|
||||||
|
const Snapshot &snapshot, const QString &replacement,
|
||||||
|
const std::function<void ()> &callback)
|
||||||
|
{
|
||||||
|
Internal::CanonicalSymbol cs(doc, snapshot);
|
||||||
|
CPlusPlus::Symbol *canonicalSymbol = cs(cursor);
|
||||||
|
if (canonicalSymbol)
|
||||||
|
renameUsages(canonicalSymbol, cs.context(), replacement, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppModelManager::findMacroUsages(const CPlusPlus::Macro ¯o)
|
void CppModelManager::findMacroUsages(const CPlusPlus::Macro ¯o)
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
@@ -149,7 +150,13 @@ public:
|
|||||||
int position) const;
|
int position) const;
|
||||||
|
|
||||||
void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context,
|
||||||
const QString &replacement = QString());
|
const QString &replacement = QString(),
|
||||||
|
const std::function<void()> &callback = {});
|
||||||
|
void renameUsages(const CPlusPlus::Document::Ptr &doc,
|
||||||
|
const QTextCursor &cursor,
|
||||||
|
const CPlusPlus::Snapshot &snapshot,
|
||||||
|
const QString &replacement,
|
||||||
|
const std::function<void()> &callback);
|
||||||
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
|
void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
|
||||||
|
|
||||||
void findMacroUsages(const CPlusPlus::Macro ¯o);
|
void findMacroUsages(const CPlusPlus::Macro ¯o);
|
||||||
@@ -178,6 +185,7 @@ public:
|
|||||||
RenameCallback &&renameSymbolsCallback,
|
RenameCallback &&renameSymbolsCallback,
|
||||||
Backend backend = Backend::Best);
|
Backend backend = Backend::Best);
|
||||||
static void globalRename(const CursorInEditor &data, const QString &replacement,
|
static void globalRename(const CursorInEditor &data, const QString &replacement,
|
||||||
|
const std::function<void()> &callback = {},
|
||||||
Backend backend = Backend::Best);
|
Backend backend = Backend::Best);
|
||||||
static void findUsages(const CursorInEditor &data, Backend backend = Backend::Best);
|
static void findUsages(const CursorInEditor &data, Backend backend = Backend::Best);
|
||||||
static void switchHeaderSource(bool inNextSplit, Backend backend = Backend::Best);
|
static void switchHeaderSource(bool inNextSplit, Backend backend = Backend::Best);
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Core { class SearchResult; }
|
namespace Core { class SearchResult; }
|
||||||
@@ -49,7 +50,8 @@ public:
|
|||||||
virtual void startLocalRenaming(const CursorInEditor &data,
|
virtual void startLocalRenaming(const CursorInEditor &data,
|
||||||
const ProjectPart *projectPart,
|
const ProjectPart *projectPart,
|
||||||
RenameCallback &&renameSymbolsCallback) = 0;
|
RenameCallback &&renameSymbolsCallback) = 0;
|
||||||
virtual void globalRename(const CursorInEditor &data, const QString &replacement) = 0;
|
virtual void globalRename(const CursorInEditor &data, const QString &replacement,
|
||||||
|
const std::function<void()> &callback) = 0;
|
||||||
virtual void findUsages(const CursorInEditor &data) const = 0;
|
virtual void findUsages(const CursorInEditor &data) const = 0;
|
||||||
virtual void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) = 0;
|
virtual void switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit) = 0;
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "designertr.h"
|
#include "designertr.h"
|
||||||
#include "editordata.h"
|
|
||||||
#include "formeditorw.h"
|
#include "formeditorw.h"
|
||||||
#include "formwindoweditor.h"
|
#include "formwindoweditor.h"
|
||||||
#include "qtcreatorintegration.h"
|
#include "qtcreatorintegration.h"
|
||||||
@@ -10,7 +9,9 @@
|
|||||||
#include <designer/cpp/formclasswizardpage.h>
|
#include <designer/cpp/formclasswizardpage.h>
|
||||||
|
|
||||||
#include <cppeditor/cppeditorconstants.h>
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
|
#include <cppeditor/cppeditorwidget.h>
|
||||||
#include <cppeditor/cppmodelmanager.h>
|
#include <cppeditor/cppmodelmanager.h>
|
||||||
|
#include <cppeditor/cppsemanticinfo.h>
|
||||||
#include <cppeditor/cpptoolsreuse.h>
|
#include <cppeditor/cpptoolsreuse.h>
|
||||||
#include <cppeditor/cppworkingcopy.h>
|
#include <cppeditor/cppworkingcopy.h>
|
||||||
#include <cppeditor/insertionpointlocator.h>
|
#include <cppeditor/insertionpointlocator.h>
|
||||||
@@ -19,28 +20,38 @@
|
|||||||
#include <cplusplus/Overview.h>
|
#include <cplusplus/Overview.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/messagemanager.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
#include <projectexplorer/buildsystem.h>
|
||||||
|
#include <projectexplorer/extracompiler.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/projecttree.h>
|
#include <projectexplorer/projecttree.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/mimeutils.h>
|
#include <utils/mimeutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
|
#include <utils/temporaryfile.h>
|
||||||
|
|
||||||
#include <QDesignerFormWindowInterface>
|
#include <QDesignerFormWindowInterface>
|
||||||
#include <QDesignerFormEditorInterface>
|
#include <QDesignerFormEditorInterface>
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QHash>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
enum { indentation = 4 };
|
enum { indentation = 4 };
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(log, "qtc.designer", QtWarningMsg);
|
||||||
|
|
||||||
using namespace Designer::Internal;
|
using namespace Designer::Internal;
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
@@ -60,8 +71,23 @@ static QString msgClassNotFound(const QString &uiClassName, const QList<Document
|
|||||||
.arg(uiClassName, files);
|
.arg(uiClassName, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reportRenamingError(const QString &oldName, const QString &reason)
|
||||||
|
{
|
||||||
|
Core::MessageManager::writeFlashing(
|
||||||
|
Designer::Tr::tr("Cannot rename UI symbol \"%1\" in C++ files: %2")
|
||||||
|
.arg(oldName, reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
class QtCreatorIntegration::Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// See QTCREATORBUG-19141 for why this is necessary.
|
||||||
|
QHash<QDesignerFormWindowInterface *, QPointer<ExtraCompiler>> extraCompilers;
|
||||||
|
std::optional<bool> showPropertyEditorRenameWarning = false;
|
||||||
|
};
|
||||||
|
|
||||||
QtCreatorIntegration::QtCreatorIntegration(QDesignerFormEditorInterface *core, QObject *parent)
|
QtCreatorIntegration::QtCreatorIntegration(QDesignerFormEditorInterface *core, QObject *parent)
|
||||||
: QDesignerIntegration(core, parent)
|
: QDesignerIntegration(core, parent), d(new Private)
|
||||||
{
|
{
|
||||||
setResourceFileWatcherBehaviour(ReloadResourceFileSilently);
|
setResourceFileWatcherBehaviour(ReloadResourceFileSilently);
|
||||||
Feature f = features();
|
Feature f = features();
|
||||||
@@ -77,6 +103,44 @@ QtCreatorIntegration::QtCreatorIntegration(QDesignerFormEditorInterface *core, Q
|
|||||||
slotSyncSettingsToDesigner();
|
slotSyncSettingsToDesigner();
|
||||||
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
|
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
|
||||||
this, &QtCreatorIntegration::slotSyncSettingsToDesigner);
|
this, &QtCreatorIntegration::slotSyncSettingsToDesigner);
|
||||||
|
|
||||||
|
// The problem is as follows:
|
||||||
|
// - If the user edits the object name in the property editor, the objectNameChanged() signal
|
||||||
|
// is emitted for every keystroke (QTCREATORBUG-19141). We should not try to rename
|
||||||
|
// in that case, because the signals will likely come in faster than the renaming
|
||||||
|
// procedure takes, putting the code model in some non-deterministic state.
|
||||||
|
// - Unfortunately, this condition is not trivial to detect, because the propertyChanged()
|
||||||
|
// signal is (somewhat surprisingly) emitted *after* objectNameChanged().
|
||||||
|
// - We can also not simply use a queued connection for objectNameChanged(), because then
|
||||||
|
// the ExtraCompiler might have run before our handler, and we won't find the old
|
||||||
|
// object name in the source code anymore.
|
||||||
|
// The solution is as follows:
|
||||||
|
// - Upon receiving objectNameChanged(), we retrieve the corresponding ExtraCompiler,
|
||||||
|
// block it and store it away. Then we invoke the actual handler delayed.
|
||||||
|
// - Upon receiving propertyChanged(), we check whether it refers to an object name change.
|
||||||
|
// If it does, we unblock the ExtraCompiler and remove it from our map.
|
||||||
|
// - When the real handler runs, it first checks for the ExtraCompiler. If it is not found,
|
||||||
|
// we don't do anything. Otherwise the actual renaming procedure is run.
|
||||||
|
connect(this, &QtCreatorIntegration::objectNameChanged,
|
||||||
|
this, &QtCreatorIntegration::handleSymbolRenameStage1);
|
||||||
|
connect(this, &QtCreatorIntegration::propertyChanged,
|
||||||
|
this, [this](QDesignerFormWindowInterface *formWindow, const QString &name,
|
||||||
|
const QVariant &) {
|
||||||
|
if (name == "objectName") {
|
||||||
|
if (const auto extraCompiler = d->extraCompilers.find(formWindow);
|
||||||
|
extraCompiler != d->extraCompilers.end()) {
|
||||||
|
(*extraCompiler)->unblock();
|
||||||
|
d->extraCompilers.erase(extraCompiler);
|
||||||
|
if (d->showPropertyEditorRenameWarning)
|
||||||
|
d->showPropertyEditorRenameWarning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QtCreatorIntegration::~QtCreatorIntegration()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCreatorIntegration::slotDesignerHelpRequested(const QString &manual, const QString &document)
|
void QtCreatorIntegration::slotDesignerHelpRequested(const QString &manual, const QString &document)
|
||||||
@@ -565,6 +629,162 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtCreatorIntegration::handleSymbolRenameStage1(
|
||||||
|
QDesignerFormWindowInterface *formWindow, QObject *object,
|
||||||
|
const QString &newName, const QString &oldName)
|
||||||
|
{
|
||||||
|
const FilePath uiFile = FilePath::fromString(formWindow->fileName());
|
||||||
|
qCDebug(log) << Q_FUNC_INFO << uiFile << object << oldName << newName;
|
||||||
|
if (newName.isEmpty() || newName == oldName)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get ExtraCompiler.
|
||||||
|
const Project * const project = SessionManager::projectForFile(uiFile);
|
||||||
|
if (!project) {
|
||||||
|
return reportRenamingError(oldName, Designer::Tr::tr("File \"%1\" not found in project.")
|
||||||
|
.arg(uiFile.toUserOutput()));
|
||||||
|
}
|
||||||
|
const Target * const target = project->activeTarget();
|
||||||
|
if (!target)
|
||||||
|
return reportRenamingError(oldName, Designer::Tr::tr("No active target."));
|
||||||
|
BuildSystem * const buildSystem = target->buildSystem();
|
||||||
|
if (!buildSystem)
|
||||||
|
return reportRenamingError(oldName, Designer::Tr::tr("No active build system."));
|
||||||
|
ExtraCompiler * const ec = buildSystem->extraCompilerForSource(uiFile);
|
||||||
|
if (!ec)
|
||||||
|
return reportRenamingError(oldName, Designer::Tr::tr("Failed to find the ui header."));
|
||||||
|
ec->block();
|
||||||
|
d->extraCompilers.insert(formWindow, ec);
|
||||||
|
qCDebug(log) << "\tfound extra compiler, scheduling stage 2";
|
||||||
|
QMetaObject::invokeMethod(this, [this, formWindow, newName, oldName] {
|
||||||
|
handleSymbolRenameStage2(formWindow, newName, oldName);
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtCreatorIntegration::handleSymbolRenameStage2(
|
||||||
|
QDesignerFormWindowInterface *formWindow, const QString &newName, const QString &oldName)
|
||||||
|
{
|
||||||
|
// Retrieve and check previously stored ExtraCompiler.
|
||||||
|
ExtraCompiler * const ec = d->extraCompilers.take(formWindow);
|
||||||
|
if (!ec) {
|
||||||
|
qCDebug(log) << "\tchange came from property editor, ignoring";
|
||||||
|
if (d->showPropertyEditorRenameWarning && *d->showPropertyEditorRenameWarning) {
|
||||||
|
d->showPropertyEditorRenameWarning.reset();
|
||||||
|
reportRenamingError(oldName, Designer::Tr::tr("Renaming via the property editor "
|
||||||
|
"cannot be synced with C++ code; see QTCREATORBUG-19141."
|
||||||
|
" This message will not be repeated."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResourceHandler {
|
||||||
|
public:
|
||||||
|
ResourceHandler(ExtraCompiler *ec) : m_ec(ec) {}
|
||||||
|
void setEditor(BaseTextEditor *editorToClose) { m_editorToClose = editorToClose; }
|
||||||
|
void setTempFile(std::unique_ptr<TemporaryFile> &&tempFile) {
|
||||||
|
m_tempFile = std::move(tempFile);
|
||||||
|
}
|
||||||
|
~ResourceHandler()
|
||||||
|
{
|
||||||
|
if (m_ec)
|
||||||
|
m_ec->unblock();
|
||||||
|
if (m_editorToClose)
|
||||||
|
Core::EditorManager::closeEditors({m_editorToClose}, false);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const QPointer<ExtraCompiler> m_ec;
|
||||||
|
QPointer<BaseTextEditor> m_editorToClose;
|
||||||
|
std::unique_ptr<TemporaryFile> m_tempFile;
|
||||||
|
};
|
||||||
|
const auto resourceHandler = std::make_shared<ResourceHandler>(ec);
|
||||||
|
|
||||||
|
QTC_ASSERT(ec->targets().size() == 1, return);
|
||||||
|
const FilePath uiHeader = ec->targets().first();
|
||||||
|
qCDebug(log) << '\t' << uiHeader;
|
||||||
|
const QByteArray virtualContent = ec->content(uiHeader);
|
||||||
|
if (virtualContent.isEmpty()) {
|
||||||
|
qCDebug(log) << "\textra compiler unexpectedly has no contents";
|
||||||
|
return reportRenamingError(oldName,
|
||||||
|
Designer::Tr::tr("Failed to retrieve ui header contents."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secretly open ui header file contents in editor.
|
||||||
|
// Use a temp file rather than the actual ui header path.
|
||||||
|
const auto openFlags = Core::EditorManager::DoNotMakeVisible
|
||||||
|
| Core::EditorManager::DoNotChangeCurrentEditor;
|
||||||
|
std::unique_ptr<TemporaryFile> tempFile
|
||||||
|
= std::make_unique<TemporaryFile>("XXXXXX" + uiHeader.fileName());
|
||||||
|
QTC_ASSERT(tempFile->open(), return);
|
||||||
|
qCDebug(log) << '\t' << tempFile->fileName();
|
||||||
|
const auto editor = qobject_cast<BaseTextEditor *>(
|
||||||
|
Core::EditorManager::openEditor(FilePath::fromString(tempFile->fileName()), {},
|
||||||
|
openFlags));
|
||||||
|
QTC_ASSERT(editor, return);
|
||||||
|
resourceHandler->setTempFile(std::move(tempFile));
|
||||||
|
resourceHandler->setEditor(editor);
|
||||||
|
|
||||||
|
const auto editorWidget = qobject_cast<CppEditor::CppEditorWidget *>(editor->editorWidget());
|
||||||
|
QTC_ASSERT(editorWidget && editorWidget->textDocument(), return);
|
||||||
|
|
||||||
|
// Parse temp file with built-in code model. Pretend it's the real ui header.
|
||||||
|
// In the case of clangd, this entails doing a "virtual rename" on the TextDocument,
|
||||||
|
// as the LanguageClient cannot be forced into taking a document and assuming a different
|
||||||
|
// file path.
|
||||||
|
const bool usesClangd = CppEditor::CppModelManager::usesClangd(editorWidget->textDocument());
|
||||||
|
if (usesClangd)
|
||||||
|
editorWidget->textDocument()->setFilePath(uiHeader);
|
||||||
|
editorWidget->textDocument()->setPlainText(QString::fromUtf8(virtualContent));
|
||||||
|
Snapshot snapshot = CppEditor::CppModelManager::instance()->snapshot();
|
||||||
|
snapshot.remove(uiHeader);
|
||||||
|
snapshot.remove(editor->textDocument()->filePath());
|
||||||
|
const Document::Ptr cppDoc = snapshot.preprocessedDocument(virtualContent, uiHeader);
|
||||||
|
cppDoc->check();
|
||||||
|
QTC_ASSERT(cppDoc && cppDoc->isParsed(), return);
|
||||||
|
|
||||||
|
// Locate old identifier in ui header.
|
||||||
|
const QByteArray oldNameBa = oldName.toUtf8();
|
||||||
|
const Identifier oldIdentifier(oldNameBa.constData(), oldNameBa.size());
|
||||||
|
QList<const Scope *> scopes{cppDoc->globalNamespace()};
|
||||||
|
while (!scopes.isEmpty()) {
|
||||||
|
const Scope * const scope = scopes.takeFirst();
|
||||||
|
qCDebug(log) << '\t' << scope->memberCount();
|
||||||
|
for (int i = 0; i < scope->memberCount(); ++i) {
|
||||||
|
Symbol * const symbol = scope->memberAt(i);
|
||||||
|
if (const Scope * const s = symbol->asScope())
|
||||||
|
scopes << s;
|
||||||
|
if (symbol->asNamespace())
|
||||||
|
continue;
|
||||||
|
qCDebug(log) << '\t' << Overview().prettyName(symbol->name());
|
||||||
|
if (!symbol->name()->match(&oldIdentifier))
|
||||||
|
continue;
|
||||||
|
QTextCursor cursor(editorWidget->textCursor());
|
||||||
|
cursor.setPosition(cppDoc->translationUnit()->getTokenPositionInDocument(
|
||||||
|
symbol->sourceLocation(), editorWidget->document()));
|
||||||
|
qCDebug(log) << '\t' << cursor.position() << cursor.blockNumber()
|
||||||
|
<< cursor.positionInBlock();
|
||||||
|
|
||||||
|
// Trigger non-interactive renaming. The callback is destructed after invocation,
|
||||||
|
// closing the editor, removing the temp file and unblocking the extra compiler.
|
||||||
|
// For the built-in code model, we must access the model manager directly,
|
||||||
|
// as otherwise our file path trickery would be found out.
|
||||||
|
const auto callback = [resourceHandler] { };
|
||||||
|
if (usesClangd) {
|
||||||
|
qCDebug(log) << "renaming with clangd";
|
||||||
|
editorWidget->renameUsages(uiHeader, newName, cursor, callback);
|
||||||
|
} else {
|
||||||
|
qCDebug(log) << "renaming with built-in code model";
|
||||||
|
snapshot.insert(cppDoc);
|
||||||
|
snapshot.updateDependencyTable();
|
||||||
|
CppEditor::CppModelManager::instance()->renameUsages(cppDoc, cursor, snapshot,
|
||||||
|
newName, callback);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reportRenamingError(oldName,
|
||||||
|
Designer::Tr::tr("Failed to locate corresponding symbol in ui header."));
|
||||||
|
}
|
||||||
|
|
||||||
void QtCreatorIntegration::slotSyncSettingsToDesigner()
|
void QtCreatorIntegration::slotSyncSettingsToDesigner()
|
||||||
{
|
{
|
||||||
// Set promotion-relevant parameters on integration.
|
// Set promotion-relevant parameters on integration.
|
||||||
|
@@ -17,6 +17,7 @@ class QtCreatorIntegration : public QDesignerIntegration
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QtCreatorIntegration(QDesignerFormEditorInterface *core, QObject *parent = nullptr);
|
explicit QtCreatorIntegration(QDesignerFormEditorInterface *core, QObject *parent = nullptr);
|
||||||
|
~QtCreatorIntegration();
|
||||||
|
|
||||||
QWidget *containerWindow(QWidget *widget) const override;
|
QWidget *containerWindow(QWidget *widget) const override;
|
||||||
|
|
||||||
@@ -36,6 +37,13 @@ private:
|
|||||||
const QString &signalSignature,
|
const QString &signalSignature,
|
||||||
const QStringList ¶meterNames,
|
const QStringList ¶meterNames,
|
||||||
QString *errorMessage);
|
QString *errorMessage);
|
||||||
|
void handleSymbolRenameStage1(QDesignerFormWindowInterface *formWindow, QObject *object,
|
||||||
|
const QString &newName, const QString &oldName);
|
||||||
|
void handleSymbolRenameStage2(QDesignerFormWindowInterface *formWindow,
|
||||||
|
const QString &newName, const QString &oldName);
|
||||||
|
|
||||||
|
class Private;
|
||||||
|
Private * const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -295,6 +295,7 @@ void SymbolSupport::handleFindReferencesResponse(const FindReferencesRequest::Re
|
|||||||
Core::EditorManager::openEditorAtSearchResult(item);
|
Core::EditorManager::openEditorAtSearchResult(item);
|
||||||
});
|
});
|
||||||
search->finishSearch(false);
|
search->finishSearch(false);
|
||||||
|
if (search->isInteractive())
|
||||||
search->popup();
|
search->popup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,6 +366,7 @@ bool SymbolSupport::supportsRename(TextEditor::TextDocument *document)
|
|||||||
void SymbolSupport::renameSymbol(TextEditor::TextDocument *document,
|
void SymbolSupport::renameSymbol(TextEditor::TextDocument *document,
|
||||||
const QTextCursor &cursor,
|
const QTextCursor &cursor,
|
||||||
const QString &newSymbolName,
|
const QString &newSymbolName,
|
||||||
|
const std::function<void ()> &callback,
|
||||||
bool preferLowerCaseFileNames)
|
bool preferLowerCaseFileNames)
|
||||||
{
|
{
|
||||||
const TextDocumentPositionParams params = generateDocPosParams(document, cursor, m_client);
|
const TextDocumentPositionParams params = generateDocPosParams(document, cursor, m_client);
|
||||||
@@ -376,17 +378,19 @@ void SymbolSupport::renameSymbol(TextEditor::TextDocument *document,
|
|||||||
if (!LanguageClient::supportsRename(m_client, document, prepareSupported)) {
|
if (!LanguageClient::supportsRename(m_client, document, prepareSupported)) {
|
||||||
const QString error = Tr::tr("Renaming is not supported with %1").arg(m_client->name());
|
const QString error = Tr::tr("Renaming is not supported with %1").arg(m_client->name());
|
||||||
createSearch(params, derivePlaceholder(oldSymbolName, newSymbolName),
|
createSearch(params, derivePlaceholder(oldSymbolName, newSymbolName),
|
||||||
{}, {})->finishSearch(true, error);
|
{}, callback, {})->finishSearch(true, error);
|
||||||
} else if (prepareSupported) {
|
} else if (prepareSupported) {
|
||||||
requestPrepareRename(document,
|
requestPrepareRename(document,
|
||||||
generateDocPosParams(document, cursor, m_client),
|
generateDocPosParams(document, cursor, m_client),
|
||||||
newSymbolName,
|
newSymbolName,
|
||||||
oldSymbolName,
|
oldSymbolName,
|
||||||
|
callback,
|
||||||
preferLowerCaseFileNames);
|
preferLowerCaseFileNames);
|
||||||
} else {
|
} else {
|
||||||
startRenameSymbol(generateDocPosParams(document, cursor, m_client),
|
startRenameSymbol(generateDocPosParams(document, cursor, m_client),
|
||||||
newSymbolName,
|
newSymbolName,
|
||||||
oldSymbolName,
|
oldSymbolName,
|
||||||
|
callback,
|
||||||
preferLowerCaseFileNames);
|
preferLowerCaseFileNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,6 +399,7 @@ void SymbolSupport::requestPrepareRename(TextEditor::TextDocument *document,
|
|||||||
const TextDocumentPositionParams ¶ms,
|
const TextDocumentPositionParams ¶ms,
|
||||||
const QString &placeholder,
|
const QString &placeholder,
|
||||||
const QString &oldSymbolName,
|
const QString &oldSymbolName,
|
||||||
|
const std::function<void()> &callback,
|
||||||
bool preferLowerCaseFileNames)
|
bool preferLowerCaseFileNames)
|
||||||
{
|
{
|
||||||
PrepareRenameRequest request(params);
|
PrepareRenameRequest request(params);
|
||||||
@@ -402,13 +407,15 @@ void SymbolSupport::requestPrepareRename(TextEditor::TextDocument *document,
|
|||||||
params,
|
params,
|
||||||
placeholder,
|
placeholder,
|
||||||
oldSymbolName,
|
oldSymbolName,
|
||||||
|
callback,
|
||||||
preferLowerCaseFileNames,
|
preferLowerCaseFileNames,
|
||||||
document = QPointer<TextEditor::TextDocument>(document)](
|
document = QPointer<TextEditor::TextDocument>(document)](
|
||||||
const PrepareRenameRequest::Response &response) {
|
const PrepareRenameRequest::Response &response) {
|
||||||
const std::optional<PrepareRenameRequest::Response::Error> &error = response.error();
|
const std::optional<PrepareRenameRequest::Response::Error> &error = response.error();
|
||||||
if (error.has_value()) {
|
if (error.has_value()) {
|
||||||
m_client->log(*error);
|
m_client->log(*error);
|
||||||
createSearch(params, placeholder, {}, {})->finishSearch(true, error->toString());
|
createSearch(params, placeholder, {}, callback, {})
|
||||||
|
->finishSearch(true, error->toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<PrepareRenameResult> &result = response.result();
|
const std::optional<PrepareRenameResult> &result = response.result();
|
||||||
@@ -419,6 +426,7 @@ void SymbolSupport::requestPrepareRename(TextEditor::TextDocument *document,
|
|||||||
placeholder.isEmpty() ? placeHolderResult.placeHolder()
|
placeholder.isEmpty() ? placeHolderResult.placeHolder()
|
||||||
: placeholder,
|
: placeholder,
|
||||||
oldSymbolName,
|
oldSymbolName,
|
||||||
|
callback,
|
||||||
preferLowerCaseFileNames);
|
preferLowerCaseFileNames);
|
||||||
} else if (std::holds_alternative<Range>(*result)) {
|
} else if (std::holds_alternative<Range>(*result)) {
|
||||||
auto range = std::get<Range>(*result);
|
auto range = std::get<Range>(*result);
|
||||||
@@ -429,9 +437,11 @@ void SymbolSupport::requestPrepareRename(TextEditor::TextDocument *document,
|
|||||||
startRenameSymbol(params,
|
startRenameSymbol(params,
|
||||||
derivePlaceholder(reportedSymbolName, placeholder),
|
derivePlaceholder(reportedSymbolName, placeholder),
|
||||||
reportedSymbolName,
|
reportedSymbolName,
|
||||||
|
callback,
|
||||||
preferLowerCaseFileNames);
|
preferLowerCaseFileNames);
|
||||||
} else {
|
} else {
|
||||||
startRenameSymbol(params, placeholder, oldSymbolName, preferLowerCaseFileNames);
|
startRenameSymbol(params, placeholder, oldSymbolName, callback,
|
||||||
|
preferLowerCaseFileNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,6 +459,7 @@ void SymbolSupport::requestRename(const TextDocumentPositionParams &positionPara
|
|||||||
handleRenameResponse(search, response);
|
handleRenameResponse(search, response);
|
||||||
});
|
});
|
||||||
m_client->sendMessage(request);
|
m_client->sendMessage(request);
|
||||||
|
if (search->isInteractive())
|
||||||
search->popup();
|
search->popup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,6 +491,7 @@ QList<Core::SearchResultItem> generateReplaceItems(const WorkspaceEdit &edits,
|
|||||||
Core::SearchResult *SymbolSupport::createSearch(const TextDocumentPositionParams &positionParams,
|
Core::SearchResult *SymbolSupport::createSearch(const TextDocumentPositionParams &positionParams,
|
||||||
const QString &placeholder,
|
const QString &placeholder,
|
||||||
const QString &oldSymbolName,
|
const QString &oldSymbolName,
|
||||||
|
const std::function<void()> &callback,
|
||||||
bool preferLowerCaseFileNames)
|
bool preferLowerCaseFileNames)
|
||||||
{
|
{
|
||||||
Core::SearchResult *search = Core::SearchResultWindow::instance()->startNewSearch(
|
Core::SearchResult *search = Core::SearchResultWindow::instance()->startNewSearch(
|
||||||
@@ -491,6 +503,8 @@ Core::SearchResult *SymbolSupport::createSearch(const TextDocumentPositionParams
|
|||||||
const auto extraWidget = new ReplaceWidget;
|
const auto extraWidget = new ReplaceWidget;
|
||||||
search->setAdditionalReplaceWidget(extraWidget);
|
search->setAdditionalReplaceWidget(extraWidget);
|
||||||
search->setTextToReplace(placeholder);
|
search->setTextToReplace(placeholder);
|
||||||
|
if (callback)
|
||||||
|
search->makeNonInteractive(callback);
|
||||||
|
|
||||||
connect(search, &Core::SearchResult::activated, [](const Core::SearchResultItem &item) {
|
connect(search, &Core::SearchResult::activated, [](const Core::SearchResultItem &item) {
|
||||||
Core::EditorManager::openEditorAtSearchResult(item);
|
Core::EditorManager::openEditorAtSearchResult(item);
|
||||||
@@ -521,10 +535,12 @@ Core::SearchResult *SymbolSupport::createSearch(const TextDocumentPositionParams
|
|||||||
void SymbolSupport::startRenameSymbol(const TextDocumentPositionParams &positionParams,
|
void SymbolSupport::startRenameSymbol(const TextDocumentPositionParams &positionParams,
|
||||||
const QString &placeholder,
|
const QString &placeholder,
|
||||||
const QString &oldSymbolName,
|
const QString &oldSymbolName,
|
||||||
|
const std::function<void()> &callback,
|
||||||
bool preferLowerCaseFileNames)
|
bool preferLowerCaseFileNames)
|
||||||
{
|
{
|
||||||
requestRename(positionParams,
|
requestRename(positionParams,
|
||||||
createSearch(positionParams, placeholder, oldSymbolName, preferLowerCaseFileNames));
|
createSearch(positionParams, placeholder, oldSymbolName, callback,
|
||||||
|
preferLowerCaseFileNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolSupport::handleRenameResponse(Core::SearchResult *search,
|
void SymbolSupport::handleRenameResponse(Core::SearchResult *search,
|
||||||
|
@@ -42,7 +42,9 @@ public:
|
|||||||
|
|
||||||
bool supportsRename(TextEditor::TextDocument *document);
|
bool supportsRename(TextEditor::TextDocument *document);
|
||||||
void renameSymbol(TextEditor::TextDocument *document, const QTextCursor &cursor,
|
void renameSymbol(TextEditor::TextDocument *document, const QTextCursor &cursor,
|
||||||
const QString &newSymbolName = {}, bool preferLowerCaseFileNames = true);
|
const QString &newSymbolName = {},
|
||||||
|
const std::function<void()> &callback = {},
|
||||||
|
bool preferLowerCaseFileNames = true);
|
||||||
|
|
||||||
static Core::Search::TextRange convertRange(const LanguageServerProtocol::Range &range);
|
static Core::Search::TextRange convertRange(const LanguageServerProtocol::Range &range);
|
||||||
static QStringList getFileContents(const Utils::FilePath &filePath);
|
static QStringList getFileContents(const Utils::FilePath &filePath);
|
||||||
@@ -61,16 +63,17 @@ private:
|
|||||||
void requestPrepareRename(TextEditor::TextDocument *document,
|
void requestPrepareRename(TextEditor::TextDocument *document,
|
||||||
const LanguageServerProtocol::TextDocumentPositionParams ¶ms,
|
const LanguageServerProtocol::TextDocumentPositionParams ¶ms,
|
||||||
const QString &placeholder,
|
const QString &placeholder,
|
||||||
const QString &oldSymbolName,
|
const QString &oldSymbolName, const std::function<void()> &callback,
|
||||||
bool preferLowerCaseFileNames);
|
bool preferLowerCaseFileNames);
|
||||||
void requestRename(const LanguageServerProtocol::TextDocumentPositionParams &positionParams,
|
void requestRename(const LanguageServerProtocol::TextDocumentPositionParams &positionParams,
|
||||||
Core::SearchResult *search);
|
Core::SearchResult *search);
|
||||||
Core::SearchResult *createSearch(const LanguageServerProtocol::TextDocumentPositionParams &positionParams,
|
Core::SearchResult *createSearch(const LanguageServerProtocol::TextDocumentPositionParams &positionParams,
|
||||||
const QString &placeholder, const QString &oldSymbolName,
|
const QString &placeholder, const QString &oldSymbolName,
|
||||||
|
const std::function<void()> &callback,
|
||||||
bool preferLowerCaseFileNames);
|
bool preferLowerCaseFileNames);
|
||||||
void startRenameSymbol(const LanguageServerProtocol::TextDocumentPositionParams ¶ms,
|
void startRenameSymbol(const LanguageServerProtocol::TextDocumentPositionParams ¶ms,
|
||||||
const QString &placeholder, const QString &oldSymbolName,
|
const QString &placeholder, const QString &oldSymbolName,
|
||||||
bool preferLowerCaseFileNames);
|
const std::function<void()> &callback, bool preferLowerCaseFileNames);
|
||||||
void handleRenameResponse(Core::SearchResult *search,
|
void handleRenameResponse(Core::SearchResult *search,
|
||||||
const LanguageServerProtocol::RenameRequest::Response &response);
|
const LanguageServerProtocol::RenameRequest::Response &response);
|
||||||
void applyRename(const QList<Core::SearchResultItem> &checkedItems, Core::SearchResult *search);
|
void applyRename(const QList<Core::SearchResultItem> &checkedItems, Core::SearchResult *search);
|
||||||
|
@@ -236,6 +236,12 @@ bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompiler *BuildSystem::extraCompilerForSource(const Utils::FilePath &source)
|
||||||
|
{
|
||||||
|
Q_UNUSED(source);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
MakeInstallCommand BuildSystem::makeInstallCommand(const FilePath &installRoot) const
|
MakeInstallCommand BuildSystem::makeInstallCommand(const FilePath &installRoot) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(target()->project()->hasMakeInstallEquivalent(), return {});
|
QTC_ASSERT(target()->project()->hasMakeInstallEquivalent(), return {});
|
||||||
|
@@ -19,6 +19,7 @@ namespace ProjectExplorer {
|
|||||||
|
|
||||||
class BuildConfiguration;
|
class BuildConfiguration;
|
||||||
class BuildStepList;
|
class BuildStepList;
|
||||||
|
class ExtraCompiler;
|
||||||
class Node;
|
class Node;
|
||||||
|
|
||||||
struct TestCaseInfo
|
struct TestCaseInfo
|
||||||
@@ -82,6 +83,9 @@ public:
|
|||||||
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
|
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
|
||||||
virtual QString name() const = 0;
|
virtual QString name() const = 0;
|
||||||
|
|
||||||
|
// Owned by the build system. Use only in main thread. Can go away at any time.
|
||||||
|
virtual ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source);
|
||||||
|
|
||||||
virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const;
|
virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const;
|
||||||
|
|
||||||
virtual Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const;
|
virtual Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const;
|
||||||
|
@@ -13,10 +13,12 @@
|
|||||||
|
|
||||||
#include <utils/asynctask.h>
|
#include <utils/asynctask.h>
|
||||||
#include <utils/expected.h>
|
#include <utils/expected.h>
|
||||||
|
#include <utils/guard.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
|
#include <QLoggingCategory>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@@ -26,6 +28,7 @@ namespace ProjectExplorer {
|
|||||||
|
|
||||||
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
||||||
Q_GLOBAL_STATIC(QList<ExtraCompilerFactory *>, factories);
|
Q_GLOBAL_STATIC(QList<ExtraCompilerFactory *>, factories);
|
||||||
|
Q_LOGGING_CATEGORY(log, "qtc.projectexplorer.extracompiler", QtWarningMsg);
|
||||||
|
|
||||||
class ExtraCompilerPrivate
|
class ExtraCompilerPrivate
|
||||||
{
|
{
|
||||||
@@ -37,6 +40,7 @@ public:
|
|||||||
Core::IEditor *lastEditor = nullptr;
|
Core::IEditor *lastEditor = nullptr;
|
||||||
QMetaObject::Connection activeBuildConfigConnection;
|
QMetaObject::Connection activeBuildConfigConnection;
|
||||||
QMetaObject::Connection activeEnvironmentConnection;
|
QMetaObject::Connection activeEnvironmentConnection;
|
||||||
|
Utils::Guard lock;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
@@ -55,13 +59,7 @@ ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
|
|||||||
d->contents.insert(target, QByteArray());
|
d->contents.insert(target, QByteArray());
|
||||||
d->timer.setSingleShot(true);
|
d->timer.setSingleShot(true);
|
||||||
|
|
||||||
connect(&d->timer, &QTimer::timeout, this, [this] {
|
connect(&d->timer, &QTimer::timeout, this, &ExtraCompiler::compileIfDirty);
|
||||||
if (d->dirty && d->lastEditor) {
|
|
||||||
d->dirty = false;
|
|
||||||
compileContent(d->lastEditor->document()->contents());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(BuildManager::instance(), &BuildManager::buildStateChanged,
|
connect(BuildManager::instance(), &BuildManager::buildStateChanged,
|
||||||
this, &ExtraCompiler::onTargetsBuilt);
|
this, &ExtraCompiler::onTargetsBuilt);
|
||||||
|
|
||||||
@@ -163,6 +161,16 @@ void ExtraCompiler::compileImpl(const ContentProvider &provider)
|
|||||||
d->m_taskTree->start();
|
d->m_taskTree->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::compileIfDirty()
|
||||||
|
{
|
||||||
|
qCDebug(log) << Q_FUNC_INFO;
|
||||||
|
if (!d->lock.isLocked() && d->dirty && d->lastEditor) {
|
||||||
|
qCDebug(log) << '\t' << "about to compile";
|
||||||
|
d->dirty = false;
|
||||||
|
compileContent(d->lastEditor->document()->contents());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExtraCompiler::ContentProvider ExtraCompiler::fromFileProvider() const
|
ExtraCompiler::ContentProvider ExtraCompiler::fromFileProvider() const
|
||||||
{
|
{
|
||||||
const auto provider = [fileName = source()] {
|
const auto provider = [fileName = source()] {
|
||||||
@@ -179,6 +187,20 @@ bool ExtraCompiler::isDirty() const
|
|||||||
return d->dirty;
|
return d->dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::block()
|
||||||
|
{
|
||||||
|
qCDebug(log) << Q_FUNC_INFO;
|
||||||
|
d->lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::unblock()
|
||||||
|
{
|
||||||
|
qCDebug(log) << Q_FUNC_INFO;
|
||||||
|
d->lock.unlock();
|
||||||
|
if (!d->lock.isLocked() && !d->timer.isActive())
|
||||||
|
d->timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
void ExtraCompiler::onTargetsBuilt(Project *project)
|
void ExtraCompiler::onTargetsBuilt(Project *project)
|
||||||
{
|
{
|
||||||
if (project != d->project || BuildManager::isBuilding(project))
|
if (project != d->project || BuildManager::isBuilding(project))
|
||||||
@@ -278,6 +300,7 @@ Utils::FutureSynchronizer *ExtraCompiler::futureSynchronizer() const
|
|||||||
|
|
||||||
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
|
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
|
||||||
{
|
{
|
||||||
|
qCDebug(log).noquote() << Q_FUNC_INFO << contents;
|
||||||
auto it = d->contents.find(file);
|
auto it = d->contents.find(file);
|
||||||
if (it != d->contents.end()) {
|
if (it != d->contents.end()) {
|
||||||
if (it.value() != contents) {
|
if (it.value() != contents) {
|
||||||
|
@@ -55,6 +55,8 @@ public:
|
|||||||
Utils::Tasking::TaskItem compileFileItem();
|
Utils::Tasking::TaskItem compileFileItem();
|
||||||
void compileFile();
|
void compileFile();
|
||||||
bool isDirty() const;
|
bool isDirty() const;
|
||||||
|
void block();
|
||||||
|
void unblock();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void contentsChanged(const Utils::FilePath &file);
|
void contentsChanged(const Utils::FilePath &file);
|
||||||
@@ -76,6 +78,7 @@ private:
|
|||||||
ContentProvider fromFileProvider() const;
|
ContentProvider fromFileProvider() const;
|
||||||
void compileContent(const QByteArray &content);
|
void compileContent(const QByteArray &content);
|
||||||
void compileImpl(const ContentProvider &provider);
|
void compileImpl(const ContentProvider &provider);
|
||||||
|
void compileIfDirty();
|
||||||
virtual Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0;
|
virtual Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0;
|
||||||
|
|
||||||
const std::unique_ptr<ExtraCompilerPrivate> d;
|
const std::unique_ptr<ExtraCompilerPrivate> d;
|
||||||
|
@@ -586,6 +586,13 @@ void QbsBuildSystem::delayParsing()
|
|||||||
requestDelayedParse();
|
requestDelayedParse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompiler *QbsBuildSystem::extraCompilerForSource(const Utils::FilePath &source)
|
||||||
|
{
|
||||||
|
return Utils::findOrDefault(m_extraCompilers, [source](ExtraCompiler *ec) {
|
||||||
|
return ec->source() == source;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void QbsBuildSystem::parseCurrentBuildConfiguration()
|
void QbsBuildSystem::parseCurrentBuildConfiguration()
|
||||||
{
|
{
|
||||||
m_parsingScheduled = false;
|
m_parsingScheduled = false;
|
||||||
|
@@ -105,6 +105,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class QbsProject;
|
friend class QbsProject;
|
||||||
|
|
||||||
|
ProjectExplorer::ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source) override;
|
||||||
|
|
||||||
void handleQbsParsingDone(bool success);
|
void handleQbsParsingDone(bool success);
|
||||||
void changeActiveTarget(ProjectExplorer::Target *t);
|
void changeActiveTarget(ProjectExplorer::Target *t);
|
||||||
void prepareForParsing();
|
void prepareForParsing();
|
||||||
|
@@ -2080,6 +2080,21 @@ QList<ExtraCompiler *> QmakeProFile::extraCompilers() const
|
|||||||
return m_extraCompilers;
|
return m_extraCompilers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompiler *QmakeProFile::extraCompilerForSource(const Utils::FilePath &sourceFile)
|
||||||
|
{
|
||||||
|
for (ExtraCompiler * const ec : std::as_const(m_extraCompilers)) {
|
||||||
|
if (ec->source() == sourceFile)
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
for (QmakePriFile * const priFile : std::as_const(m_children)) {
|
||||||
|
if (const auto proFile = dynamic_cast<QmakeProFile *>(priFile)) {
|
||||||
|
if (ExtraCompiler * const ec = proFile->extraCompilerForSource(sourceFile))
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void QmakeProFile::setupExtraCompiler(const FilePath &buildDir,
|
void QmakeProFile::setupExtraCompiler(const FilePath &buildDir,
|
||||||
const FileType &fileType, ExtraCompilerFactory *factory)
|
const FileType &fileType, ExtraCompilerFactory *factory)
|
||||||
{
|
{
|
||||||
|
@@ -301,6 +301,7 @@ public:
|
|||||||
const Utils::FilePath &sourceFile,
|
const Utils::FilePath &sourceFile,
|
||||||
const ProjectExplorer::FileType &sourceFileType) const;
|
const ProjectExplorer::FileType &sourceFileType) const;
|
||||||
QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const;
|
QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const;
|
||||||
|
ProjectExplorer::ExtraCompiler *extraCompilerForSource(const Utils::FilePath &sourceFile);
|
||||||
|
|
||||||
TargetInformation targetInformation() const;
|
TargetInformation targetInformation() const;
|
||||||
InstallsList installsList() const;
|
InstallsList installsList() const;
|
||||||
|
@@ -532,6 +532,11 @@ void QmakeBuildSystem::scheduleUpdateAllNowOrLater()
|
|||||||
scheduleUpdateAll(QmakeProFile::ParseLater);
|
scheduleUpdateAll(QmakeProFile::ParseLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompiler *QmakeBuildSystem::extraCompilerForSource(const Utils::FilePath &source)
|
||||||
|
{
|
||||||
|
return m_rootProFile->extraCompilerForSource(source);
|
||||||
|
}
|
||||||
|
|
||||||
QmakeBuildConfiguration *QmakeBuildSystem::qmakeBuildConfiguration() const
|
QmakeBuildConfiguration *QmakeBuildSystem::qmakeBuildConfiguration() const
|
||||||
{
|
{
|
||||||
return static_cast<QmakeBuildConfiguration *>(BuildSystem::buildConfiguration());
|
return static_cast<QmakeBuildConfiguration *>(BuildSystem::buildConfiguration());
|
||||||
|
@@ -163,6 +163,8 @@ public:
|
|||||||
void scheduleUpdateAllNowOrLater();
|
void scheduleUpdateAllNowOrLater();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ProjectExplorer::ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source) override;
|
||||||
|
|
||||||
void scheduleUpdateAll(QmakeProFile::AsyncUpdateDelay delay);
|
void scheduleUpdateAll(QmakeProFile::AsyncUpdateDelay delay);
|
||||||
void scheduleUpdateAllLater() { scheduleUpdateAll(QmakeProFile::ParseLater); }
|
void scheduleUpdateAllLater() { scheduleUpdateAll(QmakeProFile::ParseLater); }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user