1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef AAPT_LINKER_REFERENCELINKER_H 18 #define AAPT_LINKER_REFERENCELINKER_H 19 20 #include "android-base/macros.h" 21 22 #include "Resource.h" 23 #include "ResourceValues.h" 24 #include "link/Linkers.h" 25 #include "process/IResourceTableConsumer.h" 26 #include "process/SymbolTable.h" 27 #include "xml/XmlDom.h" 28 29 namespace aapt { 30 31 // A ValueTransformer that returns fully linked versions of resource and macro references. 32 class ReferenceLinkerTransformer : public CloningValueTransformer { 33 public: ReferenceLinkerTransformer(const CallSite & callsite,IAaptContext * context,SymbolTable * symbols,android::StringPool * string_pool,ResourceTable * table,xml::IPackageDeclStack * decl)34 ReferenceLinkerTransformer(const CallSite& callsite, IAaptContext* context, SymbolTable* symbols, 35 android::StringPool* string_pool, ResourceTable* table, 36 xml::IPackageDeclStack* decl) 37 : CloningValueTransformer(string_pool), 38 callsite_(callsite), 39 context_(context), 40 symbols_(symbols), 41 table_(table), 42 package_decls_(decl) { 43 } 44 45 std::unique_ptr<Reference> TransformDerived(const Reference* value) override; 46 std::unique_ptr<Item> TransformItem(const Reference* value) override; 47 std::unique_ptr<Style> TransformDerived(const Style* value) override; 48 HasError()49 bool HasError() { 50 return error_; 51 } 52 53 private: 54 // Transform a RawString value into a more specific, appropriate value, based on the 55 // Attribute. If a non RawString value is passed in, this is an identity transform. 56 std::unique_ptr<Item> ParseValueWithAttribute(std::unique_ptr<Item> value, const Attribute* attr); 57 58 const CallSite& callsite_; 59 IAaptContext* context_; 60 SymbolTable* symbols_; 61 ResourceTable* table_; 62 xml::IPackageDeclStack* package_decls_; 63 bool error_ = false; 64 }; 65 66 // Resolves all references to resources in the ResourceTable and assigns them IDs. 67 // The ResourceTable must already have IDs assigned to each resource. 68 // Once the ResourceTable is processed by this linker, it is ready to be flattened. 69 class ReferenceLinker : public IResourceTableConsumer { 70 public: 71 ReferenceLinker() = default; 72 73 // Performs name mangling and looks up the resource in the symbol table. Uses the callsite's 74 // package if the reference has no package name defined (implicit). 75 // Returns nullptr if the symbol was not found. 76 static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference, 77 const CallSite& callsite, 78 IAaptContext* context, 79 SymbolTable* symbols); 80 81 // Performs name mangling and looks up the resource in the symbol table. If the symbol is not 82 // visible by the reference at the callsite, nullptr is returned. 83 // `out_error` holds the error message. 84 static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference, 85 const CallSite& callsite, 86 IAaptContext* context, 87 SymbolTable* symbols, 88 std::string* out_error); 89 90 // Same as ResolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute. 91 // That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute. 92 static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference, 93 const CallSite& callsite, 94 IAaptContext* context, 95 SymbolTable* symbols, 96 std::string* out_error); 97 98 // Resolves the attribute reference and returns an xml::AaptAttribute if successful. 99 // If resolution fails, outError holds the error message. 100 static std::optional<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference, 101 const CallSite& callsite, 102 IAaptContext* context, 103 SymbolTable* symbols, 104 std::string* out_error); 105 106 // Writes the resource name to the DiagMessage, using the 107 // "orig_name (aka <transformed_name>)" syntax. 108 /*static void WriteResourceName(const Reference& orig, const CallSite& callsite, 109 const xml::IPackageDeclStack* decls, DiagMessage* out_msg);*/ 110 111 // Same as WriteResourceName but omits the 'attr' part. 112 static void WriteAttributeName(const Reference& ref, const CallSite& callsite, 113 const xml::IPackageDeclStack* decls, 114 android::DiagMessage* out_msg); 115 116 // Returns a fully linked version a resource reference. 117 // 118 // If the reference points to a non-macro resource, the xml::IPackageDeclStack is used to 119 // determine the fully qualified name of the referenced resource. If the symbol is visible 120 // to the reference at the callsite, a copy of the reference with an updated updated ID is 121 // returned. 122 // 123 // If the reference points to a macro, the ResourceTable is used to find the macro definition and 124 // substitute its contents in place of the reference. 125 // 126 // Returns nullptr on failure, and an error message is logged to the IDiagnostics in the context. 127 static std::unique_ptr<Item> LinkReference(const CallSite& callsite, const Reference& reference, 128 IAaptContext* context, SymbolTable* symbols, 129 ResourceTable* table, 130 const xml::IPackageDeclStack* decls); 131 132 // Links all references in the ResourceTable. 133 bool Consume(IAaptContext* context, ResourceTable* table) override; 134 135 private: 136 DISALLOW_COPY_AND_ASSIGN(ReferenceLinker); 137 }; 138 139 } // namespace aapt 140 141 #endif /* AAPT_LINKER_REFERENCELINKER_H */ 142