mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-05-28 03:10:28 -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 "IgnoreManager.hpp"
|
||||||
|
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectmanager.h>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@ -33,17 +35,52 @@ namespace QodeAssist::Context {
|
|||||||
IgnoreManager::IgnoreManager(QObject *parent)
|
IgnoreManager::IgnoreManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
connect(&m_fileWatcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
|
auto projectManager = ProjectExplorer::ProjectManager::instance();
|
||||||
for (auto it = m_projectIgnorePatterns.begin(); it != m_projectIgnorePatterns.end(); ++it) {
|
if (projectManager) {
|
||||||
if (ignoreFilePath(it.key()) == path) {
|
connect(
|
||||||
reloadIgnorePatterns(it.key());
|
projectManager,
|
||||||
break;
|
&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
|
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);
|
return matchesIgnorePatterns(relativePath, patterns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IgnoreManager::reloadIgnorePatterns(ProjectExplorer::Project *project)
|
bool IgnoreManager::matchesIgnorePatterns(const QString &path, const QStringList &patterns) const
|
||||||
{
|
{
|
||||||
if (!project)
|
QString cacheKey = path + ":" + patterns.join("|");
|
||||||
return;
|
if (m_ignoreCache.contains(cacheKey))
|
||||||
|
return m_ignoreCache[cacheKey];
|
||||||
|
|
||||||
QStringList patterns = loadIgnorePatterns(project);
|
bool result = isPathExcluded(path, patterns);
|
||||||
m_projectIgnorePatterns[project] = patterns;
|
m_ignoreCache.insert(cacheKey, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString ignoreFile = ignoreFilePath(project);
|
bool IgnoreManager::isPathExcluded(const QString &path, const QStringList &patterns) const
|
||||||
if (QFileInfo::exists(ignoreFile)) {
|
{
|
||||||
if (m_fileWatcher.files().contains(ignoreFile))
|
bool excluded = false;
|
||||||
m_fileWatcher.removePath(ignoreFile);
|
|
||||||
|
|
||||||
m_fileWatcher.addPath(ignoreFile);
|
for (const QString &pattern : patterns) {
|
||||||
|
if (pattern.isEmpty() || pattern.startsWith('#'))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!m_projectConnections.contains(project)) {
|
bool isNegative = pattern.startsWith('!');
|
||||||
auto connection = connect(project, &QObject::destroyed, this, [this, project]() {
|
QString actualPattern = isNegative ? pattern.mid(1) : pattern;
|
||||||
m_projectIgnorePatterns.remove(project);
|
|
||||||
m_projectConnections.remove(project);
|
bool matches = matchPathWithPattern(path, actualPattern);
|
||||||
});
|
|
||||||
m_projectConnections[project] = connection;
|
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)
|
QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
||||||
@ -95,14 +174,16 @@ QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
|||||||
if (!project)
|
if (!project)
|
||||||
return patterns;
|
return patterns;
|
||||||
|
|
||||||
QString path = ignoreFilePath(project);
|
QString ignoreFile = ignoreFilePath(project);
|
||||||
QFile file(path);
|
if (ignoreFile.isEmpty() || !QFile::exists(ignoreFile)) {
|
||||||
|
// LOG_MESSAGE(
|
||||||
if (!file.exists())
|
// QString("No .qodeassistignore file found for project: %1").arg(project->displayName()));
|
||||||
return patterns;
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(ignoreFile);
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
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;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,26 +194,85 @@ QStringList IgnoreManager::loadIgnorePatterns(ProjectExplorer::Project *project)
|
|||||||
patterns << line;
|
patterns << line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_MESSAGE(QString("Successfully loaded .qodeassistignore file: %1 with %2 patterns")
|
||||||
|
.arg(ignoreFile)
|
||||||
|
.arg(patterns.size()));
|
||||||
|
|
||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IgnoreManager::matchesIgnorePatterns(const QString &path, const QStringList &patterns) const
|
void IgnoreManager::reloadIgnorePatterns(ProjectExplorer::Project *project)
|
||||||
{
|
{
|
||||||
for (const QString &pattern : patterns) {
|
if (!project)
|
||||||
QString regexPattern = QRegularExpression::escape(pattern);
|
return;
|
||||||
|
|
||||||
regexPattern.replace("\\*\\*", ".*"); // ** matches any characters including /
|
QStringList patterns = loadIgnorePatterns(project);
|
||||||
regexPattern.replace("\\*", "[^/]*"); // * matches any characters except /
|
m_projectIgnorePatterns[project] = patterns;
|
||||||
regexPattern.replace("\\?", "."); // ? matches any single character
|
|
||||||
|
|
||||||
regexPattern = QString("^%1$").arg(regexPattern);
|
QStringList keysToRemove;
|
||||||
|
QString projectPath = project->projectDirectory().toUrlishString();
|
||||||
QRegularExpression regex(regexPattern);
|
for (auto it = m_ignoreCache.begin(); it != m_ignoreCache.end(); ++it) {
|
||||||
if (regex.match(path).hasMatch())
|
if (it.key().contains(projectPath))
|
||||||
return true;
|
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
|
QString IgnoreManager::ignoreFilePath(ProjectExplorer::Project *project) const
|
||||||
@ -141,14 +281,7 @@ QString IgnoreManager::ignoreFilePath(ProjectExplorer::Project *project) const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString path = project->projectDirectory().toUrlishString() + "/.qodeassist/qodeassistignore";
|
return project->projectDirectory().toUrlishString() + "/.qodeassistignore";
|
||||||
|
|
||||||
QFileInfo fileInfo(path);
|
|
||||||
if (!fileInfo.exists() || !fileInfo.isFile()) {
|
|
||||||
LOG_MESSAGE(QString("File .qodeassistignore not found at path: %1").arg(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QodeAssist::Context
|
} // namespace QodeAssist::Context
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QFileSystemWatcher>
|
#include <QHash>
|
||||||
#include <QMap>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
@ -40,15 +40,23 @@ public:
|
|||||||
|
|
||||||
bool shouldIgnore(const QString &filePath, ProjectExplorer::Project *project = nullptr) const;
|
bool shouldIgnore(const QString &filePath, ProjectExplorer::Project *project = nullptr) const;
|
||||||
void reloadIgnorePatterns(ProjectExplorer::Project *project);
|
void reloadIgnorePatterns(ProjectExplorer::Project *project);
|
||||||
|
void removeIgnorePatterns(ProjectExplorer::Project *project);
|
||||||
|
|
||||||
|
void reloadAllPatterns();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void cleanupConnections();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList loadIgnorePatterns(ProjectExplorer::Project *project);
|
|
||||||
bool matchesIgnorePatterns(const QString &path, const QStringList &patterns) const;
|
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;
|
QString ignoreFilePath(ProjectExplorer::Project *project) const;
|
||||||
|
|
||||||
mutable QMap<ProjectExplorer::Project *, QStringList> m_projectIgnorePatterns;
|
QHash<ProjectExplorer::Project *, QStringList> m_projectIgnorePatterns;
|
||||||
QFileSystemWatcher m_fileWatcher;
|
mutable QHash<QString, bool> m_ignoreCache;
|
||||||
QMap<ProjectExplorer::Project *, QMetaObject::Connection> m_projectConnections;
|
QHash<ProjectExplorer::Project *, QMetaObject::Connection> m_projectConnections;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QodeAssist::Context
|
} // namespace QodeAssist::Context
|
||||||
|
Loading…
Reference in New Issue
Block a user