blob: f2a93a868bb7da1e7419bbbb1667344f9759dfa3 [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
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070019#include "ResourceParser.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "ResourceTable.h"
21#include "ResourceUtils.h"
22#include "ResourceValues.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070023#include "ValueVisitor.h"
Jeremy Meyer56f36e82022-05-20 20:35:42 +000024#include "android-base/logging.h"
25#include "android-base/stringprintf.h"
26#include "androidfw/IDiagnostics.h"
27#include "androidfw/ResourceTypes.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070028#include "link/Linkers.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029#include "process/IResourceTableConsumer.h"
30#include "process/SymbolTable.h"
Fabien Sanglard2d34e762019-02-21 15:13:29 -080031#include "trace/TraceBuffer.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080032#include "util/Util.h"
33#include "xml/XmlUtil.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034
Adam Lesinski2eed52e2018-02-21 15:55:58 -080035using ::aapt::ResourceUtils::StringBuilder;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -070036using ::android::StringPiece;
Udam Sainib228df32019-06-18 16:50:34 -070037using ::android::base::StringPrintf;
Adam Lesinskid5083f62017-01-16 15:07:21 -080038
Adam Lesinski1ab598f2015-08-14 14:26:04 -070039namespace aapt {
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040namespace {
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070041struct LoggingResourceName {
42 LoggingResourceName(const Reference& ref, const CallSite& callsite,
43 const xml::IPackageDeclStack* decls)
44 : ref_(ref), callsite_(callsite), decls_(decls) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 }
46
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070047 const Reference& ref_;
48 const CallSite& callsite_;
49 const xml::IPackageDeclStack* decls_;
50};
51
52inline ::std::ostream& operator<<(::std::ostream& out, const LoggingResourceName& name) {
53 if (!name.ref_.name) {
54 out << name.ref_.id.value();
55 return out;
56 }
57
58 out << name.ref_.name.value();
59
60 Reference fully_qualified = name.ref_;
61 xml::ResolvePackage(name.decls_, &fully_qualified);
62
63 ResourceName& full_name = fully_qualified.name.value();
64 if (full_name.package.empty()) {
65 full_name.package = name.callsite_.package;
66 }
67
68 if (full_name != name.ref_.name.value()) {
69 out << " (aka " << full_name << ")";
70 }
71 return out;
72}
73
74} // namespace
75
76std::unique_ptr<Reference> ReferenceLinkerTransformer::TransformDerived(const Reference* value) {
77 auto linked_item =
78 ReferenceLinker::LinkReference(callsite_, *value, context_, symbols_, table_, package_decls_);
79 if (linked_item) {
80 auto linked_item_ptr = linked_item.release();
81 if (auto ref = ValueCast<Reference>(linked_item_ptr)) {
82 return std::unique_ptr<Reference>(ref);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070083 }
Jeremy Meyer56f36e82022-05-20 20:35:42 +000084 context_->GetDiagnostics()->Error(android::DiagMessage(value->GetSource())
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070085 << "value of '"
86 << LoggingResourceName(*value, callsite_, package_decls_)
87 << "' must be a resource reference");
88 delete linked_item_ptr;
89 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070090
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070091 error_ = true;
92 return CloningValueTransformer::TransformDerived(value);
93}
Adam Lesinski1ab598f2015-08-14 14:26:04 -070094
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070095std::unique_ptr<Style> ReferenceLinkerTransformer::TransformDerived(const Style* style) {
96 // We visit the Style specially because during this phase, values of attributes are either
97 // RawString or Reference values. Now that we are expected to resolve all symbols, we can lookup
98 // the attributes to find out which types are allowed for the attributes' values.
99 auto new_style = CloningValueTransformer::TransformDerived(style);
100 if (new_style->parent) {
101 new_style->parent = *TransformDerived(&style->parent.value());
102 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700104 for (Style::Entry& entry : new_style->entries) {
105 std::string err_str;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700106
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700107 // Transform the attribute reference so that it is using the fully qualified package
108 // name. This will also mark the reference as being able to see private resources if
109 // there was a '*' in the reference or if the package came from the private namespace.
110 Reference transformed_reference = entry.key;
111 ResolvePackage(package_decls_, &transformed_reference);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700112
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700113 // Find the attribute in the symbol table and check if it is visible from this callsite.
114 const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility(
115 transformed_reference, callsite_, context_, symbols_, &err_str);
116 if (symbol) {
117 // Assign our style key the correct ID. The ID may not exist.
118 entry.key.id = symbol->id;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700120 // Link/resolve the final value if it's a reference.
121 entry.value = entry.value->Transform(*this);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700122
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700123 // Try to convert the value to a more specific, typed value based on the attribute it is
124 // set to.
125 entry.value = ParseValueWithAttribute(std::move(entry.value), symbol->attribute.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700126
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700127 // Now verify that the type of this item is compatible with the
128 // attribute it is defined for. We pass `nullptr` as the DiagMessage so that this
129 // check is fast and we avoid creating a DiagMessage when the match is successful.
130 if (!symbol->attribute->Matches(*entry.value, nullptr)) {
131 // The actual type of this item is incompatible with the attribute.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000132 android::DiagMessage msg(entry.key.GetSource());
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700133
134 // Call the matches method again, this time with a DiagMessage so we fill in the actual
135 // error message.
136 symbol->attribute->Matches(*entry.value, &msg);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700137 context_->GetDiagnostics()->Error(msg);
138 error_ = true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 }
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700140 } else {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000141 context_->GetDiagnostics()->Error(android::DiagMessage(entry.key.GetSource())
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700142 << "style attribute '"
143 << LoggingResourceName(entry.key, callsite_, package_decls_)
144 << "' " << err_str);
145
146 error_ = true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 }
148 }
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700149 return new_style;
150}
Adam Lesinski467f1712015-11-16 17:35:44 -0800151
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700152std::unique_ptr<Item> ReferenceLinkerTransformer::TransformItem(const Reference* value) {
153 auto linked_value =
154 ReferenceLinker::LinkReference(callsite_, *value, context_, symbols_, table_, package_decls_);
155 if (linked_value) {
156 return linked_value;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700157 }
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700158 error_ = true;
159 return CloningValueTransformer::TransformDerived(value);
160}
Adam Lesinski467f1712015-11-16 17:35:44 -0800161
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700162// Transform a RawString value into a more specific, appropriate value, based on the
163// Attribute. If a non RawString value is passed in, this is an identity transform.
164std::unique_ptr<Item> ReferenceLinkerTransformer::ParseValueWithAttribute(
165 std::unique_ptr<Item> value, const Attribute* attr) {
166 if (RawString* raw_string = ValueCast<RawString>(value.get())) {
167 std::unique_ptr<Item> transformed =
168 ResourceUtils::TryParseItemForAttribute(*raw_string->value, attr);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700169
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700170 // If we could not parse as any specific type, try a basic STRING.
171 if (!transformed && (attr->type_mask & android::ResTable_map::TYPE_STRING)) {
172 StringBuilder string_builder;
173 string_builder.AppendText(*raw_string->value);
174 if (string_builder) {
175 transformed = util::make_unique<String>(pool_->MakeRef(string_builder.to_string()));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 }
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800177 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700179 if (transformed) {
180 return transformed;
181 }
182 }
183 return value;
184}
185
186namespace {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700187
188class EmptyDeclStack : public xml::IPackageDeclStack {
189 public:
190 EmptyDeclStack() = default;
191
Ryan Mitchell4382e442021-07-14 12:53:01 -0700192 std::optional<xml::ExtractedPackage> TransformPackageAlias(
193 const StringPiece& alias) const override {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700194 if (alias.empty()) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700195 return xml::ExtractedPackage{{}, true /*private*/};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700196 }
197 return {};
198 }
199
200 private:
201 DISALLOW_COPY_AND_ASSIGN(EmptyDeclStack);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700202};
203
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700204struct MacroDeclStack : public xml::IPackageDeclStack {
205 explicit MacroDeclStack(std::vector<Macro::Namespace> namespaces)
206 : alias_namespaces_(std::move(namespaces)) {
207 }
208
Ryan Mitchell4382e442021-07-14 12:53:01 -0700209 std::optional<xml::ExtractedPackage> TransformPackageAlias(
210 const StringPiece& alias) const override {
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700211 if (alias.empty()) {
212 return xml::ExtractedPackage{{}, true /*private*/};
213 }
214 for (auto it = alias_namespaces_.rbegin(); it != alias_namespaces_.rend(); ++it) {
215 if (alias == StringPiece(it->alias)) {
216 return xml::ExtractedPackage{it->package_name, it->is_private};
217 }
218 }
219 return {};
220 }
221
222 private:
223 std::vector<Macro::Namespace> alias_namespaces_;
224};
225
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700226// The symbol is visible if it is public, or if the reference to it is requesting private access
227// or if the callsite comes from the same package.
228bool IsSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
229 const CallSite& callsite) {
230 if (symbol.is_public || ref.private_reference) {
231 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700232 }
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700233
234 if (ref.name) {
235 const ResourceName& name = ref.name.value();
236 if (name.package.empty()) {
237 // If the symbol was found, and the package is empty, that means it was found in the local
238 // scope, which is always visible (private local).
239 return true;
240 }
241
242 // The symbol is visible if the reference is local to the same package it is defined in.
243 return callsite.package == name.package;
244 }
245
246 if (ref.id && symbol.id) {
247 return ref.id.value().package_id() == symbol.id.value().package_id();
248 }
249 return false;
Adam Lesinski467f1712015-11-16 17:35:44 -0800250}
251
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700252} // namespace
253
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800254const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference,
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700255 const CallSite& callsite,
Udam Sainib228df32019-06-18 16:50:34 -0700256 IAaptContext* context,
Chris Warrington58e2fbf2018-07-23 14:12:20 +0000257 SymbolTable* symbols) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700258 if (reference.name) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700259 const ResourceName& name = reference.name.value();
260 if (name.package.empty()) {
261 // Use the callsite's package name if no package name was defined.
Udam Sainib228df32019-06-18 16:50:34 -0700262 const SymbolTable::Symbol* symbol = symbols->FindByName(
263 ResourceName(callsite.package, name.type, name.entry));
264 if (symbol) {
265 return symbol;
266 }
267
268 // If the callsite package is the same as the current compilation package,
269 // check the feature split dependencies as well. Feature split resources
270 // can be referenced without a namespace, just like the base package.
Udam Sainib228df32019-06-18 16:50:34 -0700271 if (callsite.package == context->GetCompilationPackage()) {
272 const auto& split_name_dependencies = context->GetSplitNameDependencies();
273 for (const std::string& split_name : split_name_dependencies) {
274 std::string split_package =
275 StringPrintf("%s.%s", callsite.package.c_str(), split_name.c_str());
276 symbol = symbols->FindByName(ResourceName(split_package, name.type, name.entry));
277 if (symbol) {
278 return symbol;
279 }
280 }
281 }
282 return nullptr;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700283 }
284 return symbols->FindByName(name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700285 } else if (reference.id) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700286 return symbols->FindById(reference.id.value());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 } else {
288 return nullptr;
289 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800290}
291
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800292const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const Reference& reference,
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800293 const CallSite& callsite,
Udam Sainib228df32019-06-18 16:50:34 -0700294 IAaptContext* context,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800295 SymbolTable* symbols,
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800296 std::string* out_error) {
Udam Sainib228df32019-06-18 16:50:34 -0700297 const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, context, symbols);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700298 if (!symbol) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700299 if (out_error) *out_error = "not found";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700300 return nullptr;
301 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800302
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800303 if (!IsSymbolVisible(*symbol, reference, callsite)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 if (out_error) *out_error = "is private";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 return nullptr;
306 }
307 return symbol;
Adam Lesinski467f1712015-11-16 17:35:44 -0800308}
309
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility(
Udam Sainib228df32019-06-18 16:50:34 -0700311 const Reference& reference, const CallSite& callsite, IAaptContext* context,
312 SymbolTable* symbols, std::string* out_error) {
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800313 const SymbolTable::Symbol* symbol =
Udam Sainib228df32019-06-18 16:50:34 -0700314 ResolveSymbolCheckVisibility(reference, callsite, context, symbols, out_error);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700315 if (!symbol) {
316 return nullptr;
317 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800318
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700319 if (!symbol->attribute) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700320 if (out_error) *out_error = "is not an attribute";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700321 return nullptr;
322 }
323 return symbol;
Adam Lesinski467f1712015-11-16 17:35:44 -0800324}
325
Ryan Mitchell4382e442021-07-14 12:53:01 -0700326std::optional<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& reference,
327 const CallSite& callsite,
328 IAaptContext* context,
329 SymbolTable* symbols,
330 std::string* out_error) {
Adam Lesinskif34b6f42017-03-03 16:33:26 -0800331 const SymbolTable::Symbol* symbol =
Udam Sainib228df32019-06-18 16:50:34 -0700332 ResolveAttributeCheckVisibility(reference, callsite, context, symbols, out_error);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333 if (!symbol) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700334 return {};
335 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800336
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700337 if (!symbol->attribute) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 if (out_error) *out_error = "is not an attribute";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700339 return {};
340 }
Adam Lesinskic744ae82017-05-17 19:28:38 -0700341 return xml::AaptAttribute(*symbol->attribute, symbol->id);
Adam Lesinski467f1712015-11-16 17:35:44 -0800342}
343
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700344void ReferenceLinker::WriteAttributeName(const Reference& ref, const CallSite& callsite,
345 const xml::IPackageDeclStack* decls,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000346 android::DiagMessage* out_msg) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700347 CHECK(out_msg != nullptr);
348 if (!ref.name) {
349 *out_msg << ref.id.value();
350 return;
351 }
352
353 const ResourceName& ref_name = ref.name.value();
Iurii Makhnocff10ce2022-02-15 19:33:50 +0000354 CHECK_EQ(ref_name.type.type, ResourceType::kAttr);
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700355
356 if (!ref_name.package.empty()) {
357 *out_msg << ref_name.package << ":";
358 }
359 *out_msg << ref_name.entry;
360
361 Reference fully_qualified = ref;
362 xml::ResolvePackage(decls, &fully_qualified);
363
364 ResourceName& full_name = fully_qualified.name.value();
365 if (full_name.package.empty()) {
366 full_name.package = callsite.package;
367 }
368
369 if (full_name != ref.name.value()) {
370 *out_msg << " (aka " << full_name.package << ":" << full_name.entry << ")";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371 }
Adam Lesinski28cacf02015-11-23 14:22:47 -0800372}
373
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700374std::unique_ptr<Item> ReferenceLinker::LinkReference(const CallSite& callsite,
375 const Reference& reference,
376 IAaptContext* context, SymbolTable* symbols,
377 ResourceTable* table,
378 const xml::IPackageDeclStack* decls) {
379 if (!reference.name && !reference.id) {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700380 // This is @null.
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700381 return std::make_unique<Reference>(reference);
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700382 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800383
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700384 Reference transformed_reference = reference;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700385 xml::ResolvePackage(decls, &transformed_reference);
Adam Lesinski467f1712015-11-16 17:35:44 -0800386
Iurii Makhnocff10ce2022-02-15 19:33:50 +0000387 if (transformed_reference.name.value().type.type == ResourceType::kMacro) {
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700388 if (transformed_reference.name.value().package.empty()) {
389 transformed_reference.name.value().package = callsite.package;
390 }
391
392 auto result = table->FindResource(transformed_reference.name.value());
393 if (!result || result.value().entry->values.empty()) {
394 context->GetDiagnostics()->Error(
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000395 android::DiagMessage(reference.GetSource())
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700396 << "failed to find definition for "
397 << LoggingResourceName(transformed_reference, callsite, decls));
398 return {};
399 }
400
401 auto& macro_values = result.value().entry->values;
402 CHECK(macro_values.size() == 1) << "Macros can only be defined in the default configuration.";
403
404 auto macro = ValueCast<Macro>(macro_values[0]->value.get());
405 CHECK(macro != nullptr) << "Value of macro resource is not a Macro (actual "
406 << *macro_values[0]->value << ")";
407
408 // Re-create the state used to parse the macro tag to compile the macro contents as if it was
409 // defined inline
410 uint32_t type_flags = 0;
411 if (reference.type_flags.has_value()) {
412 type_flags = reference.type_flags.value();
413 }
414
415 MacroDeclStack namespace_stack(macro->alias_namespaces);
416 FlattenedXmlSubTree sub_tree{.raw_value = macro->raw_value,
417 .style_string = macro->style_string,
418 .untranslatable_sections = macro->untranslatable_sections,
419 .namespace_resolver = &namespace_stack,
420 .source = macro->GetSource()};
421
422 auto new_value = ResourceParser::ParseXml(sub_tree, type_flags, reference.allow_raw, *table,
423 macro_values[0]->config, *context->GetDiagnostics());
424 if (new_value == nullptr) {
425 context->GetDiagnostics()->Error(
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000426 android::DiagMessage(reference.GetSource())
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700427 << "failed to substitute macro "
428 << LoggingResourceName(transformed_reference, callsite, decls)
429 << ": failed to parse contents as one of type(s) " << Attribute::MaskString(type_flags));
430 return {};
431 }
432
433 if (auto ref = ValueCast<Reference>(new_value.get())) {
434 return LinkReference(callsite, *ref, context, symbols, table, decls);
435 }
436 return new_value;
437 }
438
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700439 std::string err_str;
Chris Warrington58e2fbf2018-07-23 14:12:20 +0000440 const SymbolTable::Symbol* s =
Udam Sainib228df32019-06-18 16:50:34 -0700441 ResolveSymbolCheckVisibility(transformed_reference, callsite, context, symbols, &err_str);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700442 if (s) {
443 // The ID may not exist. This is fine because of the possibility of building
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700444 // against libraries without assigned IDs.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700445 // Ex: Linking against own resources when building a static library.
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700446 auto new_ref = std::make_unique<Reference>(reference);
447 new_ref->id = s->id;
448 new_ref->is_dynamic = s->is_dynamic;
449 return std::move(new_ref);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700450 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800451
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000452 context->GetDiagnostics()->Error(android::DiagMessage(reference.GetSource())
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700453 << "resource "
454 << LoggingResourceName(transformed_reference, callsite, decls)
455 << " " << err_str);
456 return {};
Adam Lesinski467f1712015-11-16 17:35:44 -0800457}
458
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700459bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800460 TRACE_NAME("ReferenceLinker::Consume");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700461 EmptyDeclStack decl_stack;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700462 bool error = false;
463 for (auto& package : table->packages) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700464 // Since we're linking, each package must have a name.
465 CHECK(!package->name.empty()) << "all packages being linked must have a name";
466
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700467 for (auto& type : package->types) {
468 for (auto& entry : type->entries) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700469 // First, unmangle the name if necessary.
Iurii Makhnof0c5ff42022-02-22 13:31:02 +0000470 ResourceName name(package->name, type->named_type, entry->name);
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700471 NameMangler::Unmangle(&name.entry, &name.package);
472
473 // Symbol state information may be lost if there is no value for the resource.
Adam Lesinski71be7052017-12-12 16:48:07 -0800474 if (entry->visibility.level != Visibility::Level::kUndefined && entry->values.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000475 context->GetDiagnostics()->Error(android::DiagMessage(entry->visibility.source)
476 << "no definition for declared symbol '" << name << "'");
Ryan Mitchell75e20dd2018-11-06 16:39:36 -0800477 error = true;
478 }
479
480 // Ensure that definitions for values declared as overlayable exist
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800481 if (entry->overlayable_item && entry->values.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000482 context->GetDiagnostics()->Error(
483 android::DiagMessage(entry->overlayable_item.value().source)
484 << "no definition for overlayable symbol '" << name << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700485 error = true;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700486 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700487
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700488 // The context of this resource is the package in which it is defined.
489 const CallSite callsite{name.package};
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700490 ReferenceLinkerTransformer reference_transformer(callsite, context,
491 context->GetExternalSymbols(),
492 &table->string_pool, table, &decl_stack);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700493
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700494 for (auto& config_value : entry->values) {
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700495 config_value->value = config_value->value->Transform(reference_transformer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700496 }
497
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700498 if (reference_transformer.HasError()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700499 error = true;
500 }
501 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700502 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700503 }
504 return !error;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700505}
506
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700507} // namespace aapt