diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp index 444d9b873a2..5f860956026 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp @@ -18,11 +18,97 @@ #include #include +#include + using namespace ProjectExplorer; using namespace Utils; -namespace CompilationDatabaseProjectManager { -namespace Internal { +namespace CompilationDatabaseProjectManager::Internal { + +static QStringList jsonObjectFlags(const QJsonObject &object, QSet &flagsCache) +{ + QStringList flags; + const QJsonArray arguments = object["arguments"].toArray(); + if (arguments.isEmpty()) { + flags = splitCommandLine(object["command"].toString(), flagsCache); + } else { + flags.reserve(arguments.size()); + for (const QJsonValue &arg : arguments) { + auto flagIt = flagsCache.insert(arg.toString()); + flags.append(*flagIt); + } + } + return flags; +} + +static FilePath jsonObjectFilePath(const QJsonObject &object) +{ + const FilePath workingDir = FilePath::fromUserInput(object["directory"].toString()); + return workingDir.resolvePath(object["file"].toString()); +} + +static std::vector readJsonObjects(const QByteArray &projectFileContents) +{ + std::vector result; + + int objectStart = projectFileContents.indexOf('{'); + int objectEnd = projectFileContents.indexOf('}', objectStart + 1); + + QSet flagsCache; + while (objectStart >= 0 && objectEnd >= 0) { + const QJsonDocument document = QJsonDocument::fromJson( + projectFileContents.mid(objectStart, objectEnd - objectStart + 1)); + if (document.isNull()) { + // The end was found incorrectly, search for the next one. + objectEnd = projectFileContents.indexOf('}', objectEnd + 1); + continue; + } + + const QJsonObject object = document.object(); + const FilePath filePath = jsonObjectFilePath(object); + const QStringList flags = filterFromFileName(jsonObjectFlags(object, flagsCache), + filePath.fileName()); + result.push_back({flags, filePath, FilePath::fromUserInput(object["directory"].toString())}); + + objectStart = projectFileContents.indexOf('{', objectEnd + 1); + objectEnd = projectFileContents.indexOf('}', objectStart + 1); + } + return result; +} + +static QStringList readExtraFiles(const QString &filePath) +{ + QStringList result; + + QFile file(filePath); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString line = stream.readLine().trimmed(); + if (line.isEmpty() || line.startsWith('#')) + continue; + + result.push_back(line); + } + } + return result; +} + +static DbContents parseProject(const QByteArray &projectFileContents, + const FilePath &projectFilePath) +{ + DbContents dbContents; + dbContents.entries = readJsonObjects(projectFileContents); + dbContents.extraFileName = projectFilePath.toString() + + Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX; + dbContents.extras = readExtraFiles(dbContents.extraFileName); + std::sort(dbContents.entries.begin(), dbContents.entries.end(), + [](const DbEntry &lhs, const DbEntry &rhs) { + return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(), + rhs.flags.begin(), rhs.flags.end()); + }); + return dbContents; +} CompilationDbParser::CompilationDbParser(const QString &projectName, const FilePath &projectPath, @@ -82,7 +168,7 @@ void CompilationDbParser::start() return isIgnored; }); - m_treeScanner->setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FilePath &fn) { + m_treeScanner->setTypeFactory([](const MimeType &mimeType, const FilePath &fn) { return TreeScanner::genericFileType(mimeType, fn); }); m_treeScanner->asyncScanForFiles(m_rootPath); @@ -95,7 +181,7 @@ void CompilationDbParser::start() } // Thread 2: Parse the project file. - const QFuture future = Utils::asyncRun(&CompilationDbParser::parseProject, this); + const auto future = Utils::asyncRun(parseProject, m_projectFileContents, m_projectFilePath); Core::ProgressManager::addTask(future, Tr::tr("Parse \"%1\" project").arg(m_projectName), "CompilationDatabase.Parse"); @@ -138,94 +224,4 @@ void CompilationDbParser::finish(ParseResult result) deleteLater(); } -static QStringList jsonObjectFlags(const QJsonObject &object, QSet &flagsCache) -{ - QStringList flags; - const QJsonArray arguments = object["arguments"].toArray(); - if (arguments.isEmpty()) { - flags = splitCommandLine(object["command"].toString(), flagsCache); - } else { - flags.reserve(arguments.size()); - for (const QJsonValue &arg : arguments) { - auto flagIt = flagsCache.insert(arg.toString()); - flags.append(*flagIt); - } - } - - return flags; -} - -static FilePath jsonObjectFilePath(const QJsonObject &object) -{ - const FilePath workingDir = FilePath::fromUserInput(object["directory"].toString()); - return workingDir.resolvePath(object["file"].toString()); -} - -std::vector CompilationDbParser::readJsonObjects() const -{ - std::vector result; - - int objectStart = m_projectFileContents.indexOf('{'); - int objectEnd = m_projectFileContents.indexOf('}', objectStart + 1); - - QSet flagsCache; - while (objectStart >= 0 && objectEnd >= 0) { - const QJsonDocument document = QJsonDocument::fromJson( - m_projectFileContents.mid(objectStart, objectEnd - objectStart + 1)); - if (document.isNull()) { - // The end was found incorrectly, search for the next one. - objectEnd = m_projectFileContents.indexOf('}', objectEnd + 1); - continue; - } - - const QJsonObject object = document.object(); - const Utils::FilePath filePath = jsonObjectFilePath(object); - const QStringList flags = filterFromFileName(jsonObjectFlags(object, flagsCache), - filePath.fileName()); - result.push_back({flags, filePath, FilePath::fromUserInput(object["directory"].toString())}); - - objectStart = m_projectFileContents.indexOf('{', objectEnd + 1); - objectEnd = m_projectFileContents.indexOf('}', objectStart + 1); - } - - return result; -} - -static QStringList readExtraFiles(const QString &filePath) -{ - QStringList result; - - QFile file(filePath); - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - - while (!stream.atEnd()) { - const QString line = stream.readLine().trimmed(); - - if (line.isEmpty() || line.startsWith('#')) - continue; - - result.push_back(line); - } - } - - return result; -} - -DbContents CompilationDbParser::parseProject() -{ - DbContents dbContents; - dbContents.entries = readJsonObjects(); - dbContents.extraFileName = m_projectFilePath.toString() + - Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX; - dbContents.extras = readExtraFiles(dbContents.extraFileName); - std::sort(dbContents.entries.begin(), dbContents.entries.end(), - [](const DbEntry &lhs, const DbEntry &rhs) { - return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(), - rhs.flags.begin(), rhs.flags.end()); - }); - return dbContents; -} - -} // namespace Internal -} // namespace CompilationDatabaseProjectManager +} // namespace CompilationDatabaseProjectManager::Internal diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h index d0d8eb80798..a06ba82581e 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h @@ -10,19 +10,15 @@ #include #include -#include #include #include -#include - namespace ProjectExplorer { class FileNode; class TreeScanner; } -namespace CompilationDatabaseProjectManager { -namespace Internal { +namespace CompilationDatabaseProjectManager::Internal { enum class ParseResult { Success, Failure, Cached }; @@ -56,8 +52,6 @@ signals: private: void parserJobFinished(); void finish(ParseResult result); - DbContents parseProject(); - std::vector readJsonObjects() const; const QString m_projectName; const Utils::FilePath m_projectFilePath; @@ -73,5 +67,4 @@ private: ProjectExplorer::BuildSystem::ParseGuard m_guard; }; -} // namespace Internal -} // namespace CompilationDatabaseProjectManager +} // namespace CompilationDatabaseProjectManager::Internal