forked from qt-creator/qt-creator
CppEditor: Speed up findFilesInProject()
This function had a number of serious performance problems. As it is executed by several quickfix factories, it could cause freezes on right- clicking a symbol. Measures taken: - Check file type before file path. - Do not collect all files in the project first, but filter earlier. - Check all candidate file names at once. In an example project, I observed a speed-up of factor ~100. Some FilePath-ification was done as well. Task-number: QTCREATORBUG-29611 Change-Id: Ic5dc48ffd86f22263d1caea4b6bfea5f49e589a4 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -668,25 +668,20 @@ void CppEditorPlugin::setGlobalFileSettings(const CppFileSettings &settings)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static QStringList findFilesInProject(const QString &name, const Project *project)
|
static FilePaths findFilesInProject(const QStringList &names, const Project *project,
|
||||||
|
FileType fileType)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << Q_FUNC_INFO << name << project;
|
qDebug() << Q_FUNC_INFO << names << project;
|
||||||
|
|
||||||
if (!project)
|
if (!project)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
QString pattern = QString(1, QLatin1Char('/'));
|
const auto filter = [&](const Node *n) {
|
||||||
pattern += name;
|
const auto fn = n->asFileNode();
|
||||||
const QStringList projectFiles
|
return fn && fn->fileType() == fileType && names.contains(fn->filePath().fileName());
|
||||||
= transform(project->files(Project::AllFiles), &FilePath::toString);
|
};
|
||||||
const QStringList::const_iterator pcend = projectFiles.constEnd();
|
return project->files(filter);
|
||||||
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
|
// Return the suffixes that should be checked when trying to find a
|
||||||
@@ -778,30 +773,31 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
|
|||||||
static FilePath correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
|
static FilePath correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
|
||||||
const QStringList &candidateFileNames,
|
const QStringList &candidateFileNames,
|
||||||
const Project *project,
|
const Project *project,
|
||||||
|
FileType fileType,
|
||||||
CacheUsage cacheUsage)
|
CacheUsage cacheUsage)
|
||||||
{
|
{
|
||||||
QString bestFileName;
|
|
||||||
int compareValue = 0;
|
|
||||||
const QString filePath = fileInfo.filePath();
|
const QString filePath = fileInfo.filePath();
|
||||||
for (const QString &candidateFileName : candidateFileNames) {
|
const FilePaths projectFiles = findFilesInProject(candidateFileNames, project, fileType);
|
||||||
const QStringList projectFiles = findFilesInProject(candidateFileName, project);
|
|
||||||
// Find the file having the most common path with fileName
|
// Find the file having the most common path with fileName
|
||||||
for (const QString &projectFile : projectFiles) {
|
FilePath bestFilePath;
|
||||||
int value = commonFilePathLength(filePath, projectFile);
|
int compareValue = 0;
|
||||||
if (value > compareValue) {
|
for (const FilePath &projectFile : projectFiles) {
|
||||||
compareValue = value;
|
int value = commonFilePathLength(filePath, projectFile.toString());
|
||||||
bestFileName = projectFile;
|
if (value > compareValue) {
|
||||||
}
|
compareValue = value;
|
||||||
|
bestFilePath = projectFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bestFileName.isEmpty()) {
|
if (!bestFilePath.isEmpty()) {
|
||||||
const QFileInfo candidateFi(bestFileName);
|
QTC_ASSERT(bestFilePath.isFile(), return {});
|
||||||
QTC_ASSERT(candidateFi.isFile(), return {});
|
|
||||||
if (cacheUsage == CacheUsage::ReadWrite) {
|
if (cacheUsage == CacheUsage::ReadWrite) {
|
||||||
m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
|
m_headerSourceMapping[fileInfo.absoluteFilePath()]
|
||||||
m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
|
= bestFilePath.absoluteFilePath().toString();
|
||||||
|
m_headerSourceMapping[bestFilePath.absoluteFilePath().toString()]
|
||||||
|
= fileInfo.absoluteFilePath();
|
||||||
}
|
}
|
||||||
return FilePath::fromString(candidateFi.absoluteFilePath());
|
return bestFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@@ -878,9 +874,10 @@ FilePath correspondingHeaderOrSource(const FilePath &filePath, bool *wasHeader,
|
|||||||
Project *currentProject = projectForFile;
|
Project *currentProject = projectForFile;
|
||||||
if (!projectForFile)
|
if (!projectForFile)
|
||||||
currentProject = ProjectTree::currentProject();
|
currentProject = ProjectTree::currentProject();
|
||||||
|
const FileType requestedFileType = isHeader ? FileType::Source : FileType::Header;
|
||||||
if (currentProject) {
|
if (currentProject) {
|
||||||
const FilePath path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
|
const FilePath path = correspondingHeaderOrSourceInProject(
|
||||||
currentProject, cacheUsage);
|
fi, candidateFileNames, currentProject, requestedFileType, cacheUsage);
|
||||||
if (!path.isEmpty())
|
if (!path.isEmpty())
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
@@ -892,8 +889,8 @@ FilePath correspondingHeaderOrSource(const FilePath &filePath, bool *wasHeader,
|
|||||||
if (project == currentProject)
|
if (project == currentProject)
|
||||||
continue; // We have already checked the current project.
|
continue; // We have already checked the current project.
|
||||||
|
|
||||||
const FilePath path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
|
const FilePath path = correspondingHeaderOrSourceInProject(
|
||||||
project, cacheUsage);
|
fi, candidateFileNames, project, requestedFileType, cacheUsage);
|
||||||
if (!path.isEmpty())
|
if (!path.isEmpty())
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user