aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/compilationdatabaseprojectmanager
diff options
context:
space:
mode:
authorIvan Donchevskii <ivan.donchevskii@qt.io>2018-11-02 16:07:42 +0100
committerIvan Donchevskii <ivan.donchevskii@qt.io>2018-11-07 12:32:34 +0000
commit0fabde31abf8b6861291b7e54588a243a9e85396 (patch)
tree1f54df128073427b961e60898d8eba469d9cc0c2 /src/plugins/compilationdatabaseprojectmanager
parent9b324aaccfe167b20bfd247af84bef9431889f66 (diff)
CompilationDatabase: Speed up parsing project file
Avoid expensive indexOf and check for the exactly same flags before applying the full filter. Change-Id: I6936b2022a2b439aad7bf0a65280c3db16d00c34 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'src/plugins/compilationdatabaseprojectmanager')
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp98
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp29
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h2
3 files changed, 79 insertions, 50 deletions
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
index 155ed5185aa..f8c19219886 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
@@ -75,6 +75,7 @@ QStringList jsonObjectFlags(const QJsonObject &object)
if (arguments.isEmpty()) {
flags = splitCommandLine(object["command"].toString());
} else {
+ flags.reserve(arguments.size());
for (const QJsonValue &arg : arguments)
flags.append(arg.toString());
}
@@ -284,27 +285,43 @@ FolderNode *createFoldersIfNeeded(FolderNode *root, const Utils::FileName &folde
return parent;
}
-void createFolders(FolderNode *root, const Utils::FileName &rootPath)
+FileType fileTypeForName(const QString &fileName)
{
- root->setAbsoluteFilePathAndLine(rootPath, -1);
+ CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(fileName);
+ if (CppTools::ProjectFile::isHeader(fileKind))
+ return FileType::Header;
+ return FileType::Source;
+}
- for (Node *child : root->nodes()) {
- FileNode *fileNode = child->asFileNode();
- if (!fileNode)
- continue;
+void createTree(FolderNode *root,
+ const Utils::FileName &rootPath,
+ const CppTools::RawProjectParts &rpps)
+{
+ root->setAbsoluteFilePathAndLine(rootPath, -1);
- FolderNode *parentNode = createFoldersIfNeeded(root,
- fileNode->filePath().parentDir());
- child->setParentFolderNode(nullptr);
- std::unique_ptr<Node> childNode = root->takeNode(child);
- if (!parentNode->fileNode(child->filePath()))
- parentNode->addNode(std::move(childNode));
+ for (const CppTools::RawProjectPart &rpp : rpps) {
+ for (const QString &filePath : rpp.files) {
+ Utils::FileName fileName = Utils::FileName::fromString(filePath);
+ FolderNode *parentNode = createFoldersIfNeeded(root, fileName.parentDir());
+ if (!parentNode->fileNode(fileName)) {
+ parentNode->addNode(std::make_unique<FileNode>(fileName,
+ fileTypeForName(fileName.fileName()),
+ false));
+ }
+ }
}
}
-std::vector<QJsonObject> readJsonObjects(const QString &filePath)
+struct Entry
+{
+ QStringList flags;
+ Utils::FileName fileName;
+ QString workingDir;
+};
+
+std::vector<Entry> readJsonObjects(const QString &filePath)
{
- std::vector<QJsonObject> result;
+ std::vector<Entry> result;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
return result;
@@ -322,7 +339,12 @@ std::vector<QJsonObject> readJsonObjects(const QString &filePath)
continue;
}
- result.push_back(document.object());
+ const QJsonObject object = document.object();
+ const Utils::FileName fileName = jsonObjectFilename(object);
+ const QStringList flags
+ = filterFromFileName(jsonObjectFlags(object), fileName.toFileInfo().baseName());
+ result.push_back({flags, fileName, object["directory"].toString()});
+
objectStart = contents.indexOf('{', objectEnd + 1);
objectEnd = contents.indexOf('}', objectStart + 1);
}
@@ -334,7 +356,7 @@ std::vector<QJsonObject> readJsonObjects(const QString &filePath)
void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName &projectFile)
{
- std::vector<QJsonObject> array = readJsonObjects(projectFilePath().toString());
+ std::vector<Entry> array = readJsonObjects(projectFilePath().toString());
if (array.empty()) {
emitParsingFinished(false);
return;
@@ -346,37 +368,37 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName
Utils::FileName commonPath;
ToolChain *cToolchain = nullptr;
ToolChain *cxxToolchain = nullptr;
- for (const QJsonObject &object : array) {
- Utils::FileName fileName = jsonObjectFilename(object);
- const QStringList flags = jsonObjectFlags(object);
- commonPath = rpps.empty()
- ? fileName.parentDir()
- : Utils::FileUtils::commonPath(commonPath, fileName);
+ std::sort(array.begin(), array.end(), [](const Entry &lhs, const Entry &rhs) {
+ return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(),
+ rhs.flags.begin(), rhs.flags.end());
+ });
- ProjectExplorer::FileType type = ProjectExplorer::FileType::Unknown;
- root->addNode(std::make_unique<FileNode>(fileName, type, false));
+ const Entry *prevEntry = nullptr;
+ for (const Entry &entry : array) {
+ if (prevEntry && prevEntry->flags == entry.flags) {
+ rpps.back().files.append(entry.fileName.toString());
+ continue;
+ }
+
+ prevEntry = &entry;
+
+ commonPath = rpps.empty()
+ ? entry.fileName.parentDir()
+ : Utils::FileUtils::commonPath(commonPath, entry.fileName);
CppTools::RawProjectPart rpp = makeRawProjectPart(projectFile,
m_kit.get(),
cToolchain,
cxxToolchain,
- object["directory"].toString(),
- fileName,
- flags);
- int rppIndex = Utils::indexOf(rpps, [&rpp](const CppTools::RawProjectPart &currentRpp) {
- return rpp.buildSystemTarget == currentRpp.buildSystemTarget
- && rpp.headerPaths == currentRpp.headerPaths
- && rpp.projectMacros == currentRpp.projectMacros
- && rpp.flagsForCxx.commandLineFlags == currentRpp.flagsForCxx.commandLineFlags;
- });
- if (rppIndex == -1)
- rpps.append(rpp);
- else
- rpps[rppIndex].files.append(rpp.files);
+ entry.workingDir,
+ entry.fileName,
+ entry.flags);
+
+ rpps.append(rpp);
}
- createFolders(root.get(), commonPath);
+ createTree(root.get(), commonPath, rpps);
root->addNode(std::make_unique<FileNode>(
projectFile,
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
index 2dd20dd9e5f..1884aa1c6d3 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
@@ -81,6 +81,19 @@ static CppTools::ProjectFile::Kind fileKindFromString(QString flag)
return ProjectFile::Unclassified;
}
+QStringList filterFromFileName(const QStringList &flags, QString baseName)
+{
+ baseName.append('.'); // to match name.c, name.o, etc.
+ QStringList result;
+ result.reserve(flags.size());
+ for (const QString &flag : flags) {
+ if (!flag.contains(baseName))
+ result.push_back(flag);
+ }
+
+ return result;
+}
+
void filteredFlags(const QString &fileName,
const QString &workingDir,
QStringList &flags,
@@ -88,13 +101,13 @@ void filteredFlags(const QString &fileName,
Macros &macros,
CppTools::ProjectFile::Kind &fileKind)
{
- if (flags.isEmpty())
+ if (flags.empty())
return;
// Skip compiler call if present.
bool skipNext = Utils::HostOsInfo::isWindowsHost()
- ? (!flags.first().startsWith('/') && !flags.first().startsWith('-'))
- : (!flags.first().startsWith('-'));
+ ? (!flags.front().startsWith('/') && !flags.front().startsWith('-'))
+ : (!flags.front().startsWith('-'));
Utils::optional<HeaderPathType> includePathType;
Utils::optional<MacroType> macroType;
bool fileKindIsNext = false;
@@ -121,11 +134,6 @@ void filteredFlags(const QString &fileName,
continue;
}
- if (flag == "-o") {
- skipNext = true;
- continue;
- }
-
if (flag != "-x"
&& (fileKindIsNext || flag == "/TC" || flag == "/TP"
|| flag.startsWith("/Tc") || flag.startsWith("/Tp") || flag.startsWith("-x"))) {
@@ -139,16 +147,13 @@ void filteredFlags(const QString &fileName,
continue;
}
- if (flag == "-c" || flag == "-pedantic"
+ if (flag == "-o" || flag == "-MF" || flag == "-c" || flag == "-pedantic"
|| flag.startsWith("-O") || flag.startsWith("-W") || flag.startsWith("-w")
|| QString::compare(flag, "-fpic", Qt::CaseInsensitive) == 0
|| QString::compare(flag, "-fpie", Qt::CaseInsensitive) == 0) {
continue;
}
- if (flag.endsWith(fileName))
- continue;
-
if ((flag.startsWith("-I") || flag.startsWith("-isystem") || flag.startsWith("/I"))
&& flag != "-I" && flag != "-isystem" && flag != "/I") {
bool userInclude = flag.startsWith("-I");
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
index 5e123a8c271..e465b6ba23c 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
@@ -38,6 +38,8 @@ class Macro;
namespace CompilationDatabaseProjectManager {
+QStringList filterFromFileName(const QStringList &flags, QString baseName);
+
void filteredFlags(const QString &fileName,
const QString &workingDir,
QStringList &flags,