AAPT2: Fix product support
Previously the default product wasn't tried if 'default' wasn't specified on the command line.
Also adds support for multiple products.
Change-Id: I1e4872b34bb8d609b6444841a4e7e4dbb3bbb76b
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 1e879a0..e1f9642 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -19,6 +19,7 @@
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
+#include "util/Comparators.h"
#include "util/ImmutableMap.h"
#include "util/Util.h"
#include "xml/XmlPullParser.h"
@@ -64,26 +65,6 @@
return mask;
}
-static bool shouldStripResource(const xml::XmlPullParser* parser,
- const Maybe<std::u16string> productToMatch) {
- assert(parser->getEvent() == xml::XmlPullParser::Event::kStartElement);
-
- if (Maybe<StringPiece16> maybeProduct = xml::findNonEmptyAttribute(parser, u"product")) {
- if (!productToMatch) {
- if (maybeProduct.value() != u"default" && maybeProduct.value() != u"phone") {
- // We didn't specify a product and this is not a default product, so skip.
- return true;
- }
- } else {
- if (productToMatch && maybeProduct.value() != productToMatch.value()) {
- // We specified a product, but they don't match.
- return true;
- }
- }
- }
- return false;
-}
-
/**
* A parsed resource ready to be added to the ResourceTable.
*/
@@ -97,6 +78,35 @@
std::list<ParsedResource> childResources;
};
+bool ResourceParser::shouldStripResource(const ResourceNameRef& name,
+ const Maybe<std::u16string>& product) const {
+ if (product) {
+ for (const std::u16string& productToMatch : mOptions.products) {
+ if (product.value() == productToMatch) {
+ // We specified a product, and it is in the list, so don't strip.
+ return false;
+ }
+ }
+ }
+
+ // Nothing matched, try 'default'. Default only matches if we didn't already use another
+ // product variant.
+ if (!product || product.value() == u"default") {
+ if (Maybe<ResourceTable::SearchResult> result = mTable->findResource(name)) {
+ const ResourceEntry* entry = result.value().entry;
+ auto iter = std::lower_bound(entry->values.begin(), entry->values.end(), mConfig,
+ cmp::lessThanConfig);
+ if (iter != entry->values.end() && iter->config == mConfig && !iter->value->isWeak()) {
+ // We have a value for this config already, and it is not weak,
+ // so filter out this default.
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+}
+
// Recursively adds resources to the ResourceTable.
static bool addResourcesToTable(ResourceTable* table, const ConfigDescription& config,
IDiagnostics* diag, ParsedResource* res) {
@@ -283,17 +293,20 @@
parsedResource.source = mSource.withLine(parser->getLineNumber());
parsedResource.comment = std::move(comment);
- // Check if we should skip this product. We still need to parse it for correctness.
- const bool stripResource = shouldStripResource(parser, mOptions.product);
+ // Extract the product name if it exists.
+ Maybe<std::u16string> product;
+ if (Maybe<StringPiece16> maybeProduct = xml::findNonEmptyAttribute(parser, u"product")) {
+ product = maybeProduct.value().toString();
+ }
+ // Parse the resource regardless of product.
if (!parseResource(parser, &parsedResource)) {
error = true;
continue;
}
- // We successfully parsed the resource.
-
- if (stripResource) {
+ // We successfully parsed the resource. Check if we should include it or strip it.
+ if (shouldStripResource(parsedResource.name, product)) {
// Record that we stripped out this resource name.
// We will check that at least one variant of this resource was included.
strippedResources.insert(parsedResource.name);