summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cpptoolsplugin.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2021-08-30 10:58:08 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2021-09-01 14:53:58 +0000
commit284817fae6514701902ccdb834c2faa46462f2e8 (patch)
tree44a8c7d9813dc110b61c4639036366c7696bd7e9 /src/plugins/cpptools/cpptoolsplugin.cpp
parent3e1fa0f170d523971d2c3c12da15a6e291f56511 (diff)
downloadqt-creator-284817fae6514701902ccdb834c2faa46462f2e8.tar.gz
Merge CppTools into CppEditor
There was no proper separation of responsibilities between these plugins. In particular, CppTools had lots of editor-related functionality, so it's not clear why it was separated out in the first place. In fact, for a lot of code, it seemed quite arbitrary where it was put (just one example: switchHeaderSource() was in CppTools, wheras switchDeclarationDefinition() was in CppEditor). Merging the plugins will enable us to get rid of various convoluted pseudo-abstractions that were only introduced to keep up the artificial separation. Change-Id: Iafc3bce625b4794f6d4aa03df6cddc7f2d26716a Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/cpptools/cpptoolsplugin.cpp')
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp533
1 files changed, 0 insertions, 533 deletions
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
deleted file mode 100644
index 7418f946fe..0000000000
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cpptoolsplugin.h"
-
-#include "cppcodemodelsettingspage.h"
-#include "cppcodestylesettingspage.h"
-#include "cppfilesettingspage.h"
-#include "cppmodelmanager.h"
-#include "cppprojectfile.h"
-#include "cppprojectupdater.h"
-#include "cpptoolsbridge.h"
-#include "cpptoolsbridgeqtcreatorimplementation.h"
-#include "cpptoolsconstants.h"
-#include "cpptoolsreuse.h"
-#include "cpptoolssettings.h"
-#include "projectinfo.h"
-#include "stringtable.h"
-
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/documentmanager.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/idocument.h>
-#include <coreplugin/vcsmanager.h>
-#include <cppeditor/cppeditorconstants.h>
-#include <extensionsystem/pluginmanager.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectpanelfactory.h>
-#include <projectexplorer/projecttree.h>
-
-#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-#include <utils/hostosinfo.h>
-#include <utils/macroexpander.h>
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/qtcassert.h>
-
-#ifdef WITH_TESTS
-#include "compileroptionsbuilder_test.h"
-#include "cppcodegen_test.h"
-#include "cppcompletion_test.h"
-#include "cppheadersource_test.h"
-#include "cpplocalsymbols_test.h"
-#include "cpplocatorfilter_test.h"
-#include "cppmodelmanager_test.h"
-#include "cpppointerdeclarationformatter_test.h"
-#include "cppsourceprocessor_test.h"
-#include "functionutils.h"
-#include "includeutils.h"
-#include "projectinfo_test.h"
-#include "senddocumenttracker.h"
-#include "symbolsearcher_test.h"
-#include "typehierarchybuilder_test.h"
-#endif
-
-#include <QFileInfo>
-#include <QDir>
-#include <QDebug>
-#include <QMenu>
-#include <QAction>
-
-using namespace Core;
-using namespace CPlusPlus;
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace CppTools {
-namespace Internal {
-
-enum { debug = 0 };
-
-static CppToolsPlugin *m_instance = nullptr;
-static QHash<QString, QString> m_headerSourceMapping;
-
-class CppToolsPluginPrivate
-{
-public:
- CppToolsPluginPrivate() {}
-
- void initialize() { m_codeModelSettings.fromSettings(ICore::settings()); }
-
- ~CppToolsPluginPrivate()
- {
- ExtensionSystem::PluginManager::removeObject(&m_cppProjectUpdaterFactory);
- delete m_clangdSettingsPage;
- }
-
- StringTable stringTable;
- CppModelManager modelManager;
- CppCodeModelSettings m_codeModelSettings;
- CppToolsSettings settings;
- CppFileSettings m_fileSettings;
- CppFileSettingsPage m_cppFileSettingsPage{&m_fileSettings};
- CppCodeModelSettingsPage m_cppCodeModelSettingsPage{&m_codeModelSettings};
- ClangdSettingsPage *m_clangdSettingsPage = nullptr;
- CppCodeStyleSettingsPage m_cppCodeStyleSettingsPage;
- CppProjectUpdaterFactory m_cppProjectUpdaterFactory;
-};
-
-CppToolsPlugin::CppToolsPlugin()
-{
- m_instance = this;
- CppToolsBridge::setCppToolsBridgeImplementation(std::make_unique<CppToolsBridgeQtCreatorImplementation>());
-}
-
-CppToolsPlugin::~CppToolsPlugin()
-{
- delete d;
- d = nullptr;
- m_instance = nullptr;
-}
-
-CppToolsPlugin *CppToolsPlugin::instance()
-{
- return m_instance;
-}
-
-void CppToolsPlugin::clearHeaderSourceCache()
-{
- m_headerSourceMapping.clear();
-}
-
-FilePath CppToolsPlugin::licenseTemplatePath()
-{
- return FilePath::fromString(m_instance->d->m_fileSettings.licenseTemplatePath);
-}
-
-QString CppToolsPlugin::licenseTemplate()
-{
- return CppFileSettings::licenseTemplate();
-}
-
-bool CppToolsPlugin::usePragmaOnce()
-{
- return m_instance->d->m_fileSettings.headerPragmaOnce;
-}
-
-const QStringList &CppToolsPlugin::headerSearchPaths()
-{
- return m_instance->d->m_fileSettings.headerSearchPaths;
-}
-
-const QStringList &CppToolsPlugin::sourceSearchPaths()
-{
- return m_instance->d->m_fileSettings.sourceSearchPaths;
-}
-
-const QStringList &CppToolsPlugin::headerPrefixes()
-{
- return m_instance->d->m_fileSettings.headerPrefixes;
-}
-
-const QStringList &CppToolsPlugin::sourcePrefixes()
-{
- return m_instance->d->m_fileSettings.sourcePrefixes;
-}
-
-bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
-{
- Q_UNUSED(arguments)
- Q_UNUSED(error)
-
- d = new CppToolsPluginPrivate;
- d->initialize();
-
- CppModelManager::instance()->registerJsExtension();
- ExtensionSystem::PluginManager::addObject(&d->m_cppProjectUpdaterFactory);
-
- // Menus
- ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
- ActionContainer *mcpptools = ActionManager::createMenu(CppTools::Constants::M_TOOLS_CPP);
- QMenu *menu = mcpptools->menu();
- menu->setTitle(tr("&C++"));
- menu->setEnabled(true);
- mtools->addMenu(mcpptools);
-
- // Actions
- Context context(CppEditor::Constants::CPPEDITOR_ID);
-
- QAction *switchAction = new QAction(tr("Switch Header/Source"), this);
- Command *command = ActionManager::registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context, true);
- command->setDefaultKeySequence(QKeySequence(Qt::Key_F4));
- mcpptools->addAction(command);
- connect(switchAction, &QAction::triggered,
- this, &CppToolsPlugin::switchHeaderSource);
-
- QAction *openInNextSplitAction = new QAction(tr("Open Corresponding Header/Source in Next Split"), this);
- command = ActionManager::registerAction(openInNextSplitAction, Constants::OPEN_HEADER_SOURCE_IN_NEXT_SPLIT, context, true);
- command->setDefaultKeySequence(QKeySequence(HostOsInfo::isMacHost()
- ? tr("Meta+E, F4")
- : tr("Ctrl+E, F4")));
- mcpptools->addAction(command);
- connect(openInNextSplitAction, &QAction::triggered,
- this, &CppToolsPlugin::switchHeaderSourceInNextSplit);
-
- MacroExpander *expander = globalMacroExpander();
- expander->registerVariable("Cpp:LicenseTemplate",
- tr("The license template."),
- []() { return CppToolsPlugin::licenseTemplate(); });
- expander->registerFileVariables("Cpp:LicenseTemplatePath",
- tr("The configured path to the license template"),
- []() { return CppToolsPlugin::licenseTemplatePath(); });
-
- expander->registerVariable(
- "Cpp:PragmaOnce",
- tr("Insert \"#pragma once\" instead of \"#ifndef\" include guards into header file"),
- [] { return usePragmaOnce() ? QString("true") : QString(); });
-
- const auto panelFactory = new ProjectPanelFactory;
- panelFactory->setPriority(100);
- panelFactory->setDisplayName(tr("Clangd"));
- panelFactory->setCreateWidgetFunction([](Project *project) {
- return new ClangdProjectSettingsWidget(project);
- });
- ProjectPanelFactory::registerFactory(panelFactory);
-
- return true;
-}
-
-void CppToolsPlugin::extensionsInitialized()
-{
- // The Cpp editor plugin, which is loaded later on, registers the Cpp mime types,
- // so, apply settings here
- d->m_fileSettings.fromSettings(ICore::settings());
- if (!d->m_fileSettings.applySuffixesToMimeDB())
- qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
- if (CppModelManager::instance()->isClangCodeModelActive())
- d->m_clangdSettingsPage = new ClangdSettingsPage;
-}
-
-QVector<QObject *> CppToolsPlugin::createTestObjects() const
-{
- return {
-#ifdef WITH_TESTS
- new CodegenTest,
- new CompilerOptionsBuilderTest,
- new CompletionTest,
- new FunctionUtilsTest,
- new HeaderPathFilterTest,
- new HeaderSourceTest,
- new IncludeGroupsTest,
- new LocalSymbolsTest,
- new LocatorFilterTest,
- new ModelManagerTest,
- new PointerDeclarationFormatterTest,
- new ProjectFileCategorizerTest,
- new ProjectInfoGeneratorTest,
- new ProjectPartChooserTest,
- new DocumentTrackerTest,
- new SourceProcessorTest,
- new SymbolSearcherTest,
- new TypeHierarchyBuilderTest,
-#endif
- };
-}
-
-CppCodeModelSettings *CppToolsPlugin::codeModelSettings()
-{
- return &d->m_codeModelSettings;
-}
-
-CppFileSettings *CppToolsPlugin::fileSettings()
-{
- return &instance()->d->m_fileSettings;
-}
-
-void CppToolsPlugin::switchHeaderSource()
-{
- CppTools::switchHeaderSource();
-}
-
-void CppToolsPlugin::switchHeaderSourceInNextSplit()
-{
- QString otherFile = correspondingHeaderOrSource(
- EditorManager::currentDocument()->filePath().toString());
- if (!otherFile.isEmpty())
- EditorManager::openEditor(otherFile, Id(), EditorManager::OpenInOtherSplit);
-}
-
-static QStringList findFilesInProject(const QString &name, const Project *project)
-{
- if (debug)
- qDebug() << Q_FUNC_INFO << name << project;
-
- if (!project)
- return QStringList();
-
- QString pattern = QString(1, QLatin1Char('/'));
- pattern += name;
- const QStringList projectFiles
- = transform(project->files(Project::AllFiles), &FilePath::toString);
- const QStringList::const_iterator pcend = projectFiles.constEnd();
- QStringList candidateList;
- for (QStringList::const_iterator it = projectFiles.constBegin(); it != pcend; ++it) {
- if (it->endsWith(pattern, HostOsInfo::fileNameCaseSensitivity()))
- candidateList.append(*it);
- }
- return candidateList;
-}
-
-// Return the suffixes that should be checked when trying to find a
-// source belonging to a header and vice versa
-static QStringList matchingCandidateSuffixes(ProjectFile::Kind kind)
-{
- switch (kind) {
- case ProjectFile::AmbiguousHeader:
- case ProjectFile::CHeader:
- case ProjectFile::CXXHeader:
- case ProjectFile::ObjCHeader:
- case ProjectFile::ObjCXXHeader:
- return mimeTypeForName(Constants::C_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(Constants::CPP_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(Constants::OBJECTIVE_C_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(Constants::CUDA_SOURCE_MIMETYPE).suffixes();
- case ProjectFile::CSource:
- case ProjectFile::ObjCSource:
- return mimeTypeForName(Constants::C_HEADER_MIMETYPE).suffixes();
- case ProjectFile::CXXSource:
- case ProjectFile::ObjCXXSource:
- case ProjectFile::CudaSource:
- case ProjectFile::OpenCLSource:
- return mimeTypeForName(Constants::CPP_HEADER_MIMETYPE).suffixes();
- default:
- return QStringList();
- }
-}
-
-static QStringList baseNameWithAllSuffixes(const QString &baseName, const QStringList &suffixes)
-{
- QStringList result;
- const QChar dot = QLatin1Char('.');
- for (const QString &suffix : suffixes) {
- QString fileName = baseName;
- fileName += dot;
- fileName += suffix;
- result += fileName;
- }
- return result;
-}
-
-static QStringList baseNamesWithAllPrefixes(const QStringList &baseNames, bool isHeader)
-{
- QStringList result;
- const QStringList &sourcePrefixes = m_instance->sourcePrefixes();
- const QStringList &headerPrefixes = m_instance->headerPrefixes();
-
- for (const QString &name : baseNames) {
- for (const QString &prefix : isHeader ? headerPrefixes : sourcePrefixes) {
- if (name.startsWith(prefix)) {
- QString nameWithoutPrefix = name.mid(prefix.size());
- result += nameWithoutPrefix;
- for (const QString &prefix : isHeader ? sourcePrefixes : headerPrefixes)
- result += prefix + nameWithoutPrefix;
- }
- }
- for (const QString &prefix : isHeader ? sourcePrefixes : headerPrefixes)
- result += prefix + name;
-
- }
- return result;
-}
-
-static QStringList baseDirWithAllDirectories(const QDir &baseDir, const QStringList &directories)
-{
- QStringList result;
- for (const QString &dir : directories)
- result << QDir::cleanPath(baseDir.absoluteFilePath(dir));
- return result;
-}
-
-static int commonFilePathLength(const QString &s1, const QString &s2)
-{
- int length = qMin(s1.length(), s2.length());
- for (int i = 0; i < length; ++i)
- if (HostOsInfo::fileNameCaseSensitivity() == Qt::CaseSensitive) {
- if (s1[i] != s2[i])
- return i;
- } else {
- if (s1[i].toLower() != s2[i].toLower())
- return i;
- }
- return length;
-}
-
-static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
- const QStringList &candidateFileNames,
- const Project *project,
- CacheUsage cacheUsage)
-{
- QString bestFileName;
- int compareValue = 0;
- const QString filePath = fileInfo.filePath();
- for (const QString &candidateFileName : candidateFileNames) {
- const QStringList projectFiles = findFilesInProject(candidateFileName, project);
- // Find the file having the most common path with fileName
- for (const QString &projectFile : projectFiles) {
- int value = commonFilePathLength(filePath, projectFile);
- if (value > compareValue) {
- compareValue = value;
- bestFileName = projectFile;
- }
- }
- }
- if (!bestFileName.isEmpty()) {
- const QFileInfo candidateFi(bestFileName);
- QTC_ASSERT(candidateFi.isFile(), return QString());
- if (cacheUsage == CacheUsage::ReadWrite) {
- m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
- m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
- }
- return candidateFi.absoluteFilePath();
- }
-
- return QString();
-}
-
-} // namespace Internal
-
-QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, CacheUsage cacheUsage)
-{
- using namespace Internal;
-
- const QFileInfo fi(fileName);
- ProjectFile::Kind kind = ProjectFile::classify(fileName);
- const bool isHeader = ProjectFile::isHeader(kind);
- if (wasHeader)
- *wasHeader = isHeader;
- if (m_headerSourceMapping.contains(fi.absoluteFilePath()))
- return m_headerSourceMapping.value(fi.absoluteFilePath());
-
- if (debug)
- qDebug() << Q_FUNC_INFO << fileName << kind;
-
- if (kind == ProjectFile::Unsupported)
- return QString();
-
- const QString baseName = fi.completeBaseName();
- const QString privateHeaderSuffix = QLatin1String("_p");
- const QStringList suffixes = matchingCandidateSuffixes(kind);
-
- QStringList candidateFileNames = baseNameWithAllSuffixes(baseName, suffixes);
- if (isHeader) {
- if (baseName.endsWith(privateHeaderSuffix)) {
- QString sourceBaseName = baseName;
- sourceBaseName.truncate(sourceBaseName.size() - privateHeaderSuffix.size());
- candidateFileNames += baseNameWithAllSuffixes(sourceBaseName, suffixes);
- }
- } else {
- QString privateHeaderBaseName = baseName;
- privateHeaderBaseName.append(privateHeaderSuffix);
- candidateFileNames += baseNameWithAllSuffixes(privateHeaderBaseName, suffixes);
- }
-
- const QDir absoluteDir = fi.absoluteDir();
- QStringList candidateDirs(absoluteDir.absolutePath());
- // If directory is not root, try matching against its siblings
- const QStringList searchPaths = isHeader ? m_instance->sourceSearchPaths()
- : m_instance->headerSearchPaths();
- candidateDirs += baseDirWithAllDirectories(absoluteDir, searchPaths);
-
- candidateFileNames += baseNamesWithAllPrefixes(candidateFileNames, isHeader);
-
- // Try to find a file in the same or sibling directories first
- for (const QString &candidateDir : qAsConst(candidateDirs)) {
- for (const QString &candidateFileName : qAsConst(candidateFileNames)) {
- const QString candidateFilePath = candidateDir + QLatin1Char('/') + candidateFileName;
- const QString normalized = FileUtils::normalizedPathName(candidateFilePath);
- const QFileInfo candidateFi(normalized);
- if (candidateFi.isFile()) {
- if (cacheUsage == CacheUsage::ReadWrite) {
- m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
- if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
- m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
- }
- return candidateFi.absoluteFilePath();
- }
- }
- }
-
- // Find files in the current project
- Project *currentProject = ProjectTree::currentProject();
- if (currentProject) {
- const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
- currentProject, cacheUsage);
- if (!path.isEmpty())
- return path;
-
- // Find files in other projects
- } else {
- CppModelManager *modelManager = CppModelManager::instance();
- const QList<ProjectInfo::ConstPtr> projectInfos = modelManager->projectInfos();
- for (const ProjectInfo::ConstPtr &projectInfo : projectInfos) {
- const Project *project = projectForProjectInfo(*projectInfo);
- if (project == currentProject)
- continue; // We have already checked the current project.
-
- const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
- project, cacheUsage);
- if (!path.isEmpty())
- return path;
- }
- }
-
- return QString();
-}
-
-} // namespace CppTools