// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "virtualfilesystemoverlay.h" #include #include #include #include #include #include #include #include static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.vfso", QtWarningMsg) namespace ClangTools { namespace Internal { VirtualFileSystemOverlay::VirtualFileSystemOverlay(const QString &rootPattern) : m_root(rootPattern) , m_overlayFilePath(m_root.filePath("vfso.yaml")) { } void VirtualFileSystemOverlay::update() { overlayFilePath().removeRecursively(); std::map> documentRoots; const QList &modifiedDocuments = Core::DocumentManager::modifiedDocuments(); QHash newSaved; for (Core::IDocument *doc : modifiedDocuments) { auto document = qobject_cast(doc); if (!document) continue; documentRoots[doc->filePath().absolutePath()] << doc; AutoSavedPath saved = m_saved.take(document); if (saved.revision != document->document()->revision()) { saved.path.removeRecursively(); saved.revision = document->document()->revision(); saved.path = m_root.filePath(doc->filePath().fileName() + ".auto"); while (saved.path.exists()) saved.path = saved.path.stringAppended(".1"); if (Utils::Result res = doc->save(saved.path, true); !res) { qCDebug(LOG) << res.error(); continue; } } newSaved[doc] = saved; } for (const AutoSavedPath &path : std::as_const(m_saved)) { QString error; if (!path.path.removeRecursively(&error)) qCDebug(LOG) << error; } m_saved = newSaved; m_mapping.clear(); for (auto it = m_saved.constBegin(), end = m_saved.constEnd(); it != end; ++it) m_mapping[it.value().path] = it.key()->filePath(); auto toContent = [this](Core::IDocument *document) { QJsonObject content; content["name"] = document->filePath().fileName(); content["type"] = "file"; content["external-contents"] = m_saved[document].path.toUserOutput(); return content; }; QJsonObject main; main["version"] = 0; QJsonArray jsonRoots; for (auto [root, documents] : documentRoots) { QJsonObject jsonRoot; jsonRoot["type"] = "directory"; jsonRoot["name"] = root.toUserOutput(); QJsonArray contents; for (auto doc : std::as_const(documents)) contents << toContent(doc); jsonRoot["contents"] = contents; jsonRoots << jsonRoot; } main["roots"] = jsonRoots; QJsonDocument overlay(main); const Utils::expected_str res = m_overlayFilePath.writeFileContents( overlay.toJson(QJsonDocument::Compact)); if (!res) qCDebug(LOG) << "failed to write vfso to " << m_overlayFilePath; } Utils::FilePath VirtualFileSystemOverlay::overlayFilePath() const { return m_overlayFilePath; } Utils::FilePath VirtualFileSystemOverlay::autoSavedFilePath(Core::IDocument *doc) const { const auto it = m_saved.constFind(doc); if (it != m_saved.constEnd()) return it.value().path; return doc->filePath(); } Utils::FilePath VirtualFileSystemOverlay::originalFilePath(const Utils::FilePath &file) const { return m_mapping.value(file, file); } } // namespace Internal } // namespace ClangTools