From b87e3a53dbc00e26a53838510b096987f83ba845 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 31 May 2024 09:22:14 +0200 Subject: [PATCH 01/26] Fix json templates Amends 6cd7aed8ebe6b1e18d875f1559c70ff46bc09881. Change-Id: Ia8369c69530854488007ef28c191fdfbca4c082c Reviewed-by: hjk --- src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in | 2 +- src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in | 2 +- src/plugins/designer/Designer.json.in | 2 +- src/plugins/vcsbase/VcsBase.json.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in b/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in index 5ee0e41c3fc..920b3ec31bb 100644 --- a/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in +++ b/src/plugins/appstatisticsmonitor/AppStatisticsMonitor.json.in @@ -15,7 +15,7 @@ ], "Description" : "Visualize CPU and Memory consumption for running applications", "LongDescription" : [ - "Select an application to monitor its performance in real-time.", + "Select an application to monitor its performance in real-time." ], "Url" : "https://www.qt.io", ${IDE_PLUGIN_DEPENDENCIES} diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in b/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in index 010f6b8721f..72621cda105 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in @@ -15,7 +15,7 @@ "Category" : "Build Systems", "Description" : "Automate the configuration of build systems with CMake", "LongDescription" : [ - "CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files." + "CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files.", "You also need:", "- CMake", "Qt Online Installer installs a CMake version that you can use." diff --git a/src/plugins/designer/Designer.json.in b/src/plugins/designer/Designer.json.in index fb84ac1388b..966becb0d41 100644 --- a/src/plugins/designer/Designer.json.in +++ b/src/plugins/designer/Designer.json.in @@ -15,7 +15,7 @@ "Category" : "Qt Creator", "Description" : "Design Qt-widgets based UIs", "LongDescription" : [ - "Create widgets and forms that are integrated with Qt C++ code.", + "Create widgets and forms that are integrated with Qt C++ code." ], "Url" : "https://www.qt.io", ${DESIGNER_PLUGIN_ARGUMENTS} diff --git a/src/plugins/vcsbase/VcsBase.json.in b/src/plugins/vcsbase/VcsBase.json.in index 49933bc2aeb..a1717a9138a 100644 --- a/src/plugins/vcsbase/VcsBase.json.in +++ b/src/plugins/vcsbase/VcsBase.json.in @@ -16,7 +16,7 @@ "Description" : "Provides the technical basis for version control system (VCS) extensions", "LongDescription" : [ "You also need:", - "- An extension for a VCS tool, such as Git, and the tool + "- An extension for a VCS tool, such as Git, and the tool" ], "Url" : "https://www.qt.io", ${IDE_PLUGIN_DEPENDENCIES} From 4bbbf29e7ded9c55c58eba2944b480c4bba9df06 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 31 May 2024 08:14:38 +0200 Subject: [PATCH 02/26] Lua: Remove wizard meta files We removed the wizard stuff from lua, but I forgot to remove the documentation Change-Id: I9d96d1d38ed4090c51361ee1e37fedb5a7358870 Reviewed-by: hjk --- src/plugins/lua/CMakeLists.txt | 2 -- src/plugins/lua/lua.qbs | 1 - src/plugins/lua/meta/wizard.lua | 61 --------------------------------- 3 files changed, 64 deletions(-) delete mode 100644 src/plugins/lua/meta/wizard.lua diff --git a/src/plugins/lua/CMakeLists.txt b/src/plugins/lua/CMakeLists.txt index cb7ccb17e34..253d6f06ee6 100644 --- a/src/plugins/lua/CMakeLists.txt +++ b/src/plugins/lua/CMakeLists.txt @@ -39,7 +39,6 @@ add_qtc_plugin(Lua meta/simpletypes.lua meta/utils.lua meta/widgets.lua - meta/wizard.lua # generateqtbindings.cpp # Use this if you need to generate some code. ) @@ -66,7 +65,6 @@ set(META_FILES meta/simpletypes.lua meta/utils.lua meta/widgets.lua - meta/wizard.lua ) qtc_copy_to_builddir(copy_lua_meta_files diff --git a/src/plugins/lua/lua.qbs b/src/plugins/lua/lua.qbs index 5f00384139c..1b49d94f519 100644 --- a/src/plugins/lua/lua.qbs +++ b/src/plugins/lua/lua.qbs @@ -68,7 +68,6 @@ QtcPlugin { "simpletypes.lua", "utils.lua", "widgets.lua", - "wizard.lua", ] qbs.install: true qbs.installDir: qtc.ide_data_path + "/lua/meta/" diff --git a/src/plugins/lua/meta/wizard.lua b/src/plugins/lua/meta/wizard.lua deleted file mode 100644 index fb5b000d514..00000000000 --- a/src/plugins/lua/meta/wizard.lua +++ /dev/null @@ -1,61 +0,0 @@ ----@meta Wizard - ----@module "Layout" -local Layout = require("Layout") - ----@module "Core" -local Core = require("Core") - -local wizard = {} - ----@class (exact) WizardFactoryOptions ----@field id string ----@field displayName string ----@field description string ----@field category string ----@field displayCategory string ----@field icon? string ----@field iconText? string ----@field factory function A function returning a Wizard - ---- Registers a wizard factory. ----@param options WizardFactoryOptions -function wizard.registerFactory(options) end - ----@class Wizard -Wizard = {} - ----@class (exact) WizardPageOptions ----@field title string ----@field layout LayoutItem ----@field initializePage? function The function called before showing the page - ----Add a page to the wizard ----@param options WizardPageOptions -function Wizard:addPage(options) end - ----@class SummaryPage -Wizard.SummaryPage = {} - ----Set the files to be shown on the summary page ----@param generatedFiles Core.GeneratedFile[] -function Wizard.SummaryPage:setFiles(generatedFiles) end - ----@class SummaryPageOptions ----@field title? string ----@field initializePage? function The function called before showing the page - ----Add a summary page to the wizard ----@param options SummaryPageOptions ----@return SummaryPage -function Wizard:addSummaryPage(options) end - ----@class WizardOptions ----@field fileFactory function A function returning a GeneratedFile[] - ----Create a wizard ----@param options WizardOptions ----@return Wizard -function wizard.create(options) end - -return wizard From b0354eaf16508b57ee5fc669c4f009400a8e377f Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 30 May 2024 09:55:21 +0200 Subject: [PATCH 03/26] Utils: Add gzip support to unarchiver Change-Id: I223d97169cd9e1850d221370d8dd16b770918e20 Reviewed-by: hjk --- src/libs/utils/unarchiver.cpp | 44 +++++++++++++++++++++++++++++++++++ src/libs/utils/unarchiver.h | 6 ++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/unarchiver.cpp b/src/libs/utils/unarchiver.cpp index 84365654253..d9092e4ca95 100644 --- a/src/libs/utils/unarchiver.cpp +++ b/src/libs/utils/unarchiver.cpp @@ -43,6 +43,7 @@ static const QList &sTools() { static QList tools; if (tools.isEmpty()) { + // clang-format off if (HostOsInfo::isWindowsHost()) { tools << Tool{{"powershell", "-command Expand-Archive -Force '%{src}' '%{dest}'", CommandLine::Raw}, {"application/zip"}, @@ -74,6 +75,10 @@ static const QList &sTools() tools << Tool{{"cmake", {"-E", "tar", "xvjf", "%{src}"}}, {"application/x-bzip-compressed-tar"}, additionalCMakeDirs}; + // Keep this at the end so its only used as last resort. Otherwise it might be used for + // .tar.gz files. + tools << Tool{{"gzip", {"-d", "%{src}", "-c"}}, {"application/gzip"}, {}}; + // clang-format on } return tools; } @@ -147,6 +152,45 @@ void Unarchiver::start() m_sourceAndCommand->m_sourceFile, m_destDir); m_destDir.ensureWritableDir(); + if (command.executable().fileName() == "gzip") { + std::shared_ptr outputFile = std::make_shared( + (m_destDir / m_gzipFileDestName).toFSPathString()); + + if (!outputFile->open(QIODevice::WriteOnly)) { + emit outputReceived(Tr::tr("Failed to open output file.")); + emit done(DoneResult::Error); + return; + } + + m_process.reset(new Process); + QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this, outputFile] { + const QByteArray data = m_process->readAllRawStandardOutput(); + if (outputFile->write(data) != data.size()) { + emit outputReceived(Tr::tr("Failed to write output file.")); + emit done(DoneResult::Error); + } + }); + QObject::connect(m_process.get(), &Process::readyReadStandardError, this, [this] { + emit outputReceived(m_process->readAllStandardError()); + }); + QObject::connect(m_process.get(), &Process::done, this, [outputFile, this] { + outputFile->close(); + const bool success = m_process->result() == ProcessResult::FinishedWithSuccess; + if (!success) { + outputFile->remove(); + emit outputReceived(Tr::tr("Command failed.")); + } + emit done(toDoneResult(success)); + }); + emit outputReceived( + Tr::tr("Running %1\nin \"%2\".\n\n", "Running in ") + .arg(command.toUserOutput(), m_destDir.toUserOutput())); + m_process->setCommand(command); + m_process->setWorkingDirectory(m_destDir); + m_process->start(); + return; + } + m_process.reset(new Process); m_process->setProcessChannelMode(QProcess::MergedChannels); QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this] { diff --git a/src/libs/utils/unarchiver.h b/src/libs/utils/unarchiver.h index 61818318bb7..23fcad07a81 100644 --- a/src/libs/utils/unarchiver.h +++ b/src/libs/utils/unarchiver.h @@ -32,7 +32,10 @@ public: void setSourceAndCommand(const SourceAndCommand &data) { m_sourceAndCommand = data; } void setDestDir(const FilePath &destDir) { m_destDir = destDir; } - + void setGZipFileDestName(const QString &gzipFileDestName) + { + m_gzipFileDestName = gzipFileDestName; + } void start(); signals: @@ -43,6 +46,7 @@ private: std::optional m_sourceAndCommand; FilePath m_destDir; std::unique_ptr m_process; + QString m_gzipFileDestName; }; class QTCREATOR_UTILS_EXPORT UnarchiverTaskAdapter : public Tasking::TaskAdapter From 5c23ab8c2dd3aca246e7754fc8e9023ae71d3bed Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 28 May 2024 11:14:43 +0200 Subject: [PATCH 04/26] Cdbbridge: report dumptime of fetchVariables Change-Id: I866fd5dbf547a4d6ec1ab9806080419735131d19 Reviewed-by: hjk --- share/qtcreator/debugger/cdbbridge.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index b5fc683cbae..7fdd057bb11 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -7,6 +7,7 @@ import sys import cdbext import re import threading +import time from utils import TypeCode sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) @@ -443,6 +444,7 @@ class Dumper(DumperBase): self.put('{name="%s",value="",type="",numchild="0"},' % msg) def fetchVariables(self, args): + start_time = time.perf_counter() self.resetStats() (ok, res) = self.tryFetchInterpreterVariables(args) if ok: @@ -476,6 +478,8 @@ class Dumper(DumperBase): self.put(',qtnamespace="%s"' % self.qtNamespaceToReport) self.qtNamespaceToReport = None + runtime = time.perf_counter() - start_time + self.put(',runtime="%s"' % runtime) self.reportResult(''.join(self.output), args) self.output = [] From 1c2fbaa84631196c30cd6801d7e70e6c673a2ba5 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 28 May 2024 11:40:59 +0200 Subject: [PATCH 05/26] Debugger: track variable fetch time in dumper tests for cdb Change-Id: I85073edc2e3660e2bfaff32f53e4a2f98f03c514 Reviewed-by: hjk --- tests/auto/debugger/tst_dumpers.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 55ae944ef69..14c0e3500ab 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1931,6 +1931,9 @@ void tst_Dumpers::dumper() } while (localsBeginPos != -1); actual.fromString(QString::fromLocal8Bit(contents)); context.nameSpace = actual["result"]["qtnamespace"].data(); + int runtime = actual["result"]["runtime"].data().toFloat() * 1000; + qCDebug(lcDumpers, "CaseInner: %5d", runtime); + m_totalInnerTime += runtime; actual = actual["result"]["data"]; } From 0e301004b85c84b8df5519af1468340c4b483837 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 24 May 2024 13:52:27 +0200 Subject: [PATCH 06/26] ClangCodeModel: Allow more than one in-flight "follow symbol" The original code was written with only the interactive case in mind, but nowadays we also start "follow symbol" operations internally as part of e.g. quickfixes. Change-Id: I95928297fab16f9b0469bfd66ad687447b902fd9 Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 33 ++++++++++++------- .../clangcodemodel/clangdfollowsymbol.cpp | 18 ++++++---- .../clangcodemodel/clangdfollowsymbol.h | 6 +++- .../cppeditor/cppcodemodelsettings.cpp | 11 +++++++ src/plugins/cppeditor/cppcodemodelsettings.h | 16 ++++++++- src/plugins/cppeditor/cppeditorwidget.cpp | 1 + .../quickfixes/createdeclarationfromuse.cpp | 1 + .../quickfixes/moveclasstoownfile.cpp | 1 + .../cppeditor/quickfixes/rewritecomment.cpp | 2 ++ .../synchronizememberfunctionorder.cpp | 1 + 10 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 32ee429c4d1..f3600352642 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -349,7 +349,7 @@ public: ClangdClient * const q; const CppEditor::ClangdSettings::Data settings; - ClangdFollowSymbol *followSymbol = nullptr; + QList followSymbolOps; ClangdSwitchDeclDef *switchDeclDef = nullptr; ClangdFindLocalReferences *findLocalRefs = nullptr; std::optional versionNumber; @@ -501,8 +501,8 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c ClangdClient::~ClangdClient() { - if (d->followSymbol) - d->followSymbol->clear(); + for (ClangdFollowSymbol * const followSymbol : std::as_const(d->followSymbolOps)) + followSymbol->clear(); delete d; } @@ -990,7 +990,7 @@ MessageId ClangdClient::requestSymbolInfo(const Utils::FilePath &filePath, const #ifdef WITH_TESTS ClangdFollowSymbol *ClangdClient::currentFollowSymbolOperation() { - return d->followSymbol; + return d->followSymbolOps.isEmpty() ? nullptr : d->followSymbolOps.first(); } #endif @@ -1005,8 +1005,20 @@ void ClangdClient::followSymbol(TextDocument *document, { QTC_ASSERT(documentOpen(document), openDocument(document)); - if (d->followSymbol) - d->followSymbol->cancel(); + const ClangdFollowSymbol::Origin origin + = CppEditor::CppCodeModelSettings::isInteractiveFollowSymbol() + ? ClangdFollowSymbol::Origin::User + : ClangdFollowSymbol::Origin::Code; + if (origin == ClangdFollowSymbol::Origin::User) { + for (auto it = d->followSymbolOps.begin(); it != d->followSymbolOps.end(); ) { + if ((*it)->isInteractive()) { + (*it)->cancel(); + it = d->followSymbolOps.erase(it); + } else { + ++it; + } + } + } const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document); if (followTo == FollowTo::SymbolDef && !resolveTarget) { @@ -1020,14 +1032,13 @@ void ClangdClient::followSymbol(TextDocument *document, qCDebug(clangdLog) << "follow symbol requested" << document->filePath() << adjustedCursor.blockNumber() << adjustedCursor.positionInBlock(); - auto clangdFollowSymbol = new ClangdFollowSymbol(this, adjustedCursor, editorWidget, document, - callback, followTo, openInSplit); + auto clangdFollowSymbol = new ClangdFollowSymbol(this, origin, adjustedCursor, editorWidget, + document, callback, followTo, openInSplit); connect(clangdFollowSymbol, &ClangdFollowSymbol::done, this, [this, clangdFollowSymbol] { clangdFollowSymbol->deleteLater(); - if (clangdFollowSymbol == d->followSymbol) - d->followSymbol = nullptr; + d->followSymbolOps.removeOne(clangdFollowSymbol); }); - d->followSymbol = clangdFollowSymbol; + d->followSymbolOps << clangdFollowSymbol; } void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &cursor, diff --git a/src/plugins/clangcodemodel/clangdfollowsymbol.cpp b/src/plugins/clangcodemodel/clangdfollowsymbol.cpp index 2bedda4d986..29fa15fe8bb 100644 --- a/src/plugins/clangcodemodel/clangdfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangdfollowsymbol.cpp @@ -73,10 +73,10 @@ private: class ClangdFollowSymbol::Private { public: - Private(ClangdFollowSymbol *q, ClangdClient *client, const QTextCursor &cursor, + Private(ClangdFollowSymbol *q, ClangdClient *client, Origin origin, const QTextCursor &cursor, CppEditorWidget *editorWidget, const FilePath &filePath, const LinkHandler &callback, bool openInSplit) - : q(q), client(client), cursor(cursor), editorWidget(editorWidget), + : q(q), client(client), origin(origin), cursor(cursor), editorWidget(editorWidget), uri(client->hostPathToServerUri(filePath)), callback(callback), virtualFuncAssistProvider(q), docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1), @@ -94,6 +94,7 @@ public: ClangdFollowSymbol * const q; ClangdClient * const client; + const Origin origin; const QTextCursor cursor; const QPointer editorWidget; const DocumentUri uri; @@ -117,11 +118,11 @@ public: bool done = false; }; -ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor, - CppEditorWidget *editorWidget, TextDocument *document, const LinkHandler &callback, - FollowTo followTo, bool openInSplit) +ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, Origin origin, + const QTextCursor &cursor, CppEditorWidget *editorWidget, TextDocument *document, + const LinkHandler &callback, FollowTo followTo, bool openInSplit) : QObject(client), - d(new Private(this, client, cursor, editorWidget, document->filePath(), callback, + d(new Private(this, client, origin, cursor, editorWidget, document->filePath(), callback, openInSplit)) { // Abort if the user does something else with the document in the meantime. @@ -193,6 +194,11 @@ void ClangdFollowSymbol::clear() d->pendingGotoDefRequests.clear(); } +bool ClangdFollowSymbol::isInteractive() const +{ + return d->origin == Origin::User; +} + void ClangdFollowSymbol::emitDone(const Link &link) { if (d->done) diff --git a/src/plugins/clangcodemodel/clangdfollowsymbol.h b/src/plugins/clangcodemodel/clangdfollowsymbol.h index 33cef520d88..539ae461bc2 100644 --- a/src/plugins/clangcodemodel/clangdfollowsymbol.h +++ b/src/plugins/clangcodemodel/clangdfollowsymbol.h @@ -23,7 +23,9 @@ class ClangdFollowSymbol : public QObject { Q_OBJECT public: - ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor, + enum class Origin { User, Code }; + + ClangdFollowSymbol(ClangdClient *client, Origin origin, const QTextCursor &cursor, CppEditor::CppEditorWidget *editorWidget, TextEditor::TextDocument *document, const Utils::LinkHandler &callback, FollowTo followTo, bool openInSplit); @@ -31,6 +33,8 @@ public: void cancel(); void clear(); + bool isInteractive() const; + signals: void done(); diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index 53c009d4c39..5dde29a49cf 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -83,6 +83,7 @@ bool operator==(const CppEditor::CppCodeModelSettings &s1, && s1.useBuiltinPreprocessor == s2.useBuiltinPreprocessor && s1.indexerFileSizeLimitInMb == s2.indexerFileSizeLimitInMb && s1.m_categorizeFindReferences == s2.m_categorizeFindReferences + && s1.interactiveFollowSymbol == s2.interactiveFollowSymbol && s1.ignoreFiles == s2.ignoreFiles && s1.ignorePattern == s2.ignorePattern; } @@ -204,6 +205,16 @@ void CppCodeModelSettings::setCategorizeFindReferences(bool categorize) globalInstance().m_categorizeFindReferences = categorize; } +bool CppCodeModelSettings::isInteractiveFollowSymbol() +{ + return globalInstance().interactiveFollowSymbol; +} + +void CppCodeModelSettings::setInteractiveFollowSymbol(bool interactive) +{ + globalInstance().interactiveFollowSymbol = interactive; +} + CppCodeModelProjectSettings::CppCodeModelProjectSettings(ProjectExplorer::Project *project) : m_project(project) { diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h index 9bf2b6862db..9f2f3d1718d 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.h +++ b/src/plugins/cppeditor/cppcodemodelsettings.h @@ -55,6 +55,9 @@ public: static bool categorizeFindReferences(); static void setCategorizeFindReferences(bool categorize); + static bool isInteractiveFollowSymbol(); + static void setInteractiveFollowSymbol(bool interactive); + QString ignorePattern; PCHUsage pchUsage = PchUse_BuildSystem; int indexerFileSizeLimitInMb = 5; @@ -63,7 +66,10 @@ public: bool useBuiltinPreprocessor = true; bool ignoreFiles = false; bool enableIndexing = true; - bool m_categorizeFindReferences = false; // Ephemeral! + + // Ephemeral! + bool m_categorizeFindReferences = false; + bool interactiveFollowSymbol = true; private: CppCodeModelSettings(Utils::QtcSettings *s) { fromSettings(s); } @@ -76,6 +82,14 @@ private: namespace Internal { void setupCppCodeModelSettingsPage(); void setupCppCodeModelProjectSettingsPanel(); + +class NonInteractiveFollowSymbolMarker +{ +public: + NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(false); } + ~NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(true); } +}; + } // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index d5d64597b92..609b35051c4 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -623,6 +623,7 @@ void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor curso const CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()}; CppModelManager::globalRename(cursorInEditor, replacement); }; + NonInteractiveFollowSymbolMarker niMarker; CppModelManager::followSymbol(CursorInEditor{cursor, textDocument()->filePath(), this, diff --git a/src/plugins/cppeditor/quickfixes/createdeclarationfromuse.cpp b/src/plugins/cppeditor/quickfixes/createdeclarationfromuse.cpp index f7a760a99e7..a0e8ad21417 100644 --- a/src/plugins/cppeditor/quickfixes/createdeclarationfromuse.cpp +++ b/src/plugins/cppeditor/quickfixes/createdeclarationfromuse.cpp @@ -370,6 +370,7 @@ private: if (!link.hasValidTarget()) collectOperations(interface, result); }; + NonInteractiveFollowSymbolMarker niMarker; CppModelManager::followSymbol(cursorInEditor, followSymbolFallback, false, false, FollowSymbolMode::Exact, CppModelManager::Backend::Builtin); diff --git a/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp b/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp index e556f80300b..e8a6c9b33fe 100644 --- a/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp +++ b/src/plugins/cppeditor/quickfixes/moveclasstoownfile.cpp @@ -294,6 +294,7 @@ private: // Force queued execution, as the built-in editor can run the callback synchronously. const auto followSymbol = [cursorInEditor, callback] { + NonInteractiveFollowSymbolMarker niMarker; CppModelManager::followSymbol( cursorInEditor, callback, true, false, FollowSymbolMode::Exact); }; diff --git a/src/plugins/cppeditor/quickfixes/rewritecomment.cpp b/src/plugins/cppeditor/quickfixes/rewritecomment.cpp index 518705039bb..fcdaaa00458 100644 --- a/src/plugins/cppeditor/quickfixes/rewritecomment.cpp +++ b/src/plugins/cppeditor/quickfixes/rewritecomment.cpp @@ -246,6 +246,8 @@ private: (const Link &link) { moveComments(link, symbolLoc, comments); }; + NonInteractiveFollowSymbolMarker niMarker; + CppCodeModelSettings::setInteractiveFollowSymbol(false); CppModelManager::followSymbol(cursorInEditor, callback, true, false, FollowSymbolMode::Exact); } diff --git a/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp b/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp index eddc4d6e5ba..0c7cf72b336 100644 --- a/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp +++ b/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp @@ -120,6 +120,7 @@ private: // Force queued execution, as the built-in editor can run the callback synchronously. const auto followSymbol = [cursorInEditor, callback] { + NonInteractiveFollowSymbolMarker niMarker; CppModelManager::followSymbol( cursorInEditor, callback, true, false, FollowSymbolMode::Exact); }; From 0fffe1058d24cf554cd77f50d586ad2b6be78f38 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 28 May 2024 13:29:31 +0200 Subject: [PATCH 07/26] CppEditor: Make more use of CppQuickFixInterface::currentFile() As in 5cc44b8cab445168c3f90d16a85f3c5b61b67334, this time with the non- trivial cases. Change-Id: I48c3f27c83903457473afa6175c8522d2ff23f96 Reviewed-by: David Schulz --- .../cppcodegenerationquickfixes.cpp | 19 +++++++------------ .../quickfixes/cppinsertvirtualmethods.cpp | 3 +-- .../quickfixes/insertfunctiondefinition.cpp | 3 +-- .../quickfixes/movefunctiondefinition.cpp | 16 ++++++---------- .../cppeditor/quickfixes/rewritecomment.cpp | 19 +++++++++++-------- .../synchronizememberfunctionorder.cpp | 6 +++++- 6 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp b/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp index 2d486e18173..7adf62cb815 100644 --- a/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp +++ b/src/plugins/cppeditor/quickfixes/cppcodegenerationquickfixes.cpp @@ -260,15 +260,14 @@ static void extractNames(const CppRefactoringFilePtr &file, class GetterSetterRefactoringHelper { public: - GetterSetterRefactoringHelper(CppQuickFixOperation *operation, - const FilePath &filePath, - Class *clazz) + GetterSetterRefactoringHelper(CppQuickFixOperation *operation, Class *clazz) : m_operation(operation) , m_changes(m_operation->snapshot()) , m_locator(m_changes) - , m_headerFile(m_changes.cppFile(filePath)) + , m_headerFile(operation->currentFile()) , m_sourceFile([&] { - FilePath cppFilePath = correspondingHeaderOrSource(filePath, &m_isHeaderHeaderFile); + FilePath cppFilePath = correspondingHeaderOrSource(m_headerFile->filePath(), + &m_isHeaderHeaderFile); if (!m_isHeaderHeaderFile || !cppFilePath.exists()) { // there is no "source" file return m_headerFile; @@ -1271,11 +1270,10 @@ private: const ClassSpecifierAST *m_classAST; InsertionPointLocator::AccessSpec m_accessSpec; GenerateConstructorRefactoringHelper(CppQuickFixOperation *operation, - const FilePath &filePath, Class *clazz, const ClassSpecifierAST *classAST, InsertionPointLocator::AccessSpec accessSpec) - : GetterSetterRefactoringHelper(operation, filePath, clazz) + : GetterSetterRefactoringHelper(operation, clazz) , m_classAST(classAST) , m_accessSpec(accessSpec) {} @@ -1416,7 +1414,6 @@ private: } }; GenerateConstructorRefactoringHelper helper(this, - currentFile()->filePath(), m_classAST->symbol, m_classAST, accessSpec); @@ -1509,7 +1506,7 @@ public: void perform() override { - GetterSetterRefactoringHelper helper(this, currentFile()->filePath(), m_data.clazz); + GetterSetterRefactoringHelper helper(this, m_data.clazz); helper.performGeneration(m_data, m_generateFlags); helper.applyChanges(); } @@ -1829,9 +1826,7 @@ private: } if (m_candidates.empty()) return; - GetterSetterRefactoringHelper helper(this, - currentFile()->filePath(), - m_candidates.front().data.clazz); + GetterSetterRefactoringHelper helper(this, m_candidates.front().data.clazz); for (MemberInfo &mi : m_candidates) { if (mi.requestedFlags != 0) { helper.performGeneration(mi.data, mi.requestedFlags); diff --git a/src/plugins/cppeditor/quickfixes/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/quickfixes/cppinsertvirtualmethods.cpp index 31193e5cec0..1a2ee5ab878 100644 --- a/src/plugins/cppeditor/quickfixes/cppinsertvirtualmethods.cpp +++ b/src/plugins/cppeditor/quickfixes/cppinsertvirtualmethods.cpp @@ -767,8 +767,7 @@ public: printer.showTemplateParameters = true; Utils::ChangeSet headerChangeSet; const CppRefactoringChanges refactoring(snapshot()); - const Utils::FilePath filePath = currentFile()->filePath(); - const CppRefactoringFilePtr headerFile = refactoring.cppFile(filePath); + const CppRefactoringFilePtr headerFile = currentFile(); const LookupContext targetContext(headerFile->cppDocument(), snapshot()); const Class *targetClass = m_classAST->symbol; diff --git a/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp b/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp index 740c42909d1..693b2c4a1d8 100644 --- a/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp +++ b/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp @@ -155,8 +155,7 @@ public: // rewrite the function name if (nameIncludesOperatorName(decl->name())) { - CppRefactoringFilePtr file = refactoring.cppFile(op->filePath()); - const QString operatorNameText = file->textOf(declAST->core_declarator); + const QString operatorNameText = op->currentFile()->textOf(declAST->core_declarator); oo.includeWhiteSpaceInOperatorName = operatorNameText.contains(QLatin1Char(' ')); } const QString name = oo.prettyName(LookupContext::minimalName(decl, targetCoN, diff --git a/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp b/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp index f6223629ae9..e6ec6a8b9f1 100644 --- a/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp +++ b/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp @@ -86,10 +86,10 @@ public: }; MoveFuncDefRefactoringHelper(CppQuickFixOperation *operation, MoveType type, - const FilePath &fromFile, const FilePath &toFile) + const FilePath &toFile) : m_operation(operation), m_type(type), m_changes(m_operation->snapshot()) { - m_fromFile = m_changes.cppFile(fromFile); + m_fromFile = operation->currentFile(); m_toFile = (m_type == MoveOutside) ? m_fromFile : m_changes.cppFile(toFile); } @@ -159,19 +159,18 @@ public: , m_funcDef(funcDef) , m_type(type) , m_cppFilePath(cppFilePath) - , m_headerFilePath(funcDef->symbol->filePath()) { if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) { setDescription(Tr::tr("Move Definition Outside Class")); } else { - const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir()); + const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir()); setDescription(Tr::tr("Move Definition to %1").arg(resolved.displayName())); } } void perform() override { - MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath); + MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath); helper.performMove(m_funcDef); helper.applyChanges(); } @@ -180,7 +179,6 @@ private: FunctionDefinitionAST *m_funcDef; MoveFuncDefRefactoringHelper::MoveType m_type; const FilePath m_cppFilePath; - const FilePath m_headerFilePath; }; class MoveAllFuncDefOutsideOp : public CppQuickFixOperation @@ -193,12 +191,11 @@ public: , m_type(type) , m_classDef(classDef) , m_cppFilePath(cppFileName) - , m_headerFilePath(classDef->symbol->filePath()) { if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) { setDescription(Tr::tr("Definitions Outside Class")); } else { - const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir()); + const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir()); setDescription(Tr::tr("Move All Function Definitions to %1") .arg(resolved.displayName())); } @@ -206,7 +203,7 @@ public: void perform() override { - MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath); + MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath); for (DeclarationListAST *it = m_classDef->member_specifier_list; it; it = it->next) { if (FunctionDefinitionAST *funcAST = it->value->asFunctionDefinition()) { if (funcAST->symbol && !funcAST->symbol->isGenerated()) @@ -220,7 +217,6 @@ private: MoveFuncDefRefactoringHelper::MoveType m_type; ClassSpecifierAST *m_classDef; const FilePath m_cppFilePath; - const FilePath m_headerFilePath; }; class MoveFuncDefToDeclOp : public CppQuickFixOperation diff --git a/src/plugins/cppeditor/quickfixes/rewritecomment.cpp b/src/plugins/cppeditor/quickfixes/rewritecomment.cpp index fcdaaa00458..3ac7fede2c5 100644 --- a/src/plugins/cppeditor/quickfixes/rewritecomment.cpp +++ b/src/plugins/cppeditor/quickfixes/rewritecomment.cpp @@ -235,16 +235,17 @@ public: private: void perform() override { - const auto textDoc = const_cast(currentFile()->document()); - const int pos = currentFile()->cppDocument()->translationUnit()->getTokenPositionInDocument( + const CppRefactoringFilePtr file = currentFile(); + const auto textDoc = const_cast(file->document()); + const int pos = file->cppDocument()->translationUnit()->getTokenPositionInDocument( m_symbol->sourceLocation(), textDoc); QTextCursor cursor(textDoc); cursor.setPosition(pos); - const CursorInEditor cursorInEditor(cursor, currentFile()->filePath(), editor(), + const CursorInEditor cursorInEditor(cursor, file->filePath(), editor(), editor()->textDocument()); - const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens] + const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens, file] (const Link &link) { - moveComments(link, symbolLoc, comments); + moveComments(file, link, symbolLoc, comments); }; NonInteractiveFollowSymbolMarker niMarker; CppCodeModelSettings::setInteractiveFollowSymbol(false); @@ -252,14 +253,16 @@ private: FollowSymbolMode::Exact); } - static void moveComments(const Link &targetLoc, const Link &symbolLoc, - const QList &comments) + static void moveComments( + const CppRefactoringFilePtr &sourceFile, + const Link &targetLoc, + const Link &symbolLoc, + const QList &comments) { if (!targetLoc.hasValidTarget() || targetLoc.hasSameLocation(symbolLoc)) return; CppRefactoringChanges changes(CppModelManager::snapshot()); - const CppRefactoringFilePtr sourceFile = changes.cppFile(symbolLoc.targetFilePath); const CppRefactoringFilePtr targetFile = targetLoc.targetFilePath == symbolLoc.targetFilePath ? sourceFile diff --git a/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp b/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp index 0c7cf72b336..8429e6762f0 100644 --- a/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp +++ b/src/plugins/cppeditor/quickfixes/synchronizememberfunctionorder.cpp @@ -41,6 +41,7 @@ public: setDescription( Tr::tr("Re-order Member Function Definitions According to Declaration Order")); m_state->decls = decls; + m_state->currentFile = currentFile(); } private: @@ -71,6 +72,7 @@ private: QList decls; QHash defLocations; + CppRefactoringFilePtr currentFile; int remainingFollowSymbolOps = 0; }; @@ -158,7 +160,9 @@ private: if (defLocsExpectedOrder == defLocsActualOrder) continue; - CppRefactoringFilePtr file = factory.cppFile(it.key()); + CppRefactoringFilePtr file = it.key() == state->currentFile->filePath() + ? state->currentFile + : factory.cppFile(it.key()); ChangeSet changes; for (int i = 0; i < defLocsActualOrder.size(); ++i) { const DefLocation &actualLoc = defLocsActualOrder[i]; From 0ccfccd5c512097f67d077e733affea30ca7098b Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 30 May 2024 19:20:48 +0200 Subject: [PATCH 08/26] ExtensionManager: Some cleanups Stuff you notice 10 Minutes after pushing the code you worked on for days. Change-Id: I24614b8129f80c8986ec11d5146c5631dae5d515 Reviewed-by: Cristian Adam --- .../extensionmanagerplugin.cpp | 3 +- .../extensionmanagerwidget.cpp | 13 ++++---- .../extensionmanager/extensionsbrowser.cpp | 8 ++--- .../extensionmanager/extensionsmodel.cpp | 31 ++++++------------- 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/plugins/extensionmanager/extensionmanagerplugin.cpp b/src/plugins/extensionmanager/extensionmanagerplugin.cpp index d94d5aa7ac5..979a75ad291 100644 --- a/src/plugins/extensionmanager/extensionmanagerplugin.cpp +++ b/src/plugins/extensionmanager/extensionmanagerplugin.cpp @@ -26,7 +26,6 @@ #include #include -using namespace ExtensionSystem; using namespace Core; using namespace Utils; @@ -45,7 +44,7 @@ public: Theme::IconsBaseColor}}); const Icon FLAT_ACTIVE({{":/extensionmanager/images/mode_extensionmanager_mask.png", Theme::IconsModeWelcomeActiveColor}}); - setIcon(Utils::Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE)); + setIcon(Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE)); setPriority(72); using namespace Layouting; diff --git a/src/plugins/extensionmanager/extensionmanagerwidget.cpp b/src/plugins/extensionmanager/extensionmanagerwidget.cpp index 78acb32e28e..363b8cb90ee 100644 --- a/src/plugins/extensionmanager/extensionmanagerwidget.cpp +++ b/src/plugins/extensionmanager/extensionmanagerwidget.cpp @@ -280,7 +280,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t) const LinksData linksData = current.data(RoleDescriptionLinks).value(); if (!linksData.isEmpty()) { QString linksHtml; - const QStringList links = Utils::transform(linksData, [](const LinksData::Type &link) { + const QStringList links = transform(linksData, [](const LinksData::Type &link) { const QString anchor = link.first.isEmpty() ? link.second : link.first; return QString::fromLatin1("%2 >") .arg(link.second).arg(anchor); @@ -293,7 +293,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t) if (!imagesData.isEmpty()) { const QString examplesBoxCss = QString::fromLatin1("height: 168px; background-color: %1; ") - .arg(creatorTheme()->color(Theme::Token_Background_Default).name()); + .arg(creatorColor(Theme::Token_Background_Default).name()); description.append(QString(R"(
%2
@@ -362,8 +362,8 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t) if (!tags.isEmpty()) { const QString tagTemplate = QString(R"( %2 - )").arg(creatorTheme()->color(Theme::Token_Stroke_Subtle).name()); - const QStringList tagsFmt = Utils::transform(tags, [&tagTemplate](const QString &tag) { + )").arg(creatorColor(Theme::Token_Stroke_Subtle).name()); + const QStringList tagsFmt = transform(tags, [&tagTemplate](const QString &tag) { return tagTemplate.arg(tag); }); description.append(QString(R"( @@ -397,8 +397,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t) if (isPack) { const PluginsData plugins = current.data(RolePlugins).value(); - const QStringList extensions = Utils::transform(plugins, - &QPair::first); + const QStringList extensions = transform(plugins, &QPair::first); const QString extensionsFmt = extensions.join("
"); description.append(QString(R"(
%2
@@ -422,7 +421,7 @@ void ExtensionManagerWidget::fetchAndInstallPlugin(const QUrl &url) StorageStruct() { progressDialog.reset(new QProgressDialog(Tr::tr("Downloading Plugin..."), Tr::tr("Cancel"), 0, 0, - Core::ICore::dialogParent())); + ICore::dialogParent())); progressDialog->setWindowModality(Qt::ApplicationModal); progressDialog->setFixedSize(progressDialog->sizeHint()); progressDialog->setAutoClose(false); diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 81264c59bd7..b5d42ec4f95 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -198,7 +198,7 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent) auto manageLabel = new QLabel(Tr::tr("Manage Extensions")); manageLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH1)); - d->searchBox = new Core::SearchBox; + d->searchBox = new SearchBox; d->searchBox->setFixedWidth(itemSize.width()); d->updateButton = new Button(Tr::tr("Install..."), Button::MediumPrimary); @@ -252,10 +252,8 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent) connect(d->updateButton, &QAbstractButton::pressed, this, []() { executePluginInstallWizard(); }); - connect(ExtensionSystem::PluginManager::instance(), - &ExtensionSystem::PluginManager::pluginsChanged, this, updateModel); - connect(ExtensionSystem::PluginManager::instance(), - &ExtensionSystem::PluginManager::initializationDone, + connect(PluginManager::instance(), &PluginManager::pluginsChanged, this, updateModel); + connect(PluginManager::instance(), &PluginManager::initializationDone, this, &ExtensionsBrowser::fetchExtensions); connect(d->searchBox, &QLineEdit::textChanged, d->filterProxyModel, &QSortFilterProxyModel::setFilterWildcard); diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index 2315164e11f..881125555df 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -3,9 +3,6 @@ #include "extensionsmodel.h" -#include "extensionsbrowser.h" - -#include "extensionmanagertr.h" #include "utils/algorithm.h" #include @@ -30,16 +27,16 @@ namespace ExtensionManager::Internal { Q_LOGGING_CATEGORY(modelLog, "qtc.extensionmanager.model", QtWarningMsg) -struct PluginDependency +struct Dependency { QString name; QString version; }; -using PluginDependencies = QList; +using Dependencies = QList; struct Plugin { - PluginDependencies dependencies; + Dependencies dependencies; QString copyright; QString name; QString packageUrl; @@ -74,10 +71,10 @@ static Plugin pluginFromJson(const QJsonObject &obj) const QJsonObject metaDataObj = obj.value("meta_data").toObject(); const QJsonArray dependenciesArray = metaDataObj.value("Dependencies").toArray(); - PluginDependencies dependencies; + Dependencies dependencies; for (const QJsonValueConstRef &dependencyVal : dependenciesArray) { const QJsonObject dependencyObj = dependencyVal.toObject(); - dependencies.append(PluginDependency{ + dependencies.append(Dependency{ .name = dependencyObj.value("Name").toString(), .version = dependencyObj.value("Version").toString(), }); @@ -189,19 +186,12 @@ static Extensions parseExtensionsRepoReply(const QByteArray &jsonData) return parsedExtensions; } -class ExtensionsModelPrivate : public QObject +class ExtensionsModelPrivate { public: - ExtensionsModelPrivate(ExtensionsModel *parent) - : q(parent) - { - } - void setExtensions(const Extensions &extensions); void removeLocalExtensions(); - ExtensionsModel *q; - Extensions allExtensions; // Original, complete extensions entries Extensions absentExtensions; // All packs + plugin extensions that are not (yet) installed }; @@ -224,7 +214,7 @@ void ExtensionsModelPrivate::removeLocalExtensions() ExtensionsModel::ExtensionsModel(QObject *parent) : QAbstractListModel(parent) - , d(new ExtensionsModelPrivate(this)) + , d(new ExtensionsModelPrivate) { } @@ -250,7 +240,7 @@ static QVariant dataFromPluginSpec(const PluginSpec *pluginSpec, int role) return pluginSpec->copyright(); case RoleDependencies: { QStringList dependencies = transform(pluginSpec->dependencies(), - &ExtensionSystem::PluginDependency::toString); + &PluginDependency::toString); dependencies.sort(); return dependencies; } @@ -301,7 +291,7 @@ static QStringList dependenciesFromExtension(const Extension &extension) { QStringList dependencies; for (const Plugin &plugin : extension.plugins) { - for (const PluginDependency &dependency : plugin.dependencies) { + for (const Dependency &dependency : plugin.dependencies) { const QString withVersion = QString::fromLatin1("%1 (%2)").arg(dependency.name) .arg(dependency.version); dependencies.append(withVersion); @@ -404,8 +394,7 @@ void ExtensionsModel::setExtensionsJson(const QByteArray &json) PluginSpec *ExtensionsModel::pluginSpecForName(const QString &pluginName) { - return Utils::findOrDefault(PluginManager::plugins(), - Utils::equal(&PluginSpec::name, pluginName)); + return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::name, pluginName)); } } // ExtensionManager::Internal From a1727a9d6d718bc312f011a8ab66930a519204e2 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 31 May 2024 13:46:46 +0200 Subject: [PATCH 09/26] Debugger: fix compiling dumper tests Change-Id: Ic06483bfeee376e9cc3e7beb516b9bde9cb5b46d Reviewed-by: hjk --- tests/auto/debugger/tst_dumpers.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 14c0e3500ab..d8ed605f822 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1171,6 +1171,7 @@ private: bool m_isQnxGdb = false; bool m_useGLibCxxDebug = false; int m_totalDumpTime = 0; + int m_totalInnerTime = 0; }; void tst_Dumpers::initTestCase() @@ -1344,6 +1345,8 @@ void tst_Dumpers::cleanup() void tst_Dumpers::cleanupTestCase() { qCDebug(lcDumpers) << "Dumpers total: " << QTime::fromMSecsSinceStartOfDay(m_totalDumpTime); + qCDebug(lcDumpers, "TotalOuter: %5d", m_totalDumpTime); + qCDebug(lcDumpers, "TotalInner: %5d", m_totalInnerTime); } void tst_Dumpers::dumper() @@ -1890,6 +1893,9 @@ void tst_Dumpers::dumper() actual.fromStringMultiple(QString::fromLocal8Bit(contents)); context.nameSpace = actual["qtnamespace"].data(); + int runtime = actual["runtime"].data().toFloat() * 1000; + qCDebug(lcDumpers, "CaseInner: %5d", runtime); + m_totalInnerTime += runtime; actual = actual["data"]; //qCDebug(lcDumpers) << "FOUND NS: " << context.nameSpace; @@ -1914,6 +1920,9 @@ void tst_Dumpers::dumper() context.nameSpace.clear(); contents.replace("\\\"", "\""); actual.fromString(QString::fromLocal8Bit(contents)); + int runtime = actual["runtime"].data().toFloat() * 1000; + qCDebug(lcDumpers, "CaseInner: %5d", runtime); + m_totalInnerTime += runtime; } else { QByteArray localsAnswerStart("|R|42|"); QByteArray locals("|script|"); From 04abc375f5b3a9aad42da32b0b98ccb489a49fca Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 28 May 2024 07:40:25 +0200 Subject: [PATCH 10/26] Lua: Improve memory management Previously the PluginSpec would create a keep around a single lua vm that was then shared with the actual plugin instance. This made it unclear when the VM was freed. Now we instead cleanup the lua vm used to fetch the plugin infos immediately and instead create a fresh vm for the actual plugin instance that can then follow the normal Plugin lifecylce. Change-Id: I81bb9ecf57706c2ba1b0d8db83ab26b3b8e944f2 Reviewed-by: David Schulz --- src/plugins/lua/luaengine.cpp | 44 +++++++++++++++++++++---------- src/plugins/lua/luaengine.h | 6 ++--- src/plugins/lua/luapluginspec.cpp | 39 ++++++++++++++------------- src/plugins/lua/luapluginspec.h | 5 ++-- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index 505313da865..29ca17fad6e 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -4,6 +4,7 @@ #include "luaengine.h" #include "luapluginspec.h" +#include "luatr.h" #include #include @@ -172,14 +173,6 @@ expected_str LuaEngine::connectHooks( return {}; } -expected_str LuaEngine::connectHooks(sol::state_view lua, const sol::table &hookTable) -{ - if (!hookTable) - return {}; - - return instance().connectHooks(lua, hookTable, ""); -} - expected_str LuaEngine::loadPlugin(const Utils::FilePath &path) { auto contents = path.fileContents(); @@ -204,12 +197,16 @@ expected_str LuaEngine::loadPlugin(const Utils::FilePath &path) sol::table pluginInfo = result.get(); if (!pluginInfo.valid()) return make_unexpected(QString("Script did not return a table with plugin info")); - return LuaPluginSpec::create(path, std::move(lua), pluginInfo); + return LuaPluginSpec::create(path, pluginInfo); } -expected_str LuaEngine::prepareSetup( - sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional hookTable) +expected_str LuaEngine::prepareSetup( + sol::state_view lua, const LuaPluginSpec &pluginSpec) { + auto contents = pluginSpec.filePath().fileContents(); + if (!contents) + return make_unexpected(contents.error()); + // TODO: Only open libraries requested by the plugin lua.open_libraries( sol::lib::base, @@ -261,10 +258,29 @@ expected_str LuaEngine::prepareSetup( for (const auto &func : d->m_autoProviders) func(lua); - if (hookTable) - return LuaEngine::connectHooks(lua, *hookTable); + sol::protected_function_result result = lua.safe_script( + std::string_view(contents->data(), contents->size()), + sol::script_pass_on_error, + pluginSpec.filePath().fileName().toUtf8().constData()); - return {}; + auto pluginTable = result.get>(); + if (!pluginTable) + return make_unexpected(Tr::tr("Script did not return a table")); + + auto hookTable = pluginTable->get>("hooks"); + + if (hookTable) { + auto connectResult = connectHooks(lua, *hookTable, {}); + if (!connectResult) + return make_unexpected(connectResult.error()); + } + + auto setupFunction = pluginTable->get_or("setup", {}); + + if (!setupFunction) + return make_unexpected(Tr::tr("Plugin info table did not contain a setup function")); + + return setupFunction; } bool LuaEngine::isCoroutine(lua_State *state) diff --git a/src/plugins/lua/luaengine.h b/src/plugins/lua/luaengine.h index 688c728808e..f8fa085d6d0 100644 --- a/src/plugins/lua/luaengine.h +++ b/src/plugins/lua/luaengine.h @@ -55,15 +55,13 @@ public: static LuaEngine &instance(); Utils::expected_str loadPlugin(const Utils::FilePath &path); - Utils::expected_str prepareSetup( - sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional hookTable); + Utils::expected_str prepareSetup( + sol::state_view lua, const LuaPluginSpec &pluginSpec); static void registerProvider(const QString &packageName, const PackageProvider &provider); static void autoRegister(const std::function ®isterFunction); static void registerHook(QString name, const std::function &hookProvider); - static Utils::expected_str connectHooks(sol::state_view lua, const sol::table &hookTable); - static bool isCoroutine(lua_State *state); static sol::table toTable(const sol::state_view &lua, const QJsonValue &v); diff --git a/src/plugins/lua/luapluginspec.cpp b/src/plugins/lua/luapluginspec.cpp index 4c4ac66d4e0..c3fcd558a55 100644 --- a/src/plugins/lua/luapluginspec.cpp +++ b/src/plugins/lua/luapluginspec.cpp @@ -34,28 +34,19 @@ class LuaPluginSpecPrivate { public: FilePath pluginScriptPath; - - sol::state lua; - sol::table pluginTable; - - sol::function setupFunction; + bool printToOutputPane = false; + std::unique_ptr activeLuaState; }; LuaPluginSpec::LuaPluginSpec() : d(new LuaPluginSpecPrivate()) {} -expected_str LuaPluginSpec::create(const FilePath &filePath, - sol::state lua, - sol::table pluginTable) +expected_str LuaPluginSpec::create(const FilePath &filePath, sol::table pluginTable) { std::unique_ptr pluginSpec(new LuaPluginSpec()); - pluginSpec->d->lua = std::move(lua); - pluginSpec->d->pluginTable = pluginTable; - - pluginSpec->d->setupFunction = pluginTable.get_or("setup", {}); - if (!pluginSpec->d->setupFunction) + if (!pluginTable.get_or("setup", {})) return make_unexpected(QString("Plugin info table did not contain a setup function")); QJsonValue v = LuaEngine::toJson(pluginTable); @@ -75,6 +66,7 @@ expected_str LuaPluginSpec::create(const FilePath &filePath, pluginSpec->setLocation(filePath.parentDir()); pluginSpec->d->pluginScriptPath = filePath; + pluginSpec->d->printToOutputPane = pluginTable.get_or("printToOutputPane", false); return pluginSpec.release(); } @@ -94,16 +86,19 @@ bool LuaPluginSpec::loadLibrary() } bool LuaPluginSpec::initializePlugin() { - expected_str setupResult - = LuaEngine::instance() - .prepareSetup(d->lua, *this, d->pluginTable.get>("hooks")); + QTC_ASSERT(!d->activeLuaState, return false); + + std::unique_ptr activeLuaState = std::make_unique(); + + expected_str setupResult + = LuaEngine::instance().prepareSetup(*activeLuaState, *this); if (!setupResult) { setError(Lua::Tr::tr("Failed to prepare plugin setup: %1").arg(setupResult.error())); return false; } - auto result = d->setupFunction.call(); + auto result = setupResult->call(); if (result.get_type() == sol::type::boolean && result.get() == false) { setError(Lua::Tr::tr("Plugin setup function returned false")); @@ -117,6 +112,8 @@ bool LuaPluginSpec::initializePlugin() } } + d->activeLuaState = std::move(activeLuaState); + setState(PluginSpec::State::Initialized); return true; } @@ -133,14 +130,18 @@ bool LuaPluginSpec::delayedInitialize() } ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop() { + d->activeLuaState.reset(); return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown; } -void LuaPluginSpec::kill() {} +void LuaPluginSpec::kill() +{ + d->activeLuaState.reset(); +} bool LuaPluginSpec::printToOutputPane() const { - return d->pluginTable.get_or("printToOutputPane", false); + return d->printToOutputPane; } } // namespace Lua diff --git a/src/plugins/lua/luapluginspec.h b/src/plugins/lua/luapluginspec.h index 2d72bb53907..7c2ab3318bd 100644 --- a/src/plugins/lua/luapluginspec.h +++ b/src/plugins/lua/luapluginspec.h @@ -39,9 +39,8 @@ class LuaPluginSpec : public ExtensionSystem::PluginSpec LuaPluginSpec(); public: - static Utils::expected_str create(const Utils::FilePath &filePath, - sol::state lua, - sol::table pluginTable); + static Utils::expected_str create( + const Utils::FilePath &filePath, sol::table pluginTable); ExtensionSystem::IPlugin *plugin() const override; From 58ac9aea688851760e931a101dcb76d552431bc8 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 31 May 2024 12:50:40 +0200 Subject: [PATCH 11/26] LayoutBuilder: Add a few Label related functions ... and use them in the CoPilot settings Change-Id: Id861cf34274d2afe798d4735072d02c2c8f724e3 Reviewed-by: Marcus Tillmanns --- src/libs/utils/layoutbuilder.cpp | 25 +++++++++ src/libs/utils/layoutbuilder.h | 25 +++++++++ src/plugins/copilot/copilotsettings.cpp | 67 ++++++++++++------------- 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index cd4fde81109..09e3a83520e 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -763,6 +763,31 @@ void Label::setText(const QString &text) access(this)->setText(text); } +void Label::setTextFormat(Qt::TextFormat format) +{ + access(this)->setTextFormat(format); +} + +void Label::setWordWrap(bool on) +{ + access(this)->setWordWrap(on); +} + +void Label::setTextInteractionFlags(Qt::TextInteractionFlags flags) +{ + access(this)->setTextInteractionFlags(flags); +} + +void Label::setOpenExternalLinks(bool on) +{ + access(this)->setOpenExternalLinks(on); +} + +void Label::onLinkHovered(const std::function &func, QObject *guard) +{ + QObject::connect(access(this), &QLabel::linkHovered, guard, func); +} + // Group Group::Group(std::initializer_list ps) diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index 3a7eca26a57..07a6b9478ef 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -279,6 +279,11 @@ public: Label(const QString &text); void setText(const QString &); + void setTextFormat(Qt::TextFormat); + void setWordWrap(bool); + void setTextInteractionFlags(Qt::TextInteractionFlags); + void setOpenExternalLinks(bool); + void onLinkHovered(const std::function &, QObject *guard); }; class QTCREATOR_UTILS_EXPORT Group : public Widget @@ -446,6 +451,26 @@ class TitleId {}; auto title(auto p) { return IdAndArg{TitleId{}, p}; } void doit(auto x, TitleId, auto p) { x->setTitle(p); } +class TextFormatId {}; +auto textFormat(auto p) { return IdAndArg{TextFormatId{}, p}; } +void doit(auto x, TextFormatId, auto p) { x->setTextFormat(p); } + +class WordWrapId {}; +auto wordWrap(auto p) { return IdAndArg{WordWrapId{}, p}; } +void doit(auto x, WordWrapId, auto p) { x->setWordWrap(p); } + +class TextInteractionFlagId {}; +auto textInteractionFlags(auto p) { return IdAndArg{TextInteractionFlagId{}, p}; } +void doit(auto x, TextInteractionFlagId, auto p) { x->setTextInteractionFlags(p); } + +class OpenExternalLinksId {}; +auto openExternalLinks(auto p) { return IdAndArg{OpenExternalLinksId{}, p}; } +void doit(auto x, OpenExternalLinksId, auto p) { x->setOpenExternalLinks(p); } + +class OnLinkHoveredId {}; +auto onLinkHovered(auto p, QObject *guard) { return IdAndArg{OnLinkHoveredId{}, std::pair{p, guard}}; } +void doit(auto x, OnLinkHoveredId, auto p) { x->onLinkHovered(p.first, p.second); } + class GroupCheckerId {}; auto groupChecker(auto p) { return IdAndArg{GroupCheckerId{}, p}; } void doit(auto x, GroupCheckerId, auto p) { x->setGroupChecker(p); } diff --git a/src/plugins/copilot/copilotsettings.cpp b/src/plugins/copilot/copilotsettings.cpp index 9ddfa4edfbb..aeac499c631 100644 --- a/src/plugins/copilot/copilotsettings.cpp +++ b/src/plugins/copilot/copilotsettings.cpp @@ -168,41 +168,38 @@ CopilotSettings::CopilotSettings() setLayouter([this] { using namespace Layouting; - auto warningLabel = new QLabel; - warningLabel->setWordWrap(true); - warningLabel->setTextInteractionFlags( - Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse); - warningLabel->setText( - Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable " - "%1 terms. It is your responsibility to know and accept the requirements and " - "parameters of using tools like %1. This may include, but is not limited to, " - "ensuring you have the rights to allow %1 access to your code, as well as " - "understanding any implications of your use of %1 and suggestions produced " - "(like copyright, accuracy, etc.).") - .arg("Copilot")); - - auto authWidget = new AuthWidget(); - - auto helpLabel = new QLabel(); - helpLabel->setTextFormat(Qt::MarkdownText); - helpLabel->setWordWrap(true); - helpLabel->setTextInteractionFlags( - Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse); - helpLabel->setOpenExternalLinks(true); - connect(helpLabel, &QLabel::linkHovered, [](const QString &link) { - QToolTip::showText(QCursor::pos(), link); - }); - // clang-format off - helpLabel->setText(Tr::tr( - "The Copilot plugin requires node.js and the Copilot neovim plugin. " - "If you install the neovim plugin as described in %1, " - "the plugin will find the agent.js file automatically.\n\n" - "Otherwise you need to specify the path to the %2 " - "file from the Copilot neovim plugin.", - "Markdown text for the copilot instruction label") - .arg("[README.md](https://github.com/github/copilot.vim)") - .arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)")); + + Label warningLabel { + wordWrap(true), + textInteractionFlags( + Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse), + text(Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable " + "%1 terms. It is your responsibility to know and accept the requirements and " + "parameters of using tools like %1. This may include, but is not limited to, " + "ensuring you have the rights to allow %1 access to your code, as well as " + "understanding any implications of your use of %1 and suggestions produced " + "(like copyright, accuracy, etc.).") + .arg("Copilot")), + }; + + Label helpLabel { + textFormat(Qt::MarkdownText), + wordWrap(true), + textInteractionFlags( + Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse), + openExternalLinks(true), + onLinkHovered([](const QString &link) { QToolTip::showText(QCursor::pos(), link); }, this), + text(Tr::tr( + "The Copilot plugin requires node.js and the Copilot neovim plugin. " + "If you install the neovim plugin as described in %1, " + "the plugin will find the agent.js file automatically.\n\n" + "Otherwise you need to specify the path to the %2 " + "file from the Copilot neovim plugin.", + "Markdown text for the copilot instruction label") + .arg("[README.md](https://github.com/github/copilot.vim)") + .arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)")) + }; return Column { Group { @@ -213,7 +210,7 @@ CopilotSettings::CopilotSettings() } }, Form { - authWidget, br, + new AuthWidget, br, enableCopilot, br, nodeJsPath, br, distPath, br, From 45702941f8fe72635d7663253993361a20aebd40 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 23 May 2024 16:45:28 +0200 Subject: [PATCH 12/26] Fix some deprecation warnings from QCryptographicHash QT_DEPRECATED_VERSION_X_6_4("Use the QByteArrayView overload instead") void addData(const char *data, qsizetype length); Change-Id: I144765e6993a9942b372943ccbf5c783fcf9da3d Reviewed-by: Christian Stenger --- src/libs/languageutils/componentversion.cpp | 6 +- src/libs/languageutils/fakemetaobject.cpp | 120 ++++++++++---------- src/libs/qmljs/qmljsimportdependencies.cpp | 16 +-- 3 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/libs/languageutils/componentversion.cpp b/src/libs/languageutils/componentversion.cpp index f041740d3b2..edfa2c552bb 100644 --- a/src/libs/languageutils/componentversion.cpp +++ b/src/libs/languageutils/componentversion.cpp @@ -6,8 +6,6 @@ #include #include -#include - namespace LanguageUtils { // QTC_TEMP @@ -42,8 +40,8 @@ QString ComponentVersion::toString() const void ComponentVersion::addToHash(QCryptographicHash &hash) const { - hash.addData(reinterpret_cast(&_major), sizeof(_major)); - hash.addData(reinterpret_cast(&_minor), sizeof(_minor)); + hash.addData(QByteArrayView(reinterpret_cast(&_major), sizeof(_major))); + hash.addData(QByteArrayView(reinterpret_cast(&_minor), sizeof(_minor))); } } // namespace LanguageUtils diff --git a/src/libs/languageutils/fakemetaobject.cpp b/src/libs/languageutils/fakemetaobject.cpp index 4c553cdc7b5..da7877c1b63 100644 --- a/src/libs/languageutils/fakemetaobject.cpp +++ b/src/libs/languageutils/fakemetaobject.cpp @@ -6,6 +6,21 @@ using namespace LanguageUtils; +static QByteArrayView asData(const void *mem, size_t len) +{ + return QByteArrayView(reinterpret_cast(mem), len); +} + +static void addData(QCryptographicHash &hash, int x) +{ + hash.addData(asData(&x, sizeof(int))); +} + +static void addData(QCryptographicHash &hash, const QString &x) +{ + hash.addData(asData(x.constData(), x.size() * sizeof(QChar))); +} + FakeMetaEnum::FakeMetaEnum() {} @@ -39,15 +54,12 @@ bool FakeMetaEnum::hasKey(const QString &key) const void FakeMetaEnum::addToHash(QCryptographicHash &hash) const { - int len = m_name.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_name.constData()), len * sizeof(QChar)); - len = m_keys.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, m_name.size()); + addData(hash, m_name); + addData(hash, m_keys.size()); for (const QString &key : std::as_const(m_keys)) { - len = key.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); + addData(hash, key.size()); + addData(hash, key); } } @@ -121,29 +133,23 @@ void FakeMetaMethod::setRevision(int r) void FakeMetaMethod::addToHash(QCryptographicHash &hash) const { - int len = m_name.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_name.constData()), len * sizeof(QChar)); - hash.addData(reinterpret_cast(&m_methodAccess), sizeof(m_methodAccess)); - hash.addData(reinterpret_cast(&m_methodTy), sizeof(m_methodTy)); - hash.addData(reinterpret_cast(&m_revision), sizeof(m_revision)); - len = m_paramNames.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, m_name.size()); + addData(hash, m_name); + addData(hash, m_methodAccess); + addData(hash, m_methodTy); + addData(hash, m_revision); + addData(hash, m_paramNames.size()); for (const QString &pName : std::as_const(m_paramNames)) { - len = pName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(pName.constData()), len * sizeof(QChar)); + addData(hash, pName.size()); + addData(hash, pName); } - len = m_paramTypes.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, m_paramTypes.size()); for (const QString &pType : std::as_const(m_paramTypes)) { - len = pType.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(pType.constData()), len * sizeof(QChar)); + addData(hash, pType.size()); + addData(hash, pType); } - len = m_returnType.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_returnType.constData()), len * sizeof(QChar)); + addData(hash, m_returnType.size()); + addData(hash, m_returnType); } QString FakeMetaMethod::describe(int baseIndent) const @@ -213,17 +219,15 @@ int FakeMetaProperty::revision() const void FakeMetaProperty::addToHash(QCryptographicHash &hash) const { - int len = m_propertyName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_propertyName.constData()), len * sizeof(QChar)); - hash.addData(reinterpret_cast(&m_revision), sizeof(m_revision)); + addData(hash, m_propertyName.size()); + addData(hash, m_propertyName); + addData(hash, m_revision); int flags = (m_isList ? (1 << 0) : 0) + (m_isPointer ? (1 << 1) : 0) + (m_isWritable ? (1 << 2) : 0); - hash.addData(reinterpret_cast(&flags), sizeof(flags)); - len = m_type.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_type.constData()), len * sizeof(QChar)); + addData(hash, flags); + addData(hash, m_type.size()); + addData(hash, m_type); } QString FakeMetaProperty::describe(int baseIndent) const @@ -361,34 +365,34 @@ QByteArray FakeMetaObject::calculateFingerprint() const { QCryptographicHash hash(QCryptographicHash::Sha1); int len = m_className.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_className.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, m_className); len = m_attachedTypeName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_attachedTypeName.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, m_attachedTypeName); len = m_defaultPropertyName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_defaultPropertyName.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, m_defaultPropertyName); len = m_enumNameToIndex.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, len); { QStringList keys(m_enumNameToIndex.keys()); keys.sort(); for (const QString &key : std::as_const(keys)) { len = key.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, key); int value = m_enumNameToIndex.value(key); - hash.addData(reinterpret_cast(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint... + addData(hash, value); m_enums.at(value).addToHash(hash); } } len = m_exports.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, len); for (const Export &e : std::as_const(m_exports)) e.addToHash(hash); // normalize order? len = m_exports.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(hash, len); for (const FakeMetaMethod &m : std::as_const(m_methods)) m.addToHash(hash); // normalize order? { @@ -396,16 +400,16 @@ QByteArray FakeMetaObject::calculateFingerprint() const keys.sort(); for (const QString &key : std::as_const(keys)) { len = key.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, key); int value = m_propNameToIdx.value(key); - hash.addData(reinterpret_cast(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint... + addData(hash, value); m_props.at(value).addToHash(hash); } } len = m_superName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(m_superName.constData()), len * sizeof(QChar)); + addData(hash, len); + addData(hash, m_superName); QByteArray res = hash.result(); res.append('F'); @@ -540,14 +544,12 @@ bool FakeMetaObject::Export::isValid() const void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const { - int len = package.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(package.constData()), len * sizeof(QChar)); - len = type.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(type.constData()), len * sizeof(QChar)); + addData(hash, package.size()); + addData(hash, package); + addData(hash, type.size()); + addData(hash, type); version.addToHash(hash); - hash.addData(reinterpret_cast(&metaObjectRevision), sizeof(metaObjectRevision)); + addData(hash, metaObjectRevision); } QString FakeMetaObject::Export::describe(int baseIndent) const diff --git a/src/libs/qmljs/qmljsimportdependencies.cpp b/src/libs/qmljs/qmljsimportdependencies.cpp index f1c4181a830..8e725fa521f 100644 --- a/src/libs/qmljs/qmljsimportdependencies.cpp +++ b/src/libs/qmljs/qmljsimportdependencies.cpp @@ -185,14 +185,14 @@ ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersio void ImportKey::addToHash(QCryptographicHash &hash) const { - hash.addData(reinterpret_cast(&type), sizeof(type)); - hash.addData(reinterpret_cast(&majorVersion), sizeof(majorVersion)); - hash.addData(reinterpret_cast(&minorVersion), sizeof(minorVersion)); + hash.addData(QByteArrayView(reinterpret_cast(&type), sizeof(type))); + hash.addData(QByteArrayView(reinterpret_cast(&majorVersion), sizeof(majorVersion))); + hash.addData(QByteArrayView(reinterpret_cast(&minorVersion), sizeof(minorVersion))); for (const QString &s : splitPath) { - hash.addData("/", 1); - hash.addData(reinterpret_cast(s.constData()), sizeof(QChar) * s.size()); + hash.addData("/"); + hash.addData(QByteArrayView(reinterpret_cast(s.constData()), sizeof(QChar) * s.size())); } - hash.addData("/", 1); + hash.addData("/"); } ImportKey ImportKey::flatKey() const { @@ -547,11 +547,11 @@ QByteArray DependencyInfo::calculateFingerprint(const ImportDependencies &deps) QStringList coreImports = Utils::toList(allCoreImports); coreImports.sort(); for (const QString &importId : std::as_const(coreImports)) { - hash.addData(reinterpret_cast(importId.constData()), importId.size() * sizeof(QChar)); + hash.addData(QByteArrayView(reinterpret_cast(importId.constData()), importId.size() * sizeof(QChar))); QByteArray coreImportFingerprint = deps.coreImport(importId).fingerprint; hash.addData(coreImportFingerprint); } - hash.addData("/", 1); + hash.addData("/"); QList imports = Utils::toList(allImports); std::sort(imports.begin(), imports.end()); for (const ImportKey &k : std::as_const(imports)) From 36f2a21f2d5260766e90e5e56f711a8a2d0db284 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 31 May 2024 12:32:33 +0200 Subject: [PATCH 13/26] ProjectExplorer: Support column numbers in file path linkification ... for task details. As a result, clicking on a linkified file path inside a task in the issues pane will now open the editor at the column specified in the compiler output, if there is one. We used to consider only the line. Change-Id: Idccba33b5b33029abfa8f29c7888af6c7f2e1622 Reviewed-by: hjk --- src/libs/utils/outputformatter.cpp | 41 +++++++++----- src/libs/utils/outputformatter.h | 9 +-- src/plugins/android/javaparser.cpp | 2 +- src/plugins/baremetal/iarewparser.cpp | 4 +- src/plugins/baremetal/keilparser.cpp | 12 ++-- src/plugins/baremetal/sdccparser.cpp | 8 +-- .../cmakeprojectmanager/cmakeparser.cpp | 21 ++++--- .../mesonprojectmanager/mesonoutputparser.cpp | 2 +- .../nim/project/nimoutputtaskparser.cpp | 2 +- src/plugins/projectexplorer/clangparser.cpp | 8 +-- src/plugins/projectexplorer/customparser.cpp | 2 +- src/plugins/projectexplorer/gccparser.cpp | 55 ++++++++++--------- src/plugins/projectexplorer/gnumakeparser.cpp | 2 +- src/plugins/projectexplorer/ldparser.cpp | 4 +- .../projectexplorer/linuxiccparser.cpp | 2 +- src/plugins/projectexplorer/lldparser.cpp | 2 +- src/plugins/projectexplorer/msvcparser.cpp | 6 +- .../projectexplorer/sanitizerparser.cpp | 5 +- .../projectexplorer/xcodebuildparser.cpp | 3 +- .../qmakeprojectmanager/qmakeparser.cpp | 2 +- src/plugins/qtsupport/qtparser.cpp | 8 +-- src/plugins/qtsupport/qttestparser.cpp | 4 +- 22 files changed, 115 insertions(+), 89 deletions(-) diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index cf00b5ee3fa..d36662f4d34 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -58,7 +58,7 @@ Link OutputLineParser::parseLinkTarget(const QString &target) return {}; return Link(FilePath::fromString(parts.first()), parts.length() > 1 ? parts.at(1).toInt() : 0, - parts.length() > 2 ? parts.at(2).toInt() : 0); + parts.length() > 2 ? parts.at(2).toInt() - 1 : 0); } // The redirection mechanism is needed for broken build tools (e.g. xcodebuild) that get invoked @@ -141,26 +141,39 @@ FilePath OutputLineParser::absoluteFilePath(const FilePath &filePath) const return filePath; } -void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs, - const FilePath &filePath, int lineNo, int pos, int len) +void OutputLineParser::addLinkSpecForAbsoluteFilePath( + OutputLineParser::LinkSpecs &linkSpecs, + const FilePath &filePath, + int lineNo, + int column, + int pos, + int len) { if (filePath.toFileInfo().isAbsolute()) - linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo)}); + linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo, column)}); } -void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs, - const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match, - int capIndex) +void OutputLineParser::addLinkSpecForAbsoluteFilePath( + OutputLineParser::LinkSpecs &linkSpecs, + const FilePath &filePath, + int lineNo, + int column, + const QRegularExpressionMatch &match, + int capIndex) { - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capIndex), - match.capturedLength(capIndex)); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, + match.capturedStart(capIndex), match.capturedLength(capIndex)); } -void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs, - const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match, - const QString &capName) +void OutputLineParser::addLinkSpecForAbsoluteFilePath( + OutputLineParser::LinkSpecs &linkSpecs, + const FilePath &filePath, + int lineNo, + int column, + const QRegularExpressionMatch &match, + const QString &capName) { - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capName), - match.capturedLength(capName)); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, + match.capturedStart(capName), match.capturedLength(capName)); } bool Utils::OutputLineParser::fileExists(const FilePath &fp) const diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h index d26dc643271..da4dfe8a3a1 100644 --- a/src/libs/utils/outputformatter.h +++ b/src/libs/utils/outputformatter.h @@ -93,12 +93,13 @@ protected: Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath) const; static QString createLinkTarget(const FilePath &filePath, int line, int column); static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath, - int lineNo, int pos, int len); + int lineNo, int column, int pos, int len); static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath, - int lineNo, const QRegularExpressionMatch &match, - int capIndex); + int lineNo, int column, + const QRegularExpressionMatch &match, int capIndex); static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath, - int lineNo, const QRegularExpressionMatch &match, + int lineNo, int column, + const QRegularExpressionMatch &match, const QString &capName); bool fileExists(const Utils::FilePath &fp) const; diff --git a/src/plugins/android/javaparser.cpp b/src/plugins/android/javaparser.cpp index 72859bfdab3..65ddfba9ad6 100644 --- a/src/plugins/android/javaparser.cpp +++ b/src/plugins/android/javaparser.cpp @@ -62,7 +62,7 @@ OutputLineParser::Result JavaParser::handleLine(const QString &line, OutputForma absoluteFilePath(file), lineno); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 2); + addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 2); scheduleTask(task, 1); return {Status::Done, linkSpecs}; } diff --git a/src/plugins/baremetal/iarewparser.cpp b/src/plugins/baremetal/iarewparser.cpp index 23a1d10a1db..286cb0e1686 100644 --- a/src/plugins/baremetal/iarewparser.cpp +++ b/src/plugins/baremetal/iarewparser.cpp @@ -117,8 +117,8 @@ OutputLineParser::Result IarParser::parseWarningOrErrorOrFatalErrorDetailsMessag m_expectSnippet = false; m_expectFilePath = false; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } diff --git a/src/plugins/baremetal/keilparser.cpp b/src/plugins/baremetal/keilparser.cpp index 4ae0c6aa648..64bf64e46fd 100644 --- a/src/plugins/baremetal/keilparser.cpp +++ b/src/plugins/baremetal/keilparser.cpp @@ -62,8 +62,8 @@ OutputLineParser::Result KeilParser::parseArmWarningOrErrorDetailsMessage(const const QString descr = match.captured(DescriptionIndex); newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno)); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } @@ -98,8 +98,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage1(con match.captured(MessageTextIndex)); newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno)); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } @@ -119,8 +119,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage2(con match.captured(MessageTextIndex)); newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno)); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } diff --git a/src/plugins/baremetal/sdccparser.cpp b/src/plugins/baremetal/sdccparser.cpp index aa97173f85c..517f051390b 100644 --- a/src/plugins/baremetal/sdccparser.cpp +++ b/src/plugins/baremetal/sdccparser.cpp @@ -73,8 +73,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma const QString descr = match.captured(MessageTextIndex); newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno)); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } @@ -90,8 +90,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma const QString descr = match.captured(MessageTextIndex); newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno)); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, - FilePathIndex); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex); return {Status::InProgress, linkSpecs}; } diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp index 7da4e383911..c5c8c30d253 100644 --- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp @@ -93,8 +93,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm match.captured(2).toInt()); m_lines = 1; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, - match, 1); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1); m_errorOrWarningLine.file = m_lastTask.file; m_errorOrWarningLine.line = m_lastTask.line; @@ -107,8 +107,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm m_lastTask = BuildSystemTask(Task::Error, QString(), absoluteFilePath(FilePath::fromUserInput(match.captured(1)))); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, - match, 1); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1); m_lines = 1; return {Status::InProgress, linkSpecs}; } @@ -121,8 +121,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm match.captured(3).toInt()); m_lines = 1; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, - match, 1); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1); m_errorOrWarningLine.file = m_lastTask.file; m_errorOrWarningLine.line = m_lastTask.line; @@ -174,8 +174,13 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm m_lastTask.line = match.captured(1).toInt(); m_expectTripleLineErrorData = LINE_DESCRIPTION; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, 0, - match.capturedStart()); + addLinkSpecForAbsoluteFilePath( + linkSpecs, + m_lastTask.file, + m_lastTask.line, + m_lastTask.column, + 0, + match.capturedStart()); return {Status::InProgress, linkSpecs}; } case LINE_DESCRIPTION: diff --git a/src/plugins/mesonprojectmanager/mesonoutputparser.cpp b/src/plugins/mesonprojectmanager/mesonoutputparser.cpp index 9ba777f0753..241f05a9160 100644 --- a/src/plugins/mesonprojectmanager/mesonoutputparser.cpp +++ b/src/plugins/mesonprojectmanager/mesonoutputparser.cpp @@ -56,7 +56,7 @@ inline Utils::OutputLineParser::LinkSpecs MesonOutputParser::addTask( fileName, match.captured(lineNumberCapIndex).toInt()); addTask(task); - addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 1); #else Q_UNUSED(type); Q_UNUSED(line); diff --git a/src/plugins/nim/project/nimoutputtaskparser.cpp b/src/plugins/nim/project/nimoutputtaskparser.cpp index 31fc1e8e77a..1fde71d3c21 100644 --- a/src/plugins/nim/project/nimoutputtaskparser.cpp +++ b/src/plugins/nim/project/nimoutputtaskparser.cpp @@ -39,7 +39,7 @@ NimParser::Result NimParser::handleLine(const QString &lne, OutputFormat) const CompileTask t(type, message, absoluteFilePath(FilePath::fromUserInput(filename)), lineNumber); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, match, 1); scheduleTask(t, 1); return {Status::Done, linkSpecs}; } diff --git a/src/plugins/projectexplorer/clangparser.cpp b/src/plugins/projectexplorer/clangparser.cpp index 28679f0ed58..05bcc3e0aa2 100644 --- a/src/plugins/projectexplorer/clangparser.cpp +++ b/src/plugins/projectexplorer/clangparser.cpp @@ -65,7 +65,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm const int lineNo = match.captured(3).toInt(); const int column = 0; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 2); createOrAmendTask(Task::Unknown, lne.trimmed(), lne, false, filePath, lineNo, column, linkSpecs); return {Status::InProgress, linkSpecs}; @@ -84,7 +84,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1))); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 1); createOrAmendTask(taskType(match.captured(8)), match.captured(9), lne, false, filePath, lineNo, column, linkSpecs); return {Status::InProgress, linkSpecs}; @@ -235,7 +235,7 @@ void ProjectExplorerTest::testClangOutputParser_data() 68, 10, QVector() << formatRange(34, 0) - << formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::-1") + << formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::10") << formatRange(62, 93))) << QString(); @@ -255,7 +255,7 @@ void ProjectExplorerTest::testClangOutputParser_data() 567, 51, QVector() << formatRange(74, 0) - << formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::-1") + << formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::51") << formatRange(138, 202))) << QString(); diff --git a/src/plugins/projectexplorer/customparser.cpp b/src/plugins/projectexplorer/customparser.cpp index e10595af78a..0e2a360af11 100644 --- a/src/plugins/projectexplorer/customparser.cpp +++ b/src/plugins/projectexplorer/customparser.cpp @@ -237,7 +237,7 @@ OutputLineParser::Result CustomParser::hasMatch( const int lineNumber = match.captured(expression.lineNumberCap()).toInt(); const QString message = match.captured(expression.messageCap()); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, match, + addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, -1, match, expression.fileNameCap()); scheduleTask(CompileTask(taskType, message, fileName, lineNumber), 1); return {Status::Done, linkSpecs}; diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp index 3e61df45dee..3a43e8ebe99 100644 --- a/src/plugins/projectexplorer/gccparser.cpp +++ b/src/plugins/projectexplorer/gccparser.cpp @@ -221,7 +221,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat const int lineNo = match.captured(2).toInt(); const int column = match.captured(3).toInt(); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, "file"); gccCreateOrAmendTask( Task::Unknown, lne.trimmed(), lne, false, filePath, lineNo, column, linkSpecs); return {Status::InProgress, linkSpecs}; @@ -234,7 +234,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(3))); LinkSpecs linkSpecs; if (!filePath.isEmpty()) - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, 3); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, 3); gccCreateOrAmendTask(type, match.captured(2), lne, false, filePath, -1, 0, linkSpecs); return {Status::Done, linkSpecs}; } @@ -243,7 +243,12 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(data->rawFilePath)); LinkSpecs linkSpecs; addLinkSpecForAbsoluteFilePath( - linkSpecs, filePath, data->line, data->fileOffset, data->rawFilePath.size()); + linkSpecs, + filePath, + data->line, + data->column, + data->fileOffset, + data->rawFilePath.size()); gccCreateOrAmendTask( data->type, data->description, lne, false, filePath, data->line, data->column, linkSpecs); return {Status::InProgress, linkSpecs}; @@ -343,9 +348,9 @@ void ProjectExplorerTest::testGccOutputParsers_data() 9, 0, QVector() << formatRange(46, 0) - << formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::-1") + << formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::0") << formatRange(75, 39) - << formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::-1") + << formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::0") << formatRange(143, 56)) << CompileTask(Task::Error, "(Each undeclared identifier is reported only once for each function it appears in.)", @@ -514,9 +519,9 @@ void ProjectExplorerTest::testGccOutputParsers_data() 264, 0, QVector() << formatRange(45, 0) - << formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::-1") + << formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::0") << formatRange(113, 106) - << formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::-1") + << formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::0") << formatRange(287, 57)) << CompileTask(Task::Error, "expected ';' before ':' token", @@ -583,9 +588,9 @@ void ProjectExplorerTest::testGccOutputParsers_data() 194, 0, QVector() << formatRange(50, 0) - << formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::-1") + << formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::0") << formatRange(117, 216) - << formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::-1") + << formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::0") << formatRange(400, 64))) << QString(); @@ -822,9 +827,9 @@ void ProjectExplorerTest::testGccOutputParsers_data() 1134, 26, QVector() << formatRange(26, 22) - << formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::-1") + << formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::0") << formatRange(87, 46) - << formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::-1") + << formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::26") << formatRange(183, 44))} << QString(); @@ -929,7 +934,7 @@ void ProjectExplorerTest::testGccOutputParsers_data() 14, 25, QVector() << formatRange(41, 22) - << formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::-1") + << formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::0") << formatRange(130, 146))} << QString(); @@ -953,11 +958,11 @@ void ProjectExplorerTest::testGccOutputParsers_data() 597, 5, QVector() << formatRange(43, 22) - << formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::-1") + << formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::0") << formatRange(96, 40) - << formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::-1") + << formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::0") << formatRange(169, 28) - << formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::-1") + << formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::5") << formatRange(230, 99))} << QString(); @@ -1233,17 +1238,17 @@ void ProjectExplorerTest::testGccOutputParsers_data() 273, 25, QVector() << formatRange(140, 22) - << formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::-1") + << formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::0") << formatRange(194, 27) - << formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::-1") + << formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::0") << formatRange(257, 27) - << formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::-1") + << formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::0") << formatRange(322, 5) - << formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::-1") + << formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::0") << formatRange(360, 51) - << formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::-1") + << formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::25") << formatRange(444, 229) - << formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::-1") + << formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::16") << formatRange(706, 221)), compileTask(Task::Error, "no match for ‘operator+’ (operand types are ‘boxed_value’ and ‘boxed_value’)\n" @@ -1477,13 +1482,13 @@ void ProjectExplorerTest::testGccOutputParsers_data() FilePath::fromUserInput("/data/dev/creator/src/libs/utils/aspects.cpp"), 3454, 13, QVector{ formatRange(82, 22), - formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::-1"), + formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::0"), formatRange(148, 5), - formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::-1"), + formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::0"), formatRange(201, 177), - formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::-1"), + formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::13"), formatRange(422, 31), - formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::-1"), + formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::51"), formatRange(501, 228)})}) << QString(); } diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp index d31ce499700..015d030d180 100644 --- a/src/plugins/projectexplorer/gnumakeparser.cpp +++ b/src/plugins/projectexplorer/gnumakeparser.cpp @@ -103,7 +103,7 @@ OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFo if (!m_suppressIssues) { const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1))); const int lineNo = match.captured(4).toInt(); - addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1); emitTask(BuildSystemTask(res.type, res.description, file, lineNo)); } return {Status::Done, linkSpecs}; diff --git a/src/plugins/projectexplorer/ldparser.cpp b/src/plugins/projectexplorer/ldparser.cpp index ea7521bd0e2..95bb4e84959 100644 --- a/src/plugins/projectexplorer/ldparser.cpp +++ b/src/plugins/projectexplorer/ldparser.cpp @@ -62,7 +62,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils: if (match.hasMatch()) { handle = true; filePath = absoluteFilePath(Utils::FilePath::fromString(match.captured("file"))); - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, 0, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file"); currentTask().setFile(filePath); } else { handle = !lne.isEmpty() && lne.at(0).isSpace(); @@ -135,7 +135,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils: } if (hasKeyword || filePath.fileName().endsWith(".o")) { LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, match, capIndex); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, -1, match, capIndex); createOrAmendTask(type, description, line, false, filePath, lineno, 0, linkSpecs); return {getStatus(), linkSpecs}; } diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp index 734f8148658..6e625b240a5 100644 --- a/src/plugins/projectexplorer/linuxiccparser.cpp +++ b/src/plugins/projectexplorer/linuxiccparser.cpp @@ -59,7 +59,7 @@ OutputLineParser::Result LinuxIccParser::handleLine(const QString &line, OutputF const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1))); const int lineNo = match.captured(2).toInt(); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 1); createOrAmendTask(type, match.captured(6).trimmed(), line, false, filePath, lineNo); m_expectFirstLine = false; return Status::InProgress; diff --git a/src/plugins/projectexplorer/lldparser.cpp b/src/plugins/projectexplorer/lldparser.cpp index 3bb4079b766..0bc36ff845e 100644 --- a/src/plugins/projectexplorer/lldparser.cpp +++ b/src/plugins/projectexplorer/lldparser.cpp @@ -46,7 +46,7 @@ Utils::OutputLineParser::Result LldParser::handleLine(const QString &line, Utils const auto file = absoluteFilePath(Utils::FilePath::fromUserInput( trimmedLine.mid(filePathOffset, filePathLen).trimmed())); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, filePathOffset, filePathLen); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, filePathOffset, filePathLen); scheduleTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(), file, lineNo), 1); return {Status::Done, linkSpecs}; diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp index 0613a0b74e8..17710cb13c3 100644 --- a/src/plugins/projectexplorer/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -114,7 +114,7 @@ OutputLineParser::Result MsvcParser::handleLine(const QString &line, OutputForma const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(2))); const int lineNo = match.captured(3).toInt(); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 2); createOrAmendTask(Task::Unknown, description, line, false, filePath, lineNo, 0, linkSpecs); return {Status::InProgress, linkSpecs}; } @@ -146,7 +146,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line) QPair position = parseFileName(match.captured(1)); const FilePath filePath = absoluteFilePath(position.first); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, -1, match, 1); const QString &description = match.captured(3) + match.captured(4).trimmed(); createOrAmendTask( taskType(match.captured(2)), @@ -228,7 +228,7 @@ OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFo const FilePath file = absoluteFilePath(position.first); const int lineNo = position.second; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1); createOrAmendTask( taskType(match.captured(2)), match.captured(3).trimmed(), line, false, file, lineNo); return {Status::InProgress, linkSpecs}; diff --git a/src/plugins/projectexplorer/sanitizerparser.cpp b/src/plugins/projectexplorer/sanitizerparser.cpp index 8da13d5d37b..546de844485 100644 --- a/src/plugins/projectexplorer/sanitizerparser.cpp +++ b/src/plugins/projectexplorer/sanitizerparser.cpp @@ -93,7 +93,8 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line m_task.file = file; m_task.line = summaryMatch.captured("line").toInt(); m_task.column = summaryMatch.captured("column").toInt(); - addLinkSpecForAbsoluteFilePath(linkSpecs, file, m_task.line, summaryMatch, "file"); + addLinkSpecForAbsoluteFilePath( + linkSpecs, file, m_task.line, m_task.column, summaryMatch, "file"); addLinkSpecs(linkSpecs); } } else { @@ -107,7 +108,7 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line const FilePath file = absoluteFilePath(FilePath::fromUserInput(fileMatch.captured("file"))); if (fileExists(file)) { addLinkSpecForAbsoluteFilePath(linkSpecs, file, fileMatch.captured("line").toInt(), - fileMatch, "file"); + fileMatch.captured("column").toInt(), fileMatch, "file"); addLinkSpecs(linkSpecs); } } diff --git a/src/plugins/projectexplorer/xcodebuildparser.cpp b/src/plugins/projectexplorer/xcodebuildparser.cpp index 8a2d3e2962a..2037614e043 100644 --- a/src/plugins/projectexplorer/xcodebuildparser.cpp +++ b/src/plugins/projectexplorer/xcodebuildparser.cpp @@ -57,7 +57,8 @@ OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, Outpu absoluteFilePath(FilePath::fromString( lne.left(filePathEndPos)))); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, 0, filePathEndPos); + addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, 0, + filePathEndPos); scheduleTask(task, 1); return {Status::Done, linkSpecs}; } diff --git a/src/plugins/qmakeprojectmanager/qmakeparser.cpp b/src/plugins/qmakeprojectmanager/qmakeparser.cpp index 57051ba5a20..0b0bdc5af08 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparser.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparser.cpp @@ -46,7 +46,7 @@ OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputForm BuildSystemTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)), match.captured(2).toInt() /* line */); LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, fileNameOffset, + addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, fileNameOffset, fileName.length()); scheduleTask(t, 1); return {Status::Done, linkSpecs}; diff --git a/src/plugins/qtsupport/qtparser.cpp b/src/plugins/qtsupport/qtparser.cpp index 387af762a3b..93fd16d90a5 100644 --- a/src/plugins/qtsupport/qtparser.cpp +++ b/src/plugins/qtsupport/qtparser.cpp @@ -45,7 +45,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils: LinkSpecs linkSpecs; const Utils::FilePath file = absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file"))); - addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file"); CompileTask task(type, match.captured("description").trimmed(), file, lineno); task.column = match.captured("column").toInt(); scheduleTask(task, 1); @@ -62,7 +62,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils: message.prepend(": ").prepend(fileName); } else if (fileName.endsWith(".ui")) { filePath = absoluteFilePath(Utils::FilePath::fromUserInput(fileName)); - addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file"); } else { isUicMessage = false; } @@ -79,7 +79,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils: LinkSpecs linkSpecs; const Utils::FilePath file = absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file"))); - addLinkSpecForAbsoluteFilePath(linkSpecs, file, 0, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, -1, -1, match, "file"); CompileTask task(type, match.captured("description"), file); scheduleTask(task, 1); return {Status::Done, linkSpecs}; @@ -95,7 +95,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils: if (!ok) lineno = -1; LinkSpecs linkSpecs; - addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file"); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file"); CompileTask task(type, match.captured("description"), file, lineno, match.captured("column").toInt()); scheduleTask(task, 1); diff --git a/src/plugins/qtsupport/qttestparser.cpp b/src/plugins/qtsupport/qttestparser.cpp index 93030f20e68..a19929b7544 100644 --- a/src/plugins/qtsupport/qttestparser.cpp +++ b/src/plugins/qtsupport/qttestparser.cpp @@ -44,8 +44,8 @@ OutputLineParser::Result QtTestParser::handleLine(const QString &line, OutputFor m_currentTask.file = absoluteFilePath(FilePath::fromString( QDir::fromNativeSeparators(match.captured("file")))); m_currentTask.line = match.captured("line").toInt(); - addLinkSpecForAbsoluteFilePath(linkSpecs, m_currentTask.file, m_currentTask.line, match, - "file"); + addLinkSpecForAbsoluteFilePath( + linkSpecs, m_currentTask.file, m_currentTask.line, m_currentTask.column, match, "file"); emitCurrentTask(); return {Status::Done, linkSpecs}; } From 2ce6255a7d4fd33e54139a9615b3037e83587887 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Fri, 31 May 2024 12:19:02 +0200 Subject: [PATCH 14/26] CMakePM: Do not check the existence of dlls for PATH handling In order to fix QTCREATORBUG-29662 the check of existence of an dll was a prerequisite to add the path to the PATH environment variable. As it turns out this is not an easy thing to do, since the ".lib" file name can be different than the ".dll" file name. Also for MinGW you can have ".dll.a" or ".a" as library filename extensions. You can also have a "lib" as prefix for the library filename. Amends 0d8a542b4f7d8a7b4d27f42ff16d309fba6cbf22 Amends 8713919f31f2aecc7e7c15f1fc9ce7906b8fefa0 Amends ac97ab1abf9bf073088925755a46f08f38721090 Task-number: QTCREATORBUG-29662 Fixes: QTCREATORBUG-30827 Fixes: QTCREATORBUG-30932 Change-Id: I90afad825d43fd4f801c2aac20ed98f013861152 Reviewed-by: Alessandro Portale --- .../fileapidataextractor.cpp | 42 ++++++------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index f1d3cee4ee3..66748345ced 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -210,9 +210,11 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, const FilePath &sourceDirectory, const FilePath &buildDirectory, bool relativeLibs, - const QSet &artifacts) + const QSet &sharedLibraryArtifacts) { const FilePath currentBuildDir = buildDirectory.resolvePath(t.buildDir); + const QSet sharedLibraryArtifactsPaths + = transform(sharedLibraryArtifacts, &FilePath::parentDir); CMakeBuildTarget ct; ct.title = t.name; @@ -306,7 +308,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, if (f.role == "libraries") tmp = tmp.parentDir(); - std::optional dllName; if (buildDir.osType() == OsTypeWindows && (f.role == "libraries")) { const auto partAsFilePath = FilePath::fromUserInput(part); part = partAsFilePath.fileName(); @@ -314,24 +315,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, // Skip object libraries on Windows. This case can happen with static qml plugins if (part.endsWith(".obj") || part.endsWith(".o")) continue; - - // Only consider dlls, not static libraries - for (const QString &suffix : - {QString(".lib"), QString(".dll.a"), QString(".a")}) { - if (part.endsWith(suffix) && !dllName) - dllName = part.chopped(suffix.length()).append(".dll"); - } - - // MinGW has libQt6Core.a -> Qt6Core.dll - // but libFoo.dll.a was already handled above - const QString mingwPrefix("lib"); - const QString mingwSuffix("a"); - const QString completeSuffix = partAsFilePath.completeSuffix(); - if (part.startsWith(mingwPrefix) && completeSuffix == mingwSuffix) { - dllName = part.chopped(mingwSuffix.length() + 1/*the '.'*/) - .sliced(mingwPrefix.length()) - .append(".dll"); - } } if (!tmp.isEmpty() && tmp.isDir()) { @@ -345,18 +328,15 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, {"/lib", "/lib64", "/usr/lib", "/usr/lib64", "/usr/local/lib"})) librarySeachPaths.append(tmp); - if (buildDir.osType() == OsTypeWindows && dllName) { - const auto validPath = [&artifacts](const FilePath& path) { - return path.exists() || artifacts.contains(path); - }; - if (validPath(tmp.pathAppended(*dllName))) + if (buildDir.osType() == OsTypeWindows) { + if (sharedLibraryArtifactsPaths.contains(tmp)) librarySeachPaths.append(tmp); // Libraries often have their import libs in ../lib and the // actual dll files in ../bin on windows. Qt is one example of that. if (tmp.fileName() == "lib") { const FilePath path = tmp.parentDir().pathAppended("bin"); - if (path.isDir() && validPath(path.pathAppended(*dllName))) + if (path.isDir()) librarySeachPaths.append(path); } } @@ -375,17 +355,19 @@ static QList generateBuildTargets(const QFuture &cancelF const FilePath &buildDirectory, bool relativeLibs) { - QSet artifacts; + QSet sharedLibraryArtifacts; for (const TargetDetails &t : input.targetDetails) - for (const FilePath &p: t.artifacts) - artifacts.insert(buildDirectory.resolvePath(p)); + if (t.type == "MODULE_LIBRARY" || t.type == "SHARED_LIBRARY") + for (const FilePath &p : t.artifacts) + sharedLibraryArtifacts.insert(buildDirectory.resolvePath(p)); QList result; result.reserve(input.targetDetails.size()); for (const TargetDetails &t : input.targetDetails) { if (cancelFuture.isCanceled()) return {}; - result.append(toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, artifacts)); + result.append( + toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, sharedLibraryArtifacts)); } return result; } From d8a582d813ac58190a4ed68e67d66309060b9aec Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 27 May 2024 06:27:30 +0200 Subject: [PATCH 15/26] Lua: Add function that returns the output of a process Change-Id: I6863926a4da90adc89d96d47da1542c886b44040 Reviewed-by: Marcus Tillmanns --- src/plugins/lua/bindings/qtcprocess.cpp | 11 +++++++++++ src/plugins/lua/meta/process.lua | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/src/plugins/lua/bindings/qtcprocess.cpp b/src/plugins/lua/bindings/qtcprocess.cpp index c1b4a4eccdd..ff2726a96ef 100644 --- a/src/plugins/lua/bindings/qtcprocess.cpp +++ b/src/plugins/lua/bindings/qtcprocess.cpp @@ -29,11 +29,22 @@ void addProcessModule() p->setEnvironment(Environment::systemEnvironment()); QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->exitCode()); }); + }; + + process["commandOutput_cb"] = + [guard + = pluginSpec->connectionGuard.get()](const QString &cmdline, const sol::function &cb) { + Process *p = new Process; + p->setCommand(CommandLine::fromUserInput((cmdline))); + p->setEnvironment(Environment::systemEnvironment()); + + QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->allOutput()); }); p->start(); }; process["runInTerminal"] = wrap(process["runInTerminal_cb"]); + process["commandOutput"] = wrap(process["commandOutput_cb"]); return process; }); diff --git a/src/plugins/lua/meta/process.lua b/src/plugins/lua/meta/process.lua index 05199907706..53b4f35b7d0 100644 --- a/src/plugins/lua/meta/process.lua +++ b/src/plugins/lua/meta/process.lua @@ -8,4 +8,10 @@ local process = {} ---@return number The exit code of the command function process.runInTerminal(cmd) end +---@async +---Runs a command and returns the output! +---@param cmd string The command to run +---@return string The output of the command +function process.commandOutput(cmd) end + return process From e078d05f510a2dd77aafa7aed79d45cbcb247208 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 31 May 2024 16:17:10 +0200 Subject: [PATCH 16/26] Utils: Fix connection error When add / remove buttons are disabled, the connection fails. Change-Id: I6c9a3233f156b88e516481a6fc8e072ea5e1c13b Reviewed-by: David Schulz --- src/libs/utils/aspects.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 25a21fb7397..bc233ed188a 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2681,22 +2681,26 @@ void StringListAspect::addToLayout(Layout &parent) } }; - connect(add, &QPushButton::clicked, this, [this, populate, editor] { - d->undoable.setSilently(d->undoable.get() << ""); - populate(); - const QTreeWidgetItem *root = editor->invisibleRootItem(); - QTreeWidgetItem *lastChild = root->child(root->childCount() - 1); - const QModelIndex index = editor->indexFromItem(lastChild, 0); - editor->edit(index); - }); + if (add) { + connect(add, &QPushButton::clicked, this, [this, populate, editor] { + d->undoable.setSilently(d->undoable.get() << ""); + populate(); + const QTreeWidgetItem *root = editor->invisibleRootItem(); + QTreeWidgetItem *lastChild = root->child(root->childCount() - 1); + const QModelIndex index = editor->indexFromItem(lastChild, 0); + editor->edit(index); + }); + } - connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] { - const QList selected = editor->selectedItems(); - QTC_ASSERT(selected.size() == 1, return); - editor->invisibleRootItem()->removeChild(selected.first()); - delete selected.first(); - d->undoable.set(undoStack(), itemsToStringList()); - }); + if (remove) { + connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] { + const QList selected = editor->selectedItems(); + QTC_ASSERT(selected.size() == 1, return); + editor->invisibleRootItem()->removeChild(selected.first()); + delete selected.first(); + d->undoable.set(undoStack(), itemsToStringList()); + }); + } connect( &d->undoable.m_signal, &UndoSignaller::changed, editor, [this, populate, itemsToStringList] { From cf1aa1d1bb32560618891d2b0290259ec1f2a5a9 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 28 May 2024 12:37:31 +0200 Subject: [PATCH 17/26] Lua: Ask user before allowing to fetch Change-Id: I58318598015a24689de19ae00bce65f004091e6b Reviewed-by: David Schulz --- src/plugins/lua/CMakeLists.txt | 6 + src/plugins/lua/bindings/fetch.cpp | 242 ++++++++++++++++-- .../lua/images/settingscategory_lua.png | Bin 0 -> 513 bytes .../lua/images/settingscategory_lua@2x.png | Bin 0 -> 1152 bytes 4 files changed, 221 insertions(+), 27 deletions(-) create mode 100644 src/plugins/lua/images/settingscategory_lua.png create mode 100644 src/plugins/lua/images/settingscategory_lua@2x.png diff --git a/src/plugins/lua/CMakeLists.txt b/src/plugins/lua/CMakeLists.txt index 253d6f06ee6..c7a62e3a8b8 100644 --- a/src/plugins/lua/CMakeLists.txt +++ b/src/plugins/lua/CMakeLists.txt @@ -42,6 +42,12 @@ add_qtc_plugin(Lua # generateqtbindings.cpp # Use this if you need to generate some code. ) +qt_add_resources(Lua lua_images_rcc + PREFIX "/lua" + FILES + images/settingscategory_lua.png + images/settingscategory_lua@2x.png +) set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON) diff --git a/src/plugins/lua/bindings/fetch.cpp b/src/plugins/lua/bindings/fetch.cpp index 35e3255943f..22d1bc64cbd 100644 --- a/src/plugins/lua/bindings/fetch.cpp +++ b/src/plugins/lua/bindings/fetch.cpp @@ -3,11 +3,22 @@ #include "../luaengine.h" #include "../luaqttypes.h" +#include "../luatr.h" +#include +#include + +#include +#include +#include #include +#include +#include +#include #include #include +#include #include #include #include @@ -37,35 +48,205 @@ static QString opToString(QNetworkAccessManager::Operation op) void addFetchModule() { - LuaEngine::registerProvider( - "Fetch", [](sol::state_view lua) -> sol::object { - const ScriptPluginSpec *pluginSpec = lua.get("PluginSpec"); + class Module : Utils::AspectContainer + { + Utils::StringListAspect pluginsAllowedToFetch{this}; + Utils::StringListAspect pluginsNotAllowedToFetch{this}; - sol::table async = lua.script("return require('async')", "_fetch_").get(); - sol::function wrap = async["wrap"]; + class LuaOptionsPage : public Core::IOptionsPage + { + public: + LuaOptionsPage(Module *module) + { + setId("BB.Lua.Fetch"); + setDisplayName(Tr::tr("Network access")); + setCategory("ZY.Lua"); + setDisplayCategory("Lua"); + setCategoryIconPath(":/lua/images/settingscategory_lua.png"); + setSettingsProvider( + [module] { return static_cast(module); }); + } + }; - sol::table fetch = lua.create_table(); + LuaOptionsPage settingsPage{this}; - auto networkReplyType = lua.new_usertype( - "QNetworkReply", - "error", - sol::property([](QNetworkReply *self) -> int { return self->error(); }), - "readAll", - [](QNetworkReply *r) { return r->readAll().toStdString(); }, - "__tostring", - [](QNetworkReply *r) { - return QString("QNetworkReply(%1 \"%2\") => %3") - .arg(opToString(r->operation())) - .arg(r->url().toString()) - .arg(r->error()); - }); + public: + Module() + { + setSettingsGroup("Lua.Fetch"); - fetch["fetch_cb"] = [guard = pluginSpec->connectionGuard.get()]( - const sol::table &options, - const sol::function &callback, - const sol::this_state &thisState) { - auto url = options.get("url"); + pluginsAllowedToFetch.setSettingsKey("pluginsAllowedToFetch"); + pluginsAllowedToFetch.setLabelText("Plugins allowed to fetch data from the internet"); + pluginsAllowedToFetch.setToolTip( + "List of plugins that are allowed to fetch data from the internet"); + pluginsAllowedToFetch.setUiAllowAdding(false); + pluginsAllowedToFetch.setUiAllowEditing(false); + pluginsNotAllowedToFetch.setSettingsKey("pluginsNotAllowedToFetch"); + pluginsNotAllowedToFetch.setLabelText( + "Plugins not allowed to fetch data from the internet"); + pluginsNotAllowedToFetch.setToolTip( + "List of plugins that are not allowed to fetch data from the internet"); + pluginsNotAllowedToFetch.setUiAllowAdding(false); + pluginsNotAllowedToFetch.setUiAllowEditing(false); + + setLayouter([this] { + using namespace Layouting; + // clang-format off + return Form { + pluginsAllowedToFetch, br, + pluginsNotAllowedToFetch, br, + }; + // clang-format on + }); + + readSettings(); + } + + ~Module() { writeSettings(); } + + enum class IsAllowed { Yes, No, NeedsToAsk }; + + IsAllowed isAllowedToFetch(const QString &pluginName) const + { + if (pluginsAllowedToFetch().contains(pluginName)) + return IsAllowed::Yes; + if (pluginsNotAllowedToFetch().contains(pluginName)) + return IsAllowed::No; + return IsAllowed::NeedsToAsk; + } + + void setAllowedToFetch(const QString &pluginName, IsAllowed allowed) + { + if (allowed == IsAllowed::Yes) + pluginsAllowedToFetch.appendValue(pluginName); + else if (allowed == IsAllowed::No) + pluginsNotAllowedToFetch.appendValue(pluginName); + + if (allowed == IsAllowed::Yes) + pluginsNotAllowedToFetch.removeValue(pluginName); + else if (allowed == IsAllowed::No) + pluginsAllowedToFetch.removeValue(pluginName); + } + }; + + std::shared_ptr module = std::make_shared(); + + LuaEngine::registerProvider("Fetch", [mod = std::move(module)](sol::state_view lua) -> sol::object { + const ScriptPluginSpec *pluginSpec = lua.get("PluginSpec"); + + sol::table async = lua.script("return require('async')", "_fetch_").get(); + sol::function wrap = async["wrap"]; + + sol::table fetch = lua.create_table(); + + auto networkReplyType = lua.new_usertype( + "QNetworkReply", + "error", + sol::property([](QNetworkReply *self) -> int { return self->error(); }), + "readAll", + [](QNetworkReply *r) { return r->readAll().toStdString(); }, + "__tostring", + [](QNetworkReply *r) { + return QString("QNetworkReply(%1 \"%2\") => %3") + .arg(opToString(r->operation())) + .arg(r->url().toString()) + .arg(r->error()); + }); + + auto checkPermission = [mod, + pluginName = pluginSpec->name, + guard = pluginSpec->connectionGuard.get()]( + QString url, + std::function fetch, + std::function notAllowed) { + auto isAllowed = mod->isAllowedToFetch(pluginName); + if (isAllowed == Module::IsAllowed::Yes) { + fetch(); + return; + } + + if (isAllowed == Module::IsAllowed::No) { + notAllowed(); + return; + } + + if (QApplication::activeModalWidget()) { + // We are already showing a modal dialog, + // so we have to use a QMessageBox instead of the info bar + auto msgBox = new QMessageBox( + QMessageBox::Question, + Tr::tr("Allow Internet access"), + Tr::tr("The plugin \"%1\" would like to fetch from the following url:\n%2") + .arg(pluginName) + .arg(url), + QMessageBox::Yes | QMessageBox::No, + Core::ICore::dialogParent()); + msgBox->setCheckBox(new QCheckBox(Tr::tr("Remember choice"))); + + QObject::connect( + msgBox, &QMessageBox::accepted, guard, [mod, fetch, pluginName, msgBox]() { + if (msgBox->checkBox()->isChecked()) + mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes); + fetch(); + }); + + QObject::connect( + msgBox, &QMessageBox::rejected, guard, [mod, notAllowed, pluginName, msgBox]() { + if (msgBox->checkBox()->isChecked()) + mod->setAllowedToFetch(pluginName, Module::IsAllowed::No); + notAllowed(); + }); + + msgBox->show(); + + return; + } + + Utils::InfoBarEntry entry{ + Utils::Id::fromString("Fetch" + pluginName), + Tr::tr("The plugin \"%1\" would like to fetch data from the internet. Do " + "you want to allow this?") + .arg(pluginName)}; + entry.setDetailsWidgetCreator([pluginName, url] { + const QString markdown = Tr::tr("The plugin \"**%1**\" would like to fetch " + "from the following url:\n\n") + .arg(pluginName) + + QString("* [%3](%3)").arg(url); + + QLabel *list = new QLabel(); + list->setTextFormat(Qt::TextFormat::MarkdownText); + list->setText(markdown); + list->setMargin(Utils::StyleHelper::SpacingTokens::ExPaddingGapS); + return list; + }); + entry.addCustomButton(Tr::tr("Always Allow"), [mod, pluginName, fetch]() { + mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes); + Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName)); + fetch(); + }); + entry.addCustomButton(Tr::tr("Allow once"), [pluginName, fetch]() { + Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName)); + fetch(); + }); + + entry.setCancelButtonInfo(Tr::tr("Deny"), [mod, notAllowed, pluginName]() { + Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName)); + mod->setAllowedToFetch(pluginName, Module::IsAllowed::No); + notAllowed(); + }); + Core::ICore::infoBar()->addInfo(entry); + }; + + fetch["fetch_cb"] = [checkPermission, + pluginName = pluginSpec->name, + guard = pluginSpec->connectionGuard.get(), + mod]( + const sol::table &options, + const sol::function &callback, + const sol::this_state &thisState) { + auto url = options.get("url"); + auto actualFetch = [guard, url, options, callback, thisState]() { auto method = (options.get_or("method", "GET")).toLower(); auto headers = options.get_or("headers", {}); auto data = options.get_or("body", {}); @@ -129,10 +310,17 @@ void addFetchModule() } }; - fetch["fetch"] = wrap(fetch["fetch_cb"]); + checkPermission(url, actualFetch, [callback, pluginName]() { + callback(Tr::tr("Fetching is not allowed for the plugin \"%1\" (You can edit " + "permissions in Preferences => Lua)") + .arg(pluginName)); + }); + }; - return fetch; - }); + fetch["fetch"] = wrap(fetch["fetch_cb"]); + + return fetch; + }); } } // namespace Lua::Internal diff --git a/src/plugins/lua/images/settingscategory_lua.png b/src/plugins/lua/images/settingscategory_lua.png new file mode 100644 index 0000000000000000000000000000000000000000..7f1b6808feadaeb56b4e924a63d01457230377fd GIT binary patch literal 513 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4h9AWhNCh`Dhvz^oCO|{#S9Gmi6G3l!hU%s z0|Vn`PZ!4!jfuV!Hf9SKiX6A!zdO6*He+fUBE@olx;hg%F;#;i?WPnkQ) z7K^LNGDLGuWWDw9a>rQd2VpCCK&)5n=h)_rra zo2S#wvPfl1bFuRIW046T?@qg1w582AbIN4q6Q$Qqw$9?58t5nbW3wkKo7?d_Ym;UF zG9B=Kx-CrVin6!4(GRD8K}>Af*$kU<-)8UKm@c?(HM@T}Ps0{7$2ipoCUY!5JgnQ? zaO(2aq&1H!ICpL^S*{V4V#*tHVn&))>YRjkpFht!)avoIdF8jCUwChX+*>~PJAeIk z_NTh)Tc)y1p7Q>bz4WVA_s<*Lt{vaK_}}ULY7_p2Ew-`C|7866c3jRy%xi%e_uHVY zdMg&~ejrdkmsQo_%3L<3`Aw`p*n@c(KiTH;huVK#b5MeTck|?zzDH)QRsS2m^Yh|g T#>x|pfa2EE)z4*}Q$iB}s=MY* literal 0 HcmV?d00001 diff --git a/src/plugins/lua/images/settingscategory_lua@2x.png b/src/plugins/lua/images/settingscategory_lua@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a70400124db008e0a38a2cbb512502b9ea6251be GIT binary patch literal 1152 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4h9AWhN8@6(F_a>oCO|{#S9Gmi6G3l!hU%s z0|SeZr;B5VM`!8O+??Q0iR1OpzigUTmhTrSlgu2JU@+5dLta3kwr3B!OPa$K z#b(h|rLA+M?tMscV%pAskJ;t$^>b$!>T{OcS|=M^da&dD-|G=3^L)53Jm(fRn$73( zcH83n>KlKgb$(o6?WSkvC;dD)Vs7jyf$KSHJgv`9=$9`)b@{H^>BXuCzrMO+2H z*^0qz`}OUD2d0Vpvx=x2w=CM)_SozA`kLbG(-&_OZx=4!zbIc;$m54L!;75mw9AZ(a_4R-dAp_iQFwKB z&*Z+_j8^t%|LysFq0!WM`o0-L^4pnq@j7TEY3DH5=634*d$q2p;pcYdPpiex&J&sb zD(1iv^WF1AZQrH%?p{7;Z>odR51UCY`?wd}4fhT~Gg%fKHuCqnH1QR~2JRFU76Y4WZMR>t3 z2CZY0!jtcBFm;%dV{pJFSmZ_tW5BLCY#r@uYC>LzGPuSR#8YiMNsoLBGtqg&@QC0$|`I2kzcs1n21TQU1evtPFv zADAtEJo4wM;>v}Sg}tMHUg8g!Ai3dptb@#YN9*7J{%(B6-JdvVT_#_{r_@y|*4{He z^W5Clo_P)1jEiNAJ94YeH7uN^apNLGjx@u(t75rKGNHash>WTc|pj% zc`P@wRk9fs+o!EfvJ6+ZIy1aZ zV>~8)O~hWLopGxAl#Ht^0nxkxp&gf!y)>_G-?r(Kb85uY^s--H&R(vUT~+gPfAsSI zdj$4v-CvX&UlhC|;{f-ES@P2j^AElH$n3hGcgi`v4a;uI?b-LURo?yeerArUB>_KP ztE{x%GsjYY8uRDIWhSgv-~GNBZ%+AiI*sA)L}t!2evBsaqNhI|y_nXp<1C|4!QVy9 zTVzkKR9EQV%J|~Bu!`%)#>*4>ishfYI{Y)zm?3#x=nO3>!*|&`Y!fQqz4l9qIh%5z zv^pr@msMUG$Ej<|)jVI?FVB^8(DJS@K)Rs9*JIonD&`1Fmv#>Q%Xmv^*WNnR%t>~$h?`b?YHQ>y(;j@-8Qq!(P6 z_Uweuy49Vlzn=+Jk_q@#qvm}2&%7mPOpkx*6*@oX{zmWr>D-rQp8O$SB72(chMd_` PP|@P)>gTe~DWM4fJDV5W literal 0 HcmV?d00001 From 57826bcab6c96f7b4e5e6a862ff3ccc31c03fd64 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 31 May 2024 16:08:14 +0200 Subject: [PATCH 18/26] Core: Add IDE:Executable variable Change-Id: Ic191562bbfea0b3f0998c0e71c11d7316644937c Reviewed-by: Eike Ziller --- src/plugins/coreplugin/coreplugin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index dd99f474503..0777bd20422 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -251,6 +251,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) expander->registerVariable("HostOs:ExecutableSuffix", Tr::tr("The platform executable suffix."), [] { return QString(Utils::HostOsInfo::withExecutableSuffix("")); }); + expander->registerFileVariables("IDE:Executable", + Tr::tr("The path to the running %1 itself.").arg(QGuiApplication::applicationDisplayName()), + []() { return FilePath::fromUserInput(QCoreApplication::applicationFilePath()); }); expander->registerVariable("IDE:ResourcePath", Tr::tr("The directory where %1 finds its pre-installed resources.") .arg(QGuiApplication::applicationDisplayName()), From 7944ae0600e4fb415fc0307209dffa1fa55cf10d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 3 Jun 2024 09:20:13 +0200 Subject: [PATCH 19/26] Mercurial: Fix history key Change-Id: I3e0606639402808c5ef9fe6e4d6af83118b041bb Reviewed-by: hjk Reviewed-by: Orgad Shaneh --- src/plugins/mercurial/mercurialsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mercurial/mercurialsettings.cpp b/src/plugins/mercurial/mercurialsettings.cpp index 05c96672f90..79423ab7746 100644 --- a/src/plugins/mercurial/mercurialsettings.cpp +++ b/src/plugins/mercurial/mercurialsettings.cpp @@ -30,7 +30,7 @@ MercurialSettings::MercurialSettings() binaryPath.setExpectedKind(PathChooser::ExistingCommand); binaryPath.setDefaultValue(Constants::MERCURIALDEFAULT); binaryPath.setDisplayName(Tr::tr("Mercurial Command")); - binaryPath.setHistoryCompleter("Bazaar.Command.History"); + binaryPath.setHistoryCompleter("Mercurial.Command.History"); binaryPath.setLabelText(Tr::tr("Command:")); userName.setDisplayStyle(StringAspect::LineEditDisplay); From 1058f12a9367f12f5b99698fd770aba47096faa8 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 30 May 2024 09:57:40 +0200 Subject: [PATCH 20/26] Install: Use QMessageBox as fallback Use a QMessageBox if the InfoBar would be hidden. Change-Id: I29f10a3af6123dcf7811db68b967259f990c5a66 Reviewed-by: David Schulz --- src/plugins/lua/bindings/install.cpp | 82 +++++++++++++++++++--------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/src/plugins/lua/bindings/install.cpp b/src/plugins/lua/bindings/install.cpp index 75fb3cadb14..6b35ace0b9d 100644 --- a/src/plugins/lua/bindings/install.cpp +++ b/src/plugins/lua/bindings/install.cpp @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #include #include @@ -301,41 +303,71 @@ void addInstallModule() installOptionsList.append({url, name, version}); } + auto install = [&state, pluginSpec, installOptionsList, callback]() { + auto tree = state.createTree(); + + auto progress = new TaskProgress(tree); + progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("...")); + + tree->setRecipe( + installRecipe(pluginSpec->appDataPath, installOptionsList, callback)); + tree->start(); + }; + + auto denied = [callback]() { callback(false, "User denied installation"); }; + + if (QApplication::activeModalWidget()) { + auto msgBox = new QMessageBox( + QMessageBox::Question, + Tr::tr("Install package"), + msg, + QMessageBox::Yes | QMessageBox::No, + Core::ICore::dialogParent()); + + const QString details + = Tr::tr("The plugin \"%1\" would like to install the following " + "package(s):\n\n") + .arg(pluginSpec->name) + + Utils::transform(installOptionsList, [](const InstallOptions &options) { + return QString("* %1 - %2 (from: %3)") + .arg(options.name, options.version, options.url.toString()); + }).join("\n"); + + msgBox->setDetailedText(details); + + auto guard = pluginSpec->connectionGuard.get(); + QObject::connect(msgBox, &QMessageBox::accepted, guard, install); + QObject::connect(msgBox, &QMessageBox::rejected, guard, denied); + + msgBox->show(); + return; + } + const Utils::Id infoBarId = Utils::Id::fromString( "Install" + pluginSpec->name + QString::number(qHash(installOptionsList))); InfoBarEntry entry(infoBarId, msg, InfoBarEntry::GlobalSuppression::Enabled); - entry.addCustomButton( - Tr::tr("Install"), - [infoBarId, &state, pluginSpec, installOptionsList, callback]() { - auto tree = state.createTree(); + entry.addCustomButton(Tr::tr("Install"), [install, infoBarId]() { + install(); + Core::ICore::infoBar()->removeInfo(infoBarId); + }); - auto progress = new TaskProgress(tree); - progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("...")); + entry.setCancelButtonInfo(denied); - tree->setRecipe( - installRecipe(pluginSpec->appDataPath, installOptionsList, callback)); - tree->start(); - - Core::ICore::infoBar()->removeInfo(infoBarId); - }); - entry.setCancelButtonInfo( - [callback]() { callback(false, "User denied installation"); }); - - entry.setDetailsWidgetCreator([pluginSpec, installOptionsList]() -> QWidget * { - const QString markdown - = Tr::tr("The plugin \"**%1**\" would like to install the following " - "package(s):\n\n") - .arg(pluginSpec->name) - + Utils::transform(installOptionsList, [](const InstallOptions &options) { - return QString("* %1 - %2 (from: [%3](%3))") - .arg(options.name, options.version, options.url.toString()); - }).join("\n"); + const QString details + = Tr::tr("The plugin \"**%1**\" would like to install the following " + "package(s):\n\n") + .arg(pluginSpec->name) + + Utils::transform(installOptionsList, [](const InstallOptions &options) { + return QString("* %1 - %2 (from: [%3](%3))") + .arg(options.name, options.version, options.url.toString()); + }).join("\n"); + entry.setDetailsWidgetCreator([details]() -> QWidget * { QLabel *list = new QLabel(); list->setTextFormat(Qt::TextFormat::MarkdownText); - list->setText(markdown); + list->setText(details); list->setMargin(StyleHelper::SpacingTokens::ExPaddingGapS); return list; }); From 7ad1e20a48e9efc6bdc3ab51e697cfe24dc35fe3 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 30 May 2024 09:58:06 +0200 Subject: [PATCH 21/26] Lua: Add support for gzip files Change-Id: Id342364ffb71b8dd2e60a4332fd1d88a4951e08a Reviewed-by: David Schulz --- src/plugins/lua/bindings/install.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/bindings/install.cpp b/src/plugins/lua/bindings/install.cpp index 6b35ace0b9d..a044ff2fb8d 100644 --- a/src/plugins/lua/bindings/install.cpp +++ b/src/plugins/lua/bindings/install.cpp @@ -161,6 +161,7 @@ static Group installRecipe( emitResult(sourceAndCommand.error()); return SetupResult::StopWithError; } + unarchiver.setGZipFileDestName(installOptionsIt->name); unarchiver.setSourceAndCommand(*sourceAndCommand); unarchiver.setDestDir(destination(appDataPath, *installOptionsIt)); return SetupResult::Continue; @@ -172,6 +173,12 @@ static Group installRecipe( if (result == DoneWith::Cancel) return DoneResult::Error; + const FilePath destDir = destination(appDataPath, *installOptionsIt); + const FilePath binary = destDir / installOptionsIt->name; + + if (binary.isFile()) + binary.setPermissions(QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); + expected_str doc = getOrCreatePackageInfo(appDataPath); if (!doc) return emitResult(doc.error()); @@ -180,7 +187,7 @@ static Group installRecipe( QJsonObject installedPackage; installedPackage["version"] = installOptionsIt->version; installedPackage["name"] = installOptionsIt->name; - installedPackage["path"] = destination(appDataPath, *installOptionsIt).toFSPathString(); + installedPackage["path"] = destDir.toFSPathString(); obj[installOptionsIt->name] = installedPackage; expected_str res = savePackageInfo(appDataPath, QJsonDocument(obj)); From a273990819ecfce9dea560068ac1e7174f6664c6 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 30 May 2024 09:58:28 +0200 Subject: [PATCH 22/26] Lua: Fix LSP Plugins Change-Id: I8d79d6c56ef4f0e54866a84f0e4535c7f507e963 Reviewed-by: David Schulz --- src/plugins/luals/luals/init.lua | 67 +++++++++++++++++++----------- src/plugins/rustls/rustls/init.lua | 46 +++++++++++++++----- 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/plugins/luals/luals/init.lua b/src/plugins/luals/luals/init.lua index 04c238197ad..de7883dd023 100644 --- a/src/plugins/luals/luals/init.lua +++ b/src/plugins/luals/luals/init.lua @@ -7,6 +7,7 @@ local S = require('Settings') local Gui = require('Gui') local a = require('async') local fetch = require('Fetch').fetch +local Install = require('Install') Settings = {} @@ -44,7 +45,6 @@ local function installOrUpdateServer() if type(data) == "table" and #data > 0 then local r = data[1] - Install = require('Install') local lspPkgInfo = Install.packageInfo("lua-language-server") if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then local osTr = { mac = "darwin", windows = "win32", linux = "linux" } @@ -83,7 +83,7 @@ local function installOrUpdateServer() binary = "bin/lua-language-server.exe" end - Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary) + Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary)) Settings:apply() return end @@ -138,31 +138,53 @@ local function layoutSettings() --- "using namespace Gui" local _ENV = using(Gui) - local installButton = {} - - if Settings.binary.expandedValue:isExecutableFile() == false then - installButton = { - "Language server not found:", - Row { - PushButton { - text = "Try to install lua language server", - onClicked = function() a.sync(installServer)() end, - }, - st - } - } - end local layout = Form { Settings.binary, br, Settings.developMode, br, Settings.showSource, br, Settings.showNode, br, - table.unpack(installButton) + Row { + PushButton { + text = "Update Lua Language Server", + onClicked = function() a.sync(installOrUpdateServer)() end, + }, + st + } } - return layout end +local function binaryFromPkg() + local lspPkgInfo = Install.packageInfo("lua-language-server") + if lspPkgInfo then + local binary = "bin/lua-language-server" + if Utils.HostOsInfo.isWindowsHost() then + binary = "bin/lua-language-server.exe" + end + local binaryPath = lspPkgInfo.path:resolvePath(binary) + if binaryPath:isExecutableFile() == true then + return binaryPath + end + end + + return nil +end + +local function findBinary() + local binary = binaryFromPkg() + if binary then + return binary + end + + -- Search for the binary in the PATH + local serverPath = Utils.FilePath.fromUserInput("lua-language-server") + local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks() + if absolute:isExecutableFile() == true then + return absolute + end + return serverPath +end + local function setupAspect() ---@class Settings: AspectContainer Settings = S.AspectContainer.create({ @@ -176,14 +198,9 @@ local function setupAspect() labelText = "Binary:", toolTip = "The path to the lua-language-server binary.", expectedKind = S.Kind.ExistingCommand, - defaultPath = Utils.FilePath.fromUserInput("lua-language-server"), + defaultPath = findBinary(), }) - -- Search for the binary in the PATH - local serverPath = Settings.binary.defaultPath - local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks() - if absolute:isExecutableFile() == true then - Settings.binary.defaultPath = absolute - end + Settings.developMode = S.BoolAspect.create({ settingsKey = "LuaCopilot.DevelopMode", displayName = "Enable Develop Mode", diff --git a/src/plugins/rustls/rustls/init.lua b/src/plugins/rustls/rustls/init.lua index c83d71ae5ff..474c368f3a9 100644 --- a/src/plugins/rustls/rustls/init.lua +++ b/src/plugins/rustls/rustls/init.lua @@ -8,6 +8,7 @@ local S = require('Settings') local Gui = require('Gui') local a = require('async') local fetch = require('Fetch').fetch +local Install = require('Install') Settings = {} @@ -39,7 +40,6 @@ local function installOrUpdateServer() if r.prerelease then r = data[2] end - Install = require('Install') local lspPkgInfo = Install.packageInfo("rust-analyzer") if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then local osTr = { mac = "apple-darwin", windows = "pc-windows-msvc", linux = "unknown-linux-gnu" } @@ -80,7 +80,7 @@ local function installOrUpdateServer() binary = "rust-analyzer.exe" end - Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary) + Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary)) Settings:apply() return end @@ -130,8 +130,8 @@ local function layoutSettings() Settings.binary, br, Row { PushButton { - text("Try to install Rust language server"), - onClicked(function() a.sync(installOrUpdateServer)() end), + text = "Try to install Rust language server", + onClicked = function() a.sync(installOrUpdateServer)() end, br, }, st @@ -141,6 +141,36 @@ local function layoutSettings() return layout end +local function binaryFromPkg() + local lspPkgInfo = Install.packageInfo("rust-analyzer") + if lspPkgInfo then + local binary = "rust-analyzer" + if Utils.HostOsInfo.isWindowsHost() then + binary = "rust-analyzer.exe" + end + local binaryPath = lspPkgInfo.path:resolvePath(binary) + if binaryPath:isExecutableFile() == true then + return binaryPath + end + end + + return nil +end + +local function findBinary() + local binary = binaryFromPkg() + if binary then + return binary + end + + -- Search for the binary in the PATH + local serverPath = Utils.FilePath.fromUserInput("rust-analyzer") + local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks() + if absolute:isExecutableFile() == true then + return absolute + end + return serverPath +end local function setupAspect() ---@class Settings: AspectContainer Settings = S.AspectContainer.create({ @@ -154,14 +184,8 @@ local function setupAspect() labelText = "Binary:", toolTip = "The path to the rust analyzer binary.", expectedKind = S.Kind.ExistingCommand, - defaultPath = Utils.FilePath.fromUserInput("rust-analyzer"), + defaultPath = findBinary(), }) - -- Search for the binary in the PATH - local serverPath = Settings.binary.defaultPath - local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks() - if absolute:isExecutableFile() == true then - Settings.binary.defaultPath = absolute - end return Settings end From 3e7f6237b04e08757e0f37544a3ee2fc25df8fef Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 31 May 2024 07:56:54 +0200 Subject: [PATCH 23/26] LuaLSP: Use cached release url Change-Id: If099374736912361f898c956e571fb52dbd1fa06 Reviewed-by: David Schulz --- src/plugins/luals/luals/init.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugins/luals/luals/init.lua b/src/plugins/luals/luals/init.lua index de7883dd023..e7bc13629cc 100644 --- a/src/plugins/luals/luals/init.lua +++ b/src/plugins/luals/luals/init.lua @@ -35,12 +35,8 @@ end local function installOrUpdateServer() local data = a.wait(fetch({ - url = "https://api.github.com/repos/LuaLS/lua-language-server/releases?per_page=1", - convertToTable = true, - headers = { - Accept = "application/vnd.github.v3+json", - ["X-GitHub-Api-Version"] = "2022-11-28" - } + url = "https://qtccache.qt.io/LuaLanguageServer/LatestRelease", + convertToTable = true })) if type(data) == "table" and #data > 0 then From 649d1cd6dc11ba9422878939a4d1f052be0453da Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 22 May 2024 11:09:42 +0200 Subject: [PATCH 24/26] LocatorMatcher: Get rid of ResultCollectorTask Simplify the implementation by creating and running the ResultsDeduplicator directly on task tree start. Change-Id: I08a0d2b924f92382c31771d4bbd878cc5506501e Reviewed-by: Eike Ziller --- .../coreplugin/locator/ilocatorfilter.cpp | 124 +++--------------- 1 file changed, 21 insertions(+), 103 deletions(-) diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 0fa19f2b6e5..814d8a89571 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -237,98 +237,6 @@ private: QList> m_outputData; }; -// This instance of this object is created by LocatorMatcher tree. -// It starts a separate thread which collects and deduplicates the results reported -// by LocatorStorage instances. The ResultsCollector is started as a first task in -// LocatorMatcher and runs in parallel to all the filters started by LocatorMatcher. -// When all the results are reported (the expected number of reports is set with setFilterCount()), -// the ResultsCollector finishes. The intermediate results are reported with -// serialOutputDataReady() signal. -// The object of ResultsCollector is registered in Tasking namespace under the -// ResultsCollectorTask name. -class ResultsCollector : public QObject -{ - Q_OBJECT - -public: - ~ResultsCollector(); - void setFilterCount(int count); - void start(); - - bool isRunning() const { return m_watcher.get(); } - - std::shared_ptr deduplicator() const { return m_deduplicator; } - -signals: - void serialOutputDataReady(const LocatorFilterEntries &serialOutputData); - void done(); - -private: - int m_filterCount = 0; - std::unique_ptr> m_watcher; - std::shared_ptr m_deduplicator; -}; - -ResultsCollector::~ResultsCollector() -{ - if (!isRunning()) - return; - - m_deduplicator->cancel(); - if (Utils::futureSynchronizer()) { - Utils::futureSynchronizer()->addFuture(m_watcher->future()); - return; - } - m_watcher->future().waitForFinished(); -} - -void ResultsCollector::setFilterCount(int count) -{ - QTC_ASSERT(!isRunning(), return); - QTC_ASSERT(count >= 0, return); - - m_filterCount = count; -} - -void ResultsCollector::start() -{ - QTC_ASSERT(!m_watcher, return); - QTC_ASSERT(!isRunning(), return); - if (m_filterCount == 0) { - emit done(); - return; - } - - m_deduplicator.reset(new ResultsDeduplicator(m_filterCount)); - m_watcher.reset(new QFutureWatcher); - connect(m_watcher.get(), &QFutureWatcherBase::resultReadyAt, this, [this](int index) { - emit serialOutputDataReady(m_watcher->resultAt(index)); - }); - connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] { - emit done(); - m_watcher.release()->deleteLater(); - m_deduplicator.reset(); - }); - - // TODO: When filterCount == 1, deliver results directly and finish? - auto deduplicate = [](QPromise &promise, - const std::shared_ptr &deduplicator) { - deduplicator->run(promise); - }; - m_watcher->setFuture(Utils::asyncRun(deduplicate, m_deduplicator)); -} - -class ResultsCollectorTaskAdapter : public TaskAdapter -{ -public: - ResultsCollectorTaskAdapter() { - connect(task(), &ResultsCollector::done, this, [this] { emit done(DoneResult::Success); }); - } - void start() final { task()->start(); } -}; - -using ResultsCollectorTask = CustomTask; - class LocatorStoragePrivate { public: @@ -425,23 +333,35 @@ void LocatorMatcher::start() QTC_ASSERT(!isRunning(), return); d->m_output = {}; - const Storage collectorStorage; + struct ResultsCollector + { + ~ResultsCollector() { + if (m_deduplicator) + m_deduplicator->cancel(); + } + std::shared_ptr m_deduplicator; + }; + + const Storage collectorStorage; const LoopList iterator(d->m_tasks); const auto onCollectorSetup = [this, filterCount = d->m_tasks.size(), collectorStorage]( - ResultsCollector &collector) { - *collectorStorage = &collector; - collector.setFilterCount(filterCount); - connect(&collector, &ResultsCollector::serialOutputDataReady, - this, [this](const LocatorFilterEntries &serialOutputData) { + Async &async) { + const std::shared_ptr deduplicator(new ResultsDeduplicator(filterCount)); + collectorStorage->m_deduplicator = deduplicator; + Async *asyncPtr = &async; + connect(asyncPtr, &AsyncBase::resultReadyAt, this, [this, asyncPtr](int index) { + const LocatorFilterEntries serialOutputData = asyncPtr->resultAt(index); d->m_output += serialOutputData; emit serialOutputDataReady(serialOutputData); }); + // TODO: When filterCount == 1, deliver results directly and finish? + async.setConcurrentCallData(&ResultsDeduplicator::run, deduplicator); }; - const auto onCollectorDone = [collectorStorage] { *collectorStorage = nullptr; }; + const auto onCollectorDone = [collectorStorage] { collectorStorage->m_deduplicator->cancel(); }; const auto onTaskTreeSetup = [iterator, input = d->m_input, collectorStorage](TaskTree &taskTree) { - const std::shared_ptr deduplicator = (*collectorStorage)->deduplicator(); + const std::shared_ptr deduplicator = collectorStorage->m_deduplicator; const Storage storage = iterator->storage; const auto onSetup = [storage, input, index = iterator.iteration(), deduplicator] { *storage = std::make_shared(input, index, deduplicator); @@ -458,7 +378,7 @@ void LocatorMatcher::start() const Group root { parallel, collectorStorage, - ResultsCollectorTask(onCollectorSetup, onCollectorDone), + AsyncTask(onCollectorSetup, onCollectorDone), Group { parallelLimit(d->m_parallelLimit), iterator, @@ -1472,5 +1392,3 @@ LocatorMatcherTask LocatorFileCache::matcher() const } } // Core - -#include "ilocatorfilter.moc" From 8b5b914846764a82325691083aa5f3cd0328a780 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 22 May 2024 11:35:22 +0200 Subject: [PATCH 25/26] LocatorMatcher: Ensure the task list isn't empty Change-Id: I4a8dac16e7f68df409bc7838ba0101732864a578 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/locator/ilocatorfilter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 814d8a89571..6a32b294a3d 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -333,6 +333,10 @@ void LocatorMatcher::start() QTC_ASSERT(!isRunning(), return); d->m_output = {}; + const int filterCount = d->m_tasks.size(); + if (filterCount <= 0) + return; + struct ResultsCollector { ~ResultsCollector() { @@ -345,7 +349,7 @@ void LocatorMatcher::start() const Storage collectorStorage; const LoopList iterator(d->m_tasks); - const auto onCollectorSetup = [this, filterCount = d->m_tasks.size(), collectorStorage]( + const auto onCollectorSetup = [this, filterCount, collectorStorage]( Async &async) { const std::shared_ptr deduplicator(new ResultsDeduplicator(filterCount)); collectorStorage->m_deduplicator = deduplicator; From 100e106e70235f9a728323043ff3bb914dc6b323 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 23 May 2024 17:56:15 +0200 Subject: [PATCH 26/26] MessageManager: Transform MessageManager class into namespace Rename internal static m_messageOutputWindow into s_messageOutputWindow. Make is a std::unique_ptr. Change-Id: I27e9abf3dfa514d21f85d811e3647f65c26ddf31 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/icore.cpp | 5 +- src/plugins/coreplugin/messagemanager.cpp | 99 +++++++++-------------- src/plugins/coreplugin/messagemanager.h | 47 +++-------- 3 files changed, 51 insertions(+), 100 deletions(-) diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp index 5c0a1a8574a..da47d44b6e0 100644 --- a/src/plugins/coreplugin/icore.cpp +++ b/src/plugins/coreplugin/icore.cpp @@ -301,7 +301,6 @@ public: WindowSupport *m_windowSupport = nullptr; EditorManager *m_editorManager = nullptr; ExternalToolManager *m_externalToolManager = nullptr; - MessageManager *m_messageManager = nullptr; ProgressManagerPrivate *m_progressManager = nullptr; JsExpander *m_jsExpander = nullptr; VcsManager *m_vcsManager = nullptr; @@ -1395,7 +1394,6 @@ void ICorePrivate::init() m_rightNavigationWidget = new NavigationWidget(m_toggleRightSideBarAction, Side::Right); m_rightPaneWidget = new RightPaneWidget(); - m_messageManager = new MessageManager; m_editorManager = new EditorManager(this); m_externalToolManager = new ExternalToolManager(); @@ -1454,8 +1452,7 @@ ICorePrivate::~ICorePrivate() delete m_externalToolManager; m_externalToolManager = nullptr; - delete m_messageManager; - m_messageManager = nullptr; + MessageManager::destroy(); delete m_shortcutSettings; m_shortcutSettings = nullptr; delete m_toolSettings; diff --git a/src/plugins/coreplugin/messagemanager.cpp b/src/plugins/coreplugin/messagemanager.cpp index 464d3fce716..d8e723ecf2c 100644 --- a/src/plugins/coreplugin/messagemanager.cpp +++ b/src/plugins/coreplugin/messagemanager.cpp @@ -5,113 +5,88 @@ #include "messageoutputwindow.h" -#include #include #include -#include -#include + +#include /*! - \class Core::MessageManager + \namespace Core::MessageManager \inheaderfile coreplugin/messagemanager.h \ingroup mainclasses \inmodule QtCreator - \brief The MessageManager class is used to post messages in the + \brief The MessageManager namespace is used to post messages in the \uicontrol{General Messages} pane. */ -namespace Core { +namespace Core::MessageManager { -static MessageManager *m_instance = nullptr; -static Internal::MessageOutputWindow *m_messageOutputWindow = nullptr; +static std::unique_ptr s_messageOutputWindow; enum class Flag { Silent, Flash, Disrupt }; static void showOutputPane(Flag flags) { - QTC_ASSERT(m_messageOutputWindow, return); - + QTC_ASSERT(s_messageOutputWindow, return); switch (flags) { - case Core::Flag::Silent: + case Flag::Silent: break; - case Core::Flag::Flash: - m_messageOutputWindow->flash(); + case Flag::Flash: + s_messageOutputWindow->flash(); break; - case Core::Flag::Disrupt: - m_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus); + case Flag::Disrupt: + s_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus); break; } } static void doWrite(const QString &text, Flag flags) { - QTC_ASSERT(m_messageOutputWindow, return); - + QTC_ASSERT(s_messageOutputWindow, return); showOutputPane(flags); - m_messageOutputWindow->append(text + '\n'); + s_messageOutputWindow->append(text + '\n'); } -static void write(const QString &text, Flag flags) +static void writeImpl(const QString &text, Flag flags) { - QTC_ASSERT(m_instance, return); - if (QThread::currentThread() == m_instance->thread()) - doWrite(text, flags); - else - QMetaObject::invokeMethod(m_instance, [text, flags] { - doWrite(text, flags); - }, Qt::QueuedConnection); + QTC_ASSERT(s_messageOutputWindow, return); + QMetaObject::invokeMethod(s_messageOutputWindow.get(), [text, flags] { doWrite(text, flags); }); } /*! \internal */ -MessageManager::MessageManager() +void init() { - m_instance = this; - m_messageOutputWindow = nullptr; + s_messageOutputWindow.reset(new Internal::MessageOutputWindow); } /*! \internal */ -MessageManager::~MessageManager() +void destroy() { - if (m_messageOutputWindow) { - ExtensionSystem::PluginManager::removeObject(m_messageOutputWindow); - delete m_messageOutputWindow; - } - m_instance = nullptr; + s_messageOutputWindow.reset(); } /*! \internal */ -void MessageManager::init() +void setFont(const QFont &font) { - m_messageOutputWindow = new Internal::MessageOutputWindow; - ExtensionSystem::PluginManager::addObject(m_messageOutputWindow); + QTC_ASSERT(s_messageOutputWindow, return); + s_messageOutputWindow->setFont(font); } /*! \internal */ -void MessageManager::setFont(const QFont &font) +void setWheelZoomEnabled(bool enabled) { - QTC_ASSERT(m_messageOutputWindow, return); - - m_messageOutputWindow->setFont(font); -} - -/*! - \internal -*/ -void MessageManager::setWheelZoomEnabled(bool enabled) -{ - QTC_ASSERT(m_messageOutputWindow, return); - - m_messageOutputWindow->setWheelZoomEnabled(enabled); + QTC_ASSERT(s_messageOutputWindow, return); + s_messageOutputWindow->setWheelZoomEnabled(enabled); } /*! @@ -124,9 +99,9 @@ void MessageManager::setWheelZoomEnabled(bool enabled) \sa writeFlashing() \sa writeDisrupting() */ -void MessageManager::writeSilently(const QString &message) +void writeSilently(const QString &message) { - Core::write(message, Flag::Silent); + writeImpl(message, Flag::Silent); } /*! @@ -141,9 +116,9 @@ void MessageManager::writeSilently(const QString &message) \sa writeSilently() \sa writeDisrupting() */ -void MessageManager::writeFlashing(const QString &message) +void writeFlashing(const QString &message) { - Core::write(message, Flag::Flash); + writeImpl(message, Flag::Flash); } /*! @@ -156,15 +131,15 @@ void MessageManager::writeFlashing(const QString &message) \sa writeSilently() \sa writeFlashing() */ -void MessageManager::writeDisrupting(const QString &message) +void writeDisrupting(const QString &message) { - Core::write(message, Flag::Disrupt); + writeImpl(message, Flag::Disrupt); } /*! \overload writeSilently() */ -void MessageManager::writeSilently(const QStringList &messages) +void writeSilently(const QStringList &messages) { writeSilently(messages.join('\n')); } @@ -172,7 +147,7 @@ void MessageManager::writeSilently(const QStringList &messages) /*! \overload writeFlashing() */ -void MessageManager::writeFlashing(const QStringList &messages) +void writeFlashing(const QStringList &messages) { writeFlashing(messages.join('\n')); } @@ -180,9 +155,9 @@ void MessageManager::writeFlashing(const QStringList &messages) /*! \overload writeDisrupting() */ -void MessageManager::writeDisrupting(const QStringList &messages) +void writeDisrupting(const QStringList &messages) { writeDisrupting(messages.join('\n')); } -} // namespace Core +} // namespace Core::MessageManager diff --git a/src/plugins/coreplugin/messagemanager.h b/src/plugins/coreplugin/messagemanager.h index f28b7072305..87a4b6f6499 100644 --- a/src/plugins/coreplugin/messagemanager.h +++ b/src/plugins/coreplugin/messagemanager.h @@ -5,47 +5,26 @@ #include "core_global.h" -#include -#include +#include QT_BEGIN_NAMESPACE class QFont; QT_END_NAMESPACE -namespace Core { +namespace Core::MessageManager { -class ICore; +CORE_EXPORT void setFont(const QFont &font); +CORE_EXPORT void setWheelZoomEnabled(bool enabled); -namespace Internal { -class ICorePrivate; -class MainWindow; -} +CORE_EXPORT void writeSilently(const QString &message); +CORE_EXPORT void writeFlashing(const QString &message); +CORE_EXPORT void writeDisrupting(const QString &message); -class CORE_EXPORT MessageManager : public QObject -{ - Q_OBJECT +CORE_EXPORT void writeSilently(const QStringList &messages); +CORE_EXPORT void writeFlashing(const QStringList &messages); +CORE_EXPORT void writeDisrupting(const QStringList &messages); -public: - static void setFont(const QFont &font); - static void setWheelZoomEnabled(bool enabled); +void init(); +void destroy(); - static void writeSilently(const QString &message); - static void writeFlashing(const QString &message); - static void writeDisrupting(const QString &message); - - static void writeSilently(const QStringList &messages); - static void writeFlashing(const QStringList &messages); - static void writeDisrupting(const QStringList &messages); - -private: - MessageManager(); - ~MessageManager() override; - - static void init(); - - friend class ICore; - friend class Internal::ICorePrivate; - friend class Internal::MainWindow; -}; - -} // namespace Core +} // namespace Core::MessageManager