diff options
Diffstat (limited to 'tools/aapt2/Linker.cpp')
-rw-r--r-- | tools/aapt2/Linker.cpp | 290 |
1 files changed, 0 insertions, 290 deletions
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp deleted file mode 100644 index c37cc932cd3b..000000000000 --- a/tools/aapt2/Linker.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Linker.h" -#include "Logger.h" -#include "NameMangler.h" -#include "Resolver.h" -#include "ResourceParser.h" -#include "ResourceTable.h" -#include "ResourceValues.h" -#include "StringPiece.h" -#include "Util.h" - -#include <androidfw/AssetManager.h> -#include <array> -#include <bitset> -#include <iostream> -#include <map> -#include <ostream> -#include <set> -#include <sstream> -#include <tuple> -#include <vector> - -namespace aapt { - -Linker::Args::Args(const ResourceNameRef& r, const SourceLine& s) : referrer(r), source(s) { -} - -Linker::Linker(const std::shared_ptr<ResourceTable>& table, - const std::shared_ptr<IResolver>& resolver, const Options& options) : - mResolver(resolver), mTable(table), mOptions(options), mError(false) { -} - -bool Linker::linkAndValidate() { - std::bitset<256> usedTypeIds; - std::array<std::set<uint16_t>, 256> usedIds; - usedTypeIds.set(0); - - // Collect which resource IDs are already taken. - for (auto& type : *mTable) { - if (type->typeId != ResourceTableType::kUnsetTypeId) { - // The ID for this type has already been set. We - // mark this ID as taken so we don't re-assign it - // later. - usedTypeIds.set(type->typeId); - } - - for (auto& entry : type->entries) { - if (type->typeId != ResourceTableType::kUnsetTypeId && - entry->entryId != ResourceEntry::kUnsetEntryId) { - // The ID for this entry has already been set. We - // mark this ID as taken so we don't re-assign it - // later. - usedIds[type->typeId].insert(entry->entryId); - } - } - } - - // Assign resource IDs that are available. - size_t nextTypeIndex = 0; - for (auto& type : *mTable) { - if (type->typeId == ResourceTableType::kUnsetTypeId) { - while (nextTypeIndex < usedTypeIds.size() && usedTypeIds[nextTypeIndex]) { - nextTypeIndex++; - } - type->typeId = nextTypeIndex++; - } - - const auto endEntryIter = std::end(usedIds[type->typeId]); - auto nextEntryIter = std::begin(usedIds[type->typeId]); - size_t nextIndex = 0; - for (auto& entry : type->entries) { - if (entry->entryId == ResourceTableType::kUnsetTypeId) { - while (nextEntryIter != endEntryIter && - nextIndex == *nextEntryIter) { - nextIndex++; - ++nextEntryIter; - } - entry->entryId = nextIndex++; - } - } - } - - // Now do reference linking. - for (auto& type : *mTable) { - for (auto& entry : type->entries) { - if (entry->publicStatus.isPublic && entry->values.empty()) { - // A public resource has no values. It will not be encoded - // properly without a symbol table. This is a unresolved symbol. - addUnresolvedSymbol(ResourceNameRef{ - mTable->getPackage(), type->type, entry->name }, - entry->publicStatus.source); - continue; - } - - for (auto& valueConfig : entry->values) { - // Dispatch to the right method of this linker - // based on the value's type. - valueConfig.value->accept(*this, Args{ - ResourceNameRef{ mTable->getPackage(), type->type, entry->name }, - valueConfig.source - }); - } - } - } - return !mError; -} - -const Linker::ResourceNameToSourceMap& Linker::getUnresolvedReferences() const { - return mUnresolvedSymbols; -} - -void Linker::doResolveReference(Reference& reference, const SourceLine& source) { - Maybe<ResourceId> result = mResolver->findId(reference.name); - if (!result) { - addUnresolvedSymbol(reference.name, source); - return; - } - assert(result.value().isValid()); - - if (mOptions.linkResourceIds) { - reference.id = result.value(); - } else { - reference.id = 0; - } -} - -const Attribute* Linker::doResolveAttribute(Reference& attribute, const SourceLine& source) { - Maybe<IResolver::Entry> result = mResolver->findAttribute(attribute.name); - if (!result || !result.value().attr) { - addUnresolvedSymbol(attribute.name, source); - return nullptr; - } - - const IResolver::Entry& entry = result.value(); - assert(entry.id.isValid()); - - if (mOptions.linkResourceIds) { - attribute.id = entry.id; - } else { - attribute.id = 0; - } - return entry.attr; -} - -void Linker::visit(Reference& reference, ValueVisitorArgs& a) { - Args& args = static_cast<Args&>(a); - - if (reference.name.entry.empty()) { - // We can't have a completely bad reference. - if (!reference.id.isValid()) { - Logger::error() << "srsly? " << args.referrer << std::endl; - assert(reference.id.isValid()); - } - - // This reference has no name but has an ID. - // It is a really bad error to have no name and have the same - // package ID. - assert(reference.id.packageId() != mTable->getPackageId()); - - // The reference goes outside this package, let it stay as a - // resource ID because it will not change. - return; - } - - doResolveReference(reference, args.source); - - // TODO(adamlesinski): Verify the referencedType is another reference - // or a compatible primitive. -} - -void Linker::processAttributeValue(const ResourceNameRef& name, const SourceLine& source, - const Attribute& attr, std::unique_ptr<Item>& value) { - std::unique_ptr<Item> convertedValue; - visitFunc<RawString>(*value, [&](RawString& str) { - // This is a raw string, so check if it can be converted to anything. - // We can NOT swap value with the converted value in here, since - // we called through the original value. - - auto onCreateReference = [&](const ResourceName& name) { - // We should never get here. All references would have been - // parsed in the parser phase. - assert(false); - }; - - convertedValue = ResourceParser::parseItemForAttribute(*str.value, attr, - onCreateReference); - if (!convertedValue && attr.typeMask & android::ResTable_map::TYPE_STRING) { - // Last effort is to parse as a string. - util::StringBuilder builder; - builder.append(*str.value); - if (builder) { - convertedValue = util::make_unique<String>( - mTable->getValueStringPool().makeRef(builder.str())); - } - } - }); - - if (convertedValue) { - value = std::move(convertedValue); - } - - // Process this new or old value (it can be a reference!). - value->accept(*this, Args{ name, source }); - - // Flatten the value to see what resource type it is. - android::Res_value resValue; - value->flatten(resValue); - - // Always allow references. - const uint32_t typeMask = attr.typeMask | android::ResTable_map::TYPE_REFERENCE; - if (!(typeMask & ResourceParser::androidTypeToAttributeTypeMask(resValue.dataType))) { - Logger::error(source) - << *value - << " is not compatible with attribute " - << attr - << "." - << std::endl; - mError = true; - } -} - -void Linker::visit(Style& style, ValueVisitorArgs& a) { - Args& args = static_cast<Args&>(a); - - if (style.parent.name.isValid() || style.parent.id.isValid()) { - visit(style.parent, a); - } - - for (Style::Entry& styleEntry : style.entries) { - const Attribute* attr = doResolveAttribute(styleEntry.key, args.source); - if (attr) { - processAttributeValue(args.referrer, args.source, *attr, styleEntry.value); - } - } -} - -void Linker::visit(Attribute& attr, ValueVisitorArgs& a) { - static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | - android::ResTable_map::TYPE_FLAGS; - if (attr.typeMask & kMask) { - for (auto& symbol : attr.symbols) { - visit(symbol.symbol, a); - } - } -} - -void Linker::visit(Styleable& styleable, ValueVisitorArgs& a) { - for (auto& attrRef : styleable.entries) { - visit(attrRef, a); - } -} - -void Linker::visit(Array& array, ValueVisitorArgs& a) { - Args& args = static_cast<Args&>(a); - - for (auto& item : array.items) { - item->accept(*this, Args{ args.referrer, args.source }); - } -} - -void Linker::visit(Plural& plural, ValueVisitorArgs& a) { - Args& args = static_cast<Args&>(a); - - for (auto& item : plural.values) { - if (item) { - item->accept(*this, Args{ args.referrer, args.source }); - } - } -} - -void Linker::addUnresolvedSymbol(const ResourceNameRef& name, const SourceLine& source) { - mUnresolvedSymbols[name.toResourceName()].push_back(source); -} - -} // namespace aapt |