AAPT2: Support id reference chaining from AAPT

AAPT would allow for ids to be declared in the form:

<item name="name" type="id>@id/other</item>

@id/name should hold a reference to @id/other. When
getResources().getValue() is called on R.id.name with resolveRefs
enabled, the resuling reference should be R.id.other.

Bug: 69445910
Test: Created tests for correct parsing of id references and correct
resolving of deep references

Change-Id: Id1feb37b2565c213dc6a19b4c401906260d7fc14
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 1b6f882..19c6c31 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -586,7 +586,29 @@
 
     out_resource->name.type = ResourceType::kId;
     out_resource->name.entry = maybe_name.value().to_string();
-    out_resource->value = util::make_unique<Id>();
+
+    // Ids either represent a unique resource id or reference another resource id
+    auto item = ParseItem(parser, out_resource, resource_format);
+    if (!item) {
+      return false;
+    }
+
+    String* empty = ValueCast<String>(out_resource->value.get());
+    if (empty && *empty->value == "") {
+      // If no inner element exists, represent a unique identifier
+      out_resource->value = util::make_unique<Id>();
+    } else {
+      // If an inner element exists, the inner element must be a reference to
+      // another resource id
+      Reference* ref = ValueCast<Reference>(out_resource->value.get());
+      if (!ref || ref->name.value().type != ResourceType::kId) {
+        diag_->Error(DiagMessage(out_resource->source)
+                         << "<" << parser->element_name()
+                         << "> inner element must either be a resource reference or empty");
+        return false;
+      }
+    }
+
     return true;
   }