Merge "AAPT emits error for res with no 'default' product" into klp-dev

This commit is contained in:
Adam Lesinski
2013-10-07 22:57:38 +00:00
committed by Android (Google) Code Review

View File

@@ -636,6 +636,30 @@ bool isInProductList(const String16& needle, const String16& haystack) {
return false;
}
/*
* A simple container that holds a resource type and name. It is ordered first by type then
* by name.
*/
struct type_ident_pair_t {
String16 type;
String16 ident;
type_ident_pair_t() { };
type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { }
type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { }
inline bool operator < (const type_ident_pair_t& o) const {
int cmp = compare_type(type, o.type);
if (cmp < 0) {
return true;
} else if (cmp > 0) {
return false;
} else {
return strictly_order_type(ident, o.ident);
}
}
};
status_t parseAndAddEntry(Bundle* bundle,
const sp<AaptFile>& in,
ResXMLTree* block,
@@ -650,6 +674,7 @@ status_t parseAndAddEntry(Bundle* bundle,
const String16& product,
bool pseudolocalize,
const bool overwrite,
KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
ResourceTable* outTable)
{
status_t err;
@@ -684,6 +709,13 @@ status_t parseAndAddEntry(Bundle* bundle,
if (bundleProduct[0] == '\0') {
if (strcmp16(String16("default").string(), product.string()) != 0) {
/*
* This string has a product other than 'default'. Do not add it,
* but record it so that if we do not see the same string with
* product 'default' or no product, then report an error.
*/
skippedResourceNames->replaceValueFor(
type_ident_pair_t(curType, ident), true);
return NO_ERROR;
}
} else {
@@ -797,6 +829,11 @@ status_t compileResourceFile(Bundle* bundle,
DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
// Stores the resource names that were skipped. Typically this happens when
// AAPT is invoked without a product specified and a resource has no
// 'default' product attribute.
KeyedVector<type_ident_pair_t, bool> skippedResourceNames;
ResXMLTree::event_code_t code;
do {
code = block.next();
@@ -1544,7 +1581,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
product, false, overwrite, outTable);
product, false, overwrite, &skippedResourceNames, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1557,7 +1594,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
ident, *curTag, curIsStyled, curFormat,
curIsFormatted, product,
true, overwrite, outTable);
true, overwrite, &skippedResourceNames, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -1596,6 +1633,30 @@ status_t compileResourceFile(Bundle* bundle,
}
}
// For every resource defined, there must be exist one variant with a product attribute
// set to 'default' (or no product attribute at all).
// We check to see that for every resource that was ignored because of a mismatched
// product attribute, some product variant of that resource was processed.
for (size_t i = 0; i < skippedResourceNames.size(); i++) {
if (skippedResourceNames[i]) {
const type_ident_pair_t& p = skippedResourceNames.keyAt(i);
if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) {
const char* bundleProduct =
(bundle->getProduct() == NULL) ? "" : bundle->getProduct();
fprintf(stderr, "In resource file %s: %s\n",
in->getPrintableSource().string(),
curParams.toString().string());
fprintf(stderr, "\t%s '%s' does not match product %s.\n"
"\tYou may have forgotten to include a 'default' product variant"
" of the resource.\n",
String8(p.type).string(), String8(p.ident).string(),
bundleProduct[0] == 0 ? "default" : bundleProduct);
return UNKNOWN_ERROR;
}
}
}
return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
}
@@ -2483,8 +2544,8 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
String16 comment(c->getComment());
typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
//printf("Type symbol %s comment: %s\n", String8(e->getName()).string(),
// String8(comment).string());
//printf("Type symbol [%08x] %s comment: %s\n", rid,
// String8(c->getName()).string(), String8(comment).string());
comment = c->getTypeComment();
typeSymbols->appendTypeComment(String8(c->getName()), comment);
} else {