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

Commit 6472c7fe authored by Adam Lesinski's avatar Adam Lesinski Committed by android-build-merger
Browse files

Merge "AAPT2: Introduce notion of \'product\' to ResourceTable" into nyc-dev am: 923e6342

am: adbb5c3c

* commit 'adbb5c3c':
  AAPT2: Introduce notion of 'product' to ResourceTable
parents 408d5441 adbb5c3c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ sources := \
	io/ZipArchive.cpp \
	link/AutoVersioner.cpp \
	link/ManifestFixer.cpp \
	link/ProductFilter.cpp \
	link/PrivateAttributeMover.cpp \
	link/ReferenceLinker.cpp \
	link/TableMerger.cpp \
@@ -83,6 +84,7 @@ testSources := \
	link/AutoVersioner_test.cpp \
	link/ManifestFixer_test.cpp \
	link/PrivateAttributeMover_test.cpp \
	link/ProductFilter_test.cpp \
	link/ReferenceLinker_test.cpp \
	link/TableMerger_test.cpp \
	link/XmlReferenceLinker_test.cpp \
+3 −3
Original line number Diff line number Diff line
@@ -144,8 +144,8 @@ void Debug::printTable(ResourceTable* table) {

                PrintVisitor visitor;
                for (const auto& value : entry->values) {
                    std::cout << "      (" << value.config << ") ";
                    value.value->accept(&visitor);
                    std::cout << "      (" << value->config << ") ";
                    value->value->accept(&visitor);
                    std::cout << std::endl;
                }
            }
@@ -176,7 +176,7 @@ void Debug::printStyleGraph(ResourceTable* table, const ResourceName& targetStyl
        if (result) {
            ResourceEntry* entry = result.value().entry;
            for (const auto& value : entry->values) {
                if (Style* style = valueCast<Style>(value.value.get())) {
                if (Style* style = valueCast<Style>(value->value.get())) {
                    if (style->parent && style->parent.value().name) {
                        parents.insert(style->parent.value().name.value());
                        stylesToVisit.push(style->parent.value().name.value());
+6 −40
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#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"
@@ -71,6 +70,7 @@ static uint32_t parseFormatAttribute(const StringPiece16& str) {
struct ParsedResource {
    ResourceName name;
    ConfigDescription config;
    std::string product;
    Source source;
    ResourceId id;
    Maybe<SymbolState> symbolState;
@@ -79,35 +79,6 @@ struct ParsedResource {
    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, IDiagnostics* diag, ParsedResource* res) {
    if (res->symbolState) {
@@ -125,7 +96,8 @@ static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed
        res->value->setComment(std::move(res->comment));
        res->value->setSource(std::move(res->source));

        if (!table->addResource(res->name, res->id, res->config, std::move(res->value), diag)) {
        if (!table->addResource(res->name, res->id, res->config, res->product,
                                std::move(res->value), diag)) {
            return false;
        }
    }
@@ -295,9 +267,8 @@ bool ResourceParser::parseResources(xml::XmlPullParser* parser) {
        parsedResource.comment = std::move(comment);

        // Extract the product name if it exists.
        Maybe<std::u16string> product;
        if (Maybe<StringPiece16> maybeProduct = xml::findNonEmptyAttribute(parser, u"product")) {
            product = maybeProduct.value().toString();
            parsedResource.product = util::utf16ToUtf8(maybeProduct.value());
        }

        // Parse the resource regardless of product.
@@ -306,12 +277,7 @@ bool ResourceParser::parseResources(xml::XmlPullParser* parser) {
            continue;
        }

        // 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);
        } else if (!addResourcesToTable(mTable, mDiag, &parsedResource)) {
        if (!addResourcesToTable(mTable, mDiag, &parsedResource)) {
            error = true;
        }
    }
@@ -524,7 +490,7 @@ std::unique_ptr<Item> ResourceParser::parseXml(xml::XmlPullParser* parser, const
        // name.package can be empty here, as it will assume the package name of the table.
        std::unique_ptr<Id> id = util::make_unique<Id>();
        id->setSource(mSource.withLine(beginXmlLine));
        mTable->addResource(name, {}, std::move(id), mDiag);
        mTable->addResource(name, {}, {}, std::move(id), mDiag);
    };

    // Process the raw value.
+0 −10
Original line number Diff line number Diff line
@@ -33,13 +33,6 @@ namespace aapt {
struct ParsedResource;

struct ResourceParserOptions {
    /**
     * Optional product names by which to filter resources.
     * This is like a preprocessor definition in that we strip out resources
     * that don't match before we compile them.
     */
    std::vector<std::u16string> products;

    /**
     * Whether the default setting for this parser is to allow translation.
     */
@@ -106,9 +99,6 @@ private:
    bool parseArrayImpl(xml::XmlPullParser* parser, ParsedResource* outResource, uint32_t typeMask);
    bool parsePlural(xml::XmlPullParser* parser, ParsedResource* outResource);

    bool shouldStripResource(const ResourceNameRef& name,
                             const Maybe<std::u16string>& product) const;

    IDiagnostics* mDiag;
    ResourceTable* mTable;
    Source mSource;
+21 −39
Original line number Diff line number Diff line
@@ -48,24 +48,13 @@ struct ResourceParserTest : public ::testing::Test {
    }

    ::testing::AssertionResult testParse(const StringPiece& str) {
        return testParse(str, ConfigDescription{}, {});
        return testParse(str, ConfigDescription{});
    }

    ::testing::AssertionResult testParse(const StringPiece& str, const ConfigDescription& config) {
        return testParse(str, config, {});
    }

    ::testing::AssertionResult testParse(const StringPiece& str,
                                         std::initializer_list<std::u16string> products) {
        return testParse(str, {}, std::move(products));
    }

    ::testing::AssertionResult testParse(const StringPiece& str, const ConfigDescription& config,
                                         std::initializer_list<std::u16string> products) {
        std::stringstream input(kXmlPreamble);
        input << "<resources>\n" << str << "\n</resources>" << std::endl;
        ResourceParserOptions parserOptions;
        parserOptions.products = products;
        ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{ "test" }, config,
                              parserOptions);
        xml::XmlPullParser xmlParser(input);
@@ -546,7 +535,7 @@ TEST_F(ResourceParserTest, ParsePublicIdAsDefinition) {
    ASSERT_NE(nullptr, id);
}

TEST_F(ResourceParserTest, FilterProductsThatDontMatch) {
TEST_F(ResourceParserTest, KeepAllProducts) {
    std::string input = R"EOF(
        <string name="foo" product="phone">hi</string>
        <string name="foo" product="no-sdcard">ho</string>
@@ -555,33 +544,26 @@ TEST_F(ResourceParserTest, FilterProductsThatDontMatch) {
        <string name="bit" product="phablet">hoot</string>
        <string name="bot" product="default">yes</string>
    )EOF";
    ASSERT_TRUE(testParse(input, { std::u16string(u"no-sdcard"), std::u16string(u"phablet") }));

    String* fooStr = test::getValue<String>(&mTable, u"@string/foo");
    ASSERT_NE(nullptr, fooStr);
    EXPECT_EQ(StringPiece16(u"ho"), *fooStr->value);

    EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bar"));
    EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/baz"));
    EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bit"));
    EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bot"));
}

TEST_F(ResourceParserTest, FilterProductsThatBothMatchInOrder) {
    std::string input = R"EOF(
        <string name="foo" product="phone">phone</string>
        <string name="foo" product="default">default</string>
    )EOF";
    ASSERT_TRUE(testParse(input, { std::u16string(u"phone") }));

    String* foo = test::getValue<String>(&mTable, u"@string/foo");
    ASSERT_NE(nullptr, foo);
    EXPECT_EQ(std::u16string(u"phone"), *foo->value);
}
    ASSERT_TRUE(testParse(input));

TEST_F(ResourceParserTest, FailWhenProductFilterStripsOutAllVersionsOfResource) {
    std::string input = "<string name=\"foo\" product=\"tablet\">hello</string>\n";
    ASSERT_FALSE(testParse(input, { std::u16string(u"phone") }));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo",
                                                                 ConfigDescription::defaultConfig(),
                                                                 "phone"));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo",
                                                                 ConfigDescription::defaultConfig(),
                                                                 "no-sdcard"));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bar",
                                                                 ConfigDescription::defaultConfig(),
                                                                 ""));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/baz",
                                                                 ConfigDescription::defaultConfig(),
                                                                 ""));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bit",
                                                                 ConfigDescription::defaultConfig(),
                                                                 "phablet"));
    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bot",
                                                                 ConfigDescription::defaultConfig(),
                                                                 "default"));
}

TEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) {
Loading