blob: ad7d8b65350d0316e5fb0ced4ec45b38db1c5457 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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
Adam Lesinskice5e56e2016-10-21 17:56:45 -070017#include "link/ReferenceLinker.h"
18
19#include "android-base/logging.h"
20#include "androidfw/ResourceTypes.h"
21
Adam Lesinskicacb28f2016-10-19 12:18:14 -070022#include "Diagnostics.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070023#include "ResourceTable.h"
24#include "ResourceUtils.h"
25#include "ResourceValues.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070026#include "ValueVisitor.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070027#include "link/Linkers.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070028#include "process/IResourceTableConsumer.h"
29#include "process/SymbolTable.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080030#include "util/Util.h"
31#include "xml/XmlUtil.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070032
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070033using ::android::StringPiece;
Adam Lesinskid5083f62017-01-16 15:07:21 -080034
Adam Lesinski1ab598f2015-08-14 14:26:04 -070035namespace aapt {
36
37namespace {
38
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070039// The ReferenceLinkerVisitor will follow all references and make sure they point
40// to resources that actually exist, either in the local resource table, or as external
41// symbols. Once the target resource has been found, the ID of the resource will be assigned
42// to the reference object.
43//
44// NOTE: All of the entries in the ResourceTable must be assigned IDs.
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070045class ReferenceLinkerVisitor : public DescendingValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070046 public:
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070047 using DescendingValueVisitor::Visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070048
Adam Lesinskif34b6f42017-03-03 16:33:26 -080049 ReferenceLinkerVisitor(const CallSite& callsite, IAaptContext* context, SymbolTable* symbols,
50 StringPool* string_pool, xml::IPackageDeclStack* decl)
51 : callsite_(callsite),
52 context_(context),
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 symbols_(symbols),
54 package_decls_(decl),
Adam Lesinskif34b6f42017-03-03 16:33:26 -080055 string_pool_(string_pool) {}
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 void Visit(Reference* ref) override {
Adam Lesinskif34b6f42017-03-03 16:33:26 -080058 if (!ReferenceLinker::LinkReference(callsite_, ref, context_, symbols_, package_decls_)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070059 error_ = true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 }
61 }
62
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070063 // We visit the Style specially because during this phase, values of attributes are
64 // all RawString values. Now that we are expected to resolve all symbols, we can
65 // lookup the attributes to find out which types are allowed for the attributes' values.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070066 void Visit(Style* style) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 if (style->parent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070068 Visit(&style->parent.value());
Adam Lesinski1ab598f2015-08-14 14:26:04 -070069 }
70
Adam Lesinskicacb28f2016-10-19 12:18:14 -070071 for (Style::Entry& entry : style->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 std::string err_str;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070073
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070074 // Transform the attribute reference so that it is using the fully qualified package
75 // name. This will also mark the reference as being able to see private resources if
76 // there was a '*' in the reference or if the package came from the private namespace.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 Reference transformed_reference = entry.key;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070078 ResolvePackage(package_decls_, &transformed_reference);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070080 // Find the attribute in the symbol table and check if it is visible from this callsite.
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080081 const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility(
Adam Lesinskif34b6f42017-03-03 16:33:26 -080082 transformed_reference, callsite_, symbols_, &err_str);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070083 if (symbol) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070084 // Assign our style key the correct ID. The ID may not exist.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070085 entry.key.id = symbol->id;
86
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070087 // Try to convert the value to a more specific, typed value based on the attribute it is
88 // set to.
Adam Lesinskif34b6f42017-03-03 16:33:26 -080089 entry.value = ParseValueWithAttribute(std::move(entry.value), symbol->attribute.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090
91 // Link/resolve the final value (mostly if it's a reference).
Adam Lesinskice5e56e2016-10-21 17:56:45 -070092 entry.value->Accept(this);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070093
94 // Now verify that the type of this item is compatible with the
Adam Lesinski3124e7c2017-06-13 16:03:55 -070095 // attribute it is defined for. We pass `nullptr` as the DiagMessage so that this
96 // check is fast and we avoid creating a DiagMessage when the match is successful.
97 if (!symbol->attribute->Matches(*entry.value, nullptr)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 // The actual type of this item is incompatible with the attribute.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 DiagMessage msg(entry.key.GetSource());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700101 // Call the matches method again, this time with a DiagMessage so we fill in the actual
102 // error message.
Adam Lesinski3124e7c2017-06-13 16:03:55 -0700103 symbol->attribute->Matches(*entry.value, &msg);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 context_->GetDiagnostics()->Error(msg);
105 error_ = true;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700106 }
107
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 DiagMessage msg(entry.key.GetSource());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 msg << "style attribute '";
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700111 ReferenceLinker::WriteResourceName(entry.key, callsite_, package_decls_, &msg);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 msg << "' " << err_str;
113 context_->GetDiagnostics()->Error(msg);
114 error_ = true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 }
116 }
117 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800118
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700119 bool HasError() {
120 return error_;
121 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800122
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700124 DISALLOW_COPY_AND_ASSIGN(ReferenceLinkerVisitor);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700125
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700126 // Transform a RawString value into a more specific, appropriate value, based on the
127 // Attribute. If a non RawString value is passed in, this is an identity transform.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 std::unique_ptr<Item> ParseValueWithAttribute(std::unique_ptr<Item> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 const Attribute* attr) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 if (RawString* raw_string = ValueCast<RawString>(value.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700131 std::unique_ptr<Item> transformed =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132 ResourceUtils::TryParseItemForAttribute(*raw_string->value, attr);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700133
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 // If we could not parse as any specific type, try a basic STRING.
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800135 if (!transformed && (attr->type_mask & android::ResTable_map::TYPE_STRING)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 util::StringBuilder string_builder;
137 string_builder.Append(*raw_string->value);
138 if (string_builder) {
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800139 transformed = util::make_unique<String>(string_pool_->MakeRef(string_builder.ToString()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700140 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700142
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700143 if (transformed) {
144 return transformed;
145 }
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800146 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 return value;
148 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800150 const CallSite& callsite_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700151 IAaptContext* context_;
152 SymbolTable* symbols_;
153 xml::IPackageDeclStack* package_decls_;
154 StringPool* string_pool_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700155 bool error_ = false;
156};
157
158class EmptyDeclStack : public xml::IPackageDeclStack {
159 public:
160 EmptyDeclStack() = default;
161
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700162 Maybe<xml::ExtractedPackage> TransformPackageAlias(const StringPiece& alias) const override {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 if (alias.empty()) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700164 return xml::ExtractedPackage{{}, true /*private*/};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 }
166 return {};
167 }
168
169 private:
170 DISALLOW_COPY_AND_ASSIGN(EmptyDeclStack);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700171};
172
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700173// The symbol is visible if it is public, or if the reference to it is requesting private access
174// or if the callsite comes from the same package.
175bool IsSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
176 const CallSite& callsite) {
177 if (symbol.is_public || ref.private_reference) {
178 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 }
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700180
181 if (ref.name) {
182 const ResourceName& name = ref.name.value();
183 if (name.package.empty()) {
184 // If the symbol was found, and the package is empty, that means it was found in the local
185 // scope, which is always visible (private local).
186 return true;
187 }
188
189 // The symbol is visible if the reference is local to the same package it is defined in.
190 return callsite.package == name.package;
191 }
192
193 if (ref.id && symbol.id) {
194 return ref.id.value().package_id() == symbol.id.value().package_id();
195 }
196 return false;
Adam Lesinski467f1712015-11-16 17:35:44 -0800197}
198
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700199} // namespace
200
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800201const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference,
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700202 const CallSite& callsite,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800203 SymbolTable* symbols) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 if (reference.name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700205 const ResourceName& name = reference.name.value();
206 if (name.package.empty()) {
207 // Use the callsite's package name if no package name was defined.
208 return symbols->FindByName(ResourceName(callsite.package, name.type, name.entry));
209 }
210 return symbols->FindByName(name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700211 } else if (reference.id) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700212 return symbols->FindById(reference.id.value());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700213 } else {
214 return nullptr;
215 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800216}
217
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800218const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const Reference& reference,
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800219 const CallSite& callsite,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800220 SymbolTable* symbols,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800221 std::string* out_error) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700222 const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700223 if (!symbol) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700224 if (out_error) *out_error = "not found";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700225 return nullptr;
226 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800227
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800228 if (!IsSymbolVisible(*symbol, reference, callsite)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700229 if (out_error) *out_error = "is private";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700230 return nullptr;
231 }
232 return symbol;
Adam Lesinski467f1712015-11-16 17:35:44 -0800233}
234
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility(
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800236 const Reference& reference, const CallSite& callsite, SymbolTable* symbols,
237 std::string* out_error) {
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800238 const SymbolTable::Symbol* symbol =
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800239 ResolveSymbolCheckVisibility(reference, callsite, symbols, out_error);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700240 if (!symbol) {
241 return nullptr;
242 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800243
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700244 if (!symbol->attribute) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245 if (out_error) *out_error = "is not an attribute";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700246 return nullptr;
247 }
248 return symbol;
Adam Lesinski467f1712015-11-16 17:35:44 -0800249}
250
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800251Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& reference,
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800252 const CallSite& callsite,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800253 SymbolTable* symbols,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800254 std::string* out_error) {
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800255 const SymbolTable::Symbol* symbol =
256 ResolveAttributeCheckVisibility(reference, callsite, symbols, out_error);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 if (!symbol) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 return {};
259 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800260
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700261 if (!symbol->attribute) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700262 if (out_error) *out_error = "is not an attribute";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 return {};
264 }
Adam Lesinskic744ae82017-05-17 19:28:38 -0700265 return xml::AaptAttribute(*symbol->attribute, symbol->id);
Adam Lesinski467f1712015-11-16 17:35:44 -0800266}
267
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700268void ReferenceLinker::WriteResourceName(const Reference& ref, const CallSite& callsite,
269 const xml::IPackageDeclStack* decls, DiagMessage* out_msg) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700270 CHECK(out_msg != nullptr);
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700271 if (!ref.name) {
272 *out_msg << ref.id.value();
273 return;
274 }
Adam Lesinski28cacf02015-11-23 14:22:47 -0800275
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700276 *out_msg << ref.name.value();
277
278 Reference fully_qualified = ref;
279 xml::ResolvePackage(decls, &fully_qualified);
280
281 ResourceName& full_name = fully_qualified.name.value();
282 if (full_name.package.empty()) {
283 full_name.package = callsite.package;
284 }
285
286 if (full_name != ref.name.value()) {
287 *out_msg << " (aka " << full_name << ")";
288 }
289}
290
291void ReferenceLinker::WriteAttributeName(const Reference& ref, const CallSite& callsite,
292 const xml::IPackageDeclStack* decls,
293 DiagMessage* out_msg) {
294 CHECK(out_msg != nullptr);
295 if (!ref.name) {
296 *out_msg << ref.id.value();
297 return;
298 }
299
300 const ResourceName& ref_name = ref.name.value();
301 CHECK_EQ(ref_name.type, ResourceType::kAttr);
302
303 if (!ref_name.package.empty()) {
304 *out_msg << ref_name.package << ":";
305 }
306 *out_msg << ref_name.entry;
307
308 Reference fully_qualified = ref;
309 xml::ResolvePackage(decls, &fully_qualified);
310
311 ResourceName& full_name = fully_qualified.name.value();
312 if (full_name.package.empty()) {
313 full_name.package = callsite.package;
314 }
315
316 if (full_name != ref.name.value()) {
317 *out_msg << " (aka " << full_name.package << ":" << full_name.entry << ")";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700318 }
Adam Lesinski28cacf02015-11-23 14:22:47 -0800319}
320
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800321bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* reference,
322 IAaptContext* context, SymbolTable* symbols,
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700323 const xml::IPackageDeclStack* decls) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700324 CHECK(reference != nullptr);
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700325 if (!reference->name && !reference->id) {
326 // This is @null.
327 return true;
328 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800329
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 Reference transformed_reference = *reference;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700331 xml::ResolvePackage(decls, &transformed_reference);
Adam Lesinski467f1712015-11-16 17:35:44 -0800332
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700333 std::string err_str;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800334 const SymbolTable::Symbol* s =
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800335 ResolveSymbolCheckVisibility(transformed_reference, callsite, symbols, &err_str);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 if (s) {
337 // The ID may not exist. This is fine because of the possibility of building
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 // against libraries without assigned IDs.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700339 // Ex: Linking against own resources when building a static library.
340 reference->id = s->id;
341 return true;
342 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800343
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344 DiagMessage error_msg(reference->GetSource());
345 error_msg << "resource ";
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700346 WriteResourceName(*reference, callsite, decls, &error_msg);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700347 error_msg << " " << err_str;
348 context->GetDiagnostics()->Error(error_msg);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 return false;
Adam Lesinski467f1712015-11-16 17:35:44 -0800350}
351
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700352bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) {
353 EmptyDeclStack decl_stack;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700354 bool error = false;
355 for (auto& package : table->packages) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700356 // Since we're linking, each package must have a name.
357 CHECK(!package->name.empty()) << "all packages being linked must have a name";
358
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700359 for (auto& type : package->types) {
360 for (auto& entry : type->entries) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700361 // First, unmangle the name if necessary.
362 ResourceName name(package->name, type->type, entry->name);
363 NameMangler::Unmangle(&name.entry, &name.package);
364
365 // Symbol state information may be lost if there is no value for the resource.
366 if (entry->symbol_status.state != SymbolState::kUndefined && entry->values.empty()) {
367 context->GetDiagnostics()->Error(DiagMessage(entry->symbol_status.source)
368 << "no definition for declared symbol '" << name << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700369 error = true;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700370 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700372 // The context of this resource is the package in which it is defined.
373 const CallSite callsite{name.package};
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800374 ReferenceLinkerVisitor visitor(callsite, context, context->GetExternalSymbols(),
375 &table->string_pool, &decl_stack);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700376
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700377 for (auto& config_value : entry->values) {
378 config_value->value->Accept(&visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700379 }
380
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700381 if (visitor.HasError()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700382 error = true;
383 }
384 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700385 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700386 }
387 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700388}
389
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700390} // namespace aapt