11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Diagnostics.h" 1864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include "ReferenceLinker.h" 191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceTable.h" 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceUtils.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceValues.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ValueVisitor.h" 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/Linkers.h" 241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/IResourceTableConsumer.h" 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/SymbolTable.h" 26467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/Util.h" 27467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlUtil.h" 281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <androidfw/ResourceTypes.h> 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <cassert> 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace { 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/** 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * The ReferenceLinkerVisitor will follow all references and make sure they point 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * to resources that actually exist, either in the local resource table, or as external 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * symbols. Once the target resource has been found, the ID of the resource will be assigned 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * to the reference object. 411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * NOTE: All of the entries in the ResourceTable must be assigned IDs. 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 44467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskiclass ReferenceLinkerVisitor : public ValueVisitor { 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskipublic: 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski using ValueVisitor::visit; 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 4864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols, StringPool* stringPool, 49467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski xml::IPackageDeclStack* decl,CallSite* callSite) : 50467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski mContext(context), mSymbols(symbols), mPackageDecls(decl), mStringPool(stringPool), 51467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski mCallSite(callSite) { 521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 54467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski void visit(Reference* ref) override { 55467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!ReferenceLinker::linkReference(ref, mContext, mSymbols, mPackageDecls, mCallSite)) { 56467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski mError = true; 57467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski /** 611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * We visit the Style specially because during this phase, values of attributes are 621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * all RawString values. Now that we are expected to resolve all symbols, we can 631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * lookup the attributes to find out which types are allowed for the attributes' values. 641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski void visit(Style* style) override { 661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (style->parent) { 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski visit(&style->parent.value()); 681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (Style::Entry& entry : style->entries) { 71467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski std::string errStr; 72467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 73467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski // Transform the attribute reference so that it is using the fully qualified package 74467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski // name. This will also mark the reference as being able to see private resources if 75467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski // there was a '*' in the reference or if the package came from the private namespace. 76467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Reference transformedReference = entry.key; 77467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski transformReferenceFromNamespace(mPackageDecls, mContext->getCompilationPackage(), 78467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski &transformedReference); 79467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 80467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski // Find the attribute in the symbol table and check if it is visible from this callsite. 8164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const SymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility( 82467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski transformedReference, mContext->getNameMangler(), mSymbols, mCallSite, &errStr); 83467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (symbol) { 841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Assign our style key the correct ID. 8564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // The ID may not exist. 86467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski entry.key.id = symbol->id; 871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Try to convert the value to a more specific, typed value based on the 891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // attribute it is set to. 90467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski entry.value = parseValueWithAttribute(std::move(entry.value), 91467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski symbol->attribute.get()); 921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Link/resolve the final value (mostly if it's a reference). 941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski entry.value->accept(this); 951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Now verify that the type of this item is compatible with the attribute it 97a587065721053ad54e34f484868142407d59512dAdam Lesinski // is defined for. We pass `nullptr` as the DiagMessage so that this check is 98a587065721053ad54e34f484868142407d59512dAdam Lesinski // fast and we avoid creating a DiagMessage when the match is successful. 99a587065721053ad54e34f484868142407d59512dAdam Lesinski if (!symbol->attribute->matches(entry.value.get(), nullptr)) { 1001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // The actual type of this item is incompatible with the attribute. 10128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski DiagMessage msg(entry.key.getSource()); 102a587065721053ad54e34f484868142407d59512dAdam Lesinski 103a587065721053ad54e34f484868142407d59512dAdam Lesinski // Call the matches method again, this time with a DiagMessage so we fill 104a587065721053ad54e34f484868142407d59512dAdam Lesinski // in the actual error message. 105a587065721053ad54e34f484868142407d59512dAdam Lesinski symbol->attribute->matches(entry.value.get(), &msg); 1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mContext->getDiagnostics()->error(msg); 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mError = true; 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 109a587065721053ad54e34f484868142407d59512dAdam Lesinski 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } else { 11128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski DiagMessage msg(entry.key.getSource()); 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski msg << "style attribute '"; 11328cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski ReferenceLinker::writeResourceName(&msg, entry.key, transformedReference); 114467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski msg << "' " << errStr; 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mContext->getDiagnostics()->error(msg); 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mError = true; 1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 121467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski bool hasError() { 122467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return mError; 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 12464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 12564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiprivate: 12664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski IAaptContext* mContext; 12764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski SymbolTable* mSymbols; 12864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski xml::IPackageDeclStack* mPackageDecls; 12964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski StringPool* mStringPool; 13064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski CallSite* mCallSite; 13164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski bool mError = false; 13264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 13364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski /** 13464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Transform a RawString value into a more specific, appropriate value, based on the 13564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Attribute. If a non RawString value is passed in, this is an identity transform. 13664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski */ 13764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value, 13864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const Attribute* attr) { 13964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (RawString* rawString = valueCast<RawString>(value.get())) { 14064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<Item> transformed = 14164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski ResourceUtils::parseItemForAttribute(*rawString->value, attr); 14264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // If we could not parse as any specific type, try a basic STRING. 14464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) { 14564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski util::StringBuilder stringBuilder; 14664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski stringBuilder.append(*rawString->value); 14764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (stringBuilder) { 14864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski transformed = util::make_unique<String>( 14964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mStringPool->makeRef(stringBuilder.str())); 15064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 15164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 15264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 15364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (transformed) { 15464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return transformed; 15564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 15664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski }; 15764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return value; 15864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 161467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} // namespace 162467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 163467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski/** 164467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * The symbol is visible if it is public, or if the reference to it is requesting private access 165467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * or if the callsite comes from the same package. 166467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski */ 16764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskibool ReferenceLinker::isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref, 168467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski const CallSite& callSite) { 169467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol.isPublic && !ref.privateReference) { 170467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (ref.name) { 171467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return callSite.resource.package == ref.name.value().package; 17264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } else if (ref.id && symbol.id) { 17364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return ref.id.value().packageId() == symbol.id.value().packageId(); 174467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else { 175467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return false; 176467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 177467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 178467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return true; 179467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 180467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 18164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiconst SymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference, 18264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski NameMangler* mangler, 18364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski SymbolTable* symbols) { 184467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (reference.name) { 185467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Maybe<ResourceName> mangled = mangler->mangleName(reference.name.value()); 186467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return symbols->findByName(mangled ? mangled.value() : reference.name.value()); 187467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else if (reference.id) { 188467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return symbols->findById(reference.id.value()); 189467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else { 190467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return nullptr; 191467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 192467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 193467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 19464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiconst SymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility( 19564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols, 196467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski CallSite* callSite, std::string* outError) { 19764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols); 198467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol) { 19928cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (outError) *outError = "not found"; 200467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return nullptr; 201467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 202467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 203467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!isSymbolVisible(*symbol, reference, *callSite)) { 20428cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (outError) *outError = "is private"; 205467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return nullptr; 206467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 207467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return symbol; 208467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 209467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 21064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiconst SymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility( 21164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols, 212467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski CallSite* callSite, std::string* outError) { 21364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const SymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler, 21464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski symbols, callSite, 21564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski outError); 216467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol) { 217467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return nullptr; 218467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 219467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 220467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol->attribute) { 22128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (outError) *outError = "is not an attribute"; 222467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return nullptr; 223467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 224467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return symbol; 225467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 226467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 227467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiMaybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(const Reference& reference, 228467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski NameMangler* nameMangler, 22964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski SymbolTable* symbols, 230467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski CallSite* callSite, 231467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski std::string* outError) { 23264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols); 233467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol) { 234467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 235467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 236467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 237467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!symbol->attribute) { 23828cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (outError) *outError = "is not an attribute"; 239467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 240467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 241467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return xml::AaptAttribute{ symbol->id, *symbol->attribute }; 242467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 243467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 24428cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinskivoid ReferenceLinker::writeResourceName(DiagMessage* outMsg, const Reference& orig, 24528cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski const Reference& transformed) { 24628cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski assert(outMsg); 24728cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski 24828cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (orig.name) { 24928cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski *outMsg << orig.name.value(); 25028cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski if (transformed.name.value() != orig.name.value()) { 25128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski *outMsg << " (aka " << transformed.name.value() << ")"; 25228cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski } 25328cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski } else { 25428cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski *outMsg << orig.id.value(); 25528cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski } 25628cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski} 25728cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski 258467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskibool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context, 25964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski SymbolTable* symbols, xml::IPackageDeclStack* decls, 260467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski CallSite* callSite) { 261467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski assert(reference); 262467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski assert(reference->name || reference->id); 263467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 264467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Reference transformedReference = *reference; 265467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski transformReferenceFromNamespace(decls, context->getCompilationPackage(), 266467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski &transformedReference); 267467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 268467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski std::string errStr; 26964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const SymbolTable::Symbol* s = resolveSymbolCheckVisibility( 270467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski transformedReference, context->getNameMangler(), symbols, callSite, &errStr); 271467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (s) { 27264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // The ID may not exist. This is fine because of the possibility of building against 27364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // libraries without assigned IDs. 27464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // Ex: Linking against own resources when building a static library. 275467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski reference->id = s->id; 276467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return true; 277467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 278467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 279467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski DiagMessage errorMsg(reference->getSource()); 280467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski errorMsg << "resource "; 28128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski writeResourceName(&errorMsg, *reference, transformedReference); 282467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski errorMsg << " " << errStr; 283467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski context->getDiagnostics()->error(errorMsg); 284467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return false; 285467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 286467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 287467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskinamespace { 288467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 289467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskistruct EmptyDeclStack : public xml::IPackageDeclStack { 290467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Maybe<xml::ExtractedPackage> transformPackageAlias( 291467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski const StringPiece16& alias, const StringPiece16& localPackage) const override { 292467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (alias.empty()) { 293467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return xml::ExtractedPackage{ localPackage.toString(), true /* private */ }; 2941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 2961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 2981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace 3001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskibool ReferenceLinker::consume(IAaptContext* context, ResourceTable* table) { 3021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EmptyDeclStack declStack; 3031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski bool error = false; 3041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (auto& package : table->packages) { 3051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (auto& type : package->types) { 3061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (auto& entry : type->entries) { 3079e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski // Symbol state information may be lost if there is no value for the resource. 3089e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski if (entry->symbolStatus.state != SymbolState::kUndefined && entry->values.empty()) { 3099e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski context->getDiagnostics()->error( 3109e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski DiagMessage(entry->symbolStatus.source) 3119e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski << "no definition for declared symbol '" 3129e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski << ResourceNameRef(package->name, type->type, entry->name) 3139e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski << "'"); 3141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski error = true; 3151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 3161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 317467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski CallSite callSite = { ResourceNameRef(package->name, type->type, entry->name) }; 318467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ReferenceLinkerVisitor visitor(context, context->getExternalSymbols(), 319467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski &table->stringPool, &declStack, &callSite); 320467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 3211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (auto& configValue : entry->values) { 322e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski configValue->value->accept(&visitor); 323467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 324467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 325467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (visitor.hasError()) { 326467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski error = true; 3271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 3281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 3291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 3301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 3311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return !error; 3321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 3331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 335