refactor: IProjectScanner port; ContextManager QtC-free

This commit is contained in:
Petr Mironychev
2026-06-11 15:21:02 +02:00
parent f36173d932
commit 69672deb45
12 changed files with 435 additions and 115 deletions

View File

@@ -2,6 +2,8 @@ add_library(Context STATIC
DocumentContextReader.hpp DocumentContextReader.cpp
ChangesManager.h ChangesManager.cpp
ContextManager.hpp ContextManager.cpp
IProjectScanner.hpp
ProjectScannerQtCreator.hpp ProjectScannerQtCreator.cpp
ContentFile.hpp
DocumentReaderQtCreator.hpp
IDocumentReader.hpp

View File

@@ -6,25 +6,24 @@
#include <QFile>
#include <QFileInfo>
#include <QJsonObject>
#include <QTextStream>
#include "settings/GeneralSettings.hpp"
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projectnodes.h>
#include <texteditor/textdocument.h>
#include "Logger.hpp"
#include "ProjectScannerQtCreator.hpp"
namespace QodeAssist::Context {
ContextManager::ContextManager(QObject *parent)
: QObject(parent)
, m_ignoreManager(new IgnoreManager(this))
: ContextManager(std::make_unique<ProjectScannerQtCreator>(), parent)
{}
ContextManager::ContextManager(std::unique_ptr<IProjectScanner> scanner, QObject *parent)
: QObject(parent)
, m_scanner(std::move(scanner))
{}
ContextManager::~ContextManager() = default;
QString ContextManager::readFile(const QString &filePath) const
{
QFile file(filePath);
@@ -37,7 +36,7 @@ QString ContextManager::readFile(const QString &filePath) const
QTextStream in(&file);
QString content = in.readAll();
file.close();
return content;
}
@@ -45,9 +44,7 @@ QList<ContentFile> ContextManager::getContentFiles(const QStringList &filePaths)
{
QList<ContentFile> files;
for (const QString &path : filePaths) {
auto project = ProjectExplorer::ProjectManager::projectForFile(
Utils::FilePath::fromString(path));
if (project && m_ignoreManager->shouldIgnore(path, project)) {
if (m_scanner->shouldIgnore(path)) {
LOG_MESSAGE(QString("Ignoring file in context due to .qodeassistignore: %1").arg(path));
continue;
}
@@ -58,27 +55,6 @@ QList<ContentFile> ContextManager::getContentFiles(const QStringList &filePaths)
return files;
}
QStringList ContextManager::getProjectSourceFiles(ProjectExplorer::Project *project) const
{
QStringList sourceFiles;
if (!project)
return sourceFiles;
auto projectNode = project->rootProjectNode();
if (!projectNode)
return sourceFiles;
projectNode->forEachNode(
[&sourceFiles, this](ProjectExplorer::FileNode *fileNode) {
if (fileNode /*&& shouldProcessFile(fileNode->filePath().toString())*/) {
sourceFiles.append(fileNode->filePath().toUrlishString());
}
},
nullptr);
return sourceFiles;
}
ContentFile ContextManager::createContentFile(const QString &filePath) const
{
ContentFile contentFile;
@@ -101,72 +77,25 @@ ProgrammingLanguage ContextManager::getDocumentLanguage(const DocumentInfo &docu
bool ContextManager::isSpecifyCompletion(const DocumentInfo &documentInfo) const
{
Q_UNUSED(documentInfo)
// Language-specific completion presets were replaced by agent match rules.
return false;
}
QList<QPair<QString, QString>> ContextManager::openedFiles(const QStringList excludeFiles) const
{
auto documents = Core::DocumentModel::openedDocuments();
QList<QPair<QString, QString>> files;
for (const auto *document : std::as_const(documents)) {
auto textDocument = qobject_cast<const TextEditor::TextDocument *>(document);
if (!textDocument)
continue;
auto filePath = textDocument->filePath().toUrlishString();
auto project = ProjectExplorer::ProjectManager::projectForFile(textDocument->filePath());
if (project && m_ignoreManager->shouldIgnore(filePath, project)) {
LOG_MESSAGE(
QString("Ignoring file in context due to .qodeassistignore: %1").arg(filePath));
continue;
}
if (!excludeFiles.contains(filePath)) {
files.append({filePath, textDocument->plainText()});
}
}
return files;
}
QString ContextManager::openedFilesContext(const QStringList excludeFiles)
QString ContextManager::openedFilesContext(const QStringList &excludeFiles) const
{
QString context = "User files context:\n";
auto documents = Core::DocumentModel::openedDocuments();
for (const auto *document : documents) {
auto textDocument = qobject_cast<const TextEditor::TextDocument *>(document);
if (!textDocument)
continue;
auto filePath = textDocument->filePath().toUrlishString();
if (excludeFiles.contains(filePath))
continue;
auto project = ProjectExplorer::ProjectManager::projectForFile(textDocument->filePath());
if (project && m_ignoreManager->shouldIgnore(filePath, project)) {
LOG_MESSAGE(
QString("Ignoring file in context due to .qodeassistignore: %1").arg(filePath));
continue;
}
context += QString("File: %1\n").arg(filePath);
context += textDocument->plainText();
for (const auto &file : m_scanner->openedTextFiles(excludeFiles)) {
context += QString("File: %1\n").arg(file.filePath);
context += file.content;
context += "\n";
}
return context;
}
IgnoreManager *ContextManager::ignoreManager() const
bool ContextManager::shouldIgnore(const QString &filePath) const
{
return m_ignoreManager;
return m_scanner->shouldIgnore(filePath);
}
} // namespace QodeAssist::Context

View File

@@ -4,18 +4,16 @@
#pragma once
#include <memory>
#include <QObject>
#include <QString>
#include "ContentFile.hpp"
#include "IContextManager.hpp"
#include "IgnoreManager.hpp"
#include "IProjectScanner.hpp"
#include "ProgrammingLanguage.hpp"
namespace ProjectExplorer {
class Project;
}
namespace QodeAssist::Context {
class ContextManager : public QObject, public IContextManager
@@ -24,22 +22,22 @@ class ContextManager : public QObject, public IContextManager
public:
explicit ContextManager(QObject *parent = nullptr);
~ContextManager() override = default;
ContextManager(std::unique_ptr<IProjectScanner> scanner, QObject *parent = nullptr);
~ContextManager() override;
QString readFile(const QString &filePath) const override;
QList<ContentFile> getContentFiles(const QStringList &filePaths) const override;
QStringList getProjectSourceFiles(ProjectExplorer::Project *project) const override;
ContentFile createContentFile(const QString &filePath) const override;
ProgrammingLanguage getDocumentLanguage(const DocumentInfo &documentInfo) const override;
bool isSpecifyCompletion(const DocumentInfo &documentInfo) const override;
QList<QPair<QString, QString>> openedFiles(const QStringList excludeFiles = QStringList{}) const;
QString openedFilesContext(const QStringList excludeFiles = QStringList{});
IgnoreManager *ignoreManager() const;
QString openedFilesContext(const QStringList &excludeFiles = QStringList{}) const;
bool shouldIgnore(const QString &filePath) const;
private:
IgnoreManager *m_ignoreManager;
std::unique_ptr<IProjectScanner> m_scanner;
};
} // namespace QodeAssist::Context

View File

@@ -11,10 +11,6 @@
#include "IDocumentReader.hpp"
#include "ProgrammingLanguage.hpp"
namespace ProjectExplorer {
class Project;
}
namespace QodeAssist::Context {
class IContextManager
@@ -24,7 +20,6 @@ public:
virtual QString readFile(const QString &filePath) const = 0;
virtual QList<ContentFile> getContentFiles(const QStringList &filePaths) const = 0;
virtual QStringList getProjectSourceFiles(ProjectExplorer::Project *project) const = 0;
virtual ContentFile createContentFile(const QString &filePath) const = 0;
virtual ProgrammingLanguage getDocumentLanguage(const DocumentInfo &documentInfo) const = 0;

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2024-2026 Petr Mironychev
// SPDX-License-Identifier: GPL-3.0-or-later
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
#pragma once
#include <QList>
#include <QString>
#include <QStringList>
namespace QodeAssist::Context {
struct OpenedTextFile
{
QString filePath;
QString content;
};
class IProjectScanner
{
public:
virtual ~IProjectScanner() = default;
virtual QList<OpenedTextFile> openedTextFiles(const QStringList &excludeFiles = {}) const = 0;
virtual bool shouldIgnore(const QString &filePath) const = 0;
};
} // namespace QodeAssist::Context

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2024-2026 Petr Mironychev
// SPDX-License-Identifier: GPL-3.0-or-later
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
#include "ProjectScannerQtCreator.hpp"
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <texteditor/textdocument.h>
#include <utils/filepath.h>
#include "IgnoreManager.hpp"
namespace QodeAssist::Context {
ProjectScannerQtCreator::ProjectScannerQtCreator()
: m_ignoreManager(std::make_unique<IgnoreManager>())
{}
ProjectScannerQtCreator::~ProjectScannerQtCreator() = default;
QList<OpenedTextFile> ProjectScannerQtCreator::openedTextFiles(
const QStringList &excludeFiles) const
{
QList<OpenedTextFile> files;
const auto documents = Core::DocumentModel::openedDocuments();
for (const auto *document : documents) {
const auto *textDocument = qobject_cast<const TextEditor::TextDocument *>(document);
if (!textDocument)
continue;
const QString filePath = textDocument->filePath().toUrlishString();
if (excludeFiles.contains(filePath))
continue;
if (shouldIgnore(filePath))
continue;
files.append({filePath, textDocument->plainText()});
}
return files;
}
bool ProjectScannerQtCreator::shouldIgnore(const QString &filePath) const
{
auto *project = ProjectExplorer::ProjectManager::projectForFile(
Utils::FilePath::fromString(filePath));
return project && m_ignoreManager->shouldIgnore(filePath, project);
}
} // namespace QodeAssist::Context

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2024-2026 Petr Mironychev
// SPDX-License-Identifier: GPL-3.0-or-later
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
#pragma once
#include <memory>
#include "IProjectScanner.hpp"
namespace QodeAssist::Context {
class IgnoreManager;
class ProjectScannerQtCreator : public IProjectScanner
{
public:
ProjectScannerQtCreator();
~ProjectScannerQtCreator() override;
QList<OpenedTextFile> openedTextFiles(const QStringList &excludeFiles = {}) const override;
bool shouldIgnore(const QString &filePath) const override;
private:
std::unique_ptr<IgnoreManager> m_ignoreManager;
};
} // namespace QodeAssist::Context