Merge "AAPT2: Respect format attr in <array> resource" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
dc6da8b4df
@@ -34,42 +34,43 @@ using android::StringPiece;
|
||||
|
||||
namespace aapt {
|
||||
|
||||
constexpr const char* sXliffNamespaceUri =
|
||||
"urn:oasis:names:tc:xliff:document:1.2";
|
||||
constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
|
||||
|
||||
/**
|
||||
* Returns true if the element is <skip> or <eat-comment> and can be safely
|
||||
* ignored.
|
||||
*/
|
||||
static bool ShouldIgnoreElement(const StringPiece& ns,
|
||||
const StringPiece& name) {
|
||||
// Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
|
||||
static bool ShouldIgnoreElement(const StringPiece& ns, const StringPiece& name) {
|
||||
return ns.empty() && (name == "skip" || name == "eat-comment");
|
||||
}
|
||||
|
||||
static uint32_t ParseFormatType(const StringPiece& piece) {
|
||||
if (piece == "reference")
|
||||
static uint32_t ParseFormatTypeNoEnumsOrFlags(const StringPiece& piece) {
|
||||
if (piece == "reference") {
|
||||
return android::ResTable_map::TYPE_REFERENCE;
|
||||
else if (piece == "string")
|
||||
} else if (piece == "string") {
|
||||
return android::ResTable_map::TYPE_STRING;
|
||||
else if (piece == "integer")
|
||||
} else if (piece == "integer") {
|
||||
return android::ResTable_map::TYPE_INTEGER;
|
||||
else if (piece == "boolean")
|
||||
} else if (piece == "boolean") {
|
||||
return android::ResTable_map::TYPE_BOOLEAN;
|
||||
else if (piece == "color")
|
||||
} else if (piece == "color") {
|
||||
return android::ResTable_map::TYPE_COLOR;
|
||||
else if (piece == "float")
|
||||
} else if (piece == "float") {
|
||||
return android::ResTable_map::TYPE_FLOAT;
|
||||
else if (piece == "dimension")
|
||||
} else if (piece == "dimension") {
|
||||
return android::ResTable_map::TYPE_DIMENSION;
|
||||
else if (piece == "fraction")
|
||||
} else if (piece == "fraction") {
|
||||
return android::ResTable_map::TYPE_FRACTION;
|
||||
else if (piece == "enum")
|
||||
return android::ResTable_map::TYPE_ENUM;
|
||||
else if (piece == "flags")
|
||||
return android::ResTable_map::TYPE_FLAGS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t ParseFormatType(const StringPiece& piece) {
|
||||
if (piece == "enum") {
|
||||
return android::ResTable_map::TYPE_ENUM;
|
||||
} else if (piece == "flags") {
|
||||
return android::ResTable_map::TYPE_FLAGS;
|
||||
}
|
||||
return ParseFormatTypeNoEnumsOrFlags(piece);
|
||||
}
|
||||
|
||||
static uint32_t ParseFormatAttribute(const StringPiece& str) {
|
||||
uint32_t mask = 0;
|
||||
for (StringPiece part : util::Tokenize(str, '|')) {
|
||||
@@ -83,9 +84,7 @@ static uint32_t ParseFormatAttribute(const StringPiece& str) {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* A parsed resource ready to be added to the ResourceTable.
|
||||
*/
|
||||
// A parsed resource ready to be added to the ResourceTable.
|
||||
struct ParsedResource {
|
||||
ResourceName name;
|
||||
ConfigDescription config;
|
||||
@@ -416,8 +415,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
|
||||
can_be_bag = false;
|
||||
|
||||
// Items have their type encoded in the type attribute.
|
||||
if (Maybe<StringPiece> maybe_type =
|
||||
xml::FindNonEmptyAttribute(parser, "type")) {
|
||||
if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
|
||||
resource_type = maybe_type.value().to_string();
|
||||
} else {
|
||||
diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
|
||||
@@ -425,13 +423,11 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Maybe<StringPiece> maybe_format =
|
||||
xml::FindNonEmptyAttribute(parser, "format")) {
|
||||
if (Maybe<StringPiece> maybe_format = xml::FindNonEmptyAttribute(parser, "format")) {
|
||||
// An explicit format for this resource was specified. The resource will
|
||||
// retain
|
||||
// its type in its name, but the accepted value for this type is
|
||||
// retain its type in its name, but the accepted value for this type is
|
||||
// overridden.
|
||||
resource_format = ParseFormatType(maybe_format.value());
|
||||
resource_format = ParseFormatTypeNoEnumsOrFlags(maybe_format.value());
|
||||
if (!resource_format) {
|
||||
diag_->Error(DiagMessage(out_resource->source)
|
||||
<< "'" << maybe_format.value()
|
||||
@@ -1157,21 +1153,25 @@ bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* par
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResourceParser::ParseArray(xml::XmlPullParser* parser,
|
||||
ParsedResource* out_resource) {
|
||||
return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_ANY);
|
||||
bool ResourceParser::ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
|
||||
uint32_t resource_format = android::ResTable_map::TYPE_ANY;
|
||||
if (Maybe<StringPiece> format_attr = xml::FindNonEmptyAttribute(parser, "format")) {
|
||||
resource_format = ParseFormatTypeNoEnumsOrFlags(format_attr.value());
|
||||
if (resource_format == 0u) {
|
||||
diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
|
||||
<< "'" << format_attr.value() << "' is an invalid format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ParseArrayImpl(parser, out_resource, resource_format);
|
||||
}
|
||||
|
||||
bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser,
|
||||
ParsedResource* out_resource) {
|
||||
return ParseArrayImpl(parser, out_resource,
|
||||
android::ResTable_map::TYPE_INTEGER);
|
||||
bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
|
||||
return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_INTEGER);
|
||||
}
|
||||
|
||||
bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser,
|
||||
ParsedResource* out_resource) {
|
||||
return ParseArrayImpl(parser, out_resource,
|
||||
android::ResTable_map::TYPE_STRING);
|
||||
bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
|
||||
return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_STRING);
|
||||
}
|
||||
|
||||
bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
|
||||
|
||||
@@ -571,14 +571,39 @@ TEST_F(ResourceParserTest, ParseArray) {
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParseStringArray) {
|
||||
std::string input =
|
||||
"<string-array name=\"foo\">\n"
|
||||
" <item>\"Werk\"</item>\n"
|
||||
"</string-array>\n";
|
||||
std::string input = R"EOF(
|
||||
<string-array name="foo">
|
||||
<item>"Werk"</item>"
|
||||
</string-array>)EOF";
|
||||
ASSERT_TRUE(TestParse(input));
|
||||
EXPECT_NE(nullptr, test::GetValue<Array>(&table_, "array/foo"));
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParseArrayWithFormat) {
|
||||
std::string input = R"EOF(
|
||||
<array name="foo" format="string">
|
||||
<item>100</item>
|
||||
</array>)EOF";
|
||||
ASSERT_TRUE(TestParse(input));
|
||||
|
||||
Array* array = test::GetValue<Array>(&table_, "array/foo");
|
||||
ASSERT_NE(nullptr, array);
|
||||
|
||||
ASSERT_EQ(1u, array->items.size());
|
||||
|
||||
String* str = ValueCast<String>(array->items[0].get());
|
||||
ASSERT_NE(nullptr, str);
|
||||
EXPECT_EQ(std::string("100"), *str->value);
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParseArrayWithBadFormat) {
|
||||
std::string input = R"EOF(
|
||||
<array name="foo" format="integer">
|
||||
<item>Hi</item>
|
||||
</array>)EOF";
|
||||
ASSERT_FALSE(TestParse(input));
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParsePlural) {
|
||||
std::string input =
|
||||
"<plurals name=\"foo\">\n"
|
||||
|
||||
Reference in New Issue
Block a user