Merge changes I0b97fc00,Ib09776e6

* changes:
  Switch ResourceName to use ResourceNamedType instead of ResourceType.
  Introduce ResourceNamedType that represents pair of name + ResourceType.
This commit is contained in:
Iurii Makhno
2022-02-17 20:19:08 +00:00
committed by Android (Google) Code Review
18 changed files with 349 additions and 82 deletions

View File

@@ -80,7 +80,7 @@ class ValueHeadlinePrinter : public ConstValueVisitor {
printer_->Print(parent_name.package);
printer_->Print(":");
}
printer_->Print(to_string(parent_name.type));
printer_->Print(parent_name.type.to_string());
printer_->Print("/");
printer_->Print(parent_name.entry);
if (parent_ref.id) {

View File

@@ -134,6 +134,24 @@ static const std::map<StringPiece, ResourceType> sResourceTypeMap{
{"xml", ResourceType::kXml},
};
ResourceNamedTypeRef ResourceNamedTypeWithDefaultName(ResourceType t) {
return {to_string(t), t};
}
std::optional<ResourceNamedTypeRef> ParseResourceNamedType(const android::StringPiece& s) {
auto colon = std::find(s.begin(), s.end(), ':');
const ResourceType* parsedType;
if (colon != s.end() && colon != std::prev(s.end())) {
parsedType = ParseResourceType(s.substr(s.begin(), colon));
} else {
parsedType = ParseResourceType(s);
}
if (parsedType == nullptr) {
return std::nullopt;
}
return ResourceNamedTypeRef(s, *parsedType);
}
const ResourceType* ParseResourceType(const StringPiece& str) {
auto iter = sResourceTypeMap.find(str);
if (iter == std::end(sResourceTypeMap)) {

View File

@@ -19,22 +19,21 @@
#include <iomanip>
#include <limits>
#include <optional>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>
#include "Source.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "utils/JenkinsHash.h"
#include "Source.h"
namespace aapt {
/**
* The various types of resource types available. Corresponds
* to the 'type' in package:type/entry.
* The various types of resource types available.
*/
enum class ResourceType {
kAnim,
@@ -77,16 +76,64 @@ android::StringPiece to_string(ResourceType type);
*/
const ResourceType* ParseResourceType(const android::StringPiece& str);
/**
* Pair of type name as in ResourceTable and actual resource type.
* Corresponds to the 'type' in package:type/entry.
*
* This is to support resource types with custom names inside resource tables.
*/
struct ResourceNamedType {
std::string name;
ResourceType type = ResourceType::kRaw;
ResourceNamedType() = default;
ResourceNamedType(const android::StringPiece& n, ResourceType t);
int compare(const ResourceNamedType& other) const;
const std::string& to_string() const;
};
/**
* Same as ResourceNamedType, but uses StringPieces instead.
* Use this if you need to avoid copying and know that
* the lifetime of this object is shorter than that
* of the original string.
*/
struct ResourceNamedTypeRef {
android::StringPiece name;
ResourceType type = ResourceType::kRaw;
ResourceNamedTypeRef() = default;
ResourceNamedTypeRef(const ResourceNamedTypeRef&) = default;
ResourceNamedTypeRef(ResourceNamedTypeRef&&) = default;
ResourceNamedTypeRef(const ResourceNamedType& rhs); // NOLINT(google-explicit-constructor)
ResourceNamedTypeRef(const android::StringPiece& n, ResourceType t);
ResourceNamedTypeRef& operator=(const ResourceNamedTypeRef& rhs) = default;
ResourceNamedTypeRef& operator=(ResourceNamedTypeRef&& rhs) = default;
ResourceNamedTypeRef& operator=(const ResourceNamedType& rhs);
ResourceNamedType ToResourceNamedType() const;
std::string to_string() const;
};
ResourceNamedTypeRef ResourceNamedTypeWithDefaultName(ResourceType t);
std::optional<ResourceNamedTypeRef> ParseResourceNamedType(const android::StringPiece& s);
/**
* A resource's name. This can uniquely identify
* a resource in the ResourceTable.
*/
struct ResourceName {
std::string package;
ResourceType type = ResourceType::kRaw;
ResourceNamedType type;
std::string entry;
ResourceName() = default;
ResourceName(const android::StringPiece& p, const ResourceNamedTypeRef& t,
const android::StringPiece& e);
ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
int compare(const ResourceName& other) const;
@@ -103,13 +150,15 @@ struct ResourceName {
*/
struct ResourceNameRef {
android::StringPiece package;
ResourceType type = ResourceType::kRaw;
ResourceNamedTypeRef type;
android::StringPiece entry;
ResourceNameRef() = default;
ResourceNameRef(const ResourceNameRef&) = default;
ResourceNameRef(ResourceNameRef&&) = default;
ResourceNameRef(const ResourceName& rhs); // NOLINT(google-explicit-constructor)
ResourceNameRef(const android::StringPiece& p, const ResourceNamedTypeRef& t,
const android::StringPiece& e);
ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -294,18 +343,99 @@ inline ::std::ostream& operator<<(::std::ostream& out, const ResourceType& val)
return out << to_string(val);
}
//
// ResourceNamedType implementation.
//
inline ResourceNamedType::ResourceNamedType(const android::StringPiece& n, ResourceType t)
: name(n.to_string()), type(t) {
}
inline int ResourceNamedType::compare(const ResourceNamedType& other) const {
int cmp = static_cast<int>(type) - static_cast<int>(other.type);
if (cmp != 0) return cmp;
cmp = name.compare(other.name);
return cmp;
}
inline const std::string& ResourceNamedType::to_string() const {
return name;
}
inline bool operator<(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
return lhs.compare(rhs) < 0;
}
inline bool operator==(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
return lhs.compare(rhs) == 0;
}
inline bool operator!=(const ResourceNamedType& lhs, const ResourceNamedType& rhs) {
return lhs.compare(rhs) != 0;
}
inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNamedType& val) {
return out << val.to_string();
}
//
// ResourceNamedTypeRef implementation.
//
inline ResourceNamedTypeRef::ResourceNamedTypeRef(const android::StringPiece& n, ResourceType t)
: name(n), type(t) {
}
inline ResourceNamedTypeRef::ResourceNamedTypeRef(const ResourceNamedType& rhs)
: name(rhs.name), type(rhs.type) {
}
inline ResourceNamedTypeRef& ResourceNamedTypeRef::operator=(const ResourceNamedType& rhs) {
name = rhs.name;
type = rhs.type;
return *this;
}
inline ResourceNamedType ResourceNamedTypeRef::ToResourceNamedType() const {
return ResourceNamedType(name, type);
}
inline std::string ResourceNamedTypeRef::to_string() const {
return name.to_string();
}
inline bool operator<(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
return std::tie(lhs.type, lhs.name) < std::tie(rhs.type, rhs.name);
}
inline bool operator==(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
return std::tie(lhs.type, lhs.name) == std::tie(rhs.type, rhs.name);
}
inline bool operator!=(const ResourceNamedTypeRef& lhs, const ResourceNamedTypeRef& rhs) {
return std::tie(lhs.type, lhs.name) != std::tie(rhs.type, rhs.name);
}
inline ::std::ostream& operator<<(::std::ostream& out, const ResourceNamedTypeRef& val) {
return out << val.name;
}
//
// ResourceName implementation.
//
inline ResourceName::ResourceName(const android::StringPiece& p, const ResourceNamedTypeRef& t,
const android::StringPiece& e)
: package(p.to_string()), type(t.ToResourceNamedType()), entry(e.to_string()) {
}
inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
const android::StringPiece& e)
: package(p.to_string()), type(t), entry(e.to_string()) {}
: ResourceName(p, ResourceNamedTypeWithDefaultName(t), e) {
}
inline int ResourceName::compare(const ResourceName& other) const {
int cmp = package.compare(other.package);
if (cmp != 0) return cmp;
cmp = static_cast<int>(type) - static_cast<int>(other.type);
cmp = type.compare(other.type);
if (cmp != 0) return cmp;
cmp = entry.compare(other.entry);
return cmp;
@@ -341,9 +471,16 @@ inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name)
inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
: package(rhs.package), type(rhs.type), entry(rhs.entry) {}
inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p,
const ResourceNamedTypeRef& t,
const android::StringPiece& e)
: package(p), type(t), entry(e) {
}
inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
const android::StringPiece& e)
: package(p), type(t), entry(e) {}
: ResourceNameRef(p, ResourceNamedTypeWithDefaultName(t), e) {
}
inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
package = rhs.package;
@@ -400,7 +537,7 @@ struct hash<aapt::ResourceName> {
size_t operator()(const aapt::ResourceName& name) const {
android::hash_t h = 0;
h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.package)));
h = android::JenkinsHashMix(h, static_cast<uint32_t>(name.type));
h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.type.name)));
h = android::JenkinsHashMix(h, static_cast<uint32_t>(hash<string>()(name.entry)));
return static_cast<size_t>(h);
}

View File

@@ -604,7 +604,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
return false;
}
out_resource->name.type = ResourceType::kId;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kId).ToResourceNamedType();
out_resource->name.entry = maybe_name.value().to_string();
// Ids either represent a unique resource id or reference another resource id
@@ -623,7 +624,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
// A null reference also means there is no inner element when ids are in the form:
// <id name="name"/>
out_resource->value = util::make_unique<Id>();
} else if (!ref || ref->name.value().type != ResourceType::kId) {
} else if (!ref || ref->name.value().type.type != ResourceType::kId) {
// If an inner element exists, the inner element must be a reference to another resource id
diag_->Error(DiagMessage(out_resource->source)
<< "<" << parser->element_name()
@@ -640,7 +641,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
return false;
}
out_resource->name.type = ResourceType::kMacro;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kMacro).ToResourceNamedType();
out_resource->name.entry = maybe_name.value().to_string();
return ParseMacro(parser, out_resource);
}
@@ -656,7 +658,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
return false;
}
out_resource->name.type = item_iter->second.type;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(item_iter->second.type).ToResourceNamedType();
out_resource->name.entry = maybe_name.value().to_string();
// Only use the implied format of the type when there is no explicit format.
@@ -699,7 +702,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
if (can_be_item) {
// Try parsing the elementName (or type) as a resource. These shall only be
// resources like 'layout' or 'xml' and they can only be references.
const ResourceType* parsed_type = ParseResourceType(resource_type);
std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(resource_type);
if (parsed_type) {
if (!maybe_name) {
diag_->Error(DiagMessage(out_resource->source)
@@ -708,7 +711,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
return false;
}
out_resource->name.type = *parsed_type;
out_resource->name.type = parsed_type->ToResourceNamedType();
out_resource->name.entry = maybe_name.value().to_string();
out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
if (!out_resource->value) {
@@ -933,7 +936,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
return false;
}
const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
if (!parsed_type) {
diag_->Error(DiagMessage(out_resource->source) << "invalid resource type '"
<< maybe_type.value()
@@ -941,7 +944,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
return false;
}
out_resource->name.type = *parsed_type;
out_resource->name.type = parsed_type->ToResourceNamedType();
if (std::optional<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "id")) {
std::optional<ResourceId> maybe_id = ResourceUtils::ParseResourceId(maybe_id_str.value());
@@ -953,7 +956,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out
out_resource->id = maybe_id.value();
}
if (*parsed_type == ResourceType::kId) {
if (parsed_type->type == ResourceType::kId) {
// An ID marked as public is also the definition of an ID.
out_resource->value = util::make_unique<Id>();
}
@@ -978,7 +981,7 @@ bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resou
return false;
}
const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
if (!parsed_type) {
diag->Error(DiagMessage(out_resource->source)
<< "invalid resource type '" << maybe_type.value() << "' in <" << tag_name << ">");
@@ -1096,7 +1099,7 @@ bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser,
return false;
}
const ResourceType* parsed_type = ParseResourceType(maybe_type.value());
std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value());
if (!parsed_type) {
diag_->Error(DiagMessage(out_resource->source)
<< "invalid resource type '" << maybe_type.value() << "' in <"
@@ -1104,7 +1107,7 @@ bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser,
return false;
}
out_resource->name.type = *parsed_type;
out_resource->name.type = parsed_type->ToResourceNamedType();
return true;
}
@@ -1208,8 +1211,8 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
continue;
}
const ResourceType* type = ParseResourceType(item_type.value());
if (type == nullptr) {
std::optional<ResourceNamedTypeRef> type = ParseResourceNamedType(item_type.value());
if (!type) {
diag_->Error(DiagMessage(element_source)
<< "invalid resource type '" << item_type.value()
<< "' in <item> within an <overlayable>");
@@ -1223,7 +1226,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
overlayable_item.source = element_source;
ParsedResource child_resource{};
child_resource.name.type = *type;
child_resource.name.type = type->ToResourceNamedType();
child_resource.name.entry = item_name.value().to_string();
child_resource.overlayable_item = overlayable_item;
out_resource->child_resources.push_back(std::move(child_resource));
@@ -1289,7 +1292,8 @@ bool ResourceParser::ParseAttr(xml::XmlPullParser* parser,
bool ResourceParser::ParseAttrImpl(xml::XmlPullParser* parser,
ParsedResource* out_resource, bool weak) {
out_resource->name.type = ResourceType::kAttr;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kAttr).ToResourceNamedType();
// Attributes only end up in default configuration.
if (out_resource->config != ConfigDescription::DefaultConfig()) {
@@ -1475,7 +1479,8 @@ std::optional<Attribute::Symbol> ResourceParser::ParseEnumOrFlagItem(xml::XmlPul
}
return Attribute::Symbol{
Reference(ResourceNameRef({}, ResourceType::kId, maybe_name.value())),
Reference(ResourceNameRef({}, ResourceNamedTypeWithDefaultName(ResourceType::kId),
maybe_name.value())),
val.data, val.dataType};
}
@@ -1509,7 +1514,7 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) {
bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
ParsedResource* out_resource) {
out_resource->name.type = type;
out_resource->name.type = ResourceNamedTypeWithDefaultName(type).ToResourceNamedType();
std::unique_ptr<Style> style = util::make_unique<Style>();
@@ -1535,7 +1540,8 @@ bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* par
size_t pos = style_name.find_last_of(u'.');
if (pos != std::string::npos) {
style->parent_inferred = true;
style->parent = Reference(ResourceName({}, ResourceType::kStyle, style_name.substr(0, pos)));
style->parent = Reference(ResourceName(
{}, ResourceNamedTypeWithDefaultName(ResourceType::kStyle), style_name.substr(0, pos)));
}
}
@@ -1591,7 +1597,8 @@ bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser, ParsedResource
bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
ParsedResource* out_resource,
const uint32_t typeMask) {
out_resource->name.type = ResourceType::kArray;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kArray).ToResourceNamedType();
std::unique_ptr<Array> array = util::make_unique<Array>();
@@ -1646,7 +1653,8 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
bool ResourceParser::ParsePlural(xml::XmlPullParser* parser,
ParsedResource* out_resource) {
out_resource->name.type = ResourceType::kPlurals;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kPlurals).ToResourceNamedType();
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
@@ -1727,7 +1735,8 @@ bool ResourceParser::ParsePlural(xml::XmlPullParser* parser,
bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser,
ParsedResource* out_resource) {
out_resource->name.type = ResourceType::kStyleable;
out_resource->name.type =
ResourceNamedTypeWithDefaultName(ResourceType::kStyleable).ToResourceNamedType();
if (!options_.preserve_visibility_of_styleables) {
// This was added in change Idd21b5de4d20be06c6f8c8eb5a22ccd68afc4927 to mimic aapt1, but no one

View File

@@ -473,7 +473,7 @@ bool ResourceTable::AddResource(NewResource&& res, IDiagnostics* diag) {
}
auto package = FindOrCreatePackage(res.name.package);
auto type = package->FindOrCreateType(res.name.type);
auto type = package->FindOrCreateType(res.name.type.type);
auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry,
NameEqualRange<ResourceEntry>{});
const size_t entry_count = std::distance(entry_it.first, entry_it.second);
@@ -593,7 +593,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(
return {};
}
ResourceTableType* type = package->FindType(name.type);
ResourceTableType* type = package->FindType(name.type.type);
if (type == nullptr) {
return {};
}
@@ -612,7 +612,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(const Res
return {};
}
ResourceTableType* type = package->FindType(name.type);
ResourceTableType* type = package->FindType(name.type.type);
if (type == nullptr) {
return {};
}
@@ -633,7 +633,7 @@ bool ResourceTable::RemoveResource(const ResourceNameRef& name, ResourceId id) c
return {};
}
ResourceTableType* type = package->FindType(name.type);
ResourceTableType* type = package->FindType(name.type.type);
if (type == nullptr) {
return {};
}

View File

@@ -50,12 +50,11 @@ std::optional<ResourceName> ToResourceName(const android::ResTable::resource_nam
name_out.package =
util::Utf16ToUtf8(StringPiece16(name_in.package, name_in.packageLen));
const ResourceType* type;
std::optional<ResourceNamedTypeRef> type;
if (name_in.type) {
type = ParseResourceType(
util::Utf16ToUtf8(StringPiece16(name_in.type, name_in.typeLen)));
type = ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type, name_in.typeLen)));
} else if (name_in.type8) {
type = ParseResourceType(StringPiece(name_in.type8, name_in.typeLen));
type = ParseResourceNamedType(StringPiece(name_in.type8, name_in.typeLen));
} else {
return {};
}
@@ -64,7 +63,7 @@ std::optional<ResourceName> ToResourceName(const android::ResTable::resource_nam
return {};
}
name_out.type = *type;
name_out.type = type->ToResourceNamedType();
if (name_in.name) {
name_out.entry =
@@ -85,12 +84,12 @@ std::optional<ResourceName> ToResourceName(const android::AssetManager2::Resourc
name_out.package = std::string(name_in.package, name_in.package_len);
const ResourceType* type;
std::optional<ResourceNamedTypeRef> type;
if (name_in.type16) {
type = ParseResourceType(
util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len)));
type =
ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len)));
} else if (name_in.type) {
type = ParseResourceType(StringPiece(name_in.type, name_in.type_len));
type = ParseResourceNamedType(StringPiece(name_in.type, name_in.type_len));
} else {
return {};
}
@@ -99,7 +98,7 @@ std::optional<ResourceName> ToResourceName(const android::AssetManager2::Resourc
return {};
}
name_out.type = *type;
name_out.type = type->ToResourceNamedType();
if (name_in.entry16) {
name_out.entry =
@@ -133,7 +132,7 @@ bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_ref,
return false;
}
const ResourceType* parsed_type = ParseResourceType(type);
std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(type);
if (!parsed_type) {
return false;
}
@@ -181,7 +180,7 @@ bool ParseReference(const StringPiece& str, ResourceNameRef* out_ref,
return false;
}
if (create && name.type != ResourceType::kId) {
if (create && name.type.type != ResourceType::kId) {
return false;
}
@@ -230,7 +229,7 @@ bool ParseAttributeReference(const StringPiece& str, ResourceNameRef* out_ref) {
if (out_ref) {
out_ref->package = package;
out_ref->type = ResourceType::kAttr;
out_ref->type = ResourceNamedTypeWithDefaultName(ResourceType::kAttr);
out_ref->entry = entry;
}
return true;
@@ -272,7 +271,7 @@ std::optional<Reference> ParseStyleParentReference(const StringPiece& str, std::
}
ResourceNameRef ref;
ref.type = ResourceType::kStyle;
ref.type = ResourceNamedTypeWithDefaultName(ResourceType::kStyle);
StringPiece type_str;
android::ExtractResourceName(name, &ref.package, &type_str, &ref.entry);
@@ -323,7 +322,8 @@ std::optional<Reference> ParseXmlAttributeName(const StringPiece& str) {
p++;
}
ref.name = ResourceName(package, ResourceType::kAttr, name.empty() ? trimmed_str : name);
ref.name = ResourceName(package, ResourceNamedTypeWithDefaultName(ResourceType::kAttr),
name.empty() ? trimmed_str : name);
return std::optional<Reference>(std::move(ref));
}

View File

@@ -116,7 +116,7 @@ bool Reference::Equals(const Value* value) const {
}
bool Reference::Flatten(android::Res_value* out_value) const {
if (name && name.value().type == ResourceType::kMacro) {
if (name && name.value().type.type == ResourceType::kMacro) {
return false;
}
@@ -192,7 +192,7 @@ static void PrettyPrintReferenceImpl(const Reference& ref, bool print_package, P
if (print_package) {
printer->Print(name.to_string());
} else {
printer->Print(to_string(name.type));
printer->Print(name.type.to_string());
printer->Print("/");
printer->Print(name.entry);
}

View File

@@ -18,6 +18,9 @@
#include "test/Test.h"
using ::testing::Eq;
using ::testing::Optional;
namespace aapt {
TEST(ResourceTypeTest, ParseResourceTypes) {
@@ -125,4 +128,104 @@ TEST(ResourceTypeTest, ParseResourceTypes) {
EXPECT_EQ(type, nullptr);
}
TEST(ResourceTypeTest, ParseResourceNamedType) {
auto type = ParseResourceNamedType("anim");
EXPECT_THAT(type, Optional(Eq(ResourceNamedType("anim", ResourceType::kAnim))));
type = ParseResourceNamedType("layout");
EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout", ResourceType::kLayout))));
type = ParseResourceNamedType("layout:2");
EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:2", ResourceType::kLayout))));
type = ParseResourceNamedType("layout:another");
EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:another", ResourceType::kLayout))));
type = ParseResourceNamedType("layout:");
EXPECT_THAT(type, Eq(std::nullopt));
type = ParseResourceNamedType("layout2");
EXPECT_THAT(type, Eq(std::nullopt));
type = ParseResourceNamedType("blahaha");
EXPECT_THAT(type, Eq(std::nullopt));
}
TEST(ResourceTypeTest, ResourceNamedTypeWithDefaultName) {
auto type = ResourceNamedTypeWithDefaultName(ResourceType::kAnim);
EXPECT_THAT(type, Eq(ResourceNamedType("anim", ResourceType::kAnim)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kAnimator);
EXPECT_THAT(type, Eq(ResourceNamedType("animator", ResourceType::kAnimator)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kArray);
EXPECT_THAT(type, Eq(ResourceNamedType("array", ResourceType::kArray)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kAttr);
EXPECT_THAT(type, Eq(ResourceNamedType("attr", ResourceType::kAttr)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kAttrPrivate);
EXPECT_THAT(type, Eq(ResourceNamedType("^attr-private", ResourceType::kAttrPrivate)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kBool);
EXPECT_THAT(type, Eq(ResourceNamedType("bool", ResourceType::kBool)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kColor);
EXPECT_THAT(type, Eq(ResourceNamedType("color", ResourceType::kColor)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kConfigVarying);
EXPECT_THAT(type, Eq(ResourceNamedType("configVarying", ResourceType::kConfigVarying)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kDimen);
EXPECT_THAT(type, Eq(ResourceNamedType("dimen", ResourceType::kDimen)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kDrawable);
EXPECT_THAT(type, Eq(ResourceNamedType("drawable", ResourceType::kDrawable)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kFont);
EXPECT_THAT(type, Eq(ResourceNamedType("font", ResourceType::kFont)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kFraction);
EXPECT_THAT(type, Eq(ResourceNamedType("fraction", ResourceType::kFraction)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kId);
EXPECT_THAT(type, Eq(ResourceNamedType("id", ResourceType::kId)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kInteger);
EXPECT_THAT(type, Eq(ResourceNamedType("integer", ResourceType::kInteger)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kInterpolator);
EXPECT_THAT(type, Eq(ResourceNamedType("interpolator", ResourceType::kInterpolator)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kLayout);
EXPECT_THAT(type, Eq(ResourceNamedType("layout", ResourceType::kLayout)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kMenu);
EXPECT_THAT(type, Eq(ResourceNamedType("menu", ResourceType::kMenu)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kMipmap);
EXPECT_THAT(type, Eq(ResourceNamedType("mipmap", ResourceType::kMipmap)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kNavigation);
EXPECT_THAT(type, Eq(ResourceNamedType("navigation", ResourceType::kNavigation)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kPlurals);
EXPECT_THAT(type, Eq(ResourceNamedType("plurals", ResourceType::kPlurals)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kRaw);
EXPECT_THAT(type, Eq(ResourceNamedType("raw", ResourceType::kRaw)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kString);
EXPECT_THAT(type, Eq(ResourceNamedType("string", ResourceType::kString)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kStyle);
EXPECT_THAT(type, Eq(ResourceNamedType("style", ResourceType::kStyle)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kTransition);
EXPECT_THAT(type, Eq(ResourceNamedType("transition", ResourceType::kTransition)));
type = ResourceNamedTypeWithDefaultName(ResourceType::kXml);
EXPECT_THAT(type, Eq(ResourceNamedType("xml", ResourceType::kXml)));
}
} // namespace aapt

View File

@@ -207,7 +207,7 @@ class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
}
// Check to see if this is an 'id' with the target package.
if (name.type == ResourceType::kId && symbol->id) {
if (name.type.type == ResourceType::kId && symbol->id) {
ResourceId* id = &symbol->id.value();
if (id->package_id() > kAppPackageId) {
// Rewrite the resource ID to be compatible pre-O.

View File

@@ -275,7 +275,7 @@ bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id,
return false;
}
auto key = ResourceTypeKey{name.type, id.type_id()};
auto key = ResourceTypeKey{name.type.type, id.type_id()};
auto type = types_.find(key);
if (type == types_.end()) {
// The type has not been assigned an id yet. Ensure that the specified id is not being used by
@@ -291,7 +291,7 @@ bool IdAssignerContext::ReserveId(const ResourceName& name, ResourceId id,
if (!visibility.staged_api) {
// Ensure that non-staged resources can only exist in one type ID.
auto non_staged_type = non_staged_type_ids_.emplace(name.type, id.type_id());
auto non_staged_type = non_staged_type_ids_.emplace(name.type.type, id.type_id());
if (!non_staged_type.second && non_staged_type.first->second != id.type_id()) {
diag->Error(DiagMessage() << "can't assign ID " << id << " to resource " << name
<< " because type already has ID " << std::hex
@@ -316,14 +316,14 @@ std::optional<ResourceId> IdAssignerContext::NextId(const ResourceName& name, ID
CHECK(name.package.empty() || name.package == package_name_);
// Find the type id for non-staged resources of this type.
auto non_staged_type = non_staged_type_ids_.find(name.type);
auto non_staged_type = non_staged_type_ids_.find(name.type.type);
if (non_staged_type == non_staged_type_ids_.end()) {
auto next_type_id = type_id_finder_.NextId();
CHECK(next_type_id.has_value()) << "resource type IDs allocated have exceeded maximum (256)";
non_staged_type = non_staged_type_ids_.emplace(name.type, *next_type_id).first;
non_staged_type = non_staged_type_ids_.emplace(name.type.type, *next_type_id).first;
}
ResourceTypeKey key{name.type, non_staged_type->second};
ResourceTypeKey key{name.type.type, non_staged_type->second};
auto type = types_.find(key);
if (type == types_.end()) {
type = types_.emplace(key, TypeGroup(package_id_, key.id)).first;

View File

@@ -46,7 +46,7 @@ struct IdCollector : public xml::Visitor {
ResourceNameRef name;
bool create = false;
if (ResourceUtils::ParseReference(attr.value, &name, &create, nullptr)) {
if (create && name.type == ResourceType::kId) {
if (create && name.type.type == ResourceType::kId) {
if (!text::IsValidResourceEntryName(name.entry)) {
source_diag_->Error(DiagMessage(element->line_number)
<< "id '" << name << "' has an invalid entry name");

View File

@@ -556,8 +556,8 @@ bool BinaryResourceParser::ParseStagedAliases(const ResChunk_header* chunk) {
std::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& name,
const ConfigDescription& config,
const android::Res_value& value) {
std::unique_ptr<Item> item = ResourceUtils::ParseBinaryResValue(name.type, config, value_pool_,
value, &table_->string_pool);
std::unique_ptr<Item> item = ResourceUtils::ParseBinaryResValue(
name.type.type, config, value_pool_, value, &table_->string_pool);
if (files_ != nullptr) {
FileReference* file_ref = ValueCast<FileReference>(item.get());
if (file_ref != nullptr) {
@@ -575,7 +575,7 @@ std::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& na
std::unique_ptr<Value> BinaryResourceParser::ParseMapEntry(const ResourceNameRef& name,
const ConfigDescription& config,
const ResTable_map_entry* map) {
switch (name.type) {
switch (name.type.type) {
case ResourceType::kStyle:
// fallthrough
case ResourceType::kConfigVarying: // legacy thing used in tests
@@ -594,8 +594,8 @@ std::unique_ptr<Value> BinaryResourceParser::ParseMapEntry(const ResourceNameRef
// We can ignore the value here.
return util::make_unique<Id>();
default:
diag_->Error(DiagMessage() << "illegal map type '" << to_string(name.type) << "' ("
<< (int)name.type << ")");
diag_->Error(DiagMessage() << "illegal map type '" << name.type << "' ("
<< (int)name.type.type << ")");
break;
}
return {};

View File

@@ -229,8 +229,8 @@ static FieldReference GetRFieldReference(const ResourceName& name,
const std::string package_name =
name.package.empty() ? fallback_package_name.to_string() : name.package;
const std::string entry = JavaClassGenerator::TransformToFieldName(name.entry);
return FieldReference(
StringPrintf("%s.R.%s.%s", package_name.c_str(), to_string(name.type).data(), entry.c_str()));
return FieldReference(StringPrintf("%s.R.%s.%s", package_name.c_str(),
name.type.to_string().data(), entry.c_str()));
}
bool JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const ResourceId& id,
@@ -451,7 +451,7 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso
MethodDefinition* out_rewrite_method,
text::Printer* r_txt_printer) {
ResourceId real_id = id;
if (context_->GetMinSdkVersion() < SDK_O && name.type == ResourceType::kId &&
if (context_->GetMinSdkVersion() < SDK_O && name.type.type == ResourceType::kId &&
id.package_id() > kAppPackageId) {
// Workaround for feature splits using package IDs > 0x7F.
// See b/37498913.
@@ -489,7 +489,7 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso
if (r_txt_printer != nullptr) {
r_txt_printer->Print("int ")
.Print(to_string(name.type))
.Print(name.type.to_string())
.Print(" ")
.Print(field_name)
.Print(" ")
@@ -497,7 +497,7 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso
}
if (out_rewrite_method != nullptr) {
const StringPiece& type_str = to_string(name.type);
const std::string type_str = name.type.to_string();
out_rewrite_method->AppendStatement(
StringPrintf("%s.%s = (%s.%s & 0x00ffffff) | packageIdBits;", type_str.data(),
field_name.data(), type_str.data(), field_name.data()));
@@ -561,7 +561,7 @@ bool JavaClassGenerator::ProcessType(const StringPiece& package_name_to_generate
return false;
}
if (resource_name.type == ResourceType::kStyleable) {
if (resource_name.type.type == ResourceType::kStyleable) {
CHECK(!entry->values.empty());
const auto styleable = reinterpret_cast<const Styleable*>(entry->values.front()->value.get());
if (!ProcessStyleable(resource_name, id, *styleable, package_name_to_generate,

View File

@@ -358,7 +358,7 @@ bool CollectProguardRules(IAaptContext* context_, xml::XmlResource* res, KeepSet
return false;
}
switch (res->file.name.type) {
switch (res->file.name.type.type) {
case ResourceType::kLayout: {
LayoutVisitor visitor(res->file, keep_set);
res->root->Accept(&visitor);
@@ -465,7 +465,7 @@ bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set,
locations->insert(location);
// TODO: allow for more reference types if we can determine its safe.
if (location.name.type != ResourceType::kLayout) {
if (location.name.type.type != ResourceType::kLayout) {
return false;
}

View File

@@ -352,7 +352,7 @@ void ReferenceLinker::WriteAttributeName(const Reference& ref, const CallSite& c
}
const ResourceName& ref_name = ref.name.value();
CHECK_EQ(ref_name.type, ResourceType::kAttr);
CHECK_EQ(ref_name.type.type, ResourceType::kAttr);
if (!ref_name.package.empty()) {
*out_msg << ref_name.package << ":";
@@ -385,7 +385,7 @@ std::unique_ptr<Item> ReferenceLinker::LinkReference(const CallSite& callsite,
Reference transformed_reference = reference;
xml::ResolvePackage(decls, &transformed_reference);
if (transformed_reference.name.value().type == ResourceType::kMacro) {
if (transformed_reference.name.value().type.type == ResourceType::kMacro) {
if (transformed_reference.name.value().package.empty()) {
transformed_reference.name.value().package = callsite.package;
}

View File

@@ -349,7 +349,7 @@ bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFi
file_ref->file = file;
ResourceTablePackage* pkg = table.FindOrCreatePackage(file_desc.name.package);
pkg->FindOrCreateType(file_desc.name.type)
pkg->FindOrCreateType(file_desc.name.type.type)
->FindOrCreateEntry(file_desc.name.entry)
->FindOrCreateValue(file_desc.config, {})
->value = std::move(file_ref);

View File

@@ -185,7 +185,7 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
const ResourceName& name) {
std::optional<ResourceTable::SearchResult> result = table_->FindResource(name);
if (!result) {
if (name.type == ResourceType::kAttr) {
if (name.type.type == ResourceType::kAttr) {
// Recurse and try looking up a private attribute.
return FindByName(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
}
@@ -203,7 +203,7 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
(sr.entry->id.value().package_id() == 0) || sr.entry->visibility.staged_api;
}
if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
if (name.type.type == ResourceType::kAttr || name.type.type == ResourceType::kAttrPrivate) {
const ConfigDescription kDefaultConfig;
ResourceConfigValue* config_value = sr.entry->FindValue(kDefaultConfig);
if (config_value) {
@@ -366,7 +366,7 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName(
}
std::unique_ptr<SymbolTable::Symbol> s;
if (real_name.type == ResourceType::kAttr) {
if (real_name.type.type == ResourceType::kAttr) {
s = LookupAttributeInTable(asset_manager_, res_id);
} else {
s = util::make_unique<SymbolTable::Symbol>();
@@ -413,7 +413,7 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
ResourceName& name = maybe_name.value();
std::unique_ptr<SymbolTable::Symbol> s;
if (name.type == ResourceType::kAttr) {
if (name.type.type == ResourceType::kAttr) {
s = LookupAttributeInTable(asset_manager_, id);
} else {
s = util::make_unique<SymbolTable::Symbol>();

View File

@@ -38,7 +38,7 @@ inline android::hash_t hash_type(const ResourceName& name) {
std::hash<std::string> str_hash;
android::hash_t hash = 0;
hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.package));
hash = android::JenkinsHashMix(hash, (uint32_t)name.type);
hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.type.name));
hash = android::JenkinsHashMix(hash, (uint32_t)str_hash(name.entry));
return hash;
}