summaryrefslogtreecommitdiffstats
path: root/src/linguist/lupdate/filesignificancecheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/linguist/lupdate/filesignificancecheck.cpp')
-rw-r--r--src/linguist/lupdate/filesignificancecheck.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/linguist/lupdate/filesignificancecheck.cpp b/src/linguist/lupdate/filesignificancecheck.cpp
new file mode 100644
index 000000000..9babe6898
--- /dev/null
+++ b/src/linguist/lupdate/filesignificancecheck.cpp
@@ -0,0 +1,70 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "filesignificancecheck.h"
+
+#include <mutex>
+
+QT_BEGIN_NAMESPACE
+
+FileSignificanceCheck *FileSignificanceCheck::m_instance = nullptr;
+
+void FileSignificanceCheck::setRootDirectories(const QStringList &paths)
+{
+ const size_t pathsSize = static_cast<size_t>(paths.size());
+ m_rootDirs.resize(pathsSize);
+ for (size_t i = 0; i < pathsSize; ++i)
+ m_rootDirs[i].setPath(paths.at(i));
+}
+
+void FileSignificanceCheck::setExclusionPatterns(const QStringList &patterns)
+{
+ const size_t patternsSize = static_cast<size_t>(patterns.size());
+ m_exclusionRegExes.resize(patternsSize);
+ for (size_t i = 0; i < patternsSize; ++i)
+ m_exclusionRegExes[i] = QRegularExpression::fromWildcard(patterns.at(i));
+}
+
+/*
+ * Return true if the given source file is significant for lupdate.
+ * A file is considered insignificant if
+ * - it's not within any project root
+ * - it's excluded
+ *
+ * This method is called from multiple threads.
+ * Results are cached.
+ */
+bool FileSignificanceCheck::isFileSignificant(const std::string &filePath) const
+{
+ // cache lookup
+ std::shared_lock<std::shared_mutex> readLock(m_cacheMutex);
+ auto it = m_cache.find(filePath);
+ if (it != m_cache.end())
+ return it->second;
+
+ // cache miss
+ readLock.unlock();
+ std::unique_lock<std::shared_mutex> writeLock(m_cacheMutex);
+ QString file = QString::fromUtf8(filePath);
+ QString cleanFile = QDir::cleanPath(file);
+ for (const QRegularExpression &rx : m_exclusionRegExes) {
+ if (rx.match(cleanFile).hasMatch()) {
+ m_cache.insert({filePath, false});
+ return false;
+ }
+ }
+
+ for (const QDir &rootDir : m_rootDirs) {
+ QString relativeFilePath = rootDir.relativeFilePath(file);
+ if (!relativeFilePath.startsWith(QLatin1String("../"))
+ && QFileInfo(relativeFilePath).isRelative()) {
+ m_cache.insert({filePath, true});
+ return true;
+ }
+ }
+
+ m_cache.insert({filePath, false});
+ return false;
+}
+
+QT_END_NAMESPACE