From e90fb40678c9fdafd801142edc399895b0b94f23 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 1 Oct 2018 13:35:00 +0200 Subject: [PATCH 01/17] Reuse linksForKeyword() from QHelpEngineCore Change-Id: I740d49222842ec2f16ffc8eec8c20e9b4a7337ec Reviewed-by: Eike Ziller --- src/plugins/help/helpmanager.cpp | 68 ++++++-------------------------- 1 file changed, 13 insertions(+), 55 deletions(-) diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp index 34be168bcb0..3dbbbd65c72 100644 --- a/src/plugins/help/helpmanager.cpp +++ b/src/plugins/help/helpmanager.cpp @@ -84,11 +84,6 @@ struct HelpManagerPrivate static HelpManager *m_instance = nullptr; static HelpManagerPrivate *d = nullptr; -static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " - "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " - "NamespaceTable f WHERE a.FileId=d.FileId AND d.FolderId=e.Id AND " - "a.NamespaceId=f.Id AND a.Name='%1'"; - // -- DbCleaner struct DbCleaner @@ -227,66 +222,29 @@ QSet HelpManager::userDocumentationPaths() return d->m_userRegisteredFiles; } -static QUrl buildQUrl(const QString &ns, const QString &folder, - const QString &relFileName, const QString &anchor) -{ - QUrl url; - url.setScheme(QLatin1String("qthelp")); - url.setAuthority(ns); - url.setPath(QLatin1Char('/') + folder + QLatin1Char('/') + relFileName); - url.setFragment(anchor); - return url; -} - // This should go into Qt 4.8 once we start using it for Qt Creator QMap HelpManager::linksForKeyword(const QString &key) { - QMap links; - QTC_ASSERT(!d->m_needsSetup, return links); - - const QLatin1String sqlite("QSQLITE"); - const QLatin1String name("HelpManager::linksForKeyword"); - - DbCleaner cleaner(name); - QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); - if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { - const QStringList ®isteredDocs = d->m_helpEngine->registeredDocumentations(); - for (const QString &nameSpace : registeredDocs) { - db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); - if (db.open()) { - QSqlQuery query = QSqlQuery(db); - query.setForwardOnly(true); - query.exec(QString::fromLatin1(linksForKeyQuery).arg(key)); - while (query.next()) { - QString title = query.value(0).toString(); - if (title.isEmpty()) // generate a title + corresponding path - title = key + QLatin1String(" : ") + query.value(3).toString(); - links.insertMulti(title, buildQUrl(query.value(1).toString(), - query.value(2).toString(), query.value(3).toString(), - query.value(4).toString())); - } - } - } - } - return links; + QTC_ASSERT(!d->m_needsSetup, return {}); + return d->m_helpEngine->linksForKeyword(key); } QMap HelpManager::linksForIdentifier(const QString &id) { QMap empty; - QTC_ASSERT(!d->m_needsSetup, return empty); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->linksForIdentifier(id); } QUrl HelpManager::findFile(const QUrl &url) { - QTC_ASSERT(!d->m_needsSetup, return QUrl()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->findFile(url); } QByteArray HelpManager::fileData(const QUrl &url) { - QTC_ASSERT(!d->m_needsSetup, return QByteArray()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->fileData(url); } @@ -297,19 +255,19 @@ void HelpManager::handleHelpRequest(const QUrl &url, Core::HelpManager::HelpView QStringList HelpManager::registeredNamespaces() { - QTC_ASSERT(!d->m_needsSetup, return QStringList()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->registeredDocumentations(); } QString HelpManager::namespaceFromFile(const QString &file) { - QTC_ASSERT(!d->m_needsSetup, return QString()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->namespaceName(file); } QString HelpManager::fileFromNamespace(const QString &nameSpace) { - QTC_ASSERT(!d->m_needsSetup, return QString()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->documentationFileName(nameSpace); } @@ -325,13 +283,13 @@ void HelpManager::setCustomValue(const QString &key, const QVariant &value) QVariant HelpManager::customValue(const QString &key, const QVariant &value) { - QTC_ASSERT(!d->m_needsSetup, return QVariant()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->customValue(key, value); } HelpManager::Filters HelpManager::filters() { - QTC_ASSERT(!d->m_needsSetup, return Filters()); + QTC_ASSERT(!d->m_needsSetup, return {}); Filters filters; const QStringList &customFilters = d->m_helpEngine->customFilters(); @@ -342,12 +300,12 @@ HelpManager::Filters HelpManager::filters() HelpManager::Filters HelpManager::fixedFilters() { - Filters fixedFilters; - QTC_ASSERT(!d->m_needsSetup, return fixedFilters); + QTC_ASSERT(!d->m_needsSetup, return {}); const QLatin1String sqlite("QSQLITE"); const QLatin1String name("HelpManager::fixedCustomFilters"); + Filters fixedFilters; DbCleaner cleaner(name); QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { @@ -370,7 +328,7 @@ HelpManager::Filters HelpManager::fixedFilters() HelpManager::Filters HelpManager::userDefinedFilters() { - QTC_ASSERT(!d->m_needsSetup, return Filters()); + QTC_ASSERT(!d->m_needsSetup, return {}); Filters all = filters(); const Filters &fixed = fixedFilters(); From f2dd427f3db343dc5d29baabfaac52f8537faba8 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 30 Sep 2018 09:00:23 +0300 Subject: [PATCH 02/17] Nim: Remove superfluous lambda on Utils::sort call Change-Id: I401136a57e88736796397314d7e2d07e30fca4eb Reviewed-by: Filippo Cucchetto Reviewed-by: hjk --- src/plugins/nim/project/nimproject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index 99fd84afa2d..12007c1c104 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -144,7 +144,7 @@ void NimProject::updateProject() m_files = transform(fileNodes, [](const std::unique_ptr &fn) { return fn->filePath().toString(); }); - Utils::sort(m_files, [](const QString &a, const QString &b) { return a < b; }); + Utils::sort(m_files); if (oldFiles == m_files) return; From b1c37910f141825f4ffeb948a96a43a196c71c6f Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Sep 2018 17:50:14 +0300 Subject: [PATCH 03/17] PythonEditor: Remove dead code Change-Id: I55f7d513755857a5759ba8688e5cfeccbdaa379f Reviewed-by: hjk --- src/plugins/pythoneditor/pythoneditorplugin.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index f728f6bbc65..fe0c0b0430f 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -362,14 +362,6 @@ bool PythonProject::addFiles(const QStringList &filePaths) foreach (const QString &filePath, filePaths) newList.append(baseDir.relativeFilePath(filePath)); - QSet toAdd; - - foreach (const QString &filePath, filePaths) { - QString directory = QFileInfo(filePath).absolutePath(); - if (!toAdd.contains(directory)) - toAdd << directory; - } - bool result = saveRawList(newList, projectFilePath().toString()); refresh(); From a31655cde705996d501a0eb869a706029c2c8c90 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Sep 2018 17:55:46 +0300 Subject: [PATCH 04/17] PythonEditor: Avoid file duplication Every add/remove of a file added another entry of the project file. Change-Id: I800adc3540c3fc8b109864e86ab590af5374e30b Reviewed-by: hjk --- src/plugins/pythoneditor/pythoneditorplugin.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index fe0c0b0430f..1441ba0ee43 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -312,11 +312,13 @@ PythonProject::PythonProject(const FileName &fileName) : setDisplayName(fileName.toFileInfo().completeBaseName()); } -static QStringList readLines(const QString &absoluteFileName) +static QStringList readLines(const Utils::FileName &projectFile) { - QStringList lines; + const QString projectFileName = projectFile.fileName(); + QSet visited = { projectFileName }; + QStringList lines = { projectFileName }; - QFile file(absoluteFileName); + QFile file(projectFile.toString()); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); @@ -324,8 +326,10 @@ static QStringList readLines(const QString &absoluteFileName) QString line = stream.readLine(); if (line.isNull()) break; - + if (visited.contains(line)) + continue; lines.append(line); + visited.insert(line); } } @@ -410,8 +414,7 @@ bool PythonProject::renameFile(const QString &filePath, const QString &newFilePa void PythonProject::parseProject() { m_rawListEntries.clear(); - m_rawFileList = readLines(projectFilePath().toString()); - m_rawFileList << projectFilePath().fileName(); + m_rawFileList = readLines(projectFilePath()); m_files = processEntries(m_rawFileList, &m_rawListEntries); } From d585b85550797f1d6bb384b51c376ce871394255 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Sep 2018 17:30:58 +0300 Subject: [PATCH 05/17] PythonEditor: Support file operations Change-Id: I0fc5a3e1795fe56c753e300ed1c1ca7514964401 Reviewed-by: hjk --- .../pythoneditor/pythoneditorplugin.cpp | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index 1441ba0ee43..b17f1990a4c 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -113,6 +113,10 @@ public: bool showInSimpleTree() const override; QString addFileFilter() const override; + bool supportsAction(ProjectAction action, const Node *node) const override; + bool addFiles(const QStringList &filePaths, QStringList *) override; + bool removeFiles(const QStringList &filePaths, QStringList *) override; + bool deleteFiles(const QStringList &) override; bool renameFile(const QString &filePath, const QString &newFilePath) override; private: @@ -388,7 +392,7 @@ bool PythonProject::removeFiles(const QStringList &filePaths) bool PythonProject::setFiles(const QStringList &filePaths) { QStringList newList; - QDir baseDir(projectFilePath().toString()); + QDir baseDir(projectDirectory().toString()); foreach (const QString &filePath, filePaths) newList.append(baseDir.relativeFilePath(filePath)); @@ -403,7 +407,7 @@ bool PythonProject::renameFile(const QString &filePath, const QString &newFilePa if (i != m_rawListEntries.end()) { int index = newList.indexOf(i.value()); if (index != -1) { - QDir baseDir(projectFilePath().toString()); + QDir baseDir(projectDirectory().toString()); newList.replace(index, baseDir.relativeFilePath(newFilePath)); } } @@ -576,6 +580,37 @@ QString PythonProjectNode::addFileFilter() const return QLatin1String("*.py"); } +bool PythonProjectNode::supportsAction(ProjectAction action, const Node *node) const +{ + switch (node->nodeType()) { + case NodeType::File: + return action == ProjectAction::Rename + || action == ProjectAction::RemoveFile; + case NodeType::Folder: + case NodeType::Project: + return action == ProjectAction::AddNewFile + || action == ProjectAction::RemoveFile + || action == ProjectAction::AddExistingFile; + default: + return ProjectNode::supportsAction(action, node); + } +} + +bool PythonProjectNode::addFiles(const QStringList &filePaths, QStringList *) +{ + return m_project->addFiles(filePaths); +} + +bool PythonProjectNode::removeFiles(const QStringList &filePaths, QStringList *) +{ + return m_project->removeFiles(filePaths); +} + +bool PythonProjectNode::deleteFiles(const QStringList &) +{ + return true; +} + bool PythonProjectNode::renameFile(const QString &filePath, const QString &newFilePath) { return m_project->renameFile(filePath, newFilePath); From 681297ad7e7c5bb6814befbac3a8d082820c35e8 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 1 Oct 2018 21:56:17 +0300 Subject: [PATCH 06/17] Git: Fix reading of gitfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * QFile ctor does not open the file for read. * Replace readLine with read(8) to avoid needless read. This amends commit e9eeaf33b3a84b32b2ef31c964b8cbea738cac59. Change-Id: I33c230497ad431091d7d6b271846f5af661b4e0d Reviewed-by: AndrĂ© Hartmann --- src/plugins/git/gitversioncontrol.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp index dc0607cbb73..e36a22239e7 100644 --- a/src/plugins/git/gitversioncontrol.cpp +++ b/src/plugins/git/gitversioncontrol.cpp @@ -82,7 +82,10 @@ bool GitVersionControl::isVcsFileOrDirectory(const Utils::FileName &fileName) co return false; if (fileName.toFileInfo().isDir()) return true; - return QFile(fileName.toString()).readLine().startsWith("gitdir: "); + QFile file(fileName.toString()); + if (!file.open(QFile::ReadOnly)) + return false; + return file.read(8) == "gitdir: "; } bool GitVersionControl::isConfigured() const From 377f5badd83c42dc70ebb6c151d5cd5bd989e871 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 26 Sep 2018 09:17:55 +0200 Subject: [PATCH 07/17] Project: Inline RunConfiguration::wrapWidget helper again There are no external users left, so there's no need to expose it in the header anymore. Also saves a cast. Change-Id: I1ced368ebc9588cbc0058cc7d37f39ab80f9c595 Reviewed-by: Christian Stenger --- .../projectexplorer/runconfiguration.cpp | 19 ++++++------------- .../projectexplorer/runconfiguration.h | 1 - 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index afb4b6d9819..3b7b7d0533d 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -224,6 +224,8 @@ QWidget *RunConfiguration::createConfigurationWidget() { auto widget = new QWidget; auto formLayout = new QFormLayout(widget); + formLayout->setMargin(0); + formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); for (ProjectConfigurationAspect *aspect : m_aspects) { if (aspect->isVisible()) @@ -232,7 +234,10 @@ QWidget *RunConfiguration::createConfigurationWidget() Core::VariableChooser::addSupportForChildWidgets(widget, macroExpander()); - return wrapWidget(widget); + auto detailsWidget = new Utils::DetailsWidget; + detailsWidget->setState(DetailsWidget::NoSummary); + detailsWidget->setWidget(widget); + return detailsWidget; } void RunConfiguration::updateEnabledState() @@ -282,18 +287,6 @@ BuildConfiguration *RunConfiguration::activeBuildConfiguration() const return target()->activeBuildConfiguration(); } -QWidget *RunConfiguration::wrapWidget(QWidget *inner) const -{ - auto detailsWidget = new Utils::DetailsWidget; - detailsWidget->setState(DetailsWidget::NoSummary); - detailsWidget->setWidget(inner); - if (auto fl = qobject_cast(inner->layout())){ - fl->setMargin(0); - fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); - } - return detailsWidget; -} - Target *RunConfiguration::target() const { return static_cast(parent()); diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 33c72a9654c..ee4eb7ec613 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -205,7 +205,6 @@ protected: /// convenience function to get current build configuration. BuildConfiguration *activeBuildConfiguration() const; - QWidget *wrapWidget(QWidget *inner) const; template void setOutputFormatter() { From 2f6c6b632c25f3d9adc79b8e971129cc2ee7c3ee Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 30 Sep 2018 08:55:19 +0300 Subject: [PATCH 08/17] ProjectExplorer: Remove versionControls argument from scanForFiles Retrieving the list is cheap, there's no reason to store it and pass it through all these functions. Change-Id: I394b512c113af92f60cfb8c2f6561d1617d9cd36 Reviewed-by: hjk --- src/plugins/cmakeprojectmanager/treescanner.cpp | 13 ++++--------- src/plugins/cmakeprojectmanager/treescanner.h | 4 +--- src/plugins/nim/project/nimproject.cpp | 8 +++----- src/plugins/projectexplorer/projectnodes.cpp | 10 +++++----- src/plugins/projectexplorer/projectnodes.h | 8 +++----- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/treescanner.cpp b/src/plugins/cmakeprojectmanager/treescanner.cpp index 877491a9de7..7a25e9e2668 100644 --- a/src/plugins/cmakeprojectmanager/treescanner.cpp +++ b/src/plugins/cmakeprojectmanager/treescanner.cpp @@ -69,10 +69,7 @@ bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory) m_scanFuture = fi->future(); m_futureWatcher.setFuture(m_scanFuture); - if (m_versionControls.isEmpty()) - m_versionControls = Core::VcsManager::versionControls(); - - Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory, m_versionControls); }); + Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); }); return true; } @@ -150,14 +147,12 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti } void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, - const FileFilter &filter, const FileTypeFactory &factory, - QList &versionControls) + const FileFilter &filter, const FileTypeFactory &factory) { std::unique_ptr fip(fi); fip->reportStarted(); - Result nodes - = FileNode::scanForFilesWithVersionControls( + Result nodes = FileNode::scanForFiles( directory, [&filter, &factory](const Utils::FileName &fn) -> FileNode * { const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString()); @@ -172,7 +167,7 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& direc type = factory(mimeType, fn); return new FileNode(fn, type, false); - }, versionControls, fip.get()); + }, fip.get()); Utils::sort(nodes, ProjectExplorer::Node::sortByPath); diff --git a/src/plugins/cmakeprojectmanager/treescanner.h b/src/plugins/cmakeprojectmanager/treescanner.h index 146076f1f2a..b377ec63a49 100644 --- a/src/plugins/cmakeprojectmanager/treescanner.h +++ b/src/plugins/cmakeprojectmanager/treescanner.h @@ -88,8 +88,7 @@ signals: private: static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory, - const FileFilter &filter, const FileTypeFactory &factory, - QList &versionControls); + const FileFilter &filter, const FileTypeFactory &factory); private: FileFilter m_filter; @@ -97,7 +96,6 @@ private: FutureWatcher m_futureWatcher; Future m_scanFuture; - QList m_versionControls; }; } // namespace Internal diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index 12007c1c104..50a903044f3 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -113,11 +113,9 @@ void NimProject::collectProjectFiles() m_lastProjectScan.start(); QTC_ASSERT(!m_futureWatcher.future().isRunning(), return); FileName prjDir = projectDirectory(); - const QList versionControls = Core::VcsManager::versionControls(); - QFuture> future = Utils::runAsync([prjDir, versionControls] { - return FileNode::scanForFilesWithVersionControls( - prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); }, - versionControls); + QFuture> future = Utils::runAsync([prjDir] { + return FileNode::scanForFiles( + prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); }); }); m_futureWatcher.setFuture(future); Core::ProgressManager::addTask(future, tr("Scanning for Nim files"), "Nim.Project.Scan"); diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index b2fc067de8c..8d0a9dd7459 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -390,15 +390,15 @@ static QList scanForFilesRecursively(const Utils::FileName &director } QList -FileNode::scanForFilesWithVersionControls(const Utils::FileName &directory, - const std::function factory, - const QList &versionControls, - QFutureInterface> *future) +FileNode::scanForFiles(const Utils::FileName &directory, + const std::function factory, + QFutureInterface> *future) { QSet visited; if (future) future->setProgressRange(0, 1000000); - return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, versionControls); + return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, + Core::VcsManager::versionControls()); } bool FileNode::supportsAction(ProjectAction action, const Node *node) const diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 909be008d9e..8f8f9fd1bf0 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -36,7 +36,6 @@ #include namespace Utils { class MimeType; } -namespace Core { class IVersionControl; } namespace ProjectExplorer { @@ -191,10 +190,9 @@ public: const FileNode *asFileNode() const final { return this; } static QList - scanForFilesWithVersionControls(const Utils::FileName &directory, - const std::function factory, - const QList &versionControls, - QFutureInterface> *future = nullptr); + scanForFiles(const Utils::FileName &directory, + const std::function factory, + QFutureInterface> *future = nullptr); bool supportsAction(ProjectAction action, const Node *node) const override; private: From 1c9410e353337052bb141cbe4f519012545d735d Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 7 Sep 2018 13:29:45 +0200 Subject: [PATCH 09/17] ProjectExplorer: Rename 'extraAspect' to 'aspect' Using aspects is the standard pattern nowadays, there's nothing 'extra' to them anymore. Change-Id: I446f9d7b1db58a4899e5e44df33ce51f655e7be4 Reviewed-by: hjk Reviewed-by: Orgad Shaneh --- src/plugins/android/androidrunnerworker.cpp | 10 +++--- src/plugins/autotest/testrunconfiguration.h | 2 +- .../baremetalcustomrunconfiguration.cpp | 2 +- .../baremetal/baremetaldebugsupport.cpp | 4 +-- .../baremetal/baremetalrunconfiguration.cpp | 2 +- .../cmakerunconfiguration.cpp | 8 ++--- src/plugins/debugger/debuggerruncontrol.cpp | 6 ++-- src/plugins/ios/iosrunconfiguration.cpp | 2 +- src/plugins/ios/iosrunner.cpp | 4 +-- .../nim/project/nimrunconfiguration.cpp | 4 +-- .../customexecutablerunconfiguration.cpp | 32 +++++++++---------- .../projectexplorer/projectconfiguration.cpp | 2 +- .../projectexplorer/projectconfiguration.h | 4 +-- .../projectexplorer/runconfiguration.cpp | 20 ++++++------ .../projectexplorer/runconfiguration.h | 4 +-- .../pythoneditor/pythoneditorplugin.cpp | 14 ++++---- .../qbsprojectmanager/qbsrunconfiguration.cpp | 10 +++--- .../desktopqmakerunconfiguration.cpp | 12 +++---- src/plugins/qmlprofiler/qmlprofilertool.cpp | 2 +- .../qmlprojectrunconfiguration.cpp | 4 +-- src/plugins/qnx/qnxdebugsupport.cpp | 2 +- src/plugins/qnx/qnxrunconfiguration.cpp | 2 +- src/plugins/qnx/slog2inforunner.cpp | 2 +- .../remotelinuxcustomrunconfiguration.cpp | 4 +-- .../remotelinuxrunconfiguration.cpp | 4 +-- src/plugins/valgrind/valgrindengine.cpp | 2 +- src/plugins/winrt/winrtrunnerhelper.cpp | 8 ++--- 27 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 3015f3f28d0..f117d70c82e 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -162,7 +162,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa { auto runConfig = runner->runControl()->runConfiguration(); - auto aspect = runConfig->extraAspect(); + auto aspect = runConfig->aspect(); Core::Id runMode = runner->runMode(); const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE; m_useCppDebugger = debuggingMode && aspect->useCppDebugger(); @@ -194,23 +194,23 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target); m_apiLevel = AndroidManager::deviceApiLevel(target); - m_extraEnvVars = runConfig->extraAspect()->environment(); + m_extraEnvVars = runConfig->aspect()->environment(); qCDebug(androidRunWorkerLog) << "Environment variables for the app" << m_extraEnvVars.toStringList(); m_extraAppParams = runConfig->runnable().commandLineArguments; - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_AMSTARTARGS)) + if (auto aspect = runConfig->aspect(Constants::ANDROID_AMSTARTARGS)) m_amStartExtraArgs = static_cast(aspect)->value().split(' '); - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) { + if (auto aspect = runConfig->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) { for (const QString &shellCmd : static_cast(aspect)->value()) m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd)); } for (const QString &shellCmd : runner->recordedData(Constants::ANDROID_PRESTARTSHELLCMDLIST).toStringList()) m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd)); - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) { + if (auto aspect = runConfig->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) { for (const QString &shellCmd : static_cast(aspect)->value()) m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd)); } diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h index d625afa28b8..f9110a8ece9 100644 --- a/src/plugins/autotest/testrunconfiguration.h +++ b/src/plugins/autotest/testrunconfiguration.h @@ -57,7 +57,7 @@ public: if (auto debuggable = dynamic_cast(config)) enableQuick = debuggable->mixedDebugging(); - if (auto debugAspect = extraAspect()) { + if (auto debugAspect = aspect()) { debugAspect->setUseQmlDebugger(enableQuick); ProjectExplorer::ProjectExplorerPlugin::instance()->updateRunActions(); } diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp index 1239c9045b0..14b957d5e4a 100644 --- a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp +++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp @@ -58,7 +58,7 @@ const char *BareMetalCustomRunConfiguration::Id = "BareMetal"; bool BareMetalCustomRunConfiguration::isConfigured() const { - return !extraAspect()->executable().isEmpty(); + return !aspect()->executable().isEmpty(); } RunConfiguration::ConfigurationState diff --git a/src/plugins/baremetal/baremetaldebugsupport.cpp b/src/plugins/baremetal/baremetaldebugsupport.cpp index fdab85540c8..ab8783a446e 100644 --- a/src/plugins/baremetal/baremetaldebugsupport.cpp +++ b/src/plugins/baremetal/baremetaldebugsupport.cpp @@ -85,7 +85,7 @@ void BareMetalDebugSupport::start() { const auto rc = runControl()->runConfiguration(); QTC_ASSERT(rc, reportFailure(); return); - const auto exeAspect = rc->extraAspect(); + const auto exeAspect = rc->aspect(); QTC_ASSERT(exeAspect, reportFailure(); return); const QString bin = exeAspect->executable().toString(); @@ -124,7 +124,7 @@ void BareMetalDebugSupport::start() Runnable inferior; inferior.executable = bin; - if (auto aspect = rc->extraAspect()) + if (auto aspect = rc->aspect()) inferior.commandLineArguments = aspect->arguments(rc->macroExpander()); setInferior(inferior); setSymbolFile(bin); diff --git a/src/plugins/baremetal/baremetalrunconfiguration.cpp b/src/plugins/baremetal/baremetalrunconfiguration.cpp index 8cb2aa3a8c4..cdfa2ddca65 100644 --- a/src/plugins/baremetal/baremetalrunconfiguration.cpp +++ b/src/plugins/baremetal/baremetalrunconfiguration.cpp @@ -63,7 +63,7 @@ BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target, Core::Id id void BareMetalRunConfiguration::updateTargetInformation() { const BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey()); - extraAspect()->setExecutable(bti.targetFilePath); + aspect()->setExecutable(bti.targetFilePath); emit enabledChanged(); } diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index cb618e06579..3872fe90f4e 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -98,11 +98,11 @@ QString CMakeRunConfiguration::disabledReason() const void CMakeRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey()); - extraAspect()->setExecutable(bti.targetFilePath); - extraAspect()->setDefaultWorkingDirectory(bti.workingDirectory); - extraAspect()->buildEnvironmentHasChanged(); + aspect()->setExecutable(bti.targetFilePath); + aspect()->setDefaultWorkingDirectory(bti.workingDirectory); + aspect()->buildEnvironmentHasChanged(); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); } diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 29339121fa3..7acf8550b38 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -906,9 +906,9 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer if (runConfig) { m_runParameters.displayName = runConfig->displayName(); - if (auto symbolsAspect = runConfig->extraAspect()) + if (auto symbolsAspect = runConfig->aspect()) m_runParameters.symbolFile = symbolsAspect->value(); - if (auto terminalAspect = runConfig->extraAspect()) + if (auto terminalAspect = runConfig->aspect()) m_runParameters.useTerminal = terminalAspect->useTerminal(); } @@ -924,7 +924,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit)) m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString(); - if (auto aspect = runConfig ? runConfig->extraAspect() : nullptr) { + if (auto aspect = runConfig ? runConfig->aspect() : nullptr) { if (!aspect->useCppDebugger()) m_runParameters.cppEngineType = NoEngineType; m_runParameters.isQmlDebugging = aspect->useQmlDebugger(); diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp index 182a1dea713..8fd19bdbd5f 100644 --- a/src/plugins/ios/iosrunconfiguration.cpp +++ b/src/plugins/ios/iosrunconfiguration.cpp @@ -139,7 +139,7 @@ void IosRunConfiguration::updateDisplayNames() setDefaultDisplayName(tr("Run on %1").arg(devName)); setDisplayName(tr("Run %1 on %2").arg(applicationName()).arg(devName)); - extraAspect()->setExecutable(localExecutable()); + aspect()->setExecutable(localExecutable()); } void IosRunConfiguration::updateEnabledState() diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 07918f787e4..dc6d222e0f8 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -100,7 +100,7 @@ IosRunner::IosRunner(RunControl *runControl) stopRunningRunControl(runControl); auto runConfig = qobject_cast(runControl->runConfiguration()); m_bundleDir = runConfig->bundleDirectory().toString(); - m_arguments = runConfig->extraAspect()->arguments(runConfig->macroExpander()); + m_arguments = runConfig->aspect()->arguments(runConfig->macroExpander()); m_device = DeviceKitInformation::device(runConfig->target()->kit()); m_deviceType = runConfig->deviceType(); } @@ -387,7 +387,7 @@ IosQmlProfilerSupport::IosQmlProfilerSupport(RunControl *runControl) Runnable runnable; runnable.executable = iosRunConfig->localExecutable().toUserOutput(); runnable.commandLineArguments = - iosRunConfig->extraAspect()->arguments(iosRunConfig->macroExpander()); + iosRunConfig->aspect()->arguments(iosRunConfig->macroExpander()); runControl->setDisplayName(iosRunConfig->applicationName()); runControl->setRunnable(runnable); diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp index 21c6d50779f..c27cb75b542 100644 --- a/src/plugins/nim/project/nimrunconfiguration.cpp +++ b/src/plugins/nim/project/nimrunconfiguration.cpp @@ -67,9 +67,9 @@ void NimRunConfiguration::updateConfiguration() QTC_ASSERT(buildConfiguration, return); setActiveBuildConfiguration(buildConfiguration); const QFileInfo outFileInfo = buildConfiguration->outFilePath().toFileInfo(); - extraAspect()->setExecutable(FileName::fromString(outFileInfo.absoluteFilePath())); + aspect()->setExecutable(FileName::fromString(outFileInfo.absoluteFilePath())); const QString workingDirectory = outFileInfo.absoluteDir().absolutePath(); - extraAspect()->setDefaultWorkingDirectory(FileName::fromString(workingDirectory)); + aspect()->setDefaultWorkingDirectory(FileName::fromString(workingDirectory)); } void NimRunConfiguration::setActiveBuildConfiguration(NimBuildConfiguration *activeBuildConfiguration) diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index 3689deb50c6..1c2b315095c 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -94,7 +94,7 @@ private: CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) : QDialog(Core::ICore::dialogParent()), m_rc(rc), - m_workingDirectory(rc->extraAspect()) + m_workingDirectory(rc->aspect()) { auto vbox = new QVBoxLayout(this); vbox->addWidget(new QLabel(tr("Could not find the executable, please specify one."))); @@ -121,21 +121,21 @@ CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) m_executableChooser = new PathChooser(this); m_executableChooser->setHistoryCompleter("Qt.CustomExecutable.History"); m_executableChooser->setExpectedKind(PathChooser::ExistingCommand); - m_executableChooser->setPath(rc->extraAspect()->executable().toString()); + m_executableChooser->setPath(rc->aspect()->executable().toString()); layout->addRow(tr("Executable:"), m_executableChooser); connect(m_executableChooser, &PathChooser::rawPathChanged, this, &CustomExecutableDialog::changed); - copyAspect(rc->extraAspect(), &m_arguments); + copyAspect(rc->aspect(), &m_arguments); m_arguments.addToConfigurationLayout(layout); - copyAspect(rc->extraAspect(), &m_workingDirectory); + copyAspect(rc->aspect(), &m_workingDirectory); m_workingDirectory.addToConfigurationLayout(layout); - copyAspect(rc->extraAspect(), &m_terminal); + copyAspect(rc->aspect(), &m_terminal); m_terminal.addToConfigurationLayout(layout); - auto enviromentAspect = rc->extraAspect(); + auto enviromentAspect = rc->aspect(); connect(enviromentAspect, &EnvironmentAspect::environmentChanged, this, &CustomExecutableDialog::environmentWasChanged); environmentWasChanged(); @@ -146,10 +146,10 @@ CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) void CustomExecutableDialog::accept() { auto executable = FileName::fromString(m_executableChooser->path()); - m_rc->extraAspect()->setExecutable(executable); - copyAspect(&m_arguments, m_rc->extraAspect()); - copyAspect(&m_workingDirectory, m_rc->extraAspect()); - copyAspect(&m_terminal, m_rc->extraAspect()); + m_rc->aspect()->setExecutable(executable); + copyAspect(&m_arguments, m_rc->aspect()); + copyAspect(&m_workingDirectory, m_rc->aspect()); + copyAspect(&m_terminal, m_rc->aspect()); QDialog::accept(); } @@ -168,7 +168,7 @@ bool CustomExecutableDialog::event(QEvent *event) void CustomExecutableDialog::environmentWasChanged() { - auto aspect = m_rc->extraAspect(); + auto aspect = m_rc->aspect(); QTC_ASSERT(aspect, return); m_executableChooser->setEnvironment(aspect->environment()); } @@ -242,7 +242,7 @@ void CustomExecutableRunConfiguration::configurationDialogFinished() QString CustomExecutableRunConfiguration::rawExecutable() const { - return extraAspect()->executable().toString(); + return aspect()->executable().toString(); } bool CustomExecutableRunConfiguration::isConfigured() const @@ -253,12 +253,12 @@ bool CustomExecutableRunConfiguration::isConfigured() const Runnable CustomExecutableRunConfiguration::runnable() const { FileName workingDirectory = - extraAspect()->workingDirectory(macroExpander()); + aspect()->workingDirectory(macroExpander()); Runnable r; - r.executable = extraAspect()->executable().toString(); - r.commandLineArguments = extraAspect()->arguments(macroExpander()); - r.environment = extraAspect()->environment(); + r.executable = aspect()->executable().toString(); + r.commandLineArguments = aspect()->arguments(macroExpander()); + r.environment = aspect()->environment(); r.workingDirectory = workingDirectory.toString(); r.device = DeviceManager::instance()->defaultDevice(Constants::DESKTOP_DEVICE_TYPE); diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp index a78f5624f39..fafa53af3e2 100644 --- a/src/plugins/projectexplorer/projectconfiguration.cpp +++ b/src/plugins/projectexplorer/projectconfiguration.cpp @@ -154,7 +154,7 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map) return true; } -ProjectConfigurationAspect *ProjectConfiguration::extraAspect(Core::Id id) const +ProjectConfigurationAspect *ProjectConfiguration::aspect(Core::Id id) const { return Utils::findOrDefault(m_aspects, Utils::equal(&ProjectConfigurationAspect::id, id)); } diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h index 9e72ce0cb8d..492f19467c6 100644 --- a/src/plugins/projectexplorer/projectconfiguration.h +++ b/src/plugins/projectexplorer/projectconfiguration.h @@ -126,9 +126,9 @@ public: const QList aspects() const { return m_aspects; } - ProjectConfigurationAspect *extraAspect(Core::Id id) const; + ProjectConfigurationAspect *aspect(Core::Id id) const; - template T *extraAspect() const + template T *aspect() const { for (ProjectConfigurationAspect *aspect : m_aspects) if (T *result = qobject_cast(aspect)) diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 3b7b7d0533d..32dd8e460b5 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -193,7 +193,7 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id) }); expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"), [this](const QString &var) { - const auto envAspect = extraAspect(); + const auto envAspect = aspect(); return envAspect ? envAspect->environment().value(var) : QString(); }); expander->registerVariable(Constants::VAR_CURRENTRUN_NAME, @@ -376,14 +376,14 @@ bool RunConfiguration::fromMap(const QVariantMap &map) Runnable RunConfiguration::runnable() const { Runnable r; - if (auto aspect = extraAspect()) - r.executable = aspect->executable().toString(); - if (auto aspect = extraAspect()) - r.commandLineArguments = aspect->arguments(macroExpander()); - if (auto aspect = extraAspect()) - r.workingDirectory = aspect->workingDirectory(macroExpander()).toString(); - if (auto aspect = extraAspect()) - r.environment = aspect->environment(); + if (auto executableAspect = aspect()) + r.executable = executableAspect->executable().toString(); + if (auto argumentsAspect = aspect()) + r.commandLineArguments = argumentsAspect->arguments(macroExpander()); + if (auto workingDirectoryAspect = aspect()) + r.workingDirectory = workingDirectoryAspect->workingDirectory(macroExpander()).toString(); + if (auto environmentAspect = aspect()) + r.environment = environmentAspect->environment(); return r; } @@ -1556,7 +1556,7 @@ SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl) m_runnable = runControl->runnable(); // Default value. Can be overridden using setRunnable. m_device = runControl->device(); // Default value. Can be overridden using setDevice. if (auto runConfig = runControl->runConfiguration()) { - if (auto terminalAspect = runConfig->extraAspect()) + if (auto terminalAspect = runConfig->aspect()) m_useTerminal = terminalAspect->useTerminal(); } } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index ee4eb7ec613..9a973b42ebb 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -185,8 +185,8 @@ public: template T *currentSettings(Core::Id id) const { - if (auto aspect = qobject_cast(extraAspect(id))) - return qobject_cast(aspect->currentSettings()); + if (auto a = qobject_cast(aspect(id))) + return qobject_cast(a->currentSettings()); return nullptr; } diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index b17f1990a4c..5dd91d7067c 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -241,9 +241,9 @@ private: Runnable runnable() const final; bool supportsDebugger() const { return true; } - QString mainScript() const { return extraAspect()->value(); } - QString arguments() const { return extraAspect()->arguments(macroExpander()); } - QString interpreter() const { return extraAspect()->value(); } + QString mainScript() const { return aspect()->value(); } + QString arguments() const { return aspect()->arguments(macroExpander()); } + QString interpreter() const { return aspect()->value(); } void updateTargetInformation(); }; @@ -283,7 +283,7 @@ void PythonRunConfiguration::updateTargetInformation() const BuildTargetInfo bti = buildTargetInfo(); const QString script = bti.targetFilePath.toString(); setDefaultDisplayName(tr("Run %1").arg(script)); - extraAspect()->setValue(script); + aspect()->setValue(script); } Runnable PythonRunConfiguration::runnable() const @@ -291,9 +291,9 @@ Runnable PythonRunConfiguration::runnable() const Runnable r; QtcProcess::addArg(&r.commandLineArguments, mainScript()); QtcProcess::addArgs(&r.commandLineArguments, - extraAspect()->arguments(macroExpander())); - r.executable = extraAspect()->value(); - r.environment = extraAspect()->environment(); + aspect()->arguments(macroExpander())); + r.executable = aspect()->value(); + r.environment = aspect()->environment(); return r; } diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp index a28257d36fe..e48c7a2037a 100644 --- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp @@ -110,11 +110,11 @@ void QbsRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo & void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const { - if (auto dyldAspect = extraAspect()) { + if (auto dyldAspect = aspect()) { if (dyldAspect->value()) env.set("DYLD_IMAGE_SUFFIX", "_debug"); } - bool usingLibraryPaths = extraAspect()->value(); + bool usingLibraryPaths = aspect()->value(); const auto key = qMakePair(env.toStringList(), usingLibraryPaths); const auto it = m_envCache.constFind(key); @@ -146,16 +146,16 @@ void QbsRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = buildTargetInfo(); const FileName executable = executableToRun(bti); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); - extraAspect()->setExecutable(executable); + aspect()->setExecutable(executable); if (!executable.isEmpty()) { QString defaultWorkingDir = QFileInfo(executable.toString()).absolutePath(); if (!defaultWorkingDir.isEmpty()) { - auto wdAspect = extraAspect(); + auto wdAspect = aspect(); wdAspect->setDefaultWorkingDirectory(FileName::fromString(defaultWorkingDir)); } } diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp index b58807d5bf5..f25b77a65fc 100644 --- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp @@ -91,20 +91,20 @@ DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *target, Core: void DesktopQmakeRunConfiguration::updateTargetInformation() { setDefaultDisplayName(defaultDisplayName()); - extraAspect()->buildEnvironmentHasChanged(); + aspect()->buildEnvironmentHasChanged(); BuildTargetInfo bti = buildTargetInfo(); - auto wda = extraAspect(); + auto wda = aspect(); wda->setDefaultWorkingDirectory(bti.workingDirectory); if (wda->pathChooser()) wda->pathChooser()->setBaseFileName(target()->project()->projectDirectory()); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); - extraAspect()->setExecutable(bti.targetFilePath); + aspect()->setExecutable(bti.targetFilePath); } QVariantMap DesktopQmakeRunConfiguration::toMap() const @@ -135,9 +135,9 @@ void DesktopQmakeRunConfiguration::addToBaseEnvironment(Environment &env) const { BuildTargetInfo bti = buildTargetInfo(); if (bti.runEnvModifier) - bti.runEnvModifier(env, extraAspect()->value()); + bti.runEnvModifier(env, aspect()->value()); - if (auto dyldAspect = extraAspect()) { + if (auto dyldAspect = aspect()) { if (dyldAspect->value()) env.set(QLatin1String("DYLD_IMAGE_SUFFIX"), QLatin1String("_debug")); } diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index d42416a4a98..220d959d030 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -302,7 +302,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker) auto runConfiguration = runControl->runConfiguration(); if (runConfiguration) { auto aspect = static_cast( - runConfiguration->extraAspect(Constants::SETTINGS)); + runConfiguration->aspect(Constants::SETTINGS)); if (aspect) { if (QmlProfilerSettings *settings = static_cast(aspect->currentSettings())) { d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ? diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 8d99294c673..55e32ec508e 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -305,7 +305,7 @@ Runnable QmlProjectRunConfiguration::runnable() const Runnable r; r.executable = executable(); r.commandLineArguments = commandLineArguments(); - r.environment = extraAspect()->environment(); + r.environment = aspect()->environment(); r.workingDirectory = static_cast(project())->targetDirectory(target()).toString(); return r; } @@ -354,7 +354,7 @@ QString QmlProjectRunConfiguration::executable() const QString QmlProjectRunConfiguration::commandLineArguments() const { // arguments in .user file - QString args = extraAspect()->arguments(macroExpander()); + QString args = aspect()->arguments(macroExpander()); const Target *currentTarget = target(); const IDevice::ConstPtr device = DeviceKitInformation::device(currentTarget->kit()); const Utils::OsType osType = device ? device->osType() : Utils::HostOsInfo::hostOs(); diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index bb69ba46472..f53b27df368 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -265,7 +265,7 @@ void QnxAttachDebugSupport::showProcessesDialog() // QString projectSourceDirectory = dlg.projectSource(); QString localExecutable = dlg.localExecutable(); if (localExecutable.isEmpty()) { - if (auto aspect = runConfig->extraAspect()) + if (auto aspect = runConfig->aspect()) localExecutable = aspect->fileName().toString(); } diff --git a/src/plugins/qnx/qnxrunconfiguration.cpp b/src/plugins/qnx/qnxrunconfiguration.cpp index 73e619dbad4..f9aa3b93fc6 100644 --- a/src/plugins/qnx/qnxrunconfiguration.cpp +++ b/src/plugins/qnx/qnxrunconfiguration.cpp @@ -45,7 +45,7 @@ QnxRunConfiguration::QnxRunConfiguration(Target *target, Core::Id id) Runnable QnxRunConfiguration::runnable() const { Runnable r = RemoteLinuxRunConfiguration::runnable(); - QString libPath = extraAspect()->value(); + QString libPath = aspect()->value(); if (!libPath.isEmpty()) { r.environment.appendOrSet("LD_LIBRARY_PATH", libPath + "/lib:$LD_LIBRARY_PATH"); r.environment.appendOrSet("QML_IMPORT_PATH", libPath + "/imports:$QML_IMPORT_PATH"); diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp index e7648899a49..113d589a3c9 100644 --- a/src/plugins/qnx/slog2inforunner.cpp +++ b/src/plugins/qnx/slog2inforunner.cpp @@ -45,7 +45,7 @@ Slog2InfoRunner::Slog2InfoRunner(RunControl *runControl) : RunWorker(runControl) { setId("Slog2InfoRunner"); - m_applicationId = runControl->runConfiguration()->extraAspect()->executable().fileName(); + m_applicationId = runControl->runConfiguration()->aspect()->executable().fileName(); // See QTCREATORBUG-10712 for details. // We need to limit length of ApplicationId to 63 otherwise it would not match one in slog2info. diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp index 83f378ab8e2..b8ed968a9b9 100644 --- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp @@ -65,7 +65,7 @@ RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *tar bool RemoteLinuxCustomRunConfiguration::isConfigured() const { - return !extraAspect()->executable().isEmpty(); + return !aspect()->executable().isEmpty(); } RunConfiguration::ConfigurationState @@ -88,7 +88,7 @@ Core::Id RemoteLinuxCustomRunConfiguration::runConfigId() QString RemoteLinuxCustomRunConfiguration::runConfigDefaultDisplayName() { - QString remoteExecutable = extraAspect()->executable().toString(); + QString remoteExecutable = aspect()->executable().toString(); QString display = remoteExecutable.isEmpty() ? tr("Custom Executable") : tr("Run \"%1\"").arg(remoteExecutable); return RunConfigurationFactory::decoratedTargetName(display, target()); diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp index 7a799bf4298..6ef5f29a954 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp @@ -89,8 +89,8 @@ void RemoteLinuxRunConfiguration::updateTargetInformation() QString localExecutable = bti.targetFilePath.toString(); DeployableFile depFile = target()->deploymentData().deployableForLocalFile(localExecutable); - extraAspect()->setExecutable(FileName::fromString(depFile.remoteFilePath())); - extraAspect()->setValue(localExecutable); + aspect()->setExecutable(FileName::fromString(depFile.remoteFilePath())); + aspect()->setValue(localExecutable); emit enabledChanged(); } diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp index 6f2a6f75cef..15a882adf8f 100644 --- a/src/plugins/valgrind/valgrindengine.cpp +++ b/src/plugins/valgrind/valgrindengine.cpp @@ -86,7 +86,7 @@ void ValgrindToolRunner::start() m_runner.setDevice(device()); m_runner.setDebuggee(runnable()); - if (auto aspect = runControl()->runConfiguration()->extraAspect()) + if (auto aspect = runControl()->runConfiguration()->aspect()) m_runner.setUseTerminal(aspect->useTerminal()); connect(&m_runner, &ValgrindRunner::processOutputReceived, diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp index be9ddfa25fa..efd0e62506b 100644 --- a/src/plugins/winrt/winrtrunnerhelper.cpp +++ b/src/plugins/winrt/winrtrunnerhelper.cpp @@ -84,13 +84,13 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr bool loopbackExemptClient = false; bool loopbackExemptServer = false; - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) m_arguments = aspect->arguments(runConfiguration->macroExpander()); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) m_uninstallAfterStop = aspect->value(); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) loopbackExemptClient = aspect->value(); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) loopbackExemptServer = aspect->value(); if (loopbackExemptClient && loopbackExemptServer) m_loopbackArguments = "--loopbackexempt clientserver"; From 089b50f7d3570266a88c3902e58d4f371b12224d Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 2 Oct 2018 11:29:57 +0200 Subject: [PATCH 10/17] Debugger: Fix display of upper half of short unsigned ints Change-Id: Ie15c66c02c15420436b26c65af3cee9a19634e5c Fixes: QTCREATORBUG-21038 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index a2d97989eff..11c6b314f0e 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -2948,7 +2948,10 @@ class DumperBase: return self.detypedef().integer() elif self.type.code == TypeCodeBitfield: return self.lvalue - unsigned = self.type.name.startswith('unsigned') + # Could be something like 'short unsigned int' + unsigned = self.type.name == 'unsigned' \ + or self.type.name.startswith('unsigned ') \ + or self.type.name.find(' unsigned ') != -1 bitsize = self.type.bitsize() return self.extractInteger(bitsize, unsigned) From 931ec39f64a6cdb4a4e2301b7090e5f5b63c8eef Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Tue, 25 Sep 2018 16:19:41 +0200 Subject: [PATCH 11/17] Clang: Change the way completion fix-its are shown Move the completion information to the tooltip and show fix-it icon on the right of such item. Change-Id: I7eff410384104387e547695171e4864760c07fb9 Reviewed-by: Nikolai Kosjar --- src/libs/utils/textutils.cpp | 3 +- .../clangassistproposalitem.cpp | 89 ++++++++++++------- src/plugins/clangcodemodel/clangutils.cpp | 14 ++- src/plugins/clangcodemodel/clangutils.h | 3 +- .../codeassist/genericproposalwidget.cpp | 49 ++++++++++ 5 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp index 840325dd975..9b653bafa69 100644 --- a/src/libs/utils/textutils.cpp +++ b/src/libs/utils/textutils.cpp @@ -39,8 +39,9 @@ bool convertPosition(const QTextDocument *document, int pos, int *line, int *col (*column) = -1; return false; } else { + // line and column are both 1-based (*line) = block.blockNumber() + 1; - (*column) = pos - block.position(); + (*column) = pos - block.position() + 1; return true; } } diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp index 28e8401d8ff..6b4d0b81629 100644 --- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp @@ -27,6 +27,7 @@ #include "clangcompletionchunkstotextconverter.h" #include "clangfixitoperation.h" +#include "clangutils.h" #include #include @@ -34,10 +35,13 @@ #include #include +#include #include #include +#include #include +#include #include #include @@ -45,6 +49,7 @@ using namespace CPlusPlus; using namespace ClangBackEnd; +using namespace TextEditor; namespace ClangCodeModel { namespace Internal { @@ -73,7 +78,7 @@ bool ClangAssistProposalItem::implicitlyApplies() const return true; } -static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator, +static QString textUntilPreviousStatement(TextDocumentManipulatorInterface &manipulator, int startPosition) { static const QString stopCharacters(";{}#"); @@ -90,7 +95,7 @@ static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInt } // 7.3.3: using typename(opt) nested-name-specifier unqualified-id ; -static bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipulator, +static bool isAtUsingDeclaration(TextDocumentManipulatorInterface &manipulator, int basePosition) { SimpleLexer lexer; @@ -105,7 +110,7 @@ static bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &m if (lastToken.kind() != T_COLON_COLON) return false; - return Utils::contains(tokens, [](const Token &token) { + return ::Utils::contains(tokens, [](const Token &token) { return token.kind() == T_USING; }); } @@ -135,17 +140,17 @@ static QString methodDefinitionParameters(const CodeCompletionChunks &chunks) return result; } -void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator, +void ClangAssistProposalItem::apply(TextDocumentManipulatorInterface &manipulator, int basePosition) const { const CodeCompletion ccr = firstCodeCompletion(); if (!ccr.requiredFixIts.empty()) { + // Important: Calculate shift before changing the document. + basePosition += fixItsShift(manipulator); + ClangFixItOperation fixItOperation(Utf8String(), ccr.requiredFixIts); fixItOperation.perform(); - - const int shift = fixItsShift(manipulator); - basePosition += shift; } QString textToBeInserted = m_text; @@ -175,8 +180,8 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface textToBeInserted = converter.text(); } else if (!ccr.text.isEmpty()) { - const TextEditor::CompletionSettings &completionSettings = - TextEditor::TextEditorSettings::instance()->completionSettings(); + const CompletionSettings &completionSettings = + TextEditorSettings::instance()->completionSettings(); const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; if (autoInsertBrackets && @@ -193,9 +198,9 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface QTextCursor cursor = manipulator.textCursorAt(basePosition); bool abandonParen = false; - if (Utils::Text::matchPreviousWord(manipulator, cursor, "&")) { - Utils::Text::moveToPrevChar(manipulator, cursor); - Utils::Text::moveToPrevChar(manipulator, cursor); + if (::Utils::Text::matchPreviousWord(manipulator, cursor, "&")) { + ::Utils::Text::moveToPrevChar(manipulator, cursor); + ::Utils::Text::moveToPrevChar(manipulator, cursor); const QChar prevChar = manipulator.characterAt(cursor.position()); cursor.setPosition(basePosition); abandonParen = QString("(;,{}").contains(prevChar); @@ -206,7 +211,7 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) { const CodeCompletionChunk resultType = ccr.chunks.first(); QTC_ASSERT(resultType.kind == CodeCompletionChunk::ResultType, return;); - if (Utils::Text::matchPreviousWord(manipulator, cursor, resultType.text.toString())) { + if (::Utils::Text::matchPreviousWord(manipulator, cursor, resultType.text.toString())) { extraCharacters += methodDefinitionParameters(ccr.chunks); // To skip the next block. abandonParen = true; @@ -306,7 +311,7 @@ void ClangAssistProposalItem::setText(const QString &text) QString ClangAssistProposalItem::text() const { - return m_text + (requiresFixIts() ? fixItText() : QString()); + return m_text; } const QVector &ClangAssistProposalItem::firstCompletionFixIts() const @@ -314,39 +319,53 @@ const QVector &ClangAssistProposalItem::firstCompl return firstCodeCompletion().requiredFixIts; } -// FIXME: Indicate required fix-it without adding extra text. +std::pair fixItPositionsRange(const FixItContainer &fixIt, const QTextCursor &cursor) +{ + const QTextBlock startLine = cursor.document()->findBlockByNumber(fixIt.range.start.line - 1); + const QTextBlock endLine = cursor.document()->findBlockByNumber(fixIt.range.end.line - 1); + + const int fixItStartPos = ::Utils::Text::positionInText( + cursor.document(), + static_cast(fixIt.range.start.line), + Utils::cppEditorColumn(startLine, static_cast(fixIt.range.start.column))); + const int fixItEndPos = ::Utils::Text::positionInText( + cursor.document(), + static_cast(fixIt.range.end.line), + Utils::cppEditorColumn(endLine, static_cast(fixIt.range.end.column))); + return std::make_pair(fixItStartPos, fixItEndPos); +} + +static QString textReplacedByFixit(const FixItContainer &fixIt) +{ + TextEditorWidget *textEditorWidget = TextEditorWidget::currentTextEditorWidget(); + if (!textEditorWidget) + return QString(); + const std::pair fixItPosRange = fixItPositionsRange(fixIt, + textEditorWidget->textCursor()); + return textEditorWidget->textAt(fixItPosRange.first, + fixItPosRange.second - fixItPosRange.first); +} + QString ClangAssistProposalItem::fixItText() const { const FixItContainer &fixIt = firstCompletionFixIts().first(); - const SourceRangeContainer &range = fixIt.range; return QCoreApplication::translate("ClangCodeModel::ClangAssistProposalItem", - " (requires to correct [%1:%2-%3:%4] to \"%5\")") - .arg(range.start.line) - .arg(range.start.column) - .arg(range.end.line) - .arg(range.end.column) + "Requires to correct \"%1\" to \"%2\"") + .arg(textReplacedByFixit(fixIt)) .arg(fixIt.text.toString()); } -int ClangAssistProposalItem::fixItsShift( - const TextEditor::TextDocumentManipulatorInterface &manipulator) const +int ClangAssistProposalItem::fixItsShift(const TextDocumentManipulatorInterface &manipulator) const { const QVector &requiredFixIts = firstCompletionFixIts(); if (requiredFixIts.empty()) return 0; int shift = 0; - QTextCursor cursor = manipulator.textCursorAt(0); + const QTextCursor cursor = manipulator.textCursorAt(0); for (const FixItContainer &fixIt : requiredFixIts) { - const int fixItStartPos = Utils::Text::positionInText( - cursor.document(), - static_cast(fixIt.range.start.line), - static_cast(fixIt.range.start.column)); - const int fixItEndPos = Utils::Text::positionInText( - cursor.document(), - static_cast(fixIt.range.end.line), - static_cast(fixIt.range.end.column)); - shift += fixIt.text.toString().length() - (fixItEndPos - fixItStartPos); + const std::pair fixItPosRange = fixItPositionsRange(fixIt, cursor); + shift += fixIt.text.toString().length() - (fixItPosRange.second - fixItPosRange.first); } return shift; } @@ -425,10 +444,14 @@ QString ClangAssistProposalItem::detail() const detail += "
"; detail += CompletionChunksToTextConverter::convertToToolTipWithHtml( codeCompletion.chunks, codeCompletion.completionKind); + if (!codeCompletion.briefComment.isEmpty()) detail += "
" + codeCompletion.briefComment.toString(); } + if (requiresFixIts()) + detail += "

" + fixItText() + ""; + return detail; } diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 2d74d7f4ef1..971c0551749 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -155,8 +155,18 @@ int clangColumn(const QTextBlock &line, int cppEditorColumn) // (2) The return value is the column in Clang which is the utf8 byte offset from the beginning // of the line. // Here we convert column from (1) to (2). - // '+ 1' is for 1-based columns - return line.text().left(cppEditorColumn).toUtf8().size() + 1; + // '- 1' and '+ 1' are because of 1-based columns + return line.text().left(cppEditorColumn - 1).toUtf8().size() + 1; +} + +int cppEditorColumn(const QTextBlock &line, int clangColumn) +{ + // (1) clangColumn is the column in Clang which is the utf8 byte offset from the beginning + // of the line. + // (2) The return value is the actual column shown by CppEditor. + // Here we convert column from (1) to (2). + // '- 1' and '+ 1' are because of 1-based columns + return QString::fromUtf8(line.text().toUtf8().left(clangColumn - 1)).size() + 1; } ::Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token) diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 883dfcdf29e..956f1dee4aa 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -57,7 +57,8 @@ CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath); CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath); bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); QString projectPartIdForFile(const QString &filePath); -int clangColumn(const QTextBlock &lineText, int cppEditorColumn); +int clangColumn(const QTextBlock &line, int cppEditorColumn); +int cppEditorColumn(const QTextBlock &line, int clangColumn); QString diagnosticCategoryPrefixRemoved(const QString &text); diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 8f5d7291482..079b7b2db1d 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -31,9 +31,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -49,6 +51,7 @@ #include #include #include +#include using namespace Utils; @@ -92,6 +95,8 @@ QVariant ModelAdapter::data(const QModelIndex &index, int role) const return m_completionModel->icon(index.row()); else if (role == Qt::WhatsThisRole) return m_completionModel->detail(index.row()); + else if (role == Qt::UserRole) + return m_completionModel->proposalItem(index.row())->requiresFixIts(); return QVariant(); } @@ -146,6 +151,7 @@ private: // ----------------------- class GenericProposalListView : public QListView { + friend class ProposalItemDelegate; public: GenericProposalListView(QWidget *parent); @@ -160,10 +166,53 @@ public: void selectLastRow() { selectRow(model()->rowCount() - 1); } }; +class ProposalItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit ProposalItemDelegate(GenericProposalListView *parent = nullptr) + : QStyledItemDelegate(parent) + , m_parent(parent) + { + } + + void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + static const QIcon fixItIcon = ::Utils::Icons::CODEMODEL_FIXIT.icon(); + + QStyledItemDelegate::paint(painter, option, index); + + if (m_parent->model()->data(index, Qt::UserRole).toBool()) { + const QRect itemRect = m_parent->rectForIndex(index); + const QScrollBar *verticalScrollBar = m_parent->verticalScrollBar(); + + const int x = m_parent->width() - itemRect.height() - (verticalScrollBar->isVisible() + ? verticalScrollBar->width() + : 0); + const int iconSize = itemRect.height() - 5; + fixItIcon.paint(painter, QRect(x, itemRect.y() - m_parent->verticalOffset(), + iconSize, iconSize)); + } + } + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override + { + QSize size(QStyledItemDelegate::sizeHint(option, index)); + if (m_parent->model()->data(index, Qt::UserRole).toBool()) + size.setWidth(size.width() + m_parent->rectForIndex(index).height() - 5); + return size; + } +private: + GenericProposalListView *m_parent; +}; + GenericProposalListView::GenericProposalListView(QWidget *parent) : QListView(parent) { setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + setItemDelegate(new ProposalItemDelegate(this)); } QSize GenericProposalListView::calculateSize() const From efc39304a1a18b815c968a4fee6c6d4b2651aac2 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 27 Sep 2018 15:50:12 +0200 Subject: [PATCH 12/17] Clang: Move the majority of completion items sorting to ClangBackend With this change ClangCodeModel only needs to sort completions by prefix. Also some other optimization have become possible and are implemented here: 1. Getting completions after '{' for constructor overloads by replacing it with '(' inside usaved file. 2. Checking for all overloads requires only previous item check because all Class completions are already sorted to go before all CXXConstructor completions. Since they are not mixed no extra search is required. Change-Id: Ie0187ad96a20857a63c1d71ddec74606b803f572 Reviewed-by: Nikolai Kosjar --- .../cplusplus/examples/tidy_example.cpp | 2 + .../clangassistproposalmodel.cpp | 6 +- .../clangcompletionassistprocessor.cpp | 104 ++++++------------ .../clangbackend/source/codecompleter.cpp | 51 ++++++--- .../source/codecompletionsextractor.cpp | 72 +++++++++++- .../source/codecompletionsextractor.h | 4 +- tests/unit/unittest/codecompleter-test.cpp | 99 +++++++++++++++-- .../codecompletionsextractor-test.cpp | 12 ++ .../unittest/data/complete_smartpointer.cpp | 7 +- .../unit/unittest/data/completions_order.cpp | 9 ++ 10 files changed, 262 insertions(+), 104 deletions(-) create mode 100644 tests/unit/unittest/data/completions_order.cpp diff --git a/share/qtcreator/cplusplus/examples/tidy_example.cpp b/share/qtcreator/cplusplus/examples/tidy_example.cpp index dc921114ea1..2b41a1e83b0 100644 --- a/share/qtcreator/cplusplus/examples/tidy_example.cpp +++ b/share/qtcreator/cplusplus/examples/tidy_example.cpp @@ -203,6 +203,8 @@ public: virtual bool check(bool enable = true); }; +bool Derived2:: + // performance-unnecessary-value-param void use(Base b) { diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp index 148ebb0ad48..6e535fb04a7 100644 --- a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp @@ -56,11 +56,7 @@ void ClangAssistProposalModel::sort(const QString &/*prefix*/) return static_cast(first->prefixMatch()) < static_cast(second->prefixMatch()); } - if (first->requiresFixIts() != second->requiresFixIts()) - return first->requiresFixIts() < second->requiresFixIts(); - return (first->order() > 0 - && (first->order() < second->order() - || (first->order() == second->order() && first->text() < second->text()))); + return false; }; // Keep the order for the items with the same priority and name. diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 843778e4bbe..e87135351db 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -51,8 +51,9 @@ #include #include -#include #include +#include +#include #include #include @@ -76,20 +77,18 @@ static void addAssistProposalItem(QList &items, item->appendCodeCompletion(codeCompletion); } +// Add the next CXXMethod or CXXConstructor which is the overload for another existing item. static void addFunctionOverloadAssistProposalItem(QList &items, AssistProposalItemInterface *sameItem, const ClangCompletionAssistInterface *interface, const CodeCompletion &codeCompletion, const QString &name) { - ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first(); auto *item = static_cast(sameItem); item->setHasOverloadsWithParameters(true); - if (resultType.kind != ClangBackEnd::CodeCompletionChunk::ResultType) { - // It's the constructor. + if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind) { + // It's the constructor, currently constructor definitions do not lead here. // CLANG-UPGRADE-CHECK: Can we get here with constructor definition? - if (!item->firstCodeCompletion().hasParameters) - item->removeFirstCodeCompletion(); item->appendCodeCompletion(codeCompletion); return; } @@ -98,15 +97,27 @@ static void addFunctionOverloadAssistProposalItem(QListposition()); cursor.movePosition(QTextCursor::StartOfWord); + const ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first(); if (::Utils::Text::matchPreviousWord(*interface->textEditorWidget(), cursor, resultType.text.toString())) { + // Function definition completion - do not merge completions together. addAssistProposalItem(items, codeCompletion, name); } else { item->appendCodeCompletion(codeCompletion); } } +// Check if they are both CXXMethod or CXXConstructor. +static bool isTheSameFunctionOverload(const CodeCompletion &completion, + const QString &name, + ClangAssistProposalItem *lastItem) +{ + return completion.hasParameters + && completion.completionKind == lastItem->firstCodeCompletion().completionKind + && lastItem->text() == name; +} + static QList toAssistProposalItems( const CodeCompletions &completions, const ClangCompletionAssistInterface *interface) @@ -117,8 +128,9 @@ static QList toAssistProposalItems( QList items; items.reserve(completions.size()); for (const CodeCompletion &codeCompletion : completions) { - if (codeCompletion.text.isEmpty()) // TODO: Make isValid()? - continue; + if (codeCompletion.text.isEmpty()) + continue; // It's an OverloadCandidate which has text but no typedText. + if (signalCompletion && codeCompletion.completionKind != CodeCompletion::SignalCompletionKind) continue; if (slotCompletion && codeCompletion.completionKind != CodeCompletion::SlotCompletionKind) @@ -128,34 +140,16 @@ static QList toAssistProposalItems( ? CompletionChunksToTextConverter::convertToName(codeCompletion.chunks) : codeCompletion.text.toString(); - if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind - || codeCompletion.completionKind == CodeCompletion::ClassCompletionKind) { - auto samePreviousConstructor - = std::find_if(items.begin(), - items.end(), - [&](const AssistProposalItemInterface *item) { - return item->text() == name - && static_cast(item)->firstCodeCompletion() - .completionKind == codeCompletion.completionKind; - }); - if (samePreviousConstructor == items.end()) { - addAssistProposalItem(items, codeCompletion, name); - } else if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind){ - addFunctionOverloadAssistProposalItem(items, *samePreviousConstructor, interface, - codeCompletion, name); - } - continue; - } - - if (!items.empty() && items.last()->text() == name) { - if ((codeCompletion.completionKind == CodeCompletion::FunctionCompletionKind - || codeCompletion.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) - && codeCompletion.hasParameters) { + if (items.empty()) { + addAssistProposalItem(items, codeCompletion, name); + } else { + auto *lastItem = static_cast(items.last()); + if (isTheSameFunctionOverload(codeCompletion, name, lastItem)) { addFunctionOverloadAssistProposalItem(items, items.back(), interface, codeCompletion, name); + } else { + addAssistProposalItem(items, codeCompletion, name); } - } else { - addAssistProposalItem(items, codeCompletion, name); } } @@ -187,48 +181,14 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface * return startCompletionHelper(); // == 0 if results are calculated asynchronously } -static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions) -{ - return ::Utils::filtered(completions, [](const CodeCompletion &completion) { - return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind; - }); -} - -static CodeCompletions filterConstructorSignatures(Utf8String textBefore, - const CodeCompletions &completions) -{ - const int prevStatementEnd = textBefore.lastIndexOf(";"); - if (prevStatementEnd != -1) - textBefore = textBefore.mid(prevStatementEnd + 1); - - return ::Utils::filtered(completions, [&textBefore](const CodeCompletion &completion) { - if (completion.completionKind != CodeCompletion::ConstructorCompletionKind) - return false; - const Utf8String type = completion.chunks.at(0).text; - return textBefore.indexOf(type) != -1; - }); -} - -void ClangCompletionAssistProcessor::handleAvailableCompletions( - const CodeCompletions &completions) +void ClangCompletionAssistProcessor::handleAvailableCompletions(const CodeCompletions &completions) { QTC_CHECK(m_completions.isEmpty()); - if (m_sentRequestType == FunctionHintCompletion){ - CodeCompletions functionSignatures; - if (m_completionOperator == T_LPAREN) { - functionSignatures = filterFunctionSignatures(completions); - } else { - const QTextBlock block = m_interface->textDocument()->findBlock( - m_interface->position()); - const QString textBefore = block.text().left( - m_interface->position() - block.position()); - - functionSignatures = filterConstructorSignatures(textBefore, completions); - } - - if (!functionSignatures.isEmpty()) { - setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures)); + if (m_sentRequestType == FunctionHintCompletion) { + const CodeCompletion &firstCompletion = completions.front(); + if (firstCompletion.completionKind == CodeCompletion::FunctionOverloadCompletionKind) { + setAsyncProposalAvailable(createFunctionHintProposal(completions)); return; } // else: Proceed with a normal completion in case: diff --git a/src/tools/clangbackend/source/codecompleter.cpp b/src/tools/clangbackend/source/codecompleter.cpp index 7a11ff02d8e..5520b5b3a9d 100644 --- a/src/tools/clangbackend/source/codecompleter.cpp +++ b/src/tools/clangbackend/source/codecompleter.cpp @@ -40,6 +40,8 @@ #include "unsavedfile.h" #include "unsavedfiles.h" +#include + #include namespace ClangBackEnd { @@ -47,13 +49,14 @@ namespace ClangBackEnd { namespace { CodeCompletions toCodeCompletions(const TranslationUnit &translationUnit, - const ClangCodeCompleteResults &results) + const ClangCodeCompleteResults &results, + bool onlyFunctionOverloads) { if (results.isNull()) return CodeCompletions(); CodeCompletionsExtractor extractor(translationUnit.cxTranslationUnit(), results.data()); - CodeCompletions codeCompletions = extractor.extractAll(); + CodeCompletions codeCompletions = extractor.extractAll(onlyFunctionOverloads); return codeCompletions; } @@ -83,33 +86,49 @@ CodeCompleter::CodeCompleter(const TranslationUnit &translationUnit, { } +static void replaceWithOpeningParen(UnsavedFile &file, uint line, uint column) +{ + bool ok; + const uint pos = file.toUtf8Position(line, column, &ok); + QTC_ASSERT(ok, return;); + file.replaceAt(pos, 1, Utf8String("(", 1)); +} + CodeCompletions CodeCompleter::complete(uint line, uint column, int funcNameStartLine, int funcNameStartColumn) { + if (funcNameStartLine >= 0) { + UnsavedFile &file = unsavedFiles.unsavedFile(translationUnit.filePath()); + // Replace '{' by '(' to get proper FunctionOverloadCompletionKind for constructor. + if (file.hasCharacterAt(line, column - 1, '{')) + replaceWithOpeningParen(file, line, column - 1); + } + // Check if we have a smart pointer completion and get proper constructor signatures in results. // Results are empty when it's not a smart pointer or this completion failed. - ClangCodeCompleteResults results = completeSmartPointerCreation(line, - column, - funcNameStartLine, - funcNameStartColumn); + ClangCodeCompleteResults clangCompletions = completeSmartPointerCreation(line, + column, + funcNameStartLine, + funcNameStartColumn); - if (results.isNull() || results.isEmpty()) - results = completeHelper(line, column); + // Default completion. + if (clangCompletions.isNull() || clangCompletions.isEmpty()) + clangCompletions = completeHelper(line, column); - filterUnknownContextResults(results, unsavedFile(), line, column); + filterUnknownContextResults(clangCompletions, unsavedFile(), line, column); - return toCodeCompletions(translationUnit, results); + return toCodeCompletions(translationUnit, clangCompletions, funcNameStartLine >= 0); } // For given "make_unique" / "make_shared" / "QSharedPointer::create" return "new T(" // Otherwize return empty QString -static QString tweakName(const QString &oldName) +static QString tweakName(const Utf8String &oldName) { - QString fullName = oldName.trimmed(); - if (!fullName.contains('>')) + if (!oldName.contains('>')) return QString(); + QString fullName = QString(oldName).trimmed(); if (!fullName.endsWith('>')) { // This is the class::method case - remove ::method part if (!fullName.endsWith("create") || !fullName.contains("QSharedPointer")) @@ -138,10 +157,12 @@ ClangCodeCompleteResults CodeCompleter::completeSmartPointerCreation(uint line, bool ok; const uint startPos = file.toUtf8Position(funcNameStartLine, funcNameStartColumn, &ok); + QTC_ASSERT(ok, return ClangCodeCompleteResults();); const uint endPos = file.toUtf8Position(line, column - 1, &ok); + QTC_ASSERT(ok, return ClangCodeCompleteResults();); - Utf8String content = file.fileContent(); - const QString oldName = content.mid(startPos, endPos - startPos); + const Utf8String content = file.fileContent(); + const Utf8String oldName = content.mid(startPos, endPos - startPos); const QString updatedName = tweakName(oldName); if (updatedName.isEmpty()) return ClangCodeCompleteResults(); diff --git a/src/tools/clangbackend/source/codecompletionsextractor.cpp b/src/tools/clangbackend/source/codecompletionsextractor.cpp index bd961dc4aa5..25be6bddcf3 100644 --- a/src/tools/clangbackend/source/codecompletionsextractor.cpp +++ b/src/tools/clangbackend/source/codecompletionsextractor.cpp @@ -27,9 +27,13 @@ #include "clangbackend_global.h" #include "clangstring.h" +#include "clangtranslationunit.h" #include "codecompletionchunkconverter.h" +#include "sourcelocation.h" #include "sourcerange.h" +#include + #include namespace ClangBackEnd { @@ -85,7 +89,7 @@ bool CodeCompletionsExtractor::peek(const Utf8String &name) return false; } -CodeCompletions CodeCompletionsExtractor::extractAll() +CodeCompletions CodeCompletionsExtractor::extractAll(bool onlyFunctionOverloads) { CodeCompletions codeCompletions; codeCompletions.reserve(int(cxCodeCompleteResults->NumResults)); @@ -93,9 +97,75 @@ CodeCompletions CodeCompletionsExtractor::extractAll() while (next()) codeCompletions.append(currentCodeCompletion_); + handleCompletions(codeCompletions, onlyFunctionOverloads); + return codeCompletions; } +static CodeCompletions filterFunctionOverloads(const CodeCompletions &completions) +{ + return ::Utils::filtered(completions, [](const CodeCompletion &completion) { + return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind; + }); +} + +static ::Utils::optional classBeforeCXXConstructor(const CodeCompletion &first, + const CodeCompletion &second) +{ + // Put ClassCompletionKind elements before ConstructorCompletionKind elements + // when they have the same name. + if (first.completionKind == CodeCompletion::ClassCompletionKind + && second.completionKind == CodeCompletion::ConstructorCompletionKind + && first.text == second.text) { + return true; + } + + if (first.completionKind == CodeCompletion::ConstructorCompletionKind + && second.completionKind == CodeCompletion::ClassCompletionKind + && first.text == second.text) { + return false; + } + + return ::Utils::optional(); +} + +static void sortCodeCompletions(CodeCompletions &codeCompletions) +{ + auto currentItemsCompare = [](const CodeCompletion &first, + const CodeCompletion &second) { + // Items without fix-its come first. + if (first.requiredFixIts.empty() != second.requiredFixIts.empty()) + return first.requiredFixIts.empty() > second.requiredFixIts.empty(); + + const ::Utils::optional classBeforeConstructorWithTheSameName + = classBeforeCXXConstructor(first, second); + if (classBeforeConstructorWithTheSameName) + return classBeforeConstructorWithTheSameName.value(); + + return (first.priority > 0 + && (first.priority < second.priority + || (first.priority == second.priority && first.text < second.text))); + }; + + // Keep the order for the items with the same priority and name. + std::stable_sort(codeCompletions.begin(), codeCompletions.end(), currentItemsCompare); +} + +void CodeCompletionsExtractor::handleCompletions(CodeCompletions &codeCompletions, + bool onlyFunctionOverloads) +{ + if (onlyFunctionOverloads) { + const CodeCompletions overloadCompletions = filterFunctionOverloads(codeCompletions); + + // If filtered completions are empty the assumption we need function overloads is wrong + // therefore we do not use filtered results in that case. + if (!overloadCompletions.isEmpty()) + codeCompletions = overloadCompletions; + } + + sortCodeCompletions(codeCompletions); +} + void CodeCompletionsExtractor::extractCompletionKind() { switch (currentCxCodeCompleteResult.CursorKind) { diff --git a/src/tools/clangbackend/source/codecompletionsextractor.h b/src/tools/clangbackend/source/codecompletionsextractor.h index 1c5f963c14b..928dabd25d3 100644 --- a/src/tools/clangbackend/source/codecompletionsextractor.h +++ b/src/tools/clangbackend/source/codecompletionsextractor.h @@ -50,7 +50,7 @@ public: bool next(); bool peek(const Utf8String &name); - CodeCompletions extractAll(); + CodeCompletions extractAll(bool onlyFunctionOverloads); const CodeCompletion ¤tCodeCompletion() const; @@ -73,6 +73,8 @@ private: void decreasePriorityForQObjectInternals(); void decreasePriorityForOperators(); + void handleCompletions(CodeCompletions &codeCompletions, bool onlyFunctionOverloads); + bool hasText(const Utf8String &text, CXCompletionString cxCompletionString) const; private: diff --git a/tests/unit/unittest/codecompleter-test.cpp b/tests/unit/unittest/codecompleter-test.cpp index 0a20849bb8f..f72a9eb8281 100644 --- a/tests/unit/unittest/codecompleter-test.cpp +++ b/tests/unit/unittest/codecompleter-test.cpp @@ -43,6 +43,7 @@ using ::testing::Not; using ::testing::PrintToString; using ClangBackEnd::CodeCompletion; +using ClangBackEnd::CodeCompletionChunk; using ClangBackEnd::CodeCompleter; namespace { @@ -65,6 +66,29 @@ MATCHER_P2(IsCodeCompletion, text, completionKind, return true; } +MATCHER_P(IsOverloadCompletion, text, + std::string(negation ? "isn't" : "is") + " overload completion with text " + PrintToString(text)) +{ + Utf8String overloadName; + for (auto &chunk : arg.chunks) { + if (chunk.kind == CodeCompletionChunk::Text) { + overloadName = chunk.text; + break; + } + } + if (overloadName != text) { + *result_listener << "text is " + PrintToString(overloadName) + " and not " + PrintToString(text); + return false; + } + + if (arg.completionKind != CodeCompletion::FunctionOverloadCompletionKind) { + *result_listener << "kind is " + PrintToString(arg.completionKind) + " and not " + PrintToString(CodeCompletion::FunctionOverloadCompletionKind); + return false; + } + + return true; +} + MATCHER(HasFixIts, "") { return !arg.requiredFixIts.empty(); @@ -195,6 +219,12 @@ protected: readFileContent("/complete_smartpointer.cpp"), true }; + ClangBackEnd::FileContainer completionsOrder{ + Utf8StringLiteral(TESTDATA_DIR"/completions_order.cpp"), + {includePathArgument}, + readFileContent("/completions_order.cpp"), + true + }; }; using CodeCompleterSlowTest = CodeCompleter; @@ -306,27 +336,24 @@ TEST_F(CodeCompleterSlowTest, UniquePointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(55, 54, 55, 32), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(59, 54, 59, 32), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, SharedPointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(56, 55, 56, 33), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(60, 55, 60, 33), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, QSharedPointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(57, 60, 57, 32), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(61, 60, 61, 32), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, FunctionInUnsavedIncludedHeader) @@ -499,6 +526,60 @@ TEST_F(CodeCompleterSlowTest, GlobalCompletionAfterForwardDeclaredClassPointer) ASSERT_TRUE(!completions.isEmpty()); } +TEST_F(CodeCompleterSlowTest, ConstructorCompletionExists) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(constructorIndex != -1, true); +} + +TEST_F(CodeCompleterSlowTest, ClassConstructorCompletionsOrder) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int classIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ClassCompletionKind; + }); + int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(classIndex < constructorIndex, true); +} + +TEST_F(CodeCompleterSlowTest, SharedPointerCompletionsOrder) +{ + auto myCompleter = setupCompleter(smartPointerCompletion); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(62, 11); + + int resetIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "reset"; + }); + int barDestructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "~Bar"; + }); + + ASSERT_THAT(barDestructorIndex < resetIndex, true); +} + +TEST_F(CodeCompleterSlowTest, ConstructorHasOverloadCompletions) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int constructorsCount = Utils::count(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(constructorsCount, 2); +} + ClangBackEnd::CodeCompleter CodeCompleter::setupCompleter( const ClangBackEnd::FileContainer &fileContainer) { diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp index 3f4ca8f0df3..b7c44f2cca0 100644 --- a/tests/unit/unittest/codecompletionsextractor-test.cpp +++ b/tests/unit/unittest/codecompletionsextractor-test.cpp @@ -794,6 +794,18 @@ TEST_F(CodeCompletionsExtractorSlowTest, OverloadCandidate) }))); } +TEST_F(CodeCompletionsExtractorSlowTest, ExtractAll) +{ + ClangCodeCompleteResults completeResults(getResults(constructorDocument, 25)); + ::CodeCompletionsExtractor extractor( + constructorDocument.translationUnit().cxTranslationUnit(), + completeResults.data()); + + auto codeCompletions = extractor.extractAll(false); + + ASSERT_THAT(codeCompletions.empty(), false); +} + ClangCodeCompleteResults CodeCompletionsExtractor::getResults(const Document &document, uint line, uint column, diff --git a/tests/unit/unittest/data/complete_smartpointer.cpp b/tests/unit/unittest/data/complete_smartpointer.cpp index 1a9bbaf9788..a6e7d73a58a 100644 --- a/tests/unit/unittest/data/complete_smartpointer.cpp +++ b/tests/unit/unittest/data/complete_smartpointer.cpp @@ -27,7 +27,11 @@ template class unique_ptr {}; template -class shared_ptr {}; +class shared_ptr { +public: + void reset(); + Type *operator->(); +}; template unique_ptr make_unique(Args&&... args); @@ -55,4 +59,5 @@ void f2() std::unique_ptr bar = std::make_unique(); std::shared_ptr bar2 = std::make_shared(); QSharedPointer bar3 = QSharedPointer::create(); + bar2-> } diff --git a/tests/unit/unittest/data/completions_order.cpp b/tests/unit/unittest/data/completions_order.cpp new file mode 100644 index 00000000000..6ede7573d85 --- /dev/null +++ b/tests/unit/unittest/data/completions_order.cpp @@ -0,0 +1,9 @@ +class Constructor { +public: + Constructor() = default; + Constructor(int) {} +}; + +void testConstructor() { + +} From 07766595032f9d53539a6fe947ff10516742fe13 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 1 Oct 2018 17:54:12 +0200 Subject: [PATCH 13/17] Kit config widget: Prevent horizontal scrollbar ...by using Utils::ElidingLabel rather than a plain QLabel in QbsKitInformation. Change-Id: I4014ee918f0ea712a2975ffb4638c495fd8e0c71 Fixes: QTCREATORBUG-21102 Reviewed-by: hjk --- src/plugins/qbsprojectmanager/qbskitinformation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbskitinformation.cpp b/src/plugins/qbsprojectmanager/qbskitinformation.cpp index 6d78c09d090..95242e5e37a 100644 --- a/src/plugins/qbsprojectmanager/qbskitinformation.cpp +++ b/src/plugins/qbsprojectmanager/qbskitinformation.cpp @@ -30,11 +30,11 @@ #include #include +#include #include #include -#include #include using namespace ProjectExplorer; @@ -48,7 +48,7 @@ class ConfigWidget final : public KitConfigWidget public: ConfigWidget(Kit *kit, const KitInformation *kitInfo) : KitConfigWidget(kit, kitInfo), - m_contentLabel(new QLabel), + m_contentLabel(new Utils::ElidingLabel), m_changeButton(new QPushButton(tr("Change..."))) { connect(m_changeButton, &QPushButton::clicked, this, &ConfigWidget::changeProperties); From 7a7898e2c928f0b3c52a97deea9dbd65b11ad516 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 2 Oct 2018 10:04:36 +0200 Subject: [PATCH 14/17] Reduce priority of "Convert to Camel Case" refactoring Otherwise this is too annoying in case the function is called the way it should be. Fixes: QTCREATORBUG-8114 Change-Id: I51063a11e7979e24fc9020344aa5ff800b5064a9 Reviewed-by: Nikolai Kosjar --- src/plugins/cppeditor/cppquickfixes.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index c5004b80242..b0442e0a2a9 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -1682,9 +1682,8 @@ namespace { class ConvertToCamelCaseOp: public CppQuickFixOperation { public: - ConvertToCamelCaseOp(const CppQuickFixInterface &interface, int priority, - const QString &newName) - : CppQuickFixOperation(interface, priority) + ConvertToCamelCaseOp(const CppQuickFixInterface &interface, const QString &newName) + : CppQuickFixOperation(interface, -1) , m_name(newName) { setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Camel Case")); @@ -1744,7 +1743,7 @@ void ConvertToCamelCase::match(const CppQuickFixInterface &interface, QuickFixOp return; for (int i = 1; i < newName.length() - 1; ++i) { if (ConvertToCamelCaseOp::isConvertibleUnderscore(newName, i)) { - result << new ConvertToCamelCaseOp(interface, path.size() - 1, newName); + result << new ConvertToCamelCaseOp(interface, newName); return; } } From 049291504d493ee8126f7da723068c3d3c9c298e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 2 Oct 2018 13:02:08 +0200 Subject: [PATCH 15/17] Fix function extraction for nested classes If the function is added to a class inside a class, these must be prepended before the inner class name. Fixes: QTCREATORBUG-7271 Change-Id: I07042cdd4927af3b630c6ab1b5587971754e1199 Reviewed-by: Nikolai Kosjar --- src/plugins/cppeditor/cppquickfixes.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index b0442e0a2a9..afc777be1a8 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -3302,9 +3302,17 @@ public: // Write class qualification, if any. if (matchingClass) { - const Name *name = rewriteName(matchingClass->name(), &env, control); - funcDef.append(printer.prettyName(name)); - funcDef.append(QLatin1String("::")); + Class *current = matchingClass; + QVector classes{matchingClass->name()}; + while (current->enclosingScope()->asClass()) { + current = current->enclosingScope()->asClass(); + classes.prepend(current->name()); + } + for (const Name *n : classes) { + const Name *name = rewriteName(n, &env, control); + funcDef.append(printer.prettyName(name)); + funcDef.append(QLatin1String("::")); + } } // Write the extracted function itself and its call. From 30bd144540dfe29e655ccf9ae63504794da99ab4 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 2 Oct 2018 15:27:02 +0200 Subject: [PATCH 16/17] RemoteLinux: Add target information to runconfig name Was there until 4.6. Change-Id: I044e9a184a3f495f967bfa6712f1cd5cbe5603d5 Reviewed-by: Christian Kandeler --- .../remotelinux/remotelinuxrunconfiguration.cpp | 11 +---------- src/plugins/remotelinux/remotelinuxrunconfiguration.h | 3 --- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp index 6ef5f29a954..cbd02d72fd6 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp @@ -73,16 +73,6 @@ RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Core::I this, &RemoteLinuxRunConfiguration::updateTargetInformation); } -void RemoteLinuxRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo &) -{ - setDefaultDisplayName(defaultDisplayName()); -} - -QString RemoteLinuxRunConfiguration::defaultDisplayName() const -{ - return RunConfigurationFactory::decoratedTargetName(buildKey(), target()); -} - void RemoteLinuxRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = buildTargetInfo(); @@ -103,6 +93,7 @@ const char *RemoteLinuxRunConfiguration::IdPrefix = "RemoteLinuxRunConfiguration RemoteLinuxRunConfigurationFactory::RemoteLinuxRunConfigurationFactory() { registerRunConfiguration(RemoteLinuxRunConfiguration::IdPrefix); + setDecorateDisplayNames(true); addSupportedTargetDeviceType(RemoteLinux::Constants::GenericLinuxOsType); } diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.h b/src/plugins/remotelinux/remotelinuxrunconfiguration.h index c3d263dcb71..839da13ae5d 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.h +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.h @@ -40,9 +40,6 @@ public: static const char *IdPrefix; private: - void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &) override; - - QString defaultDisplayName() const; void updateTargetInformation(); }; From e79d68dab6876d34fdbee071175913a90272ab31 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Sat, 22 Sep 2018 23:01:39 +0200 Subject: [PATCH 17/17] Git: Improve local file detection in GitRemote * Make sure url has a proper size before accessing its elements * Also check for valid drive letter before ':' Change-Id: I958cbd492caa8a6ad4a5bf424277d8287f8cf0d4 Reviewed-by: Orgad Shaneh --- src/plugins/git/gitclient.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index fe370f45235..dbbb45a16a4 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -3385,8 +3385,14 @@ GitRemote::GitRemote(const QString &url) // Check for local remotes (refer to the root or relative path) // On Windows, local paths typically starts with : + auto startsWithWindowsDrive = [](const QString &url) { + if (!HostOsInfo::isWindowsHost() || url.size() < 2) + return false; + const QChar drive = url.at(0).toLower(); + return drive >= 'a' && drive <= 'z' && url.at(1) == ':'; + }; if (url.startsWith("file://") || url.startsWith('/') || url.startsWith('.') - || (HostOsInfo::isWindowsHost() && url[1] == ':')) { + || startsWithWindowsDrive(url)) { protocol = "file"; path = QDir::fromNativeSeparators(url.startsWith("file://") ? url.mid(7) : url); isValid = QDir(path).exists() || QDir(path + ".git").exists();