AAPT2: Fixup namespace implementation

A few pieces were missing in the namespace mangling implementation.
Namespace aware libraries now work, along with R class generation.

Bug: 64706588
Test: make AaptTestNamespace_App
Change-Id: I12f78d6aa909e782c0faf7ceaa36058f2e6c864a
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 414e56e..71e828b 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -30,23 +30,18 @@
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
-using android::StringPiece;
+using ::android::StringPiece;
 
 namespace aapt {
 
 namespace {
 
-/**
- * The ReferenceLinkerVisitor will follow all references and make sure they
- * point
- * to resources that actually exist, either in the local resource table, or as
- * external
- * symbols. Once the target resource has been found, the ID of the resource will
- * be assigned
- * to the reference object.
- *
- * NOTE: All of the entries in the ResourceTable must be assigned IDs.
- */
+// The ReferenceLinkerVisitor will follow all references and make sure they point
+// to resources that actually exist, either in the local resource table, or as external
+// symbols. Once the target resource has been found, the ID of the resource will be assigned
+// to the reference object.
+//
+// NOTE: All of the entries in the ResourceTable must be assigned IDs.
 class ReferenceLinkerVisitor : public ValueVisitor {
  public:
   using ValueVisitor::Visit;
@@ -65,14 +60,9 @@
     }
   }
 
-  /**
-   * We visit the Style specially because during this phase, values of
-   * attributes are
-   * all RawString values. Now that we are expected to resolve all symbols, we
-   * can
-   * lookup the attributes to find out which types are allowed for the
-   * attributes' values.
-   */
+  // We visit the Style specially because during this phase, values of attributes are
+  // all RawString values. Now that we are expected to resolve all symbols, we can
+  // lookup the attributes to find out which types are allowed for the attributes' values.
   void Visit(Style* style) override {
     if (style->parent) {
       Visit(&style->parent.value());
@@ -81,28 +71,21 @@
     for (Style::Entry& entry : style->entries) {
       std::string err_str;
 
-      // Transform the attribute reference so that it is using the fully
-      // qualified package
-      // name. This will also mark the reference as being able to see private
-      // resources if
-      // there was a '*' in the reference or if the package came from the
-      // private namespace.
+      // Transform the attribute reference so that it is using the fully qualified package
+      // name. This will also mark the reference as being able to see private resources if
+      // there was a '*' in the reference or if the package came from the private namespace.
       Reference transformed_reference = entry.key;
-      TransformReferenceFromNamespace(package_decls_,
-                                      context_->GetCompilationPackage(),
-                                      &transformed_reference);
+      ResolvePackage(package_decls_, &transformed_reference);
 
-      // Find the attribute in the symbol table and check if it is visible from
-      // this callsite.
+      // Find the attribute in the symbol table and check if it is visible from this callsite.
       const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility(
           transformed_reference, callsite_, symbols_, &err_str);
       if (symbol) {
-        // Assign our style key the correct ID.
-        // The ID may not exist.
+        // Assign our style key the correct ID. The ID may not exist.
         entry.key.id = symbol->id;
 
-        // Try to convert the value to a more specific, typed value based on the
-        // attribute it is set to.
+        // Try to convert the value to a more specific, typed value based on the attribute it is
+        // set to.
         entry.value = ParseValueWithAttribute(std::move(entry.value), symbol->attribute.get());
 
         // Link/resolve the final value (mostly if it's a reference).
@@ -115,8 +98,8 @@
           // The actual type of this item is incompatible with the attribute.
           DiagMessage msg(entry.key.GetSource());
 
-          // Call the matches method again, this time with a DiagMessage so we
-          // fill in the actual error message.
+          // Call the matches method again, this time with a DiagMessage so we fill in the actual
+          // error message.
           symbol->attribute->Matches(*entry.value, &msg);
           context_->GetDiagnostics()->Error(msg);
           error_ = true;
@@ -125,7 +108,7 @@
       } else {
         DiagMessage msg(entry.key.GetSource());
         msg << "style attribute '";
-        ReferenceLinker::WriteResourceName(&msg, entry.key, transformed_reference);
+        ReferenceLinker::WriteResourceName(entry.key, callsite_, package_decls_, &msg);
         msg << "' " << err_str;
         context_->GetDiagnostics()->Error(msg);
         error_ = true;
@@ -133,17 +116,15 @@
     }
   }
 
-  bool HasError() { return error_; }
+  bool HasError() {
+    return error_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ReferenceLinkerVisitor);
 
-  /**
-   * Transform a RawString value into a more specific, appropriate value, based
-   * on the
-   * Attribute. If a non RawString value is passed in, this is an identity
-   * transform.
-   */
+  // Transform a RawString value into a more specific, appropriate value, based on the
+  // Attribute. If a non RawString value is passed in, this is an identity transform.
   std::unique_ptr<Item> ParseValueWithAttribute(std::unique_ptr<Item> value,
                                                 const Attribute* attr) {
     if (RawString* raw_string = ValueCast<RawString>(value.get())) {
@@ -178,11 +159,9 @@
  public:
   EmptyDeclStack() = default;
 
-  Maybe<xml::ExtractedPackage> TransformPackageAlias(
-      const StringPiece& alias,
-      const StringPiece& local_package) const override {
+  Maybe<xml::ExtractedPackage> TransformPackageAlias(const StringPiece& alias) const override {
     if (alias.empty()) {
-      return xml::ExtractedPackage{local_package.to_string(), true /* private */};
+      return xml::ExtractedPackage{{}, true /*private*/};
     }
     return {};
   }
@@ -191,32 +170,44 @@
   DISALLOW_COPY_AND_ASSIGN(EmptyDeclStack);
 };
 
-}  // namespace
-
-/**
- * The symbol is visible if it is public, or if the reference to it is
- * requesting private access
- * or if the callsite comes from the same package.
- */
-bool ReferenceLinker::IsSymbolVisible(const SymbolTable::Symbol& symbol,
-                                      const Reference& ref,
-                                      const CallSite& callsite) {
-  if (!symbol.is_public && !ref.private_reference) {
-    if (ref.name) {
-      return callsite.resource.package == ref.name.value().package;
-    } else if (ref.id && symbol.id) {
-      return ref.id.value().package_id() == symbol.id.value().package_id();
-    } else {
-      return false;
-    }
+// The symbol is visible if it is public, or if the reference to it is requesting private access
+// or if the callsite comes from the same package.
+bool IsSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
+                     const CallSite& callsite) {
+  if (symbol.is_public || ref.private_reference) {
+    return true;
   }
-  return true;
+
+  if (ref.name) {
+    const ResourceName& name = ref.name.value();
+    if (name.package.empty()) {
+      // If the symbol was found, and the package is empty, that means it was found in the local
+      // scope, which is always visible (private local).
+      return true;
+    }
+
+    // The symbol is visible if the reference is local to the same package it is defined in.
+    return callsite.package == name.package;
+  }
+
+  if (ref.id && symbol.id) {
+    return ref.id.value().package_id() == symbol.id.value().package_id();
+  }
+  return false;
 }
 
+}  // namespace
+
 const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference,
+                                                          const CallSite& callsite,
                                                           SymbolTable* symbols) {
   if (reference.name) {
-    return symbols->FindByName(reference.name.value());
+    const ResourceName& name = reference.name.value();
+    if (name.package.empty()) {
+      // Use the callsite's package name if no package name was defined.
+      return symbols->FindByName(ResourceName(callsite.package, name.type, name.entry));
+    }
+    return symbols->FindByName(name);
   } else if (reference.id) {
     return symbols->FindById(reference.id.value());
   } else {
@@ -228,7 +219,7 @@
                                                                          const CallSite& callsite,
                                                                          SymbolTable* symbols,
                                                                          std::string* out_error) {
-  const SymbolTable::Symbol* symbol = ResolveSymbol(reference, symbols);
+  const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols);
   if (!symbol) {
     if (out_error) *out_error = "not found";
     return nullptr;
@@ -274,24 +265,62 @@
   return xml::AaptAttribute(*symbol->attribute, symbol->id);
 }
 
-void ReferenceLinker::WriteResourceName(DiagMessage* out_msg,
-                                        const Reference& orig,
-                                        const Reference& transformed) {
+void ReferenceLinker::WriteResourceName(const Reference& ref, const CallSite& callsite,
+                                        const xml::IPackageDeclStack* decls, DiagMessage* out_msg) {
   CHECK(out_msg != nullptr);
+  if (!ref.name) {
+    *out_msg << ref.id.value();
+    return;
+  }
 
-  if (orig.name) {
-    *out_msg << orig.name.value();
-    if (transformed.name.value() != orig.name.value()) {
-      *out_msg << " (aka " << transformed.name.value() << ")";
-    }
-  } else {
-    *out_msg << orig.id.value();
+  *out_msg << ref.name.value();
+
+  Reference fully_qualified = ref;
+  xml::ResolvePackage(decls, &fully_qualified);
+
+  ResourceName& full_name = fully_qualified.name.value();
+  if (full_name.package.empty()) {
+    full_name.package = callsite.package;
+  }
+
+  if (full_name != ref.name.value()) {
+    *out_msg << " (aka " << full_name << ")";
+  }
+}
+
+void ReferenceLinker::WriteAttributeName(const Reference& ref, const CallSite& callsite,
+                                         const xml::IPackageDeclStack* decls,
+                                         DiagMessage* out_msg) {
+  CHECK(out_msg != nullptr);
+  if (!ref.name) {
+    *out_msg << ref.id.value();
+    return;
+  }
+
+  const ResourceName& ref_name = ref.name.value();
+  CHECK_EQ(ref_name.type, ResourceType::kAttr);
+
+  if (!ref_name.package.empty()) {
+    *out_msg << ref_name.package << ":";
+  }
+  *out_msg << ref_name.entry;
+
+  Reference fully_qualified = ref;
+  xml::ResolvePackage(decls, &fully_qualified);
+
+  ResourceName& full_name = fully_qualified.name.value();
+  if (full_name.package.empty()) {
+    full_name.package = callsite.package;
+  }
+
+  if (full_name != ref.name.value()) {
+    *out_msg << " (aka " << full_name.package << ":" << full_name.entry << ")";
   }
 }
 
 bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* reference,
                                     IAaptContext* context, SymbolTable* symbols,
-                                    xml::IPackageDeclStack* decls) {
+                                    const xml::IPackageDeclStack* decls) {
   CHECK(reference != nullptr);
   if (!reference->name && !reference->id) {
     // This is @null.
@@ -299,7 +328,7 @@
   }
 
   Reference transformed_reference = *reference;
-  TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference);
+  xml::ResolvePackage(decls, &transformed_reference);
 
   std::string err_str;
   const SymbolTable::Symbol* s =
@@ -314,7 +343,7 @@
 
   DiagMessage error_msg(reference->GetSource());
   error_msg << "resource ";
-  WriteResourceName(&error_msg, *reference, transformed_reference);
+  WriteResourceName(*reference, callsite, decls, &error_msg);
   error_msg << " " << err_str;
   context->GetDiagnostics()->Error(error_msg);
   return false;
@@ -324,21 +353,24 @@
   EmptyDeclStack decl_stack;
   bool error = false;
   for (auto& package : table->packages) {
+    // Since we're linking, each package must have a name.
+    CHECK(!package->name.empty()) << "all packages being linked must have a name";
+
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
-        // Symbol state information may be lost if there is no value for the
-        // resource.
-        if (entry->symbol_status.state != SymbolState::kUndefined &&
-            entry->values.empty()) {
-          context->GetDiagnostics()->Error(
-              DiagMessage(entry->symbol_status.source)
-              << "no definition for declared symbol '"
-              << ResourceNameRef(package->name, type->type, entry->name)
-              << "'");
+        // First, unmangle the name if necessary.
+        ResourceName name(package->name, type->type, entry->name);
+        NameMangler::Unmangle(&name.entry, &name.package);
+
+        // Symbol state information may be lost if there is no value for the resource.
+        if (entry->symbol_status.state != SymbolState::kUndefined && entry->values.empty()) {
+          context->GetDiagnostics()->Error(DiagMessage(entry->symbol_status.source)
+                                           << "no definition for declared symbol '" << name << "'");
           error = true;
         }
 
-        CallSite callsite = {ResourceNameRef(package->name, type->type, entry->name)};
+        // The context of this resource is the package in which it is defined.
+        const CallSite callsite{name.package};
         ReferenceLinkerVisitor visitor(callsite, context, context->GetExternalSymbols(),
                                        &table->string_pool, &decl_stack);