aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2017-07-24 11:10:28 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2017-08-03 09:52:57 +0000
commit3b95913c674edcdf94eea673aa81d4f670231555 (patch)
tree4c8136e08faeedcd351e75301f6ebe0276988df0
parentde14d18638b6aaf7c52847fec2e534f50c14b95d (diff)
Add FileTagger.priority
Enable users to override FileTagger items by creating a conflicting FileTagger that has a higher numerical priority value. [ChangeLog] Introduced the property FileTagger.priority, and enable users to override FileTagger items. Change-Id: Idc6f5d003b7ad468f03a2eae5d19404c1f3eb06b Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--doc/reference/items/language/filetagger.qdoc26
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp1
-rw-r--r--src/lib/corelib/language/evaluator.cpp9
-rw-r--r--src/lib/corelib/language/evaluator.h2
-rw-r--r--src/lib/corelib/language/language.cpp17
-rw-r--r--src/lib/corelib/language/language.h9
-rw-r--r--src/lib/corelib/language/projectresolver.cpp8
-rw-r--r--tests/auto/language/testdata/filetags.qbs20
-rw-r--r--tests/auto/language/tst_language.cpp1
9 files changed, 85 insertions, 8 deletions
diff --git a/doc/reference/items/language/filetagger.qdoc b/doc/reference/items/language/filetagger.qdoc
index 4a87824f2..55fbb4ac9 100644
--- a/doc/reference/items/language/filetagger.qdoc
+++ b/doc/reference/items/language/filetagger.qdoc
@@ -34,9 +34,21 @@
\keyword QML.FileTagger
\title FileTagger Item
- \brief Maps file patterns to tags.
+ \brief Assigns file tags to files.
- This item maps file patterns to tags. It can be attached to a product or a module.
+ This item assigns file tags to files.
+ The FileTagger item can appear in \c{Product} items or \c{Module} items.
+
+ For every source artifact that has no file tag, \QBS will search for a
+ FileTagger with a pattern that matches the file name of the source
+ artifact. If a matching file tagger is found, then the file tags specified
+ in the FileTagger item are assigned to the source artifact.
+
+ If there is more than one matching FileTagger, all file taggers with the
+ same highest priority are taken into account and their file tags are
+ accumulated.
+
+ The FileTagger item can be attached to a product or a module.
In the latter case, its effect is the same as if it had been attached to all products having
a dependency on the respective module. For instance, the cpp module of \QBS has, among others,
the following file tagger:
@@ -71,17 +83,27 @@
\li Property
\li Type
\li Default
+ \li Since
\li Description
\row
\li patterns
\li stringList
\li none
+ \li 1.0
\li The patterns to match against. Supports the usual wildcards '*', '?' and '[]'.
Neither the list itself nor any of its elements may be empty.
\row
\li fileTags
\li list
\li empty list
+ \li 1.0
\li Tags to attach to a product's files. These can then be matched by a rule.
+ \row
+ \li priority
+ \li int
+ \li 0
+ \li 1.10
+ \li The priority of the FileTagger. A higher numerical value means
+ higher priority.
\endtable
*/
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp
index c8ad3c245..32a85665d 100644
--- a/src/lib/corelib/language/builtindeclarations.cpp
+++ b/src/lib/corelib/language/builtindeclarations.cpp
@@ -235,6 +235,7 @@ void BuiltinDeclarations::addFileTaggerItem()
item << conditionProperty();
item << PropertyDeclaration(QLatin1String("patterns"), PropertyDeclaration::StringList);
item << PropertyDeclaration(QLatin1String("fileTags"), PropertyDeclaration::StringList);
+ item << PropertyDeclaration(QLatin1String("priority"), PropertyDeclaration::Integer);
insert(item);
}
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp
index c4b5419fb..193e73618 100644
--- a/src/lib/corelib/language/evaluator.cpp
+++ b/src/lib/corelib/language/evaluator.cpp
@@ -92,6 +92,15 @@ bool Evaluator::boolValue(const Item *item, const QString &name, bool defaultVal
return v.toBool();
}
+int Evaluator::intValue(const Item *item, const QString &name, int defaultValue,
+ bool *propertyWasSet)
+{
+ QScriptValue v;
+ if (!evaluateProperty(&v, item, name, propertyWasSet))
+ return defaultValue;
+ return v.toInt32();
+}
+
FileTags Evaluator::fileTagsValue(const Item *item, const QString &name, bool *propertySet)
{
return FileTags::fromStringList(stringListValue(item, name, propertySet));
diff --git a/src/lib/corelib/language/evaluator.h b/src/lib/corelib/language/evaluator.h
index 80ab9a3b4..840c808ed 100644
--- a/src/lib/corelib/language/evaluator.h
+++ b/src/lib/corelib/language/evaluator.h
@@ -69,6 +69,8 @@ public:
QScriptValue value(const Item *item, const QString &name, bool *propertySet = 0);
bool boolValue(const Item *item, const QString &name, bool defaultValue = false,
bool *propertyWasSet = 0);
+ int intValue(const Item *item, const QString &name, int defaultValue = 0,
+ bool *propertyWasSet = 0);
FileTags fileTagsValue(const Item *item, const QString &name, bool *propertySet = 0);
QString stringValue(const Item *item, const QString &name,
const QString &defaultValue = QString(), bool *propertyWasSet = 0);
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp
index 4c66b4e16..988e7489e 100644
--- a/src/lib/corelib/language/language.cpp
+++ b/src/lib/corelib/language/language.cpp
@@ -69,6 +69,7 @@
#include <QtScript/qscriptvalue.h>
#include <algorithm>
+#include <memory>
#include <mutex>
namespace qbs {
@@ -84,8 +85,8 @@ template<typename T> bool equals(const T *v1, const T *v2)
}
-FileTagger::FileTagger(const QStringList &patterns, const FileTags &fileTags)
- : m_fileTags(fileTags)
+FileTagger::FileTagger(const QStringList &patterns, const FileTags &fileTags, int priority)
+ : m_fileTags(fileTags), m_priority(priority)
{
setPatterns(patterns);
}
@@ -107,6 +108,7 @@ void FileTagger::load(PersistentPool &pool)
{
setPatterns(pool.load<QStringList>());
pool.load(m_fileTags);
+ pool.load(m_priority);
}
void FileTagger::store(PersistentPool &pool) const
@@ -116,6 +118,7 @@ void FileTagger::store(PersistentPool &pool) const
patterns << regExp.pattern();
pool.store(patterns);
pool.store(m_fileTags);
+ pool.store(m_priority);
}
@@ -501,9 +504,19 @@ QList<SourceArtifactPtr> ResolvedProduct::allEnabledFiles() const
FileTags ResolvedProduct::fileTagsForFileName(const QString &fileName) const
{
FileTags result;
+ std::unique_ptr<int> priority;
for (const FileTaggerConstPtr &tagger : qAsConst(fileTaggers)) {
for (const QRegExp &pattern : tagger->patterns()) {
if (FileInfo::globMatches(pattern, fileName)) {
+ if (priority) {
+ if (*priority != tagger->priority()) {
+ // The taggers are expected to be sorted by priority.
+ QBS_ASSERT(*priority > tagger->priority(), return result);
+ return result;
+ }
+ } else {
+ priority.reset(new int(tagger->priority()));
+ }
result.unite(tagger->fileTags());
break;
}
diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h
index 4df1fd976..64d51a47f 100644
--- a/src/lib/corelib/language/language.h
+++ b/src/lib/corelib/language/language.h
@@ -78,15 +78,17 @@ class FileTagger : public PersistentObject
{
public:
static FileTaggerPtr create() { return FileTaggerPtr(new FileTagger); }
- static FileTaggerPtr create(const QStringList &patterns, const FileTags &fileTags) {
- return FileTaggerPtr(new FileTagger(patterns, fileTags));
+ static FileTaggerPtr create(const QStringList &patterns, const FileTags &fileTags,
+ int priority) {
+ return FileTaggerPtr(new FileTagger(patterns, fileTags, priority));
}
const QList<QRegExp> &patterns() const { return m_patterns; }
const FileTags &fileTags() const { return m_fileTags; }
+ int priority() const { return m_priority; }
private:
- FileTagger(const QStringList &patterns, const FileTags &fileTags);
+ FileTagger(const QStringList &patterns, const FileTags &fileTags, int priority);
FileTagger() {}
void setPatterns(const QStringList &patterns);
@@ -96,6 +98,7 @@ private:
QList<QRegExp> m_patterns;
FileTags m_fileTags;
+ int m_priority = 0;
};
class Probe : public PersistentObject
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index 348b0af42..d1d70e445 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -943,7 +943,9 @@ void ProjectResolver::resolveFileTagger(Item *item, ProjectContext *projectConte
if (pattern.isEmpty())
throw ErrorInfo(Tr::tr("A FileTagger pattern must not be empty."), item->location());
}
- fileTaggers += FileTagger::create(patterns, fileTags);
+
+ const int priority = m_evaluator->intValue(item, QLatin1String("priority"));
+ fileTaggers += FileTagger::create(patterns, fileTags, priority);
}
void ProjectResolver::resolveScanner(Item *item, ProjectResolver::ProjectContext *projectContext)
@@ -1185,6 +1187,10 @@ void ProjectResolver::postProcess(const ResolvedProductPtr &product,
ProjectContext *projectContext) const
{
product->fileTaggers += projectContext->fileTaggers;
+ std::sort(std::begin(product->fileTaggers), std::end(product->fileTaggers),
+ [] (const FileTaggerConstPtr &a, const FileTaggerConstPtr &b) {
+ return a->priority() > b->priority();
+ });
for (const RulePtr &rule : qAsConst(projectContext->rules)) {
RulePtr clonedRule = rule->clone();
clonedRule->product = product.get();
diff --git a/tests/auto/language/testdata/filetags.qbs b/tests/auto/language/testdata/filetags.qbs
index eb1cf57c6..b2a85f953 100644
--- a/tests/auto/language/testdata/filetags.qbs
+++ b/tests/auto/language/testdata/filetags.qbs
@@ -58,4 +58,24 @@ Project {
fileTags: ["zzz"]
}
}
+
+ Product {
+ name: "prioritized_filetagger"
+ files: ["main.cpp"]
+ FileTagger {
+ patterns: ["*.cpp"]
+ fileTags: ["cpp1"]
+ priority: 3
+ }
+ FileTagger {
+ patterns: ["*.cpp"]
+ fileTags: ["cpp2"]
+ priority: 3
+ }
+ FileTagger {
+ patterns: ["*.cpp"]
+ fileTags: ["ignored"]
+ priority: 2
+ }
+ }
}
diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp
index fc04f9e6a..78a8caf1a 100644
--- a/tests/auto/language/tst_language.cpp
+++ b/tests/auto/language/tst_language.cpp
@@ -2305,6 +2305,7 @@ void TestLanguage::fileTags_data()
QTest::newRow("set_file_tag_via_group") << 2 << (QStringList() << "c++");
QTest::newRow("override_file_tag_via_group") << 2 << (QStringList() << "c++");
QTest::newRow("add_file_tag_via_group") << 2 << (QStringList() << "cpp" << "zzz");
+ QTest::newRow("prioritized_filetagger") << 1 << (QStringList() << "cpp1" << "cpp2");
QTest::newRow("cleanup") << 0 << QStringList();
}