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

Commit 28cacf09 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Record source/comments for compound values' children

Values like styles or arrays have children which need to have
their source and comments preserved.

Change-Id: I6fc713ba36627e6d66c7930b4080cc1403bac207
parent a5870657
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -919,6 +919,7 @@ bool ResourceParser::parseStyleItem(xml::XmlPullParser* parser, Style* style) {
    }

    transformReferenceFromNamespace(parser, u"", &maybeKey.value());
    maybeKey.value().setSource(source);

    std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
    if (!value) {
+22 −0
Original line number Diff line number Diff line
@@ -66,6 +66,28 @@ struct ExtendedTypes {
    };
};

/**
 * New types for a ResTable_map.
 */
struct ExtendedResTableMapTypes {
    enum {
        /**
         * Type that contains the source path of the next item in the map.
         */
        ATTR_SOURCE_PATH = Res_MAKEINTERNAL(0xffff),

        /**
         * Type that contains the source line of the next item in the map.
         */
        ATTR_SOURCE_LINE = Res_MAKEINTERNAL(0xfffe),

        /**
         * Type that contains the comment of the next item in the map.
         */
        ATTR_COMMENT = Res_MAKEINTERNAL(0xfffd)
    };
};

/**
 * Followed by exportedSymbolCount ExportedSymbol structs, followed by the string pool.
 */
+38 −3
Original line number Diff line number Diff line
@@ -108,15 +108,19 @@ struct MapFlattenVisitor : public RawValueVisitor {
    SymbolWriter* mSymbols;
    FlatEntry* mEntry;
    BigBuffer* mBuffer;
    StringPool* mSourcePool;
    StringPool* mCommentPool;
    bool mUseExtendedChunks;

    size_t mEntryCount = 0;
    Maybe<uint32_t> mParentIdent;
    Maybe<ResourceNameRef> mParentName;

    MapFlattenVisitor(SymbolWriter* symbols, FlatEntry* entry, BigBuffer* buffer,
                      StringPool* sourcePool, StringPool* commentPool,
                      bool useExtendedChunks) :
            mSymbols(symbols), mEntry(entry), mBuffer(buffer),
            mUseExtendedChunks(useExtendedChunks) {
            mSymbols(symbols), mEntry(entry), mBuffer(buffer), mSourcePool(sourcePool),
            mCommentPool(commentPool), mUseExtendedChunks(useExtendedChunks) {
    }

    void flattenKey(Reference* key, ResTable_map* outEntry) {
@@ -158,6 +162,32 @@ struct MapFlattenVisitor : public RawValueVisitor {
        mEntryCount++;
    }

    void flattenMetaData(Value* value) {
        if (!mUseExtendedChunks) {
            return;
        }

        Reference key(ResourceId{ ExtendedResTableMapTypes::ATTR_SOURCE_PATH });
        StringPool::Ref sourcePathRef = mSourcePool->makeRef(
                util::utf8ToUtf16(value->getSource().path));
        BinaryPrimitive val(Res_value::TYPE_INT_DEC,
                            static_cast<uint32_t>(sourcePathRef.getIndex()));
        flattenEntry(&key, &val);

        if (value->getSource().line) {
            key.id = ResourceId(ExtendedResTableMapTypes::ATTR_SOURCE_LINE);
            val.value.data = static_cast<uint32_t>(value->getSource().line.value());
            flattenEntry(&key, &val);
        }

        if (!value->getComment().empty()) {
            key.id = ResourceId(ExtendedResTableMapTypes::ATTR_COMMENT);
            StringPool::Ref commentRef = mCommentPool->makeRef(value->getComment());
            val.value.data = static_cast<uint32_t>(commentRef.getIndex());
            flattenEntry(&key, &val);
        }
    }

    void visit(Attribute* attr) override {
        {
            Reference key(ResourceId{ ResTable_map::ATTR_TYPE });
@@ -211,6 +241,7 @@ struct MapFlattenVisitor : public RawValueVisitor {

        for (Style::Entry& entry : style->entries) {
            flattenEntry(&entry.key, entry.value.get());
            flattenMetaData(&entry.key);
        }
    }

@@ -218,6 +249,7 @@ struct MapFlattenVisitor : public RawValueVisitor {
        for (auto& attrRef : styleable->entries) {
            BinaryPrimitive val(Res_value{});
            flattenEntry(&attrRef, &val);
            flattenMetaData(&attrRef);
        }
    }

@@ -227,6 +259,7 @@ struct MapFlattenVisitor : public RawValueVisitor {
            flattenValue(item.get(), outEntry);
            outEntry->value.size = util::hostToDevice16(sizeof(outEntry->value));
            mEntryCount++;
            flattenMetaData(item.get());
        }
    }

@@ -270,6 +303,7 @@ struct MapFlattenVisitor : public RawValueVisitor {

            Reference key(q);
            flattenEntry(&key, plural->values[i].get());
            flattenMetaData(plural->values[i].get());
        }
    }
};
@@ -389,7 +423,8 @@ private:
        } else {
            const size_t beforeEntry = buffer->size();
            ResTable_entry_ext* outEntry = writeEntry<ResTable_entry_ext, false>(entry, buffer);
            MapFlattenVisitor visitor(mSymbols, entry, buffer, mOptions.useExtendedChunks);
            MapFlattenVisitor visitor(mSymbols, entry, buffer, mSourcePool, mSourcePool,
                                      mOptions.useExtendedChunks);
            entry->value->accept(&visitor);
            outEntry->count = util::hostToDevice32(visitor.mEntryCount);
            if (visitor.mParentName) {
+22 −29
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ public:
                // fast and we avoid creating a DiagMessage when the match is successful.
                if (!symbol->attribute->matches(entry.value.get(), nullptr)) {
                    // The actual type of this item is incompatible with the attribute.
                    DiagMessage msg(style->getSource());
                    DiagMessage msg(entry.key.getSource());

                    // Call the matches method again, this time with a DiagMessage so we fill
                    // in the actual error message.
@@ -143,16 +143,11 @@ public:
                }

            } else {
                DiagMessage msg(style->getSource());
                DiagMessage msg(entry.key.getSource());
                msg << "style attribute '";
                if (entry.key.name) {
                    msg << entry.key.name.value().package << ":" << entry.key.name.value().entry;
                } else {
                    msg << entry.key.id.value();
                }
                ReferenceLinker::writeResourceName(&msg, entry.key, transformedReference);
                msg << "' " << errStr;
                mContext->getDiagnostics()->error(msg);
                mContext->getDiagnostics()->note(DiagMessage(style->getSource()) << entry.key);
                mError = true;
            }
        }
@@ -201,16 +196,12 @@ const ISymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
        CallSite* callSite, std::string* outError) {
    const ISymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
    if (!symbol) {
        std::stringstream errStr;
        errStr << "not found";
        if (outError) *outError = errStr.str();
        if (outError) *outError = "not found";
        return nullptr;
    }

    if (!isSymbolVisible(*symbol, reference, *callSite)) {
        std::stringstream errStr;
        errStr << "is private";
        if (outError) *outError = errStr.str();
        if (outError) *outError = "is private";
        return nullptr;
    }
    return symbol;
@@ -227,9 +218,7 @@ const ISymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
    }

    if (!symbol->attribute) {
        std::stringstream errStr;
        errStr << "is not an attribute";
        if (outError) *outError = errStr.str();
        if (outError) *outError = "is not an attribute";
        return nullptr;
    }
    return symbol;
@@ -246,14 +235,26 @@ Maybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(const Reference&
    }

    if (!symbol->attribute) {
        std::stringstream errStr;
        errStr << "is not an attribute";
        if (outError) *outError = errStr.str();
        if (outError) *outError = "is not an attribute";
        return {};
    }
    return xml::AaptAttribute{ symbol->id, *symbol->attribute };
}

void ReferenceLinker::writeResourceName(DiagMessage* outMsg, const Reference& orig,
                                        const Reference& transformed) {
    assert(outMsg);

    if (orig.name) {
        *outMsg << orig.name.value();
        if (transformed.name.value() != orig.name.value()) {
            *outMsg << " (aka " << transformed.name.value() << ")";
        }
    } else {
        *outMsg << orig.id.value();
    }
}

bool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context,
                                    ISymbolTable* symbols, xml::IPackageDeclStack* decls,
                                    CallSite* callSite) {
@@ -274,15 +275,7 @@ bool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context,

    DiagMessage errorMsg(reference->getSource());
    errorMsg << "resource ";
    if (reference->name) {
        errorMsg << reference->name.value();
        if (transformedReference.name.value() != reference->name.value()) {
            errorMsg << " (aka " << transformedReference.name.value() << ")";
        }
    } else {
        errorMsg << reference->id.value();
    }

    writeResourceName(&errorMsg, *reference, transformedReference);
    errorMsg << " " << errStr;
    context->getDiagnostics()->error(errorMsg);
    return false;
+7 −0
Original line number Diff line number Diff line
@@ -79,6 +79,13 @@ struct ReferenceLinker : public IResourceTableConsumer {
                                                         CallSite* callSite,
                                                         std::string* outError);

    /**
     * Writes the resource name to the DiagMessage, using the "orig_name (aka <transformed_name>)"
     * syntax.
     */
    static void writeResourceName(DiagMessage* outMsg, const Reference& orig,
                                  const Reference& transformed);

    /**
     * Transforms the package name of the reference to the fully qualified package name using
     * the xml::IPackageDeclStack, then mangles and looks up the symbol. If the symbol is visible
Loading