AAPT2: Add descriptions of Attributes in Styleables for R.java
Change-Id: I69e7b73cbdfe4baf502348397435c501ae29ff5e
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index a8f9bfe..eaaf06f 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -51,6 +51,11 @@
// doesn't support unique_ptr.
std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
mCache.put(name, sharedSymbol);
+
+ if (sharedSymbol->id) {
+ // The symbol has an ID, so we can also cache this!
+ mIdCache.put(sharedSymbol->id.value(), sharedSymbol);
+ }
return sharedSymbol.get();
}
}
@@ -76,6 +81,25 @@
return nullptr;
}
+const SymbolTable::Symbol* SymbolTable::findByReference(const Reference& ref) {
+ // First try the ID. This is because when we lookup by ID, we only fill in the ID cache.
+ // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed
+ // ID lookup, then a successfull name lookup. Subsequent look ups will hit immediately
+ // because the ID is cached too.
+ //
+ // If we looked up by name first, a cache miss would mean we failed to lookup by name, then
+ // succeeded to lookup by ID. Subsequent lookups will miss then hit.
+ const SymbolTable::Symbol* symbol = nullptr;
+ if (ref.id) {
+ symbol = findById(ref.id.value());
+ }
+
+ if (ref.name && !symbol) {
+ symbol = findByName(ref.name.value());
+ }
+ return symbol;
+}
+
std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::findByName(
const ResourceName& name) {
Maybe<ResourceTable::SearchResult> result = mTable->findResource(name);
@@ -102,7 +126,7 @@
if (configValue) {
// This resource has an Attribute.
if (Attribute* attr = valueCast<Attribute>(configValue->value.get())) {
- symbol->attribute = util::make_unique<Attribute>(*attr);
+ symbol->attribute = std::make_shared<Attribute>(*attr);
} else {
return {};
}
@@ -133,7 +157,7 @@
// Check to see if it is an attribute.
for (size_t i = 0; i < (size_t) count; i++) {
if (entry[i].map.name.ident == android::ResTable_map::ATTR_TYPE) {
- s->attribute = util::make_unique<Attribute>(false);
+ s->attribute = std::make_shared<Attribute>(false);
s->attribute->typeMask = entry[i].map.value.data;
break;
}
@@ -272,4 +296,15 @@
return {};
}
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByReference(
+ const Reference& ref) {
+ // AssetManager always prefers IDs.
+ if (ref.id) {
+ return findById(ref.id.value());
+ } else if (ref.name) {
+ return findByName(ref.name.value());
+ }
+ return {};
+}
+
} // namespace aapt
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 8ea1c75..0a6a4a5 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -52,7 +52,7 @@
public:
struct Symbol {
Maybe<ResourceId> id;
- std::unique_ptr<Attribute> attribute;
+ std::shared_ptr<Attribute> attribute;
bool isPublic;
};
@@ -69,6 +69,12 @@
const Symbol* findByName(const ResourceName& name);
const Symbol* findById(ResourceId id);
+ /**
+ * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
+ * are available.
+ */
+ const Symbol* findByReference(const Reference& ref);
+
private:
std::vector<std::unique_ptr<ISymbolSource>> mSources;
@@ -90,6 +96,18 @@
virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
+
+ /**
+ * Default implementation tries the name if it exists, else the ID.
+ */
+ virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) {
+ if (ref.name) {
+ return findByName(ref.name.value());
+ } else if (ref.id) {
+ return findById(ref.id.value());
+ }
+ return {};
+ }
};
/**
@@ -122,6 +140,7 @@
std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
+ std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override;
private:
android::AssetManager mAssets;