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

Commit 104e028c authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Support generating Manifest.java"

parents 082a4c86 ca5638fd
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -45,9 +45,11 @@ sources := \
	ConfigDescription.cpp \
	ConfigDescription.cpp \
	Debug.cpp \
	Debug.cpp \
	Flags.cpp \
	Flags.cpp \
	JavaClassGenerator.cpp \
	java/AnnotationProcessor.cpp \
	java/JavaClassGenerator.cpp \
	java/ManifestClassGenerator.cpp \
	java/ProguardRules.cpp \
	Locale.cpp \
	Locale.cpp \
	ProguardRules.cpp \
	Resource.cpp \
	Resource.cpp \
	ResourceParser.cpp \
	ResourceParser.cpp \
	ResourceTable.cpp \
	ResourceTable.cpp \
@@ -76,7 +78,8 @@ testSources := \
	util/StringPiece_test.cpp \
	util/StringPiece_test.cpp \
	util/Util_test.cpp \
	util/Util_test.cpp \
	ConfigDescription_test.cpp \
	ConfigDescription_test.cpp \
	JavaClassGenerator_test.cpp \
	java/JavaClassGenerator_test.cpp \
	java/ManifestClassGenerator_test.cpp \
	Locale_test.cpp \
	Locale_test.cpp \
	Resource_test.cpp \
	Resource_test.cpp \
	ResourceParser_test.cpp \
	ResourceParser_test.cpp \
+0 −2
Original line number Original line Diff line number Diff line
@@ -36,7 +36,6 @@ StringPiece16 toString(ResourceType type) {
        case ResourceType::kFraction:      return u"fraction";
        case ResourceType::kFraction:      return u"fraction";
        case ResourceType::kId:            return u"id";
        case ResourceType::kId:            return u"id";
        case ResourceType::kInteger:       return u"integer";
        case ResourceType::kInteger:       return u"integer";
        case ResourceType::kIntegerArray:  return u"integer-array";
        case ResourceType::kInterpolator:  return u"interpolator";
        case ResourceType::kInterpolator:  return u"interpolator";
        case ResourceType::kLayout:        return u"layout";
        case ResourceType::kLayout:        return u"layout";
        case ResourceType::kMenu:          return u"menu";
        case ResourceType::kMenu:          return u"menu";
@@ -65,7 +64,6 @@ static const std::map<StringPiece16, ResourceType> sResourceTypeMap {
        { u"fraction", ResourceType::kFraction },
        { u"fraction", ResourceType::kFraction },
        { u"id", ResourceType::kId },
        { u"id", ResourceType::kId },
        { u"integer", ResourceType::kInteger },
        { u"integer", ResourceType::kInteger },
        { u"integer-array", ResourceType::kIntegerArray },
        { u"interpolator", ResourceType::kInterpolator },
        { u"interpolator", ResourceType::kInterpolator },
        { u"layout", ResourceType::kLayout },
        { u"layout", ResourceType::kLayout },
        { u"menu", ResourceType::kMenu },
        { u"menu", ResourceType::kMenu },
+0 −1
Original line number Original line Diff line number Diff line
@@ -47,7 +47,6 @@ enum class ResourceType {
    kFraction,
    kFraction,
    kId,
    kId,
    kInteger,
    kInteger,
    kIntegerArray,
    kInterpolator,
    kInterpolator,
    kLayout,
    kLayout,
    kMenu,
    kMenu,
+63 −48
Original line number Original line Diff line number Diff line
@@ -308,6 +308,9 @@ bool ResourceParser::parseResources(XmlPullParser* parser) {
        } else if (elementName == u"dimen") {
        } else if (elementName == u"dimen") {
            parsedResource.name.type = ResourceType::kDimen;
            parsedResource.name.type = ResourceType::kDimen;
            result = parsePrimitive(parser, &parsedResource);
            result = parsePrimitive(parser, &parsedResource);
        } else if (elementName == u"fraction") {
            parsedResource.name.type = ResourceType::kFraction;
            result = parsePrimitive(parser, &parsedResource);
        } else if (elementName == u"style") {
        } else if (elementName == u"style") {
            parsedResource.name.type = ResourceType::kStyle;
            parsedResource.name.type = ResourceType::kStyle;
            result = parseStyle(parser, &parsedResource);
            result = parseStyle(parser, &parsedResource);
@@ -321,7 +324,7 @@ bool ResourceParser::parseResources(XmlPullParser* parser) {
            parsedResource.name.type = ResourceType::kArray;
            parsedResource.name.type = ResourceType::kArray;
            result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_STRING);
            result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_STRING);
        } else if (elementName == u"integer-array") {
        } else if (elementName == u"integer-array") {
            parsedResource.name.type = ResourceType::kIntegerArray;
            parsedResource.name.type = ResourceType::kArray;
            result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_INTEGER);
            result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_INTEGER);
        } else if (elementName == u"declare-styleable") {
        } else if (elementName == u"declare-styleable") {
            parsedResource.name.type = ResourceType::kStyleable;
            parsedResource.name.type = ResourceType::kStyleable;
@@ -464,6 +467,8 @@ bool ResourceParser::parsePrimitive(XmlPullParser* parser, ParsedResource* outRe
        typeMask |= android::ResTable_map::TYPE_INTEGER;
        typeMask |= android::ResTable_map::TYPE_INTEGER;
        break;
        break;


    case ResourceType::kFraction:
        // fallthrough
    case ResourceType::kDimen:
    case ResourceType::kDimen:
        typeMask |= android::ResTable_map::TYPE_DIMENSION
        typeMask |= android::ResTable_map::TYPE_DIMENSION
                  | android::ResTable_map::TYPE_FLOAT
                  | android::ResTable_map::TYPE_FLOAT
@@ -576,6 +581,12 @@ static uint32_t parseFormatAttribute(const StringPiece16& str) {
    return mask;
    return mask;
}
}


/**
 * Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
 */
static bool shouldIgnoreElement(const StringPiece16& ns, const StringPiece16& name) {
    return ns.empty() && (name == u"skip" || name == u"eat-comment");
}


bool ResourceParser::parseAttr(XmlPullParser* parser, ParsedResource* outResource) {
bool ResourceParser::parseAttr(XmlPullParser* parser, ParsedResource* outResource) {
    outResource->source = mSource.withLine(parser->getLineNumber());
    outResource->source = mSource.withLine(parser->getLineNumber());
@@ -613,25 +624,30 @@ bool ResourceParser::parseAttrImpl(XmlPullParser* parser, ParsedResource* outRes
    bool error = false;
    bool error = false;
    const size_t depth = parser->getDepth();
    const size_t depth = parser->getDepth();
    while (XmlPullParser::nextChildNode(parser, depth)) {
    while (XmlPullParser::nextChildNode(parser, depth)) {
        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
        if (parser->getEvent() == XmlPullParser::Event::kComment) {
            // Skip comments and text.
            comment = util::trimWhitespace(parser->getComment()).toString();
            continue;
        } else if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
            // Skip text.
            continue;
            continue;
        }
        }


        const Source itemSource = mSource.withLine(parser->getLineNumber());
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementName = parser->getElementName();
        const std::u16string& elementName = parser->getElementName();
        if (elementNamespace == u"" && (elementName == u"flag" || elementName == u"enum")) {
        if (elementNamespace.empty() && (elementName == u"flag" || elementName == u"enum")) {
            if (elementName == u"enum") {
            if (elementName == u"enum") {
                if (typeMask & android::ResTable_map::TYPE_FLAGS) {
                if (typeMask & android::ResTable_map::TYPE_FLAGS) {
                    mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                    mDiag->error(DiagMessage(itemSource)
                                 << "can not define an <enum>; already defined a <flag>");
                                 << "can not define an <enum>; already defined a <flag>");
                    error = true;
                    error = true;
                    continue;
                    continue;
                }
                }
                typeMask |= android::ResTable_map::TYPE_ENUM;
                typeMask |= android::ResTable_map::TYPE_ENUM;

            } else if (elementName == u"flag") {
            } else if (elementName == u"flag") {
                if (typeMask & android::ResTable_map::TYPE_ENUM) {
                if (typeMask & android::ResTable_map::TYPE_ENUM) {
                    mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                    mDiag->error(DiagMessage(itemSource)
                                 << "can not define a <flag>; already defined an <enum>");
                                 << "can not define a <flag>; already defined an <enum>");
                    error = true;
                    error = true;
                    continue;
                    continue;
@@ -642,21 +658,22 @@ bool ResourceParser::parseAttrImpl(XmlPullParser* parser, ParsedResource* outRes
            if (Maybe<Attribute::Symbol> s = parseEnumOrFlagItem(parser, elementName)) {
            if (Maybe<Attribute::Symbol> s = parseEnumOrFlagItem(parser, elementName)) {
                ParsedResource childResource;
                ParsedResource childResource;
                childResource.name = s.value().symbol.name.value();
                childResource.name = s.value().symbol.name.value();
                childResource.source = mSource.withLine(parser->getLineNumber());
                childResource.source = itemSource;
                childResource.value = util::make_unique<Id>();
                childResource.value = util::make_unique<Id>();
                outResource->childResources.push_back(std::move(childResource));
                outResource->childResources.push_back(std::move(childResource));

                s.value().symbol.setComment(std::move(comment));
                s.value().symbol.setSource(itemSource);
                items.push_back(std::move(s.value()));
                items.push_back(std::move(s.value()));
            } else {
            } else {
                error = true;
                error = true;
            }
            }
        } else if (elementName == u"skip" || elementName == u"eat-comment") {
        } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
            comment = u"";
            mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");

        } else {
            mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                         << ":" << elementName << ">");
            error = true;
            error = true;
        }
        }

        comment = {};
    }
    }


    if (error) {
    if (error) {
@@ -716,11 +733,10 @@ static Maybe<ResourceName> parseXmlAttributeName(StringPiece16 str) {
        p++;
        p++;
    }
    }


    return ResourceName{ package.toString(), ResourceType::kAttr,
    return ResourceName(package.toString(), ResourceType::kAttr,
        name.empty() ? str.toString() : name.toString() };
                        name.empty() ? str.toString() : name.toString());
}
}



bool ResourceParser::parseStyleItem(XmlPullParser* parser, Style* style) {
bool ResourceParser::parseStyleItem(XmlPullParser* parser, Style* style) {
    const Source source = mSource.withLine(parser->getLineNumber());
    const Source source = mSource.withLine(parser->getLineNumber());


@@ -783,7 +799,6 @@ bool ResourceParser::parseStyle(XmlPullParser* parser, ParsedResource* outResour
    }
    }


    bool error = false;
    bool error = false;
    std::u16string comment;
    const size_t depth = parser->getDepth();
    const size_t depth = parser->getDepth();
    while (XmlPullParser::nextChildNode(parser, depth)) {
    while (XmlPullParser::nextChildNode(parser, depth)) {
        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
@@ -796,11 +811,7 @@ bool ResourceParser::parseStyle(XmlPullParser* parser, ParsedResource* outResour
        if (elementNamespace == u"" && elementName == u"item") {
        if (elementNamespace == u"" && elementName == u"item") {
            error |= !parseStyleItem(parser, style.get());
            error |= !parseStyleItem(parser, style.get());


        } else if (elementNamespace.empty() &&
        } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
                (elementName == u"skip" || elementName == u"eat-comment")) {
            comment = u"";

        } else {
            mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
            mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                         << ":" << elementName << ">");
                         << ":" << elementName << ">");
            error = true;
            error = true;
@@ -820,7 +831,6 @@ bool ResourceParser::parseArray(XmlPullParser* parser, ParsedResource* outResour
    const Source source = mSource.withLine(parser->getLineNumber());
    const Source source = mSource.withLine(parser->getLineNumber());
    std::unique_ptr<Array> array = util::make_unique<Array>();
    std::unique_ptr<Array> array = util::make_unique<Array>();


    std::u16string comment;
    bool error = false;
    bool error = false;
    const size_t depth = parser->getDepth();
    const size_t depth = parser->getDepth();
    while (XmlPullParser::nextChildNode(parser, depth)) {
    while (XmlPullParser::nextChildNode(parser, depth)) {
@@ -839,13 +849,10 @@ bool ResourceParser::parseArray(XmlPullParser* parser, ParsedResource* outResour
                error = true;
                error = true;
                continue;
                continue;
            }
            }
            item->setSource(itemSource);
            array->items.emplace_back(std::move(item));
            array->items.emplace_back(std::move(item));


        } else if (elementNamespace.empty() &&
        } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
                (elementName == u"skip" || elementName == u"eat-comment")) {
            comment = u"";

        } else {
            mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
            mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                         << "unknown tag <" << elementNamespace << ":" << elementName << ">");
                         << "unknown tag <" << elementNamespace << ":" << elementName << ">");
            error = true;
            error = true;
@@ -864,7 +871,6 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
    const Source source = mSource.withLine(parser->getLineNumber());
    const Source source = mSource.withLine(parser->getLineNumber());
    std::unique_ptr<Plural> plural = util::make_unique<Plural>();
    std::unique_ptr<Plural> plural = util::make_unique<Plural>();


    std::u16string comment;
    bool error = false;
    bool error = false;
    const size_t depth = parser->getDepth();
    const size_t depth = parser->getDepth();
    while (XmlPullParser::nextChildNode(parser, depth)) {
    while (XmlPullParser::nextChildNode(parser, depth)) {
@@ -873,13 +879,14 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
            continue;
            continue;
        }
        }


        const Source itemSource = mSource.withLine(parser->getLineNumber());
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementName = parser->getElementName();
        const std::u16string& elementName = parser->getElementName();
        if (elementNamespace.empty() && elementName == u"item") {
        if (elementNamespace.empty() && elementName == u"item") {
            const auto endAttrIter = parser->endAttributes();
            const auto endAttrIter = parser->endAttributes();
            auto attrIter = parser->findAttribute(u"", u"quantity");
            auto attrIter = parser->findAttribute(u"", u"quantity");
            if (attrIter == endAttrIter || attrIter->value.empty()) {
            if (attrIter == endAttrIter || attrIter->value.empty()) {
                mDiag->error(DiagMessage(source) << "<item> in <plurals> requires attribute "
                mDiag->error(DiagMessage(itemSource) << "<item> in <plurals> requires attribute "
                             << "'quantity'");
                             << "'quantity'");
                error = true;
                error = true;
                continue;
                continue;
@@ -900,7 +907,7 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
            } else if (trimmedQuantity == u"other") {
            } else if (trimmedQuantity == u"other") {
                index = Plural::Other;
                index = Plural::Other;
            } else {
            } else {
                mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                mDiag->error(DiagMessage(itemSource)
                             << "<item> in <plural> has invalid value '" << trimmedQuantity
                             << "<item> in <plural> has invalid value '" << trimmedQuantity
                             << "' for attribute 'quantity'");
                             << "' for attribute 'quantity'");
                error = true;
                error = true;
@@ -908,7 +915,7 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
            }
            }


            if (plural->values[index]) {
            if (plural->values[index]) {
                mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                mDiag->error(DiagMessage(itemSource)
                             << "duplicate quantity '" << trimmedQuantity << "'");
                             << "duplicate quantity '" << trimmedQuantity << "'");
                error = true;
                error = true;
                continue;
                continue;
@@ -918,11 +925,10 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
                                                   kNoRawString))) {
                                                   kNoRawString))) {
                error = true;
                error = true;
            }
            }
        } else if (elementNamespace.empty() &&
            plural->values[index]->setSource(itemSource);
                (elementName == u"skip" || elementName == u"eat-comment")) {

            comment = u"";
        } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
        } else {
            mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
            mDiag->error(DiagMessage(source) << "unknown tag <" << elementNamespace << ":"
                         << elementName << ">");
                         << elementName << ">");
            error = true;
            error = true;
        }
        }
@@ -944,43 +950,52 @@ bool ResourceParser::parseDeclareStyleable(XmlPullParser* parser, ParsedResource
    bool error = false;
    bool error = false;
    const size_t depth = parser->getDepth();
    const size_t depth = parser->getDepth();
    while (XmlPullParser::nextChildNode(parser, depth)) {
    while (XmlPullParser::nextChildNode(parser, depth)) {
        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
        if (parser->getEvent() == XmlPullParser::Event::kComment) {
            // Ignore text and comments.
            comment = util::trimWhitespace(parser->getComment()).toString();
            continue;
        } else if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
            // Ignore text.
            continue;
            continue;
        }
        }


        const Source itemSource = mSource.withLine(parser->getLineNumber());
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementNamespace = parser->getElementNamespace();
        const std::u16string& elementName = parser->getElementName();
        const std::u16string& elementName = parser->getElementName();
        if (elementNamespace.empty() && elementName == u"attr") {
        if (elementNamespace.empty() && elementName == u"attr") {
            const auto endAttrIter = parser->endAttributes();
            const auto endAttrIter = parser->endAttributes();
            auto attrIter = parser->findAttribute(u"", u"name");
            auto attrIter = parser->findAttribute(u"", u"name");
            if (attrIter == endAttrIter || attrIter->value.empty()) {
            if (attrIter == endAttrIter || attrIter->value.empty()) {
                mDiag->error(DiagMessage(source) << "<attr> tag must have a 'name' attribute");
                mDiag->error(DiagMessage(itemSource) << "<attr> tag must have a 'name' attribute");
                error = true;
                error = true;
                continue;
                continue;
            }
            }


            // Create the ParsedResource that will add the attribute to the table.
            ParsedResource childResource;
            ParsedResource childResource;
            childResource.name = ResourceName({}, ResourceType::kAttr, attrIter->value);
            childResource.name = ResourceName({}, ResourceType::kAttr, attrIter->value);
            childResource.source = mSource.withLine(parser->getLineNumber());
            childResource.source = itemSource;
            childResource.comment = std::move(comment);


            if (!parseAttrImpl(parser, &childResource, true)) {
            if (!parseAttrImpl(parser, &childResource, true)) {
                error = true;
                error = true;
                continue;
                continue;
            }
            }


            styleable->entries.push_back(Reference(childResource.name));
            // Create the reference to this attribute.
            outResource->childResources.push_back(std::move(childResource));
            Reference childRef(childResource.name);
            childRef.setComment(childResource.comment);
            childRef.setSource(itemSource);
            styleable->entries.push_back(std::move(childRef));


        } else if (elementNamespace.empty() &&
            outResource->childResources.push_back(std::move(childResource));
                (elementName == u"skip" || elementName == u"eat-comment")) {
            comment = u"";


        } else {
        } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
            mDiag->error(DiagMessage(source) << "unknown tag <" << elementNamespace << ":"
            mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
                         << elementName << ">");
                         << elementName << ">");
            error = true;
            error = true;
        }
        }

        comment = {};
    }
    }


    if (error) {
    if (error) {
+28 −0
Original line number Original line Diff line number Diff line
@@ -414,6 +414,34 @@ TEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) {
    EXPECT_EQ(value->getComment(), u"One");
    EXPECT_EQ(value->getComment(), u"One");
}
}


TEST_F(ResourceParserTest, ParseNestedComments) {
    // We only care about declare-styleable and enum/flag attributes because comments
    // from those end up in R.java
    std::string input = R"EOF(
        <declare-styleable name="foo">
          <!-- The name of the bar -->
          <attr name="barName" format="string|reference" />
        </declare-styleable>

        <attr name="foo">
          <!-- The very first -->
          <enum name="one" value="1" />
        </attr>)EOF";
    ASSERT_TRUE(testParse(input));

    Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo");
    ASSERT_NE(nullptr, styleable);
    ASSERT_EQ(1u, styleable->entries.size());

    EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment());

    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
    ASSERT_NE(nullptr, attr);
    ASSERT_EQ(1u, attr->symbols.size());

    EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment());
}

/*
/*
 * Declaring an ID as public should not require a separate definition
 * Declaring an ID as public should not require a separate definition
 * (as an ID has no value).
 * (as an ID has no value).
Loading