mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-05-27 19:00:30 -04:00
fix: Check patterns and remove filewatcher (#166)
* fix: Check patterns and remove filewatcher * fix: Don't show log for non-existent ignore file
This commit is contained in:
parent
2f9622e23e
commit
8cb6a2f6d2
@ -20,6 +20,8 @@
|
||||
#include "IgnoreManager.hpp"
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
@ -33,17 +35,52 @@ namespace QodeAssist::Context {
|
||||
IgnoreManager::IgnoreManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&m_fileWatcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
|
||||
for (auto it = m_projectIgnorePatterns.begin(); it != m_projectIgnorePatterns.end(); ++it) {
|
||||
if (ignoreFilePath(it.key()) == path) {
|
||||
reloadIgnorePatterns(it.key());
|
||||
break;
|
||||
auto projectManager = ProjectExplorer::ProjectManager::instance();
|
||||
if (projectManager) {
|
||||
connect(
|
||||
projectManager,
|
||||
&ProjectExplorer::ProjectManager::projectAdded,
|
||||
this,
|
||||
&IgnoreManager::reloadIgnorePatterns);
|
||||
|
||||
connect(
|
||||
projectManager,
|
||||
&ProjectExplorer::ProjectManager::projectRemoved,
|
||||
this,
|
||||
&IgnoreManager::removeIgnorePatterns);
|
||||
|
||||
const QList<ProjectExplorer::Project *> projects = projectManager->projects();
|
||||
for (ProjectExplorer::Project *project : projects) {
|
||||
if (project) {
|
||||
reloadIgnorePatterns(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
connect(
|
||||
QCoreApplication::instance(),
|
||||
&QCoreApplication::aboutToQuit,
|
||||
this,
|
||||
&IgnoreManager::cleanupConnections);
|
||||
}
|
||||
|
||||
IgnoreManager::~IgnoreManager() = default;
|
||||
IgnoreManager::~IgnoreManager()
|
||||
{
|
||||
cleanupConnections();
|
||||
}
|
||||
|
||||
void IgnoreManager::cleanupConnections()
|
||||
{
|
||||
QList<ProjectExplorer::Project *> projects = m_projectConnections.keys();
|
||||
for (ProjectExplorer::Project *project : projects) {
|
||||
if (project) {
|
||||
disconnect(m_projectConnections.take(project));
|
||||
}
|
||||
}
|
||||
m_projectConnections.clear();
|
||||
m_projectIgnorePatterns.clear();
|
||||
m_ignoreCache.clear();
|
||||
}
|
||||
|
||||
bool IgnoreManager::shouldIgnore(const QString &filePath, ProjectExplorer::Project *project) const
|
||||
{
|
||||
@ -64,29 +101,71 @@ bool IgnoreManager::shouldIgnore(const QString &filePath, ProjectExplorer::Proje
|
||||
return matchesIgnorePatterns(relativePath, patterns);
|
||||
}
|
||||
|
||||
void IgnoreManager::reloadIgnorePatterns(ProjectExplorer::Project *project)
|
||||
bool IgnoreManager::matchesIgnorePatterns(const QString &path, const QStringList &patterns) const
|
||||
{
|
||||
if (!project)
|
||||
return;
|
||||
QString cacheKey = path + ":" + patterns.join("|");
|
||||
if (m_ignoreCache.contains(cacheKey))
|
||||
return m_ignoreCache[cacheKey];
|
||||
|
||||
QStringList patterns = loadIgnorePatterns(project);
|
||||
m_projectIgnorePatterns[project] = patterns;
|
||||
bool result = isPathExcluded(path, patterns);
|
||||
m_ignoreCache.insert(cacheKey, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QString ignoreFile = ignoreFilePath(project);
|
||||
if (QFileInfo::exists(ignoreFile)) {
|
||||
if (m_fileWatcher.files().contains(ignoreFile))
|
||||
m_fileWatcher.removePath(ignoreFile);
|
||||
bool IgnoreManager::isPathExcluded(const QString &path, const QStringList &patterns) const
|
||||
{
|
||||
bool excluded = false;
|
||||
|
||||
m_fileWatcher.addPath(ignoreFile);
|
||||
for (const QString &pattern : patterns) {
|
||||
if (pattern.isEmpty() || pattern.startsWith('#'))
|
||||
continue;
|
||||
|
||||
if (!m_projectConnections.contains(project)) {
|
||||
auto connection = connect(project, &QObject::destroyed, this, [this, project]() {
|
||||
m_projectIgnorePatterns.remove(project);
|
||||
m_projectConnections.remove(project);
|
||||
});
|
||||
m_projectConnections[project] = connection;
|
||||
bool isNegative = pattern.startsWith('!');
|
||||
QString actualPattern = isNegative ? pattern.mid(1) : pattern;
|
||||
|
||||
bool matches = matchPathWithPattern(path, actualPattern);
|
||||
|
||||
if (matches) {
|
||||
excluded = !isNegative;
|
||||
}
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
|
||||
bool IgnoreManager::matchPathWithPattern(const QString &path, const QString &pattern) const
|
||||
{
|
||||
QString adjustedPattern = pattern.trimmed();
|
||||
|
||||
bool matchFromRoot = adjustedPattern.startsWith('/');
|
||||
if (matchFromRoot)
|
||||
adjustedPattern = adjustedPattern.mid(1);
|
||||
|
||||
bool matchDirOnly = adjustedPattern.endsWith('/');
|
||||
if (matchDirOnly)
|
||||
adjustedPattern.chop(1);
|
||||
|
||||
QString regexPattern = QRegularExpression::escape(adjustedPattern);
|
||||
|
||||
regexPattern.replace("\\*\\*", ".*");
|
||||
|
||||
regexPattern.replace("\\*", "[^/]*");
|
||||
|
||||
regexPattern.replace("\\?", ".");
|
||||
|
||||
if (matchFromRoot)
|
||||
regexPattern = QString("^%1").arg(regexPattern);
|
||||
else
|
||||
regexPattern = QString("(^|/)%1").arg(regexPattern);
|
||||
|
||||
if (matchDirOnly)
|
||||
regexPattern = QString("%1$").arg(regexPattern);
|
||||
else
|
||||
regexPattern = QString("%1($|/)").arg(regexPattern);
|
||||
|
||||
QRegularExpression regex(regexPattern);
|
||||
QRegularExpressionMatch match = regex.match(path);
|
||||
return match.hasMatch();
|
||||
}
|
||||
|
||||
QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
||||
@ -95,14 +174,16 @@ QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
||||
if (!project)
|
||||
return patterns;
|
||||
|
||||
QString path = ignoreFilePath(project);
|
||||
QFile file(path);
|
||||
|
||||
if (!file.exists())
|
||||
QString ignoreFile = ignoreFilePath(project);
|
||||
if (ignoreFile.isEmpty() || !QFile::exists(ignoreFile)) {
|
||||
// LOG_MESSAGE(
|
||||
// QString("No .qodeassistignore file found for project: %1").arg(project->displayName()));
|
||||
return patterns;
|
||||
}
|
||||
|
||||
QFile file(ignoreFile);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_MESSAGE(QString("Could not open .qodeassistignore file: %1").arg(path));
|
||||
LOG_MESSAGE(QString("Could not open .qodeassistignore file: %1").arg(ignoreFile));
|
||||
return patterns;
|
||||
}
|
||||
|
||||
@ -113,26 +194,85 @@ QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
||||
patterns << line;
|
||||
}
|
||||
|
||||
LOG_MESSAGE(QString("Successfully loaded .qodeassistignore file: %1 with %2 patterns")
|
||||
.arg(ignoreFile)
|
||||
.arg(patterns.size()));
|
||||
|
||||
return patterns;
|
||||
}
|
||||
|
||||
bool IgnoreManager::matchesIgnorePatterns(const QString &path, const QStringList &patterns) const
|
||||
void IgnoreManager::reloadIgnorePatterns(ProjectExplorer::Project *project)
|
||||
{
|
||||
for (const QString &pattern : patterns) {
|
||||
QString regexPattern = QRegularExpression::escape(pattern);
|
||||
if (!project)
|
||||
return;
|
||||
|
||||
regexPattern.replace("\\*\\*", ".*"); // ** matches any characters including /
|
||||
regexPattern.replace("\\*", "[^/]*"); // * matches any characters except /
|
||||
regexPattern.replace("\\?", "."); // ? matches any single character
|
||||
QStringList patterns = loadIgnorePatterns(project);
|
||||
m_projectIgnorePatterns[project] = patterns;
|
||||
|
||||
regexPattern = QString("^%1$").arg(regexPattern);
|
||||
|
||||
QRegularExpression regex(regexPattern);
|
||||
if (regex.match(path).hasMatch())
|
||||
return true;
|
||||
QStringList keysToRemove;
|
||||
QString projectPath = project->projectDirectory().toUrlishString();
|
||||
for (auto it = m_ignoreCache.begin(); it != m_ignoreCache.end(); ++it) {
|
||||
if (it.key().contains(projectPath))
|
||||
keysToRemove << it.key();
|
||||
}
|
||||
|
||||
return false;
|
||||
for (const QString &key : keysToRemove)
|
||||
m_ignoreCache.remove(key);
|
||||
|
||||
if (!m_projectConnections.contains(project)) {
|
||||
QPointer<ProjectExplorer::Project> projectPtr(project);
|
||||
auto connection = connect(project, &QObject::destroyed, this, [this, projectPtr]() {
|
||||
if (projectPtr) {
|
||||
m_projectIgnorePatterns.remove(projectPtr);
|
||||
m_projectConnections.remove(projectPtr);
|
||||
|
||||
QStringList keysToRemove;
|
||||
for (auto it = m_ignoreCache.begin(); it != m_ignoreCache.end(); ++it) {
|
||||
if (it.key().contains(projectPtr->projectDirectory().toUrlishString()))
|
||||
keysToRemove << it.key();
|
||||
}
|
||||
|
||||
for (const QString &key : keysToRemove)
|
||||
m_ignoreCache.remove(key);
|
||||
}
|
||||
});
|
||||
|
||||
m_projectConnections[project] = connection;
|
||||
}
|
||||
}
|
||||
|
||||
void IgnoreManager::removeIgnorePatterns(ProjectExplorer::Project *project)
|
||||
{
|
||||
m_projectIgnorePatterns.remove(project);
|
||||
|
||||
QStringList keysToRemove;
|
||||
for (auto it = m_ignoreCache.begin(); it != m_ignoreCache.end(); ++it) {
|
||||
if (it.key().contains(project->projectDirectory().toUrlishString()))
|
||||
keysToRemove << it.key();
|
||||
}
|
||||
|
||||
for (const QString &key : keysToRemove)
|
||||
m_ignoreCache.remove(key);
|
||||
|
||||
if (m_projectConnections.contains(project)) {
|
||||
disconnect(m_projectConnections[project]);
|
||||
m_projectConnections.remove(project);
|
||||
}
|
||||
|
||||
LOG_MESSAGE(QString("Removed ignore patterns for project: %1").arg(project->displayName()));
|
||||
}
|
||||
|
||||
void IgnoreManager::reloadAllPatterns()
|
||||
{
|
||||
QList<ProjectExplorer::Project *> projects = m_projectIgnorePatterns.keys();
|
||||
|
||||
for (ProjectExplorer::Project *project : projects) {
|
||||
if (project) {
|
||||
reloadIgnorePatterns(project);
|
||||
}
|
||||
}
|
||||
|
||||
m_ignoreCache.clear();
|
||||
}
|
||||
|
||||
QString IgnoreManager::ignoreFilePath(ProjectExplorer::Project *project) const
|
||||
@ -141,14 +281,7 @@ QString IgnoreManager::ignoreFilePath(ProjectExplorer::Project *project) const
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString path = project->projectDirectory().toUrlishString() + "/.qodeassist/qodeassistignore";
|
||||
|
||||
QFileInfo fileInfo(path);
|
||||
if (!fileInfo.exists() || !fileInfo.isFile()) {
|
||||
LOG_MESSAGE(QString("File .qodeassistignore not found at path: %1").arg(path));
|
||||
}
|
||||
|
||||
return path;
|
||||
return project->projectDirectory().toUrlishString() + "/.qodeassistignore";
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Context
|
||||
|
@ -19,9 +19,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QStringList>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
@ -40,15 +40,23 @@ public:
|
||||
|
||||
bool shouldIgnore(const QString &filePath, ProjectExplorer::Project *project = nullptr) const;
|
||||
void reloadIgnorePatterns(ProjectExplorer::Project *project);
|
||||
void removeIgnorePatterns(ProjectExplorer::Project *project);
|
||||
|
||||
void reloadAllPatterns();
|
||||
|
||||
private slots:
|
||||
void cleanupConnections();
|
||||
|
||||
private:
|
||||
QStringList loadIgnorePatterns(ProjectExplorer::Project *project);
|
||||
bool matchesIgnorePatterns(const QString &path, const QStringList &patterns) const;
|
||||
bool isPathExcluded(const QString &path, const QStringList &patterns) const;
|
||||
bool matchPathWithPattern(const QString &path, const QString &pattern) const;
|
||||
QStringList loadIgnorePatterns(ProjectExplorer::Project *project);
|
||||
QString ignoreFilePath(ProjectExplorer::Project *project) const;
|
||||
|
||||
mutable QMap<ProjectExplorer::Project *, QStringList> m_projectIgnorePatterns;
|
||||
QFileSystemWatcher m_fileWatcher;
|
||||
QMap<ProjectExplorer::Project *, QMetaObject::Connection> m_projectConnections;
|
||||
QHash<ProjectExplorer::Project *, QStringList> m_projectIgnorePatterns;
|
||||
mutable QHash<QString, bool> m_ignoreCache;
|
||||
QHash<ProjectExplorer::Project *, QMetaObject::Connection> m_projectConnections;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Context
|
||||
|
Loading…
Reference in New Issue
Block a user