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