aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2024-01-25 17:08:14 +0100
committerhjk <hjk@qt.io>2024-01-26 12:44:53 +0000
commit7f061c723a7e96b988d7b9b56dea727c4ca6fd7b (patch)
tree94ae07dea8618623a7e7c80a14d691dcc6010b5c
parente71d16ef90ebf5983ac657aae42d52991de923e7 (diff)
CppEditor: Move CppHeaderSource implementation and test to same files
... and remove the now-empty cppeditorplugin.h Change-Id: Ia28b180c280ba7b10ce0f2826f2ac69d128a453c Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--src/plugins/cppeditor/CMakeLists.txt4
-rw-r--r--src/plugins/cppeditor/builtineditordocumentprocessor.cpp1
-rw-r--r--src/plugins/cppeditor/cppautocompleter.cpp1
-rw-r--r--src/plugins/cppeditor/cppeditor.qbs5
-rw-r--r--src/plugins/cppeditor/cppeditordocument.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp252
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.cpp1
-rw-r--r--src/plugins/cppeditor/cppfilesettingspage.cpp2
-rw-r--r--src/plugins/cppeditor/cppheadersource.cpp368
-rw-r--r--src/plugins/cppeditor/cppheadersource.h (renamed from src/plugins/cppeditor/cppeditorplugin.h)8
-rw-r--r--src/plugins/cppeditor/cppheadersource_test.cpp95
-rw-r--r--src/plugins/cppeditor/cppheadersource_test.h22
-rw-r--r--src/plugins/cppeditor/cppinsertvirtualmethods.cpp1
-rw-r--r--src/plugins/cppeditor/cpplocatorfilter.cpp1
-rw-r--r--src/plugins/cppeditor/cppquickfix_test.cpp1
-rw-r--r--src/plugins/cppeditor/cpptoolsjsextension.cpp1
-rw-r--r--src/plugins/cppeditor/fileandtokenactions_test.cpp3
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp3
-rw-r--r--src/plugins/designer/qtcreatorintegration.cpp1
19 files changed, 384 insertions, 388 deletions
diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt
index c64817cfb0..ec5ad89cea 100644
--- a/src/plugins/cppeditor/CMakeLists.txt
+++ b/src/plugins/cppeditor/CMakeLists.txt
@@ -40,7 +40,7 @@ add_qtc_plugin(CppEditor
cppeditorconstants.h
cppeditordocument.cpp cppeditordocument.h
cppeditoroutline.cpp cppeditoroutline.h
- cppeditorplugin.cpp cppeditorplugin.h
+ cppeditorplugin.cpp
cppeditorwidget.cpp cppeditorwidget.h
cppelementevaluator.cpp cppelementevaluator.h
cppfileiterationorder.cpp cppfileiterationorder.h
@@ -49,6 +49,7 @@ add_qtc_plugin(CppEditor
cppfollowsymbolundercursor.cpp cppfollowsymbolundercursor.h
cppfunctiondecldeflink.cpp cppfunctiondecldeflink.h
cppfunctionparamrenaminghandler.cpp cppfunctionparamrenaminghandler.h
+ cppheadersource.cpp cppheadersource.h
cpphighlighter.cpp cpphighlighter.h
cppincludehierarchy.cpp cppincludehierarchy.h
cppincludesfilter.cpp cppincludesfilter.h
@@ -121,7 +122,6 @@ extend_qtc_plugin(CppEditor
cppcodegen_test.cpp cppcodegen_test.h
cppcompletion_test.cpp cppcompletion_test.h
cppdoxygen_test.cpp cppdoxygen_test.h
- cppheadersource_test.cpp cppheadersource_test.h
cppincludehierarchy_test.cpp cppincludehierarchy_test.h
cpplocalsymbols_test.cpp cpplocalsymbols_test.h
cpplocatorfilter_test.cpp cpplocatorfilter_test.h
diff --git a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
index 9c7535ee74..4d43546334 100644
--- a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
+++ b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp
@@ -7,7 +7,6 @@
#include "cppchecksymbols.h"
#include "cppcodemodelsettings.h"
#include "cppeditordocument.h"
-#include "cppeditorplugin.h"
#include "cppmodelmanager.h"
#include "cpptoolsreuse.h"
#include "cppworkingcopy.h"
diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp
index dcd2cebacd..0710131862 100644
--- a/src/plugins/cppeditor/cppautocompleter.cpp
+++ b/src/plugins/cppeditor/cppautocompleter.cpp
@@ -13,7 +13,6 @@
#ifdef WITH_TESTS
#include "cppeditorconstants.h"
-#include "cppeditorplugin.h"
#include "cppeditorwidget.h"
#include <coreplugin/editormanager/editormanager.h>
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 2e8581a50c..b684b0e0ea 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -95,7 +95,6 @@ QtcPlugin {
"cppeditoroutline.cpp",
"cppeditoroutline.h",
"cppeditorplugin.cpp",
- "cppeditorplugin.h",
"cppelementevaluator.cpp",
"cppelementevaluator.h",
"cppfileiterationorder.cpp",
@@ -110,6 +109,8 @@ QtcPlugin {
"cppfunctiondecldeflink.h",
"cppfunctionparamrenaminghandler.cpp",
"cppfunctionparamrenaminghandler.h",
+ "cppheadersource.cpp",
+ "cppheadersource.h",
"cpphighlighter.cpp",
"cpphighlighter.h",
"cppincludehierarchy.cpp",
@@ -252,8 +253,6 @@ QtcPlugin {
"cppcompletion_test.h",
"cppdoxygen_test.cpp",
"cppdoxygen_test.h",
- "cppheadersource_test.cpp",
- "cppheadersource_test.h",
"cppincludehierarchy_test.cpp",
"cppincludehierarchy_test.h",
"cpplocalsymbols_test.cpp",
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index 8d4adebf14..d1297b1dd3 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -6,11 +6,9 @@
#include "baseeditordocumentparser.h"
#include "cppcodeformatter.h"
#include "cppeditorconstants.h"
-#include "cppeditorplugin.h"
#include "cppeditortr.h"
#include "cppmodelmanager.h"
#include "cppeditorconstants.h"
-#include "cppeditorplugin.h"
#include "cppeditortr.h"
#include "cpphighlighter.h"
#include "cppquickfixassistant.h"
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index 24d821aac2..a5f1275538 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -1,8 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include "cppeditorplugin.h"
-
#include "cppautocompleter.h"
#include "cppcodemodelinspectordialog.h"
#include "cppcodemodelsettings.h"
@@ -14,9 +12,9 @@
#include "cppeditorwidget.h"
#include "cppfilesettingspage.h"
#include "cppincludehierarchy.h"
+#include "cppheadersource.h"
#include "cppmodelmanager.h"
#include "cppoutline.h"
-#include "cppprojectfile.h"
#include "cppprojectupdater.h"
#include "cppquickfixes.h"
#include "cppquickfixprojectsettingswidget.h"
@@ -24,7 +22,6 @@
#include "cpptoolsreuse.h"
#include "cpptoolssettings.h"
#include "cpptypehierarchy.h"
-#include "projectinfo.h"
#include "resourcepreviewhoverhandler.h"
#ifdef WITH_TESTS
@@ -32,7 +29,6 @@
#include "cppcodegen_test.h"
#include "cppcompletion_test.h"
#include "cppdoxygen_test.h"
-#include "cppheadersource_test.h"
#include "cpphighlighter.h"
#include "cppincludehierarchy_test.h"
#include "cppinsertvirtualmethods.h"
@@ -89,7 +85,6 @@
#include <utils/mimeconstants.h>
#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
-#include <utils/stringtable.h>
#include <utils/theme/theme.h>
#include <QAction>
@@ -106,11 +101,7 @@ using namespace ProjectExplorer;
using namespace TextEditor;
using namespace Utils;
-namespace CppEditor {
-namespace Internal {
-
-enum { QUICKFIX_INTERVAL = 20 };
-enum { debug = 0 };
+namespace CppEditor::Internal {
static CppEditorWidget *currentCppEditorWidget()
{
@@ -183,8 +174,6 @@ public:
CppProjectUpdaterFactory m_cppProjectUpdaterFactory;
};
-static QHash<FilePath, FilePath> m_headerSourceMapping;
-
class CppEditorPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -498,7 +487,7 @@ void CppEditorPlugin::registerTests()
addTest<CppHighlighterTest>();
addTest<FunctionUtilsTest>();
addTest<HeaderPathFilterTest>();
- addTest<HeaderSourceTest>();
+ addTestCreator(createCppHeaderSourceTest);
addTest<IncludeGroupsTest>();
addTest<LocalSymbolsTest>();
addTest<LocatorFilterTest>();
@@ -551,239 +540,6 @@ void CppEditorPluginPrivate::inspectCppCodeModel()
}
}
-void clearHeaderSourceCache()
-{
- m_headerSourceMapping.clear();
-}
-
-static FilePaths findFilesInProject(const QStringList &names, const Project *project,
- FileType fileType)
-{
- if (debug)
- qDebug() << Q_FUNC_INFO << names << project;
-
- if (!project)
- return {};
-
- const auto filter = [&](const Node *n) {
- const auto fn = n->asFileNode();
- return fn && fn->fileType() == fileType && names.contains(fn->filePath().fileName());
- };
- return project->files(filter);
-}
-
-// 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)
-{
- using namespace Utils::Constants;
- switch (kind) {
- case ProjectFile::AmbiguousHeader:
- case ProjectFile::CHeader:
- case ProjectFile::CXXHeader:
- case ProjectFile::ObjCHeader:
- case ProjectFile::ObjCXXHeader:
- return mimeTypeForName(C_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(CPP_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(OBJECTIVE_C_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(OBJECTIVE_CPP_SOURCE_MIMETYPE).suffixes()
- + mimeTypeForName(CUDA_SOURCE_MIMETYPE).suffixes();
- case ProjectFile::CSource:
- case ProjectFile::ObjCSource:
- return mimeTypeForName(C_HEADER_MIMETYPE).suffixes();
- case ProjectFile::CXXSource:
- case ProjectFile::ObjCXXSource:
- case ProjectFile::CudaSource:
- case ProjectFile::OpenCLSource:
- return mimeTypeForName(CPP_HEADER_MIMETYPE).suffixes();
- default:
- return {};
- }
-}
-
-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 CppFileSettings &settings,
- const QStringList &baseNames, bool isHeader)
-{
- QStringList result;
- const QStringList &sourcePrefixes = settings.sourcePrefixes;
- const QStringList &headerPrefixes = settings.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 FilePath correspondingHeaderOrSourceInProject(const FilePath &filePath,
- const QStringList &candidateFileNames,
- const Project *project,
- FileType fileType,
- CacheUsage cacheUsage)
-{
- const FilePaths projectFiles = findFilesInProject(candidateFileNames, project, fileType);
-
- // Find the file having the most common path with fileName
- FilePath bestFilePath;
- int compareValue = 0;
- for (const FilePath &projectFile : projectFiles) {
- int value = commonFilePathLength(filePath.toString(), projectFile.toString());
- if (value > compareValue) {
- compareValue = value;
- bestFilePath = projectFile;
- }
- }
- if (!bestFilePath.isEmpty()) {
- QTC_ASSERT(bestFilePath.isFile(), return {});
- if (cacheUsage == CacheUsage::ReadWrite) {
- m_headerSourceMapping[filePath] = bestFilePath;
- m_headerSourceMapping[bestFilePath] = filePath;
- }
- return bestFilePath;
- }
-
- return {};
-}
-
-} // namespace Internal
-
-using namespace Internal;
-
-FilePath correspondingHeaderOrSource(const FilePath &filePath, bool *wasHeader, CacheUsage cacheUsage)
-{
- ProjectFile::Kind kind = ProjectFile::classify(filePath.fileName());
- const bool isHeader = ProjectFile::isHeader(kind);
- if (wasHeader)
- *wasHeader = isHeader;
- if (const auto it = m_headerSourceMapping.constFind(filePath);
- it != m_headerSourceMapping.constEnd()) {
- return it.value();
- }
-
- Project * const projectForFile = ProjectManager::projectForFile(filePath);
- const CppFileSettings settings = cppFileSettingsForProject(projectForFile);
-
- if (debug)
- qDebug() << Q_FUNC_INFO << filePath.fileName() << kind;
-
- if (kind == ProjectFile::Unsupported)
- return {};
-
- const QString baseName = filePath.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 = filePath.toFileInfo().absoluteDir();
- QStringList candidateDirs(absoluteDir.absolutePath());
- // If directory is not root, try matching against its siblings
- const QStringList searchPaths = isHeader ? settings.sourceSearchPaths
- : settings.headerSearchPaths;
- candidateDirs += baseDirWithAllDirectories(absoluteDir, searchPaths);
-
- candidateFileNames += baseNamesWithAllPrefixes(settings, candidateFileNames, isHeader);
-
- // Try to find a file in the same or sibling directories first
- for (const QString &candidateDir : std::as_const(candidateDirs)) {
- for (const QString &candidateFileName : std::as_const(candidateFileNames)) {
- const FilePath candidateFilePath
- = FilePath::fromString(candidateDir + '/' + candidateFileName).normalizedPathName();
- if (candidateFilePath.isFile()) {
- if (cacheUsage == CacheUsage::ReadWrite) {
- m_headerSourceMapping[filePath] = candidateFilePath;
- if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
- m_headerSourceMapping[candidateFilePath] = filePath;
- }
- return candidateFilePath;
- }
- }
- }
-
- // Find files in the current project
- Project *currentProject = projectForFile;
- if (!projectForFile)
- currentProject = ProjectTree::currentProject();
- const FileType requestedFileType = isHeader ? FileType::Source : FileType::Header;
- if (currentProject) {
- const FilePath path = correspondingHeaderOrSourceInProject(
- filePath, candidateFileNames, currentProject, requestedFileType, cacheUsage);
- if (!path.isEmpty())
- return path;
-
- // Find files in other projects
- } else {
- const QList<ProjectInfo::ConstPtr> projectInfos = CppModelManager::projectInfos();
- for (const ProjectInfo::ConstPtr &projectInfo : projectInfos) {
- const Project *project = projectForProjectInfo(*projectInfo);
- if (project == currentProject)
- continue; // We have already checked the current project.
-
- const FilePath path = correspondingHeaderOrSourceInProject(
- filePath, candidateFileNames, project, requestedFileType, cacheUsage);
- if (!path.isEmpty())
- return path;
- }
- }
-
- return {};
-}
-
-} // namespace CppEditor
+} // CppEditor::Internal
#include "cppeditorplugin.moc"
diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp
index 2d8a699727..958a908915 100644
--- a/src/plugins/cppeditor/cppeditorwidget.cpp
+++ b/src/plugins/cppeditor/cppeditorwidget.cpp
@@ -8,7 +8,6 @@
#include "cppeditorconstants.h"
#include "cppeditordocument.h"
#include "cppeditoroutline.h"
-#include "cppeditorplugin.h"
#include "cppeditortr.h"
#include "cppfunctiondecldeflink.h"
#include "cppfunctionparamrenaminghandler.h"
diff --git a/src/plugins/cppeditor/cppfilesettingspage.cpp b/src/plugins/cppeditor/cppfilesettingspage.cpp
index d11a811498..2c8fa41054 100644
--- a/src/plugins/cppeditor/cppfilesettingspage.cpp
+++ b/src/plugins/cppeditor/cppfilesettingspage.cpp
@@ -3,8 +3,8 @@
#include "cppfilesettingspage.h"
-#include "cppeditorplugin.h"
#include "cppeditortr.h"
+#include "cppheadersource.h"
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
diff --git a/src/plugins/cppeditor/cppheadersource.cpp b/src/plugins/cppeditor/cppheadersource.cpp
new file mode 100644
index 0000000000..84dcb98c70
--- /dev/null
+++ b/src/plugins/cppeditor/cppheadersource.cpp
@@ -0,0 +1,368 @@
+// Copyright (C) 2016 Orgad Shaneh <orgads@gmail.com>.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "cppheadersource.h"
+
+#include "cpptoolsreuse.h"
+#include "cpptoolstestcase.h"
+#include "cppfilesettingspage.h"
+#include "cppmodelmanager.h"
+#include "cppfilesettingspage.h"
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/projecttree.h>
+
+#include <utils/fileutils.h>
+#include <utils/mimeconstants.h>
+#include <utils/mimeutils.h>
+#include <utils/temporarydirectory.h>
+
+#include <QDir>
+
+#ifdef WITH_TESTS
+#include <QtTest>
+#endif
+
+using namespace CppEditor::Internal;
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace CppEditor {
+
+enum { debug = 0 };
+
+static QHash<FilePath, FilePath> m_headerSourceMapping;
+
+void Internal::clearHeaderSourceCache()
+{
+ m_headerSourceMapping.clear();
+}
+
+static inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); }
+
+static void createTempFile(const FilePath &filePath)
+{
+ QString fileName = filePath.toString();
+ QFile file(fileName);
+ QDir(QFileInfo(fileName).absolutePath()).mkpath(_("."));
+ file.open(QFile::WriteOnly);
+ file.close();
+}
+
+static QString baseTestDir()
+{
+ return Utils::TemporaryDirectory::masterDirectoryPath() + "/qtc_cppheadersource/";
+}
+
+static FilePaths findFilesInProject(const QStringList &names, const Project *project,
+ FileType fileType)
+{
+ if (debug)
+ qDebug() << Q_FUNC_INFO << names << project;
+
+ if (!project)
+ return {};
+
+ const auto filter = [&](const Node *n) {
+ const auto fn = n->asFileNode();
+ return fn && fn->fileType() == fileType && names.contains(fn->filePath().fileName());
+ };
+ return project->files(filter);
+}
+
+// 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)
+{
+ using namespace Utils::Constants;
+ switch (kind) {
+ case ProjectFile::AmbiguousHeader:
+ case ProjectFile::CHeader:
+ case ProjectFile::CXXHeader:
+ case ProjectFile::ObjCHeader:
+ case ProjectFile::ObjCXXHeader:
+ return mimeTypeForName(C_SOURCE_MIMETYPE).suffixes()
+ + mimeTypeForName(CPP_SOURCE_MIMETYPE).suffixes()
+ + mimeTypeForName(OBJECTIVE_C_SOURCE_MIMETYPE).suffixes()
+ + mimeTypeForName(OBJECTIVE_CPP_SOURCE_MIMETYPE).suffixes()
+ + mimeTypeForName(CUDA_SOURCE_MIMETYPE).suffixes();
+ case ProjectFile::CSource:
+ case ProjectFile::ObjCSource:
+ return mimeTypeForName(C_HEADER_MIMETYPE).suffixes();
+ case ProjectFile::CXXSource:
+ case ProjectFile::ObjCXXSource:
+ case ProjectFile::CudaSource:
+ case ProjectFile::OpenCLSource:
+ return mimeTypeForName(CPP_HEADER_MIMETYPE).suffixes();
+ default:
+ return {};
+ }
+}
+
+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 CppFileSettings &settings,
+ const QStringList &baseNames, bool isHeader)
+{
+ QStringList result;
+ const QStringList &sourcePrefixes = settings.sourcePrefixes;
+ const QStringList &headerPrefixes = settings.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 FilePath correspondingHeaderOrSourceInProject(const FilePath &filePath,
+ const QStringList &candidateFileNames,
+ const Project *project,
+ FileType fileType,
+ CacheUsage cacheUsage)
+{
+ const FilePaths projectFiles = findFilesInProject(candidateFileNames, project, fileType);
+
+ // Find the file having the most common path with fileName
+ FilePath bestFilePath;
+ int compareValue = 0;
+ for (const FilePath &projectFile : projectFiles) {
+ int value = commonFilePathLength(filePath.toString(), projectFile.toString());
+ if (value > compareValue) {
+ compareValue = value;
+ bestFilePath = projectFile;
+ }
+ }
+ if (!bestFilePath.isEmpty()) {
+ QTC_ASSERT(bestFilePath.isFile(), return {});
+ if (cacheUsage == CacheUsage::ReadWrite) {
+ m_headerSourceMapping[filePath] = bestFilePath;
+ m_headerSourceMapping[bestFilePath] = filePath;
+ }
+ return bestFilePath;
+ }
+
+ return {};
+}
+
+FilePath correspondingHeaderOrSource(const FilePath &filePath, bool *wasHeader, CacheUsage cacheUsage)
+{
+ ProjectFile::Kind kind = ProjectFile::classify(filePath.fileName());
+ const bool isHeader = ProjectFile::isHeader(kind);
+ if (wasHeader)
+ *wasHeader = isHeader;
+ if (const auto it = m_headerSourceMapping.constFind(filePath);
+ it != m_headerSourceMapping.constEnd()) {
+ return it.value();
+ }
+
+ Project * const projectForFile = ProjectManager::projectForFile(filePath);
+ const CppFileSettings settings = cppFileSettingsForProject(projectForFile);
+
+ if (debug)
+ qDebug() << Q_FUNC_INFO << filePath.fileName() << kind;
+
+ if (kind == ProjectFile::Unsupported)
+ return {};
+
+ const QString baseName = filePath.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 = filePath.toFileInfo().absoluteDir();
+ QStringList candidateDirs(absoluteDir.absolutePath());
+ // If directory is not root, try matching against its siblings
+ const QStringList searchPaths = isHeader ? settings.sourceSearchPaths
+ : settings.headerSearchPaths;
+ candidateDirs += baseDirWithAllDirectories(absoluteDir, searchPaths);
+
+ candidateFileNames += baseNamesWithAllPrefixes(settings, candidateFileNames, isHeader);
+
+ // Try to find a file in the same or sibling directories first
+ for (const QString &candidateDir : std::as_const(candidateDirs)) {
+ for (const QString &candidateFileName : std::as_const(candidateFileNames)) {
+ const FilePath candidateFilePath
+ = FilePath::fromString(candidateDir + '/' + candidateFileName).normalizedPathName();
+ if (candidateFilePath.isFile()) {
+ if (cacheUsage == CacheUsage::ReadWrite) {
+ m_headerSourceMapping[filePath] = candidateFilePath;
+ if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
+ m_headerSourceMapping[candidateFilePath] = filePath;
+ }
+ return candidateFilePath;
+ }
+ }
+ }
+
+ // Find files in the current project
+ Project *currentProject = projectForFile;
+ if (!projectForFile)
+ currentProject = ProjectTree::currentProject();
+ const FileType requestedFileType = isHeader ? FileType::Source : FileType::Header;
+ if (currentProject) {
+ const FilePath path = correspondingHeaderOrSourceInProject(
+ filePath, candidateFileNames, currentProject, requestedFileType, cacheUsage);
+ if (!path.isEmpty())
+ return path;
+
+ // Find files in other projects
+ } else {
+ const QList<ProjectInfo::ConstPtr> projectInfos = CppModelManager::projectInfos();
+ for (const ProjectInfo::ConstPtr &projectInfo : projectInfos) {
+ const Project *project = projectForProjectInfo(*projectInfo);
+ if (project == currentProject)
+ continue; // We have already checked the current project.
+
+ const FilePath path = correspondingHeaderOrSourceInProject(
+ filePath, candidateFileNames, project, requestedFileType, cacheUsage);
+ if (!path.isEmpty())
+ return path;
+ }
+ }
+
+ return {};
+}
+
+} // CppEditor
+
+#ifdef WITH_TESTS
+
+namespace CppEditor::Internal {
+
+class HeaderSourceTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void test_data();
+ void test();
+};
+
+void HeaderSourceTest::test()
+{
+ QFETCH(QString, sourceFileName);
+ QFETCH(QString, headerFileName);
+
+ CppEditor::Tests::TemporaryDir temporaryDir;
+ QVERIFY(temporaryDir.isValid());
+
+ const QDir path = QDir(temporaryDir.path() + QLatin1Char('/') + _(QTest::currentDataTag()));
+ const FilePath sourcePath = FilePath::fromString(path.absoluteFilePath(sourceFileName));
+ const FilePath headerPath = FilePath::fromString(path.absoluteFilePath(headerFileName));
+ createTempFile(sourcePath);
+ createTempFile(headerPath);
+
+ bool wasHeader;
+ clearHeaderSourceCache();
+ QCOMPARE(correspondingHeaderOrSource(sourcePath, &wasHeader, CacheUsage::ReadWrite), headerPath);
+ QVERIFY(!wasHeader);
+ clearHeaderSourceCache();
+ QCOMPARE(correspondingHeaderOrSource(headerPath, &wasHeader, CacheUsage::ReadWrite), sourcePath);
+ QVERIFY(wasHeader);
+}
+
+void HeaderSourceTest::test_data()
+{
+ QTest::addColumn<QString>("sourceFileName");
+ QTest::addColumn<QString>("headerFileName");
+ QTest::newRow("samedir") << _("foo.cpp") << _("foo.h");
+ QTest::newRow("includesub") << _("foo.cpp") << _("include/foo.h");
+ QTest::newRow("headerprefix") << _("foo.cpp") << _("testh_foo.h");
+ QTest::newRow("sourceprefixwsub") << _("testc_foo.cpp") << _("include/foo.h");
+ QTest::newRow("sourceAndHeaderPrefixWithBothsub") << _("src/testc_foo.cpp") << _("include/testh_foo.h");
+}
+
+void HeaderSourceTest::initTestCase()
+{
+ QDir(baseTestDir()).mkpath(_("."));
+ CppFileSettings &fs = globalCppFileSettings();
+ fs.headerSearchPaths.append(QLatin1String("include"));
+ fs.headerSearchPaths.append(QLatin1String("../include"));
+ fs.sourceSearchPaths.append(QLatin1String("src"));
+ fs.sourceSearchPaths.append(QLatin1String("../src"));
+ fs.headerPrefixes.append(QLatin1String("testh_"));
+ fs.sourcePrefixes.append(QLatin1String("testc_"));
+}
+
+void HeaderSourceTest::cleanupTestCase()
+{
+ Utils::FilePath::fromString(baseTestDir()).removeRecursively();
+ CppFileSettings &fs = globalCppFileSettings();
+ fs.headerSearchPaths.removeLast();
+ fs.headerSearchPaths.removeLast();
+ fs.sourceSearchPaths.removeLast();
+ fs.sourceSearchPaths.removeLast();
+ fs.headerPrefixes.removeLast();
+ fs.sourcePrefixes.removeLast();
+}
+
+QObject *createCppHeaderSourceTest()
+{
+ return new HeaderSourceTest;
+}
+
+} // namespace CppEditor::Internal
+
+#include "cppheadersource.moc"
+
+#endif // WITH_TESTS
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppheadersource.h
index 8dde52b15e..a408e4aac3 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppheadersource.h
@@ -1,10 +1,16 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
+#include <QObject>
+
namespace CppEditor::Internal {
void clearHeaderSourceCache();
+#ifdef WITH_TESTS
+QObject *createCppHeaderSourceTest();
+#endif
+
} // CppEditor::Internal
diff --git a/src/plugins/cppeditor/cppheadersource_test.cpp b/src/plugins/cppeditor/cppheadersource_test.cpp
deleted file mode 100644
index 2b6621c74f..0000000000
--- a/src/plugins/cppeditor/cppheadersource_test.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2016 Orgad Shaneh <orgads@gmail.com>.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cppheadersource_test.h"
-
-#include "cppeditorplugin.h"
-#include "cpptoolsreuse.h"
-#include "cpptoolstestcase.h"
-#include "cppfilesettingspage.h"
-
-#include <utils/fileutils.h>
-#include <utils/temporarydirectory.h>
-
-#include <QDir>
-#include <QtTest>
-
-using namespace Utils;
-
-static inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); }
-
-static void createTempFile(const FilePath &filePath)
-{
- QString fileName = filePath.toString();
- QFile file(fileName);
- QDir(QFileInfo(fileName).absolutePath()).mkpath(_("."));
- file.open(QFile::WriteOnly);
- file.close();
-}
-
-static QString baseTestDir()
-{
- return Utils::TemporaryDirectory::masterDirectoryPath() + "/qtc_cppheadersource/";
-}
-
-namespace CppEditor::Internal {
-
-void HeaderSourceTest::test()
-{
- QFETCH(QString, sourceFileName);
- QFETCH(QString, headerFileName);
-
- CppEditor::Tests::TemporaryDir temporaryDir;
- QVERIFY(temporaryDir.isValid());
-
- const QDir path = QDir(temporaryDir.path() + QLatin1Char('/') + _(QTest::currentDataTag()));
- const FilePath sourcePath = FilePath::fromString(path.absoluteFilePath(sourceFileName));
- const FilePath headerPath = FilePath::fromString(path.absoluteFilePath(headerFileName));
- createTempFile(sourcePath);
- createTempFile(headerPath);
-
- bool wasHeader;
- clearHeaderSourceCache();
- QCOMPARE(correspondingHeaderOrSource(sourcePath, &wasHeader), headerPath);
- QVERIFY(!wasHeader);
- clearHeaderSourceCache();
- QCOMPARE(correspondingHeaderOrSource(headerPath, &wasHeader), sourcePath);
- QVERIFY(wasHeader);
-}
-
-void HeaderSourceTest::test_data()
-{
- QTest::addColumn<QString>("sourceFileName");
- QTest::addColumn<QString>("headerFileName");
- QTest::newRow("samedir") << _("foo.cpp") << _("foo.h");
- QTest::newRow("includesub") << _("foo.cpp") << _("include/foo.h");
- QTest::newRow("headerprefix") << _("foo.cpp") << _("testh_foo.h");
- QTest::newRow("sourceprefixwsub") << _("testc_foo.cpp") << _("include/foo.h");
- QTest::newRow("sourceAndHeaderPrefixWithBothsub") << _("src/testc_foo.cpp") << _("include/testh_foo.h");
-}
-
-void HeaderSourceTest::initTestCase()
-{
- QDir(baseTestDir()).mkpath(_("."));
- CppFileSettings &fs = globalCppFileSettings();
- fs.headerSearchPaths.append(QLatin1String("include"));
- fs.headerSearchPaths.append(QLatin1String("../include"));
- fs.sourceSearchPaths.append(QLatin1String("src"));
- fs.sourceSearchPaths.append(QLatin1String("../src"));
- fs.headerPrefixes.append(QLatin1String("testh_"));
- fs.sourcePrefixes.append(QLatin1String("testc_"));
-}
-
-void HeaderSourceTest::cleanupTestCase()
-{
- Utils::FilePath::fromString(baseTestDir()).removeRecursively();
- CppFileSettings &fs = globalCppFileSettings();
- fs.headerSearchPaths.removeLast();
- fs.headerSearchPaths.removeLast();
- fs.sourceSearchPaths.removeLast();
- fs.sourceSearchPaths.removeLast();
- fs.headerPrefixes.removeLast();
- fs.sourcePrefixes.removeLast();
-}
-
-} // namespace CppEditor::Internal
diff --git a/src/plugins/cppeditor/cppheadersource_test.h b/src/plugins/cppeditor/cppheadersource_test.h
deleted file mode 100644
index 5f11c0272e..0000000000
--- a/src/plugins/cppeditor/cppheadersource_test.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <QObject>
-
-namespace CppEditor::Internal {
-
-class HeaderSourceTest : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void test_data();
- void test();
-};
-
-} // namespace CppEditor::Internal
diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
index fd76b8522a..50a9c2c48a 100644
--- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
+++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
@@ -40,7 +40,6 @@
#include <QVBoxLayout>
#ifdef WITH_TESTS
-#include "cppeditorplugin.h"
#include "cppquickfix_test.h"
#include <QtTest>
#endif
diff --git a/src/plugins/cppeditor/cpplocatorfilter.cpp b/src/plugins/cppeditor/cpplocatorfilter.cpp
index c6d1be6663..8fab8f4dcd 100644
--- a/src/plugins/cppeditor/cpplocatorfilter.cpp
+++ b/src/plugins/cppeditor/cpplocatorfilter.cpp
@@ -4,7 +4,6 @@
#include "cpplocatorfilter.h"
#include "cppeditorconstants.h"
-#include "cppeditorplugin.h"
#include "cppeditortr.h"
#include "cpplocatordata.h"
#include "cppmodelmanager.h"
diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp
index 3b3d88f149..b0064ab790 100644
--- a/src/plugins/cppeditor/cppquickfix_test.cpp
+++ b/src/plugins/cppeditor/cppquickfix_test.cpp
@@ -4,7 +4,6 @@
#include "cppquickfix_test.h"
#include "cppcodestylepreferences.h"
-#include "cppeditorplugin.h"
#include "cppeditorwidget.h"
#include "cppmodelmanager.h"
#include "cppquickfixassistant.h"
diff --git a/src/plugins/cppeditor/cpptoolsjsextension.cpp b/src/plugins/cppeditor/cpptoolsjsextension.cpp
index e5b3499a96..607744eec1 100644
--- a/src/plugins/cppeditor/cpptoolsjsextension.cpp
+++ b/src/plugins/cppeditor/cpptoolsjsextension.cpp
@@ -3,7 +3,6 @@
#include "cpptoolsjsextension.h"
-#include "cppeditorplugin.h"
#include "cppfilesettingspage.h"
#include "cpplocatordata.h"
#include "cppworkingcopy.h"
diff --git a/src/plugins/cppeditor/fileandtokenactions_test.cpp b/src/plugins/cppeditor/fileandtokenactions_test.cpp
index ca6411116f..f341cc1808 100644
--- a/src/plugins/cppeditor/fileandtokenactions_test.cpp
+++ b/src/plugins/cppeditor/fileandtokenactions_test.cpp
@@ -3,14 +3,11 @@
#include "fileandtokenactions_test.h"
-#include "cppeditorplugin.h"
#include "cppeditorwidget.h"
#include "cppquickfix.h"
#include "cppquickfixassistant.h"
-#include "cppquickfixes.h"
#include "cppinsertvirtualmethods.h"
#include "cppmodelmanager.h"
-#include "cpptoolsreuse.h"
#include "cpptoolstestcase.h"
#include "cpptypehierarchy.h"
#include "cppworkingcopy.h"
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 0c06f86783..d18e8dc391 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -4,12 +4,9 @@
#include "followsymbol_switchmethoddecldef_test.h"
#include "cppcodemodelsettings.h"
-#include "cppeditorplugin.h"
#include "cppeditorwidget.h"
-#include "cppelementevaluator.h"
#include "cppfollowsymbolundercursor.h"
#include "cppmodelmanager.h"
-#include "cpptoolsreuse.h"
#include "cpptoolstestcase.h"
#include "cppvirtualfunctionassistprovider.h"
#include "cppvirtualfunctionproposalitem.h"
diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp
index 0428067105..267e0ddeeb 100644
--- a/src/plugins/designer/qtcreatorintegration.cpp
+++ b/src/plugins/designer/qtcreatorintegration.cpp
@@ -12,7 +12,6 @@
#include <designer/cpp/formclasswizardpage.h>
#include <cppeditor/cppeditorconstants.h>
-#include <cppeditor/cppeditorplugin.h>
#include <cppeditor/cppeditorwidget.h>
#include <cppeditor/cppmodelmanager.h>
#include <cppeditor/cppsemanticinfo.h>