diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 7833472559f..71e32c33beb 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -52,15 +52,16 @@ #include "followsymbolinterface.h" #include -#include -#include -#include #include -#include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include @@ -511,6 +512,10 @@ CppModelManager::CppModelManager() : CppModelManagerBase(nullptr) , d(new CppModelManagerPrivate) { + // Used for weak dependency in VcsBaseSubmitEditor + setObjectName("CppModelManager"); + ExtensionSystem::PluginManager::addObject(this); + d->m_indexingSupporter = nullptr; d->m_enableGC = true; @@ -561,6 +566,8 @@ CppModelManager::CppModelManager() CppModelManager::~CppModelManager() { + ExtensionSystem::PluginManager::removeObject(this); + delete d->m_internalIndexingSupport; delete d; } @@ -1305,6 +1312,60 @@ void CppModelManager::renameIncludes(const QString &oldFileName, const QString & } } +// Return the class name which function belongs to +static const char *belongingClassName(const Function *function) +{ + if (!function) + return nullptr; + + if (auto funcName = function->name()) { + if (auto qualifiedNameId = funcName->asQualifiedNameId()) { + if (const Name *funcBaseName = qualifiedNameId->base()) { + if (auto identifier = funcBaseName->identifier()) + return identifier->chars(); + } + } + } + + return nullptr; +} + +QSet CppModelManager::symbolsInFiles(const QSet &files) const +{ + QSet uniqueSymbols; + const Snapshot cppSnapShot = snapshot(); + + // Iterate over the files and get interesting symbols + for (const Utils::FilePath &file : files) { + // Add symbols from the C++ code model + const CPlusPlus::Document::Ptr doc = cppSnapShot.document(file); + if (!doc.isNull() && doc->control()) { + const CPlusPlus::Control *ctrl = doc->control(); + CPlusPlus::Symbol **symPtr = ctrl->firstSymbol(); // Read-only + while (symPtr != ctrl->lastSymbol()) { + const CPlusPlus::Symbol *sym = *symPtr; + + const CPlusPlus::Identifier *symId = sym->identifier(); + // Add any class, function or namespace identifiers + if ((sym->isClass() || sym->isFunction() || sym->isNamespace()) && symId + && symId->chars()) { + uniqueSymbols.insert(QString::fromUtf8(symId->chars())); + } + + // Handle specific case : get "Foo" in "void Foo::function() {}" + if (sym->isFunction() && !sym->asFunction()->isDeclaration()) { + const char *className = belongingClassName(sym->asFunction()); + if (className) + uniqueSymbols.insert(QString::fromUtf8(className)); + } + + ++symPtr; + } + } + } + return uniqueSymbols; +} + void CppModelManager::onCoreAboutToClose() { Core::ProgressManager::cancelTasks(CppTools::Constants::TASK_INDEX); diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 9deaa2e3927..8567de9c304 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -230,6 +230,9 @@ public: void renameIncludes(const QString &oldFileName, const QString &newFileName); + // for VcsBaseSubmitEditor + Q_INVOKABLE QSet symbolsInFiles(const QSet &files) const; + signals: /// Project data might be locked while this is emitted. void aboutToRemoveFiles(const QStringList &files); diff --git a/src/plugins/vcsbase/CMakeLists.txt b/src/plugins/vcsbase/CMakeLists.txt index b6d234b4f24..1cffe26be04 100644 --- a/src/plugins/vcsbase/CMakeLists.txt +++ b/src/plugins/vcsbase/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_plugin(VcsBase - PLUGIN_DEPENDS Core CppTools DiffEditor ProjectExplorer TextEditor - PLUGIN_RECOMMENDS CodePaster + PLUGIN_DEPENDS Core DiffEditor ProjectExplorer TextEditor + PLUGIN_RECOMMENDS CodePaster CppTools SOURCES baseannotationhighlighter.cpp baseannotationhighlighter.h basevcseditorfactory.cpp basevcseditorfactory.h diff --git a/src/plugins/vcsbase/vcsbase.qbs b/src/plugins/vcsbase/vcsbase.qbs index 036c99adce0..df5686db5ca 100644 --- a/src/plugins/vcsbase/vcsbase.qbs +++ b/src/plugins/vcsbase/vcsbase.qbs @@ -11,11 +11,11 @@ QtcPlugin { Depends { name: "Core" } Depends { name: "TextEditor" } Depends { name: "ProjectExplorer" } - Depends { name: "CppTools" } Depends { name: "DiffEditor" } pluginRecommends: [ - "CodePaster" + "CodePaster", + "CppTools" ] files: [ diff --git a/src/plugins/vcsbase/vcsbase_dependencies.pri b/src/plugins/vcsbase/vcsbase_dependencies.pri index f398e2926be..2606ce19c8f 100644 --- a/src/plugins/vcsbase/vcsbase_dependencies.pri +++ b/src/plugins/vcsbase/vcsbase_dependencies.pri @@ -8,7 +8,7 @@ QTC_PLUGIN_DEPENDS += \ coreplugin \ texteditor \ projectexplorer \ - cpptools \ diffeditor QTC_PLUGIN_RECOMMENDS += \ - cpaster + cpaster \ + cpptools diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 3d07ced719d..3c60cbd474b 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -36,12 +36,14 @@ #include "vcsplugin.h" #include -#include #include #include #include +#include +#include + #include #include #include @@ -78,30 +80,9 @@ enum { debug = 0 }; enum { wantToolBar = 0 }; // Return true if word is meaningful and can be added to a completion model -static bool acceptsWordForCompletion(const char *word) +static bool acceptsWordForCompletion(const QString &word) { - if (!word) - return false; - static const std::size_t minWordLength = 7; - return std::strlen(word) >= minWordLength; -} - -// Return the class name which function belongs to -static const char *belongingClassName(const CPlusPlus::Function *function) -{ - if (!function) - return nullptr; - - if (auto funcName = function->name()) { - if (auto qualifiedNameId = funcName->asQualifiedNameId()) { - if (const CPlusPlus::Name *funcBaseName = qualifiedNameId->base()) { - if (auto identifier = funcBaseName->identifier()) - return identifier->chars(); - } - } - } - - return nullptr; + return word.size() >= 7; } /*! @@ -407,6 +388,17 @@ QStringList VcsBaseSubmitEditor::checkedFiles() const return d->m_widget->checkedFiles(); } +static QSet filesFromModel(SubmitFileModel *model) +{ + QSet result; + result.reserve(model->rowCount()); + for (int row = 0; row < model->rowCount(); ++row) { + result.insert(FilePath::fromString( + QFileInfo(model->repositoryRoot(), model->file(row)).absoluteFilePath())); + } + return result; +} + void VcsBaseSubmitEditor::setFileModel(SubmitFileModel *model) { QTC_ASSERT(model, return); @@ -421,49 +413,21 @@ void VcsBaseSubmitEditor::setFileModel(SubmitFileModel *model) if (!selected.isEmpty()) d->m_widget->setSelectedRows(selected); - QSet uniqueSymbols; - const CPlusPlus::Snapshot cppSnapShot = CppTools::CppModelManager::instance()->snapshot(); - - // Iterate over the files and get interesting symbols - for (int row = 0; row < model->rowCount(); ++row) { - const QFileInfo fileInfo(model->repositoryRoot(), model->file(row)); - - // Add file name - uniqueSymbols.insert(fileInfo.fileName()); - - const QString filePath = fileInfo.absoluteFilePath(); - // Add symbols from the C++ code model - const CPlusPlus::Document::Ptr doc = cppSnapShot.document(filePath); - if (!doc.isNull() && doc->control()) { - const CPlusPlus::Control *ctrl = doc->control(); - CPlusPlus::Symbol **symPtr = ctrl->firstSymbol(); // Read-only - while (symPtr != ctrl->lastSymbol()) { - const CPlusPlus::Symbol *sym = *symPtr; - - const CPlusPlus::Identifier *symId = sym->identifier(); - // Add any class, function or namespace identifiers - if ((sym->isClass() || sym->isFunction() || sym->isNamespace()) - && (symId && acceptsWordForCompletion(symId->chars()))) - { - uniqueSymbols.insert(QString::fromUtf8(symId->chars())); - } - - // Handle specific case : get "Foo" in "void Foo::function() {}" - if (sym->isFunction() && !sym->asFunction()->isDeclaration()) { - const char *className = belongingClassName(sym->asFunction()); - if (acceptsWordForCompletion(className)) - uniqueSymbols.insert(QString::fromUtf8(className)); - } - - ++symPtr; - } - } + const QSet files = filesFromModel(model); + // add file names to completion + QSet completionItems = Utils::transform(files, &FilePath::fileName); + QObject *cppModelManager = ExtensionSystem::PluginManager::getObjectByName("CppModelManager"); + if (cppModelManager) { + const auto symbols = ExtensionSystem::invoke>(cppModelManager, + "symbolsInFiles", + files); + completionItems += Utils::filtered(symbols, acceptsWordForCompletion); } // Populate completer with symbols - if (!uniqueSymbols.isEmpty()) { + if (!completionItems.isEmpty()) { QCompleter *completer = d->m_widget->descriptionEdit()->completer(); - QStringList symbolsList = Utils::toList(uniqueSymbols); + QStringList symbolsList = Utils::toList(completionItems); symbolsList.sort(); completer->setModel(new QStringListModel(symbolsList, completer)); }