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