summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRyan Mitchell <rtmitchell@google.com>2021-04-14 17:31:37 -0700
committerRyan Mitchell <rtmitchell@google.com>2021-04-21 08:32:30 -0700
commitefcdb95fa7cf2da7d599e0bcda250514ac5ee048 (patch)
tree5e18cdf4f5a2ad45c2e1c8e5a66ee1a7d96d7ed2 /tools
parent41d65a1ba0a7f2696278607b52f310f4d021949d (diff)
downloadbase-efcdb95fa7cf2da7d599e0bcda250514ac5ee048.tar.gz
Aapt2 ValueTransformer
For future macro support, aapt2 must be able to convert Reference values into other Value types. Currently a DescendingValueVisitor is used to visit all of the References in a ResourceTable or a compiled XML file to set their resource ids during the link phase. This was fine since we were only mutating the resource id of the visited Reference. A macro may reference a String, BinaryPrimitive, or any other Item type. During the link phase, we will need to transform references to macros into the values of the macros. The only parameter in the methods of the ValueVisitor interface is a raw pointer to the type being visited. The visitor interface does not support reassigning the visited type to a different type. ValueTransformer is a new interface for consuming a Value type and transforming it into a compatible Value type. This change refactors Value::Clone to use this interface. Bug: 175616308 Test: aapt2_tests Change-Id: Ic1b9d718b932c208764114cd9c74d880e189ccb0
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt2/Android.bp1
-rw-r--r--tools/aapt2/ResourceTable.cpp3
-rw-r--r--tools/aapt2/ResourceValues.cpp199
-rw-r--r--tools/aapt2/ResourceValues.h71
-rw-r--r--tools/aapt2/ResourceValues_test.cpp12
-rw-r--r--tools/aapt2/ValueTransformer.cpp50
-rw-r--r--tools/aapt2/ValueTransformer.h128
-rw-r--r--tools/aapt2/ValueTransformer_inline.h47
-rw-r--r--tools/aapt2/cmd/Link.cpp5
-rw-r--r--tools/aapt2/compile/PseudolocaleGenerator.cpp3
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp5
-rw-r--r--tools/aapt2/java/JavaClassGenerator_test.cpp6
-rw-r--r--tools/aapt2/link/AutoVersioner.cpp3
-rw-r--r--tools/aapt2/link/TableMerger.cpp11
-rw-r--r--tools/aapt2/link/XmlCompatVersioner.cpp9
-rw-r--r--tools/aapt2/split/TableSplitter.cpp4
-rw-r--r--tools/aapt2/test/Context.h3
-rw-r--r--tools/aapt2/xml/XmlDom.cpp3
18 files changed, 420 insertions, 143 deletions
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 3937cee99e3b..12dc156f75be 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -162,6 +162,7 @@ cc_library_host_static {
"Configuration.proto",
"Resources.proto",
"ResourcesInternal.proto",
+ "ValueTransformer.cpp",
],
proto: {
export_proto_headers: true,
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 27f7bdd83c9e..45ea65430bb6 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -577,6 +577,7 @@ Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNam
std::unique_ptr<ResourceTable> ResourceTable::Clone() const {
std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>();
+ CloningValueTransformer cloner(&new_table->string_pool);
for (const auto& pkg : packages) {
ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name);
for (const auto& type : pkg->types) {
@@ -593,7 +594,7 @@ std::unique_ptr<ResourceTable> ResourceTable::Clone() const {
for (const auto& config_value : entry->values) {
ResourceConfigValue* new_value =
new_entry->FindOrCreateValue(config_value->config, config_value->product);
- new_value->value.reset(config_value->value->Clone(&new_table->string_pool));
+ new_value->value = config_value->value->Transform(cloner);
}
}
}
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 4f0fa8ae29ba..574bd2e44a84 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -47,6 +47,14 @@ std::ostream& operator<<(std::ostream& out, const Value& value) {
return out;
}
+std::unique_ptr<Value> Value::Transform(ValueTransformer& transformer) const {
+ return std::unique_ptr<Value>(this->TransformValueImpl(transformer));
+}
+
+std::unique_ptr<Item> Item::Transform(ValueTransformer& transformer) const {
+ return std::unique_ptr<Item>(this->TransformItemImpl(transformer));
+}
+
template <typename Derived>
void BaseValue<Derived>::Accept(ValueVisitor* visitor) {
visitor->Visit(static_cast<Derived*>(this));
@@ -77,13 +85,6 @@ bool RawString::Equals(const Value* value) const {
return *this->value == *other->value;
}
-RawString* RawString::Clone(StringPool* new_pool) const {
- RawString* rs = new RawString(new_pool->MakeRef(value));
- rs->comment_ = comment_;
- rs->source_ = source_;
- return rs;
-}
-
bool RawString::Flatten(android::Res_value* out_value) const {
out_value->dataType = android::Res_value::TYPE_STRING;
out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
@@ -136,10 +137,6 @@ bool Reference::Flatten(android::Res_value* out_value) const {
return true;
}
-Reference* Reference::Clone(StringPool* /*new_pool*/) const {
- return new Reference(*this);
-}
-
void Reference::Print(std::ostream* out) const {
if (reference_type == Type::kResource) {
*out << "(reference) @";
@@ -220,10 +217,6 @@ bool Id::Flatten(android::Res_value* out) const {
return true;
}
-Id* Id::Clone(StringPool* /*new_pool*/) const {
- return new Id(*this);
-}
-
void Id::Print(std::ostream* out) const {
*out << "(id)";
}
@@ -266,14 +259,6 @@ bool String::Flatten(android::Res_value* out_value) const {
return true;
}
-String* String::Clone(StringPool* new_pool) const {
- String* str = new String(new_pool->MakeRef(value));
- str->comment_ = comment_;
- str->source_ = source_;
- str->untranslatable_sections = untranslatable_sections;
- return str;
-}
-
void String::Print(std::ostream* out) const {
*out << "(string) \"" << *value << "\"";
}
@@ -321,14 +306,6 @@ bool StyledString::Flatten(android::Res_value* out_value) const {
return true;
}
-StyledString* StyledString::Clone(StringPool* new_pool) const {
- StyledString* str = new StyledString(new_pool->MakeRef(value));
- str->comment_ = comment_;
- str->source_ = source_;
- str->untranslatable_sections = untranslatable_sections;
- return str;
-}
-
void StyledString::Print(std::ostream* out) const {
*out << "(styled string) \"" << value->value << "\"";
for (const StringPool::Span& span : value->spans) {
@@ -357,15 +334,6 @@ bool FileReference::Flatten(android::Res_value* out_value) const {
return true;
}
-FileReference* FileReference::Clone(StringPool* new_pool) const {
- FileReference* fr = new FileReference(new_pool->MakeRef(path));
- fr->file = file;
- fr->type = type;
- fr->comment_ = comment_;
- fr->source_ = source_;
- return fr;
-}
-
void FileReference::Print(std::ostream* out) const {
*out << "(file) " << *path;
switch (type) {
@@ -406,10 +374,6 @@ bool BinaryPrimitive::Flatten(::android::Res_value* out_value) const {
return true;
}
-BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
- return new BinaryPrimitive(*this);
-}
-
void BinaryPrimitive::Print(std::ostream* out) const {
*out << StringPrintf("(primitive) type=0x%02x data=0x%08x", value.dataType, value.data);
}
@@ -587,10 +551,6 @@ bool Attribute::IsCompatibleWith(const Attribute& attr) const {
return this_type_mask == that_type_mask;
}
-Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
- return new Attribute(*this);
-}
-
std::string Attribute::MaskString() const {
if (type_mask == android::ResTable_map::TYPE_ANY) {
return "any";
@@ -893,18 +853,6 @@ bool Style::Equals(const Value* value) const {
});
}
-Style* Style::Clone(StringPool* new_pool) const {
- Style* style = new Style();
- style->parent = parent;
- style->parent_inferred = parent_inferred;
- style->comment_ = comment_;
- style->source_ = source_;
- for (auto& entry : entries) {
- style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
- }
- return style;
-}
-
void Style::Print(std::ostream* out) const {
*out << "(style) ";
if (parent && parent.value().name) {
@@ -920,7 +868,8 @@ void Style::Print(std::ostream* out) const {
Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
Style::Entry cloned_entry{entry.key};
if (entry.value != nullptr) {
- cloned_entry.value.reset(entry.value->Clone(pool));
+ CloningValueTransformer cloner(pool);
+ cloned_entry.value = entry.value->Transform(cloner);
}
return cloned_entry;
}
@@ -993,16 +942,6 @@ bool Array::Equals(const Value* value) const {
});
}
-Array* Array::Clone(StringPool* new_pool) const {
- Array* array = new Array();
- array->comment_ = comment_;
- array->source_ = source_;
- for (auto& item : elements) {
- array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
- }
- return array;
-}
-
void Array::Print(std::ostream* out) const {
*out << "(array) [" << util::Joiner(elements, ", ") << "]";
}
@@ -1030,19 +969,6 @@ bool Plural::Equals(const Value* value) const {
return true;
}
-Plural* Plural::Clone(StringPool* new_pool) const {
- Plural* p = new Plural();
- p->comment_ = comment_;
- p->source_ = source_;
- const size_t count = values.size();
- for (size_t i = 0; i < count; i++) {
- if (values[i]) {
- p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool));
- }
- }
- return p;
-}
-
void Plural::Print(std::ostream* out) const {
*out << "(plural)";
if (values[Zero]) {
@@ -1086,10 +1012,6 @@ bool Styleable::Equals(const Value* value) const {
});
}
-Styleable* Styleable::Clone(StringPool* /*new_pool*/) const {
- return new Styleable(*this);
-}
-
void Styleable::Print(std::ostream* out) const {
*out << "(styleable) "
<< " [" << util::Joiner(entries, ", ") << "]";
@@ -1126,4 +1048,105 @@ void Styleable::MergeWith(Styleable* other) {
entries.insert(entries.end(), references.begin(), references.end());
}
+template <typename T>
+std::unique_ptr<T> CopyValueFields(std::unique_ptr<T> new_value, const T* value) {
+ new_value->SetSource(value->GetSource());
+ new_value->SetComment(value->GetComment());
+ return new_value;
+}
+
+CloningValueTransformer::CloningValueTransformer(StringPool* new_pool)
+ : ValueTransformer(new_pool) {
+}
+
+std::unique_ptr<Reference> CloningValueTransformer::TransformDerived(const Reference* value) {
+ return std::make_unique<Reference>(*value);
+}
+
+std::unique_ptr<Id> CloningValueTransformer::TransformDerived(const Id* value) {
+ return std::make_unique<Id>(*value);
+}
+
+std::unique_ptr<RawString> CloningValueTransformer::TransformDerived(const RawString* value) {
+ auto new_value = std::make_unique<RawString>(pool_->MakeRef(value->value));
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<String> CloningValueTransformer::TransformDerived(const String* value) {
+ auto new_value = std::make_unique<String>(pool_->MakeRef(value->value));
+ new_value->untranslatable_sections = value->untranslatable_sections;
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<StyledString> CloningValueTransformer::TransformDerived(const StyledString* value) {
+ auto new_value = std::make_unique<StyledString>(pool_->MakeRef(value->value));
+ new_value->untranslatable_sections = value->untranslatable_sections;
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<FileReference> CloningValueTransformer::TransformDerived(
+ const FileReference* value) {
+ auto new_value = std::make_unique<FileReference>(pool_->MakeRef(value->path));
+ new_value->file = value->file;
+ new_value->type = value->type;
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<BinaryPrimitive> CloningValueTransformer::TransformDerived(
+ const BinaryPrimitive* value) {
+ return std::make_unique<BinaryPrimitive>(*value);
+}
+
+std::unique_ptr<Attribute> CloningValueTransformer::TransformDerived(const Attribute* value) {
+ auto new_value = std::make_unique<Attribute>();
+ new_value->type_mask = value->type_mask;
+ new_value->min_int = value->min_int;
+ new_value->max_int = value->max_int;
+ for (const Attribute::Symbol& s : value->symbols) {
+ new_value->symbols.emplace_back(Attribute::Symbol{
+ .symbol = *s.symbol.Transform(*this),
+ .value = s.value,
+ .type = s.type,
+ });
+ }
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<Style> CloningValueTransformer::TransformDerived(const Style* value) {
+ auto new_value = std::make_unique<Style>();
+ new_value->parent = value->parent;
+ new_value->parent_inferred = value->parent_inferred;
+ for (auto& entry : value->entries) {
+ new_value->entries.push_back(Style::Entry{entry.key, entry.value->Transform(*this)});
+ }
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<Array> CloningValueTransformer::TransformDerived(const Array* value) {
+ auto new_value = std::make_unique<Array>();
+ for (auto& item : value->elements) {
+ new_value->elements.emplace_back(item->Transform(*this));
+ }
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<Plural> CloningValueTransformer::TransformDerived(const Plural* value) {
+ auto new_value = std::make_unique<Plural>();
+ const size_t count = value->values.size();
+ for (size_t i = 0; i < count; i++) {
+ if (value->values[i]) {
+ new_value->values[i] = value->values[i]->Transform(*this);
+ }
+ }
+ return CopyValueFields(std::move(new_value), value);
+}
+
+std::unique_ptr<Styleable> CloningValueTransformer::TransformDerived(const Styleable* value) {
+ auto new_value = std::make_unique<Styleable>();
+ for (const Reference& s : value->entries) {
+ new_value->entries.emplace_back(*s.Transform(*this));
+ }
+ return CopyValueFields(std::move(new_value), value);
+}
+
} // namespace aapt
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index fe0883be50aa..025864d385cf 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -28,6 +28,7 @@
#include "Diagnostics.h"
#include "Resource.h"
#include "StringPool.h"
+#include "ValueTransformer.h"
#include "io/File.h"
#include "text/Printer.h"
#include "util/Maybe.h"
@@ -100,9 +101,8 @@ class Value {
// Calls the appropriate overload of ConstValueVisitor.
virtual void Accept(ConstValueVisitor* visitor) const = 0;
- // Clone the value. `new_pool` is the new StringPool that
- // any resources with strings should use when copying their string.
- virtual Value* Clone(StringPool* new_pool) const = 0;
+ // Transform this Value into another Value using the transformer.
+ std::unique_ptr<Value> Transform(ValueTransformer& transformer) const;
// Human readable printout of this value.
virtual void Print(std::ostream* out) const = 0;
@@ -118,6 +118,9 @@ class Value {
std::string comment_;
bool weak_ = false;
bool translatable_ = true;
+
+ private:
+ virtual Value* TransformValueImpl(ValueTransformer& transformer) const = 0;
};
// Inherit from this to get visitor accepting implementations for free.
@@ -129,12 +132,15 @@ struct BaseValue : public Value {
// A resource item with a single value. This maps to android::ResTable_entry.
struct Item : public Value {
- // Clone the Item.
- virtual Item* Clone(StringPool* new_pool) const override = 0;
-
// Fills in an android::Res_value structure with this Item's binary representation.
// Returns false if an error occurred.
virtual bool Flatten(android::Res_value* out_value) const = 0;
+
+ // Transform this Item into another Item using the transformer.
+ std::unique_ptr<Item> Transform(ValueTransformer& transformer) const;
+
+ private:
+ virtual Item* TransformItemImpl(ValueTransformer& transformer) const = 0;
};
// Inherit from this to get visitor accepting implementations for free.
@@ -147,7 +153,7 @@ struct BaseItem : public Item {
// A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE.
// A reference can be symbolic (with the name set to a valid resource name) or be
// numeric (the id is set to a valid resource ID).
-struct Reference : public BaseItem<Reference> {
+struct Reference : public TransformableItem<Reference, BaseItem<Reference>> {
enum class Type {
kResource,
kAttribute,
@@ -166,7 +172,6 @@ struct Reference : public BaseItem<Reference> {
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- Reference* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
void PrettyPrint(text::Printer* printer) const override;
@@ -178,27 +183,25 @@ bool operator<(const Reference&, const Reference&);
bool operator==(const Reference&, const Reference&);
// An ID resource. Has no real value, just a place holder.
-struct Id : public BaseItem<Id> {
+struct Id : public TransformableItem<Id, BaseItem<Id>> {
Id() {
weak_ = true;
}
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out) const override;
- Id* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
// A raw, unprocessed string. This may contain quotations, escape sequences, and whitespace.
// This shall *NOT* end up in the final resource table.
-struct RawString : public BaseItem<RawString> {
+struct RawString : public TransformableItem<RawString, BaseItem<RawString>> {
StringPool::Ref value;
explicit RawString(const StringPool::Ref& ref);
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- RawString* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
@@ -220,7 +223,7 @@ inline bool operator!=(const UntranslatableSection& a, const UntranslatableSecti
return a.start != b.start || a.end != b.end;
}
-struct String : public BaseItem<String> {
+struct String : public TransformableItem<String, BaseItem<String>> {
StringPool::Ref value;
// Sections of the string to NOT translate. Mainly used
@@ -232,12 +235,11 @@ struct String : public BaseItem<String> {
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- String* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
void PrettyPrint(text::Printer* printer) const override;
};
-struct StyledString : public BaseItem<StyledString> {
+struct StyledString : public TransformableItem<StyledString, BaseItem<StyledString>> {
StringPool::StyleRef value;
// Sections of the string to NOT translate. Mainly used
@@ -249,11 +251,10 @@ struct StyledString : public BaseItem<StyledString> {
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- StyledString* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
-struct FileReference : public BaseItem<FileReference> {
+struct FileReference : public TransformableItem<FileReference, BaseItem<FileReference>> {
StringPool::Ref path;
// A handle to the file object from which this file can be read.
@@ -269,12 +270,11 @@ struct FileReference : public BaseItem<FileReference> {
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- FileReference* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
// Represents any other android::Res_value.
-struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
+struct BinaryPrimitive : public TransformableItem<BinaryPrimitive, BaseItem<BinaryPrimitive>> {
android::Res_value value;
BinaryPrimitive() = default;
@@ -283,12 +283,11 @@ struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
bool Equals(const Value* value) const override;
bool Flatten(android::Res_value* out_value) const override;
- BinaryPrimitive* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
void PrettyPrint(text::Printer* printer) const override;
};
-struct Attribute : public BaseValue<Attribute> {
+struct Attribute : public TransformableValue<Attribute, BaseValue<Attribute>> {
struct Symbol {
Reference symbol;
uint32_t value;
@@ -311,13 +310,12 @@ struct Attribute : public BaseValue<Attribute> {
// TYPE_ENUMS are never compatible.
bool IsCompatibleWith(const Attribute& attr) const;
- Attribute* Clone(StringPool* new_pool) const override;
std::string MaskString() const;
void Print(std::ostream* out) const override;
bool Matches(const Item& item, DiagMessage* out_msg = nullptr) const;
};
-struct Style : public BaseValue<Style> {
+struct Style : public TransformableValue<Style, BaseValue<Style>> {
struct Entry {
Reference key;
std::unique_ptr<Item> value;
@@ -333,7 +331,6 @@ struct Style : public BaseValue<Style> {
std::vector<Entry> entries;
bool Equals(const Value* value) const override;
- Style* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
// Merges `style` into this Style. All identical attributes of `style` take precedence, including
@@ -341,29 +338,26 @@ struct Style : public BaseValue<Style> {
void MergeWith(Style* style, StringPool* pool);
};
-struct Array : public BaseValue<Array> {
+struct Array : public TransformableValue<Array, BaseValue<Array>> {
std::vector<std::unique_ptr<Item>> elements;
bool Equals(const Value* value) const override;
- Array* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
-struct Plural : public BaseValue<Plural> {
+struct Plural : public TransformableValue<Plural, BaseValue<Plural>> {
enum { Zero = 0, One, Two, Few, Many, Other, Count };
std::array<std::unique_ptr<Item>, Count> values;
bool Equals(const Value* value) const override;
- Plural* Clone(StringPool* new_pool) const override;
void Print(std::ostream* out) const override;
};
-struct Styleable : public BaseValue<Styleable> {
+struct Styleable : public TransformableValue<Styleable, BaseValue<Styleable>> {
std::vector<Reference> entries;
bool Equals(const Value* value) const override;
- Styleable* Clone(StringPool* newPool) const override;
void Print(std::ostream* out) const override;
void MergeWith(Styleable* styleable);
};
@@ -379,6 +373,23 @@ typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type o
return out;
}
+struct CloningValueTransformer : public ValueTransformer {
+ explicit CloningValueTransformer(StringPool* new_pool);
+
+ std::unique_ptr<Reference> TransformDerived(const Reference* value) override;
+ std::unique_ptr<Id> TransformDerived(const Id* value) override;
+ std::unique_ptr<RawString> TransformDerived(const RawString* value) override;
+ std::unique_ptr<String> TransformDerived(const String* value) override;
+ std::unique_ptr<StyledString> TransformDerived(const StyledString* value) override;
+ std::unique_ptr<FileReference> TransformDerived(const FileReference* value) override;
+ std::unique_ptr<BinaryPrimitive> TransformDerived(const BinaryPrimitive* value) override;
+ std::unique_ptr<Attribute> TransformDerived(const Attribute* value) override;
+ std::unique_ptr<Style> TransformDerived(const Style* value) override;
+ std::unique_ptr<Array> TransformDerived(const Array* value) override;
+ std::unique_ptr<Plural> TransformDerived(const Plural* value) override;
+ std::unique_ptr<Styleable> TransformDerived(const Styleable* value) override;
+};
+
} // namespace aapt
#endif // AAPT_RESOURCE_VALUES_H
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
index c4a1108ac62a..c75a4b99e138 100644
--- a/tools/aapt2/ResourceValues_test.cpp
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -62,7 +62,8 @@ TEST(ResourceValuesTest, PluralClone) {
a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
- std::unique_ptr<Plural> b(a.Clone(&pool));
+ CloningValueTransformer cloner(&pool);
+ std::unique_ptr<Plural> b(a.Transform(cloner));
EXPECT_TRUE(a.Equals(b.get()));
}
@@ -97,7 +98,8 @@ TEST(ResourceValuesTest, ArrayClone) {
a.elements.push_back(util::make_unique<String>(pool.MakeRef("one")));
a.elements.push_back(util::make_unique<String>(pool.MakeRef("two")));
- std::unique_ptr<Array> b(a.Clone(&pool));
+ CloningValueTransformer cloner(&pool);
+ std::unique_ptr<Array> b(a.Transform(cloner));
EXPECT_TRUE(a.Equals(b.get()));
}
@@ -160,7 +162,8 @@ TEST(ResourceValuesTest, StyleClone) {
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
.Build();
- std::unique_ptr<Style> b(a->Clone(nullptr));
+ CloningValueTransformer cloner(nullptr);
+ std::unique_ptr<Style> b(a->Transform(cloner));
EXPECT_TRUE(a->Equals(b.get()));
}
@@ -174,7 +177,8 @@ TEST(ResourcesValuesTest, StringClones) {
EXPECT_THAT(pool_a.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en")));
EXPECT_THAT(pool_a.strings()[0]->value, StrEq("hello"));
- std::unique_ptr<String> str_b(str_a.Clone(&pool_b));
+ CloningValueTransformer cloner(&pool_b);
+ str_a.Transform(cloner);
ASSERT_THAT(pool_b, SizeIs(1u));
EXPECT_THAT(pool_b.strings()[0]->context.config, Eq(test::ParseConfigOrDie("en")));
EXPECT_THAT(pool_b.strings()[0]->value, StrEq("hello"));
diff --git a/tools/aapt2/ValueTransformer.cpp b/tools/aapt2/ValueTransformer.cpp
new file mode 100644
index 000000000000..6eb2e30fb923
--- /dev/null
+++ b/tools/aapt2/ValueTransformer.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ValueTransformer.h"
+
+#include "ResourceValues.h"
+
+namespace aapt {
+
+#define VALUE_CREATE_VALUE_DECL(T) \
+ std::unique_ptr<Value> ValueTransformer::TransformValue(const T* value) { \
+ return TransformDerived(value); \
+ }
+
+#define VALUE_CREATE_ITEM_DECL(T) \
+ std::unique_ptr<Item> ValueTransformer::TransformItem(const T* value) { \
+ return TransformDerived(value); \
+ } \
+ std::unique_ptr<Value> ValueTransformer::TransformValue(const T* value) { \
+ return TransformItem(value); \
+ }
+
+VALUE_CREATE_ITEM_DECL(Id);
+VALUE_CREATE_ITEM_DECL(Reference);
+VALUE_CREATE_ITEM_DECL(RawString);
+VALUE_CREATE_ITEM_DECL(String);
+VALUE_CREATE_ITEM_DECL(StyledString);
+VALUE_CREATE_ITEM_DECL(FileReference);
+VALUE_CREATE_ITEM_DECL(BinaryPrimitive);
+
+VALUE_CREATE_VALUE_DECL(Attribute);
+VALUE_CREATE_VALUE_DECL(Style);
+VALUE_CREATE_VALUE_DECL(Array);
+VALUE_CREATE_VALUE_DECL(Plural);
+VALUE_CREATE_VALUE_DECL(Styleable);
+
+} // namespace aapt \ No newline at end of file
diff --git a/tools/aapt2/ValueTransformer.h b/tools/aapt2/ValueTransformer.h
new file mode 100644
index 000000000000..692511132012
--- /dev/null
+++ b/tools/aapt2/ValueTransformer.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_VALUE_TRANSFORMER_H
+#define AAPT_VALUE_TRANSFORMER_H
+
+#include <memory>
+
+#include "StringPool.h"
+
+namespace aapt {
+
+class Value;
+struct Item;
+struct Reference;
+struct Id;
+struct RawString;
+struct String;
+struct StyledString;
+struct FileReference;
+struct BinaryPrimitive;
+struct Attribute;
+struct Style;
+struct Array;
+struct Plural;
+struct Styleable;
+
+#define AAPT_TRANSFORM_VALUE(T) \
+ virtual std::unique_ptr<T> TransformDerived(const T* value) = 0; \
+ virtual std::unique_ptr<Value> TransformValue(const T* value);
+
+#define AAPT_TRANSFORM_ITEM(T) \
+ virtual std::unique_ptr<Item> TransformItem(const T* value); \
+ AAPT_TRANSFORM_VALUE(T)
+
+/**
+ * An interface for consuming a Value type and transforming it into another Value.
+ *
+ * The interface defines 2 methods for each type (T) that inherits from TransformableValue:
+ * std::unique_ptr<T> TransformDerived(const T*)
+ * std::unique_ptr<Value> TransformValue(const T*)
+ *
+ * The interface defines 3 method for each type (T) that inherits from TransformableItem:
+ * std::unique_ptr<T> TransformDerived(const T*)
+ * std::unique_ptr<Item> TransformItem(const T*)
+ * std::unique_ptr<Value> TransformValue(const T*)
+ *
+ * TransformDerived is invoked when Transform is invoked on the derived type T.
+ * TransformItem is invoked when Transform is invoked on an Item type.
+ * TransformValue is invoked when Transform is invoked on a Value type.
+ *
+ * ValueTransformerImpl transformer(&string_pool);
+ * T* derived = ...;
+ * std::unique_ptr<T> new_type = derived->Transform(transformer); // Invokes TransformDerived
+ *
+ * Item* item = derived;
+ * std::unique_ptr<Item> new_item = item->TransformItem(transformer); // Invokes TransformItem
+ *
+ * Value* value = item;
+ * std::unique_ptr<Value> new_value = value->TransformValue(transformer); // Invokes TransformValue
+ *
+ * For types that inherit from AbstractTransformableItem, the default implementation of
+ * TransformValue invokes TransformItem which invokes TransformDerived.
+ *
+ * For types that inherit from AbstractTransformableValue, the default implementation of
+ * TransformValue invokes TransformDerived.
+ */
+struct ValueTransformer {
+ // `new_pool` is the new StringPool that newly created Values should use for string storing string
+ // values.
+ explicit ValueTransformer(StringPool* new_pool);
+ virtual ~ValueTransformer() = default;
+
+ AAPT_TRANSFORM_ITEM(Id);
+ AAPT_TRANSFORM_ITEM(Reference);
+ AAPT_TRANSFORM_ITEM(RawString);
+ AAPT_TRANSFORM_ITEM(String);
+ AAPT_TRANSFORM_ITEM(StyledString);
+ AAPT_TRANSFORM_ITEM(FileReference);
+ AAPT_TRANSFORM_ITEM(BinaryPrimitive);
+
+ AAPT_TRANSFORM_VALUE(Attribute);
+ AAPT_TRANSFORM_VALUE(Style);
+ AAPT_TRANSFORM_VALUE(Array);
+ AAPT_TRANSFORM_VALUE(Plural);
+ AAPT_TRANSFORM_VALUE(Styleable);
+
+ protected:
+ StringPool* const pool_;
+};
+
+#undef AAPT_TRANSFORM_VALUE
+#undef AAPT_TRANSFORM_ITEM
+
+template <typename Derived, typename Base>
+struct TransformableValue : public Base {
+ // Transform this Derived into another Derived using the transformer.
+ std::unique_ptr<Derived> Transform(ValueTransformer& transformer) const;
+
+ private:
+ Value* TransformValueImpl(ValueTransformer& transformer) const override;
+};
+
+template <typename Derived, typename Base>
+struct TransformableItem : public TransformableValue<Derived, Base> {
+ private:
+ Item* TransformItemImpl(ValueTransformer& transformer) const override;
+};
+
+} // namespace aapt
+
+// Implementation
+#include "ValueTransformer_inline.h"
+
+#endif // AAPT_VALUE_TRANSFORMER_H \ No newline at end of file
diff --git a/tools/aapt2/ValueTransformer_inline.h b/tools/aapt2/ValueTransformer_inline.h
new file mode 100644
index 000000000000..c6c07c0fd6f9
--- /dev/null
+++ b/tools/aapt2/ValueTransformer_inline.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_VALUE_TRANSFORMER_IMPL_H
+#define AAPT_VALUE_TRANSFORMER_IMPL_H
+
+namespace aapt {
+
+inline ValueTransformer::ValueTransformer(StringPool* new_pool) : pool_(new_pool) {
+}
+
+template <typename Derived, typename Base>
+inline std::unique_ptr<Derived> TransformableValue<Derived, Base>::Transform(
+ ValueTransformer& transformer) const {
+ return transformer.TransformDerived(static_cast<const Derived*>(this));
+}
+
+template <typename Derived, typename Base>
+Value* TransformableValue<Derived, Base>::TransformValueImpl(ValueTransformer& transformer) const {
+ auto self = static_cast<const Derived*>(this);
+ auto transformed = transformer.TransformValue(self);
+ return transformed.release();
+}
+
+template <typename Derived, typename Base>
+Item* TransformableItem<Derived, Base>::TransformItemImpl(ValueTransformer& transformer) const {
+ auto self = static_cast<const Derived*>(this);
+ auto transformed = transformer.TransformItem(self);
+ return transformed.release();
+}
+
+} // namespace aapt
+
+#endif // AAPT_VALUE_TRANSFORMER_IMPL_H \ No newline at end of file
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 2a8923d927f6..2c57fb2b003e 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1656,10 +1656,11 @@ class Linker {
<< " with config \"" << config_value->config
<< "\" for round icon compatibility");
- auto value = icon_reference->Clone(&table->string_pool);
+ CloningValueTransformer cloner(&table->string_pool);
+ auto value = icon_reference->Transform(cloner);
auto round_config_value =
round_icon_entry->FindOrCreateValue(config_value->config, config_value->product);
- round_config_value->value.reset(value);
+ round_config_value->value = std::move(value);
}
}
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index 5e0300b3071b..3f574ee8e897 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -226,6 +226,7 @@ class Visitor : public ValueVisitor {
: pool_(pool), method_(method), localizer_(method) {}
void Visit(Plural* plural) override {
+ CloningValueTransformer cloner(pool_);
std::unique_ptr<Plural> localized = util::make_unique<Plural>();
for (size_t i = 0; i < plural->values.size(); i++) {
Visitor sub_visitor(pool_, method_);
@@ -234,7 +235,7 @@ class Visitor : public ValueVisitor {
if (sub_visitor.item) {
localized->values[i] = std::move(sub_visitor.item);
} else {
- localized->values[i] = std::unique_ptr<Item>(plural->values[i]->Clone(pool_));
+ localized->values[i] = plural->values[i]->Transform(cloner);
}
}
}
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index f5fe5e30bf0f..8139d7385092 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -299,6 +299,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
.Build();
// Add regular entries.
+ CloningValueTransformer cloner(&table->string_pool);
int stride = static_cast<int>(1.0f / load);
for (int i = 0; i < 100; i++) {
const ResourceName name = test::ParseNameOrDie(
@@ -308,7 +309,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i));
CHECK(table->AddResource(NewResourceBuilder(name)
.SetId(resid)
- .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)))
+ .SetValue(std::unique_ptr<Value>(value->Transform(cloner)))
.Build(),
context->GetDiagnostics()));
@@ -317,7 +318,7 @@ static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
CHECK(table->AddResource(
NewResourceBuilder(name)
.SetId(resid)
- .SetValue(std::unique_ptr<Value>(value->Clone(nullptr)), sparse_config)
+ .SetValue(std::unique_ptr<Value>(value->Transform(cloner)), sparse_config)
.Build(),
context->GetDiagnostics()));
}
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 8bb3ee93d312..d08b61e5ff66 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -334,11 +334,12 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)
styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
styleable.SetComment(StringPiece("This is a styleable"));
+ CloningValueTransformer cloner(nullptr);
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
.AddValue("android:styleable/Container",
- std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
+ std::unique_ptr<Styleable>(styleable.Transform(cloner)))
.Build();
std::unique_ptr<IAaptContext> context =
@@ -371,11 +372,12 @@ TEST(JavaClassGeneratorTest, CommentsForStyleableHiddenAttributesAreNotPresent)
styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
styleable.SetComment(StringPiece("This is a styleable"));
+ CloningValueTransformer cloner(nullptr);
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
.AddValue("android:attr/one", util::make_unique<Attribute>(attr))
.AddValue("android:styleable/Container",
- std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
+ std::unique_ptr<Styleable>(styleable.Transform(cloner)))
.Build();
std::unique_ptr<IAaptContext> context =
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index 73b92542a755..876494e617a6 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -72,6 +72,7 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
TRACE_NAME("AutoVersioner::Consume");
+ CloningValueTransformer cloner(&table->string_pool);
for (auto& package : table->packages) {
for (auto& type : package->types) {
if (type->type != ResourceType::kStyle) {
@@ -128,7 +129,7 @@ bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
ConfigDescription new_config(config_value->config);
new_config.sdkVersion = static_cast<uint16_t>(min_sdk_stripped.value());
- std::unique_ptr<Style> new_style(style->Clone(&table->string_pool));
+ std::unique_ptr<Style> new_style(style->Transform(cloner));
new_style->SetComment(style->GetComment());
new_style->SetSource(style->GetSource());
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 4ef2882ce347..bc93ec6908e7 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -280,13 +280,13 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
}
// Continue if we're taking the new resource.
-
+ CloningValueTransformer cloner(&main_table_->string_pool);
if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
std::unique_ptr<FileReference> new_file_ref;
if (mangle_package) {
new_file_ref = CloneAndMangleFile(src_package->name, *f);
} else {
- new_file_ref = std::unique_ptr<FileReference>(f->Clone(&main_table_->string_pool));
+ new_file_ref = std::unique_ptr<FileReference>(f->Transform(cloner));
}
dst_config_value->value = std::move(new_file_ref);
@@ -294,8 +294,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
Maybe<std::string> original_comment = (dst_config_value->value)
? dst_config_value->value->GetComment() : Maybe<std::string>();
- dst_config_value->value = std::unique_ptr<Value>(
- src_config_value->value->Clone(&main_table_->string_pool));
+ dst_config_value->value = src_config_value->value->Transform(cloner);
// Keep the comment from the original resource and ignore all comments from overlaying
// resources
@@ -323,7 +322,9 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
new_file_ref->file = file_ref.file;
return new_file_ref;
}
- return std::unique_ptr<FileReference>(file_ref.Clone(&main_table_->string_pool));
+
+ CloningValueTransformer cloner(&main_table_->string_pool);
+ return std::unique_ptr<FileReference>(file_ref.Transform(cloner));
}
bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFile* file) {
diff --git a/tools/aapt2/link/XmlCompatVersioner.cpp b/tools/aapt2/link/XmlCompatVersioner.cpp
index 6937ca961f06..957b64cd8dbb 100644
--- a/tools/aapt2/link/XmlCompatVersioner.cpp
+++ b/tools/aapt2/link/XmlCompatVersioner.cpp
@@ -23,9 +23,10 @@
namespace aapt {
static xml::Attribute CopyAttr(const xml::Attribute& src, StringPool* out_string_pool) {
+ CloningValueTransformer cloner(out_string_pool);
xml::Attribute dst{src.namespace_uri, src.name, src.value, src.compiled_attribute};
if (src.compiled_value != nullptr) {
- dst.compiled_value.reset(src.compiled_value->Clone(out_string_pool));
+ dst.compiled_value = src.compiled_value->Transform(cloner);
}
return dst;
}
@@ -34,6 +35,7 @@ static xml::Attribute CopyAttr(const xml::Attribute& src, StringPool* out_string
// (came from a rule).
static bool CopyAttribute(const xml::Attribute& src_attr, bool generated, xml::Element* dst_el,
StringPool* out_string_pool) {
+ CloningValueTransformer cloner(out_string_pool);
xml::Attribute* dst_attr = dst_el->FindAttribute(src_attr.namespace_uri, src_attr.name);
if (dst_attr != nullptr) {
if (generated) {
@@ -41,7 +43,7 @@ static bool CopyAttribute(const xml::Attribute& src_attr, bool generated, xml::E
dst_attr->value = src_attr.value;
dst_attr->compiled_attribute = src_attr.compiled_attribute;
if (src_attr.compiled_value != nullptr) {
- dst_attr->compiled_value.reset(src_attr.compiled_value->Clone(out_string_pool));
+ dst_attr->compiled_value = src_attr.compiled_value->Transform(cloner);
}
return true;
}
@@ -158,7 +160,8 @@ static inline std::unique_ptr<Item> CloneIfNotNull(const std::unique_ptr<Item>&
if (src == nullptr) {
return {};
}
- return std::unique_ptr<Item>(src->Clone(out_string_pool));
+ CloningValueTransformer cloner(out_string_pool);
+ return src->Transform(cloner);
}
std::vector<DegradeResult> DegradeToManyRule::Degrade(const xml::Element& src_el,
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 2f319b11e3b2..116b2ab9aa98 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -229,6 +229,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) {
for (size_t idx = 0; idx < split_count; idx++) {
const SplitConstraints& split_constraint = split_constraints_[idx];
ResourceTable* split_table = splits_[idx].get();
+ CloningValueTransformer cloner(&split_table->string_pool);
// Select the values we want from this entry for this split.
SplitValueSelector selector(split_constraint);
@@ -254,8 +255,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) {
for (ResourceConfigValue* config_value : selected_values) {
ResourceConfigValue* new_config_value =
split_entry->FindOrCreateValue(config_value->config, config_value->product);
- new_config_value->value = std::unique_ptr<Value>(
- config_value->value->Clone(&split_table->string_pool));
+ new_config_value->value = config_value->value->Transform(cloner);
}
}
}
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 553c43e6c469..5d8ded39e654 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -200,10 +200,11 @@ class StaticSymbolSourceBuilder {
private:
std::unique_ptr<SymbolTable::Symbol> CloneSymbol(SymbolTable::Symbol* sym) {
+ CloningValueTransformer cloner(nullptr);
std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
clone->id = sym->id;
if (sym->attribute) {
- clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Clone(nullptr));
+ clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Transform(cloner));
}
clone->is_public = sym->is_public;
return clone;
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 005eeb936612..2cdcfe45b50e 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -374,6 +374,7 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string*
std::unique_ptr<XmlResource> XmlResource::Clone() const {
std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
+ CloningValueTransformer cloner(&cloned->string_pool);
if (root != nullptr) {
cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
dst->attributes.reserve(src.attributes.size());
@@ -384,7 +385,7 @@ std::unique_ptr<XmlResource> XmlResource::Clone() const {
cloned_attr.value = attr.value;
cloned_attr.compiled_attribute = attr.compiled_attribute;
if (attr.compiled_value != nullptr) {
- cloned_attr.compiled_value.reset(attr.compiled_value->Clone(&cloned->string_pool));
+ cloned_attr.compiled_value = attr.compiled_value->Transform(cloner);
}
dst->attributes.push_back(std::move(cloned_attr));
}