forked from qt-creator/qt-creator
CMakeProjectManager: Add File System virtual folder
If a CMake project cannot be parsed by CMake, it is practically unusable in Qt Creator. According to discussion in QTCREATORBUG-24677, a virtual folder with the project's file system view is added to the project manager as a convenience feature. Fixes: QTCREATORBUG-24677 Change-Id: I48775bb89c704d3f7e5bb21ec6481bd5cc0f4b6c Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -517,11 +517,11 @@ void CMakeBuildSystem::clearCMakeCache()
|
|||||||
Utils::FileUtils::removeRecursively(cmakeFiles);
|
Utils::FileUtils::removeRecursively(cmakeFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CMakeProjectNode>
|
std::unique_ptr<CMakeProjectNode> CMakeBuildSystem::generateProjectTree(
|
||||||
CMakeBuildSystem::generateProjectTree(const QList<const FileNode *> &allFiles)
|
const QList<const FileNode *> &allFiles, bool includeHeaderNodes)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
auto root = m_reader.generateProjectTree(allFiles, errorMessage);
|
auto root = m_reader.generateProjectTree(allFiles, errorMessage, includeHeaderNodes);
|
||||||
checkAndReportError(errorMessage);
|
checkAndReportError(errorMessage);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
@@ -535,6 +535,8 @@ void CMakeBuildSystem::combineScanAndParse()
|
|||||||
if (m_combinedScanAndParseResult) {
|
if (m_combinedScanAndParseResult) {
|
||||||
updateProjectData();
|
updateProjectData();
|
||||||
m_currentGuard.markAsSuccess();
|
m_currentGuard.markAsSuccess();
|
||||||
|
} else {
|
||||||
|
updateFallbackProjectData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +592,7 @@ void CMakeBuildSystem::updateProjectData()
|
|||||||
|
|
||||||
Project *p = project();
|
Project *p = project();
|
||||||
{
|
{
|
||||||
auto newRoot = generateProjectTree(m_allFiles);
|
auto newRoot = generateProjectTree(m_allFiles, true);
|
||||||
if (newRoot) {
|
if (newRoot) {
|
||||||
setRootProjectNode(std::move(newRoot));
|
setRootProjectNode(std::move(newRoot));
|
||||||
CMakeConfigItem settingFileItem;
|
CMakeConfigItem settingFileItem;
|
||||||
@@ -671,6 +673,18 @@ void CMakeBuildSystem::updateProjectData()
|
|||||||
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
|
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMakeBuildSystem::updateFallbackProjectData()
|
||||||
|
{
|
||||||
|
qCDebug(cmakeBuildSystemLog) << "Updating fallback CMake project data";
|
||||||
|
|
||||||
|
QTC_ASSERT(m_treeScanner.isFinished() && !m_reader.isParsing(), return );
|
||||||
|
|
||||||
|
auto newRoot = generateProjectTree(m_allFiles, false);
|
||||||
|
setRootProjectNode(std::move(newRoot));
|
||||||
|
|
||||||
|
qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date.";
|
||||||
|
}
|
||||||
|
|
||||||
void CMakeBuildSystem::handleParsingSucceeded()
|
void CMakeBuildSystem::handleParsingSucceeded()
|
||||||
{
|
{
|
||||||
if (!cmakeBuildConfiguration()->isActive()) {
|
if (!cmakeBuildConfiguration()->isActive()) {
|
||||||
|
@@ -123,11 +123,11 @@ private:
|
|||||||
void combineScanAndParse();
|
void combineScanAndParse();
|
||||||
|
|
||||||
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
||||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
const QList<const ProjectExplorer::FileNode *> &allFiles, bool includeHeadersNode);
|
||||||
|
|
||||||
void checkAndReportError(QString &errorMessage);
|
void checkAndReportError(QString &errorMessage);
|
||||||
|
|
||||||
void updateProjectData();
|
void updateProjectData();
|
||||||
|
void updateFallbackProjectData();
|
||||||
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers();
|
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers();
|
||||||
void updateQmlJSCodeModel();
|
void updateQmlJSCodeModel();
|
||||||
|
|
||||||
|
@@ -692,5 +692,29 @@ FileApiQtcData extractData(FileApiData &input,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileApiQtcData generateFallbackData(const FilePath &topCmakeFile,
|
||||||
|
const FilePath &sourceDirectory,
|
||||||
|
const FilePath &buildDirectory,
|
||||||
|
QString errorMessage)
|
||||||
|
{
|
||||||
|
FileApiQtcData result;
|
||||||
|
|
||||||
|
result.rootProjectNode.reset(new CMakeProjectNode{sourceDirectory});
|
||||||
|
result.rootProjectNode->setDisplayName(sourceDirectory.fileName());
|
||||||
|
result.errorMessage = errorMessage;
|
||||||
|
|
||||||
|
if (!topCmakeFile.isEmpty()) {
|
||||||
|
auto node = std::make_unique<FileNode>(topCmakeFile, FileType::Project);
|
||||||
|
node->setIsGenerated(false);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<FileNode>> fileNodes;
|
||||||
|
fileNodes.emplace_back(std::move(node));
|
||||||
|
|
||||||
|
addCMakeLists(result.rootProjectNode.get(), std::move(fileNodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include <projectexplorer/rawprojectpart.h>
|
#include <projectexplorer/rawprojectpart.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/optional.h>
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
@@ -58,6 +59,10 @@ public:
|
|||||||
FileApiQtcData extractData(FileApiData &data,
|
FileApiQtcData extractData(FileApiData &data,
|
||||||
const Utils::FilePath &sourceDirectory,
|
const Utils::FilePath &sourceDirectory,
|
||||||
const Utils::FilePath &buildDirectory);
|
const Utils::FilePath &buildDirectory);
|
||||||
|
FileApiQtcData generateFallbackData(const Utils::FilePath &topCmakeFile,
|
||||||
|
const Utils::FilePath &sourceDirectory,
|
||||||
|
const Utils::FilePath &buildDirectory,
|
||||||
|
QString errorMessage);
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
@@ -193,11 +193,14 @@ CMakeConfig FileApiReader::takeParsedConfiguration(QString &errorMessage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CMakeProjectNode> FileApiReader::generateProjectTree(
|
std::unique_ptr<CMakeProjectNode> FileApiReader::generateProjectTree(
|
||||||
const QList<const FileNode *> &allFiles, QString &errorMessage)
|
const QList<const FileNode *> &allFiles, QString &errorMessage, bool includeHeaderNodes)
|
||||||
{
|
{
|
||||||
Q_UNUSED(errorMessage)
|
Q_UNUSED(errorMessage)
|
||||||
|
|
||||||
|
if (includeHeaderNodes) {
|
||||||
addHeaderNodes(m_rootProjectNode.get(), m_knownHeaders, allFiles);
|
addHeaderNodes(m_rootProjectNode.get(), m_knownHeaders, allFiles);
|
||||||
|
}
|
||||||
|
addFileSystemNodes(m_rootProjectNode.get(), allFiles);
|
||||||
return std::move(m_rootProjectNode);
|
return std::move(m_rootProjectNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,19 +233,23 @@ void FileApiReader::endState(const QFileInfo &replyFi)
|
|||||||
|
|
||||||
const FilePath sourceDirectory = m_parameters.sourceDirectory;
|
const FilePath sourceDirectory = m_parameters.sourceDirectory;
|
||||||
const FilePath buildDirectory = m_parameters.workDirectory;
|
const FilePath buildDirectory = m_parameters.workDirectory;
|
||||||
|
const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? *m_cmakeFiles.begin() : FilePath{};
|
||||||
|
|
||||||
m_lastReplyTimestamp = replyFi.lastModified();
|
m_lastReplyTimestamp = replyFi.lastModified();
|
||||||
|
|
||||||
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
|
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
|
||||||
[replyFi, sourceDirectory, buildDirectory]() {
|
[replyFi, sourceDirectory, buildDirectory, topCmakeFile]() {
|
||||||
auto result = std::make_unique<FileApiQtcData>();
|
auto result = std::make_unique<FileApiQtcData>();
|
||||||
FileApiData data = FileApiParser::parseData(replyFi,
|
FileApiData data = FileApiParser::parseData(replyFi, result->errorMessage);
|
||||||
result->errorMessage);
|
|
||||||
if (!result->errorMessage.isEmpty()) {
|
if (!result->errorMessage.isEmpty()) {
|
||||||
qWarning() << result->errorMessage;
|
qWarning() << result->errorMessage;
|
||||||
return result.release();
|
*result = generateFallbackData(topCmakeFile,
|
||||||
}
|
sourceDirectory,
|
||||||
|
buildDirectory,
|
||||||
|
result->errorMessage);
|
||||||
|
} else {
|
||||||
*result = extractData(data, sourceDirectory, buildDirectory);
|
*result = extractData(data, sourceDirectory, buildDirectory);
|
||||||
|
}
|
||||||
if (!result->errorMessage.isEmpty()) {
|
if (!result->errorMessage.isEmpty()) {
|
||||||
qWarning() << result->errorMessage;
|
qWarning() << result->errorMessage;
|
||||||
}
|
}
|
||||||
|
@@ -67,7 +67,9 @@ public:
|
|||||||
QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage);
|
QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage);
|
||||||
CMakeConfig takeParsedConfiguration(QString &errorMessage);
|
CMakeConfig takeParsedConfiguration(QString &errorMessage);
|
||||||
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
||||||
const QList<const ProjectExplorer::FileNode *> &allFiles, QString &errorMessage);
|
const QList<const ProjectExplorer::FileNode *> &allFiles,
|
||||||
|
QString &errorMessage,
|
||||||
|
bool includeHeaderNodes);
|
||||||
ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage);
|
ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@@ -208,5 +208,31 @@ void addHeaderNodes(ProjectNode *root,
|
|||||||
root->addNode(std::move(headerNode));
|
root->addNode(std::move(headerNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addFileSystemNodes(ProjectNode *root, const QList<const FileNode *> &allFiles)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(root, return );
|
||||||
|
|
||||||
|
static QIcon fileSystemNodeIcon = Core::FileIconProvider::directoryIcon(
|
||||||
|
ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN);
|
||||||
|
auto fileSystemNode = std::make_unique<VirtualFolderNode>(root->filePath());
|
||||||
|
fileSystemNode->setPriority(Node::DefaultPriority - 6);
|
||||||
|
fileSystemNode->setDisplayName(
|
||||||
|
QCoreApplication::translate("CMakeProjectManager::Internal::ProjectTreeHelper",
|
||||||
|
"<File System>"));
|
||||||
|
fileSystemNode->setIcon(fileSystemNodeIcon);
|
||||||
|
|
||||||
|
for (const FileNode *fn : allFiles) {
|
||||||
|
if (!fn->filePath().isChildOf(root->filePath()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::unique_ptr<FileNode> node(fn->clone());
|
||||||
|
node->setEnabled(false);
|
||||||
|
fileSystemNode->addNestedNode(std::move(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileSystemNode->isEmpty())
|
||||||
|
root->addNode(std::move(fileSystemNode));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
@@ -68,5 +68,7 @@ void addHeaderNodes(ProjectExplorer::ProjectNode *root,
|
|||||||
QSet<Utils::FilePath> &seenHeaders,
|
QSet<Utils::FilePath> &seenHeaders,
|
||||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||||
|
|
||||||
|
void addFileSystemNodes(ProjectExplorer::ProjectNode *root,
|
||||||
|
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
Reference in New Issue
Block a user