AAPT2: Allow compatible duplicate Attributes
If a resource XML file defines two compatible Attributes, they should
be merged without throwing an error. Ex:
<declare-styleable>
<attr name="conflict" format="string" />
</declare-styleable>
<declare-styleable>
<attr name="conflict" format="string|reference" />
</declare-styleable>
In this case, string|reference and string are the same, so these should
merge correctly.
Bug: 65699599
Test: make aapt2_tests
Test: make AaptBasicTest
Change-Id: I7b0f956d2332f7f0b458acd59ca0a606b2cfdf95
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index a782cd3..77cee06 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -507,17 +507,10 @@
}
}
-Attribute::Attribute()
- : type_mask(0u),
- min_int(std::numeric_limits<int32_t>::min()),
- max_int(std::numeric_limits<int32_t>::max()) {
-}
-
-Attribute::Attribute(bool w, uint32_t t)
+Attribute::Attribute(uint32_t t)
: type_mask(t),
min_int(std::numeric_limits<int32_t>::min()),
max_int(std::numeric_limits<int32_t>::max()) {
- weak_ = w;
}
std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
@@ -568,6 +561,20 @@
});
}
+bool Attribute::IsCompatibleWith(const Attribute& attr) const {
+ // If the high bits are set on any of these attribute type masks, then they are incompatible.
+ // We don't check that flags and enums are identical.
+ if ((type_mask & ~android::ResTable_map::TYPE_ANY) != 0 ||
+ (attr.type_mask & ~android::ResTable_map::TYPE_ANY) != 0) {
+ return false;
+ }
+
+ // Every attribute accepts a reference.
+ uint32_t this_type_mask = type_mask | android::ResTable_map::TYPE_REFERENCE;
+ uint32_t that_type_mask = attr.type_mask | android::ResTable_map::TYPE_REFERENCE;
+ return this_type_mask == that_type_mask;
+}
+
Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
return new Attribute(*this);
}