Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31031a91 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "Aapt2 ValueTransformer" into sc-dev

parents 99179144 efcdb95f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ cc_library_host_static {
        "Configuration.proto",
        "Resources.proto",
        "ResourcesInternal.proto",
        "ValueTransformer.cpp",
    ],
    proto: {
        export_proto_headers: true,
+2 −1
Original line number Diff line number Diff line
@@ -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);
        }
      }
    }
+111 −88
Original line number Diff line number Diff line
@@ -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
+41 −30
Original line number Diff line number Diff line
@@ -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
+8 −4
Original line number Diff line number Diff line
@@ -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"));
Loading