Files
QodeAssist/tools/ListProjectFilesTool.cpp
2026-04-21 08:57:06 +02:00

129 lines
3.9 KiB
C++

// Copyright (C) 2025-2026 Petr Mironychev
// SPDX-License-Identifier: GPL-3.0-or-later
#include "ListProjectFilesTool.hpp"
#include <LLMQore/ToolExceptions.hpp>
#include <logger/Logger.hpp>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <QDir>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonObject>
#include <QtConcurrent>
namespace QodeAssist::Tools {
ListProjectFilesTool::ListProjectFilesTool(QObject *parent)
: BaseTool(parent)
, m_ignoreManager(new Context::IgnoreManager(this))
{}
QString ListProjectFilesTool::id() const
{
return "list_project_files";
}
QString ListProjectFilesTool::displayName() const
{
return {"Reading project files list"};
}
QString ListProjectFilesTool::description() const
{
return "List every source file tracked by the active Qt Creator project(s), filtered by "
".qodeassistignore. Returns absolute and project-relative paths grouped by project. "
"Useful for discovering the project layout before running focused searches or reads. "
"Takes no parameters.";
}
QJsonObject ListProjectFilesTool::parametersSchema() const
{
QJsonObject definition;
definition["type"] = "object";
definition["properties"] = QJsonObject();
definition["required"] = QJsonArray();
return definition;
}
QFuture<LLMQore::ToolResult> ListProjectFilesTool::executeAsync(const QJsonObject &input)
{
Q_UNUSED(input)
return QtConcurrent::run([this]() -> LLMQore::ToolResult {
QList<ProjectExplorer::Project *> projects = ProjectExplorer::ProjectManager::projects();
if (projects.isEmpty()) {
QString error = "No projects found";
throw LLMQore::ToolRuntimeError(error);
}
QString result;
for (auto project : projects) {
if (!project)
continue;
Utils::FilePaths projectFiles = project->files(ProjectExplorer::Project::SourceFiles);
if (projectFiles.isEmpty()) {
result += QString("Project '%1': No source files found\n\n")
.arg(project->displayName());
continue;
}
QStringList fileList;
QString projectPath = project->projectDirectory().toUrlishString();
QString projectAbsolutePath = project->projectDirectory().toFSPathString();
for (const auto &filePath : projectFiles) {
QString absolutePath = filePath.toUrlishString();
if (m_ignoreManager->shouldIgnore(absolutePath, project)) {
LOG_MESSAGE(
QString("Ignoring file due to .qodeassistignore: %1").arg(absolutePath));
continue;
}
QString relativePath = QDir(projectPath).relativeFilePath(absolutePath);
fileList.append(relativePath);
}
if (fileList.isEmpty()) {
result += QString("Project '%1': No files after applying .qodeassistignore\n\n")
.arg(project->displayName());
continue;
}
fileList.sort();
result += QString("Project '%1' (%2 files):\n")
.arg(project->displayName())
.arg(fileList.size());
result += QString("Project root: %1\n\n").arg(projectAbsolutePath);
for (const QString &file : fileList) {
result += QString("- %1\n").arg(file);
}
result += "\n";
}
return LLMQore::ToolResult::text(result.trimmed());
});
}
QString ListProjectFilesTool::formatFileList(const QStringList &files) const
{
QString result = QString("Project files (%1 total):\n\n").arg(files.size());
for (const QString &file : files) {
result += QString("- %1\n").arg(file);
}
return result;
}
} // namespace QodeAssist::Tools