summaryrefslogtreecommitdiff
path: root/tools/aapt2/ResourceParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/aapt2/ResourceParser.cpp')
-rw-r--r--tools/aapt2/ResourceParser.cpp110
1 files changed, 85 insertions, 25 deletions
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 24c60b740bc3..1efabbb46fd5 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -627,6 +627,16 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
}
return true;
+ } else if (resource_type == "macro") {
+ if (!maybe_name) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<" << parser->element_name() << "> missing 'name' attribute");
+ return false;
+ }
+
+ out_resource->name.type = ResourceType::kMacro;
+ out_resource->name.entry = maybe_name.value().to_string();
+ return ParseMacro(parser, out_resource);
}
if (can_be_item) {
@@ -726,6 +736,24 @@ bool ResourceParser::ParseItem(xml::XmlPullParser* parser,
return true;
}
+std::optional<FlattenedXmlSubTree> ResourceParser::CreateFlattenSubTree(
+ xml::XmlPullParser* parser) {
+ const size_t begin_xml_line = parser->line_number();
+
+ std::string raw_value;
+ StyleString style_string;
+ std::vector<UntranslatableSection> untranslatable_sections;
+ if (!FlattenXmlSubtree(parser, &raw_value, &style_string, &untranslatable_sections)) {
+ return {};
+ }
+
+ return FlattenedXmlSubTree{.raw_value = raw_value,
+ .style_string = style_string,
+ .untranslatable_sections = untranslatable_sections,
+ .namespace_resolver = parser,
+ .source = source_.WithLine(begin_xml_line)};
+}
+
/**
* Reads the entire XML subtree and attempts to parse it as some Item,
* with typeMask denoting which items it can be. If allowRawValue is
@@ -733,42 +761,46 @@ bool ResourceParser::ParseItem(xml::XmlPullParser* parser,
* an Item. If allowRawValue is false, nullptr is returned in this
* case.
*/
-std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser,
- const uint32_t type_mask,
+std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser, const uint32_t type_mask,
const bool allow_raw_value) {
- const size_t begin_xml_line = parser->line_number();
-
- std::string raw_value;
- StyleString style_string;
- std::vector<UntranslatableSection> untranslatable_sections;
- if (!FlattenXmlSubtree(parser, &raw_value, &style_string, &untranslatable_sections)) {
+ auto sub_tree = CreateFlattenSubTree(parser);
+ if (!sub_tree.has_value()) {
return {};
}
+ return ParseXml(sub_tree.value(), type_mask, allow_raw_value, *table_, config_, *diag_);
+}
- if (!style_string.spans.empty()) {
+std::unique_ptr<Item> ResourceParser::ParseXml(const FlattenedXmlSubTree& xmlsub_tree,
+ const uint32_t type_mask, const bool allow_raw_value,
+ ResourceTable& table,
+ const android::ConfigDescription& config,
+ IDiagnostics& diag) {
+ if (!xmlsub_tree.style_string.spans.empty()) {
// This can only be a StyledString.
std::unique_ptr<StyledString> styled_string =
- util::make_unique<StyledString>(table_->string_pool.MakeRef(
- style_string, StringPool::Context(StringPool::Context::kNormalPriority, config_)));
- styled_string->untranslatable_sections = std::move(untranslatable_sections);
+ util::make_unique<StyledString>(table.string_pool.MakeRef(
+ xmlsub_tree.style_string,
+ StringPool::Context(StringPool::Context::kNormalPriority, config)));
+ styled_string->untranslatable_sections = xmlsub_tree.untranslatable_sections;
return std::move(styled_string);
}
auto on_create_reference = [&](const ResourceName& name) {
// name.package can be empty here, as it will assume the package name of the
// table.
- std::unique_ptr<Id> id = util::make_unique<Id>();
- id->SetSource(source_.WithLine(begin_xml_line));
- table_->AddResource(NewResourceBuilder(name).SetValue(std::move(id)).Build(), diag_);
+ auto id = util::make_unique<Id>();
+ id->SetSource(xmlsub_tree.source);
+ return table.AddResource(NewResourceBuilder(name).SetValue(std::move(id)).Build(), &diag);
};
// Process the raw value.
- std::unique_ptr<Item> processed_item =
- ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference);
+ std::unique_ptr<Item> processed_item = ResourceUtils::TryParseItemForAttribute(
+ xmlsub_tree.raw_value, type_mask, on_create_reference);
if (processed_item) {
// Fix up the reference.
- if (Reference* ref = ValueCast<Reference>(processed_item.get())) {
- ResolvePackage(parser, ref);
+ if (auto ref = ValueCast<Reference>(processed_item.get())) {
+ ref->allow_raw = allow_raw_value;
+ ResolvePackage(xmlsub_tree.namespace_resolver, ref);
}
return processed_item;
}
@@ -777,17 +809,16 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser,
if (type_mask & android::ResTable_map::TYPE_STRING) {
// Use the trimmed, escaped string.
std::unique_ptr<String> string = util::make_unique<String>(
- table_->string_pool.MakeRef(style_string.str, StringPool::Context(config_)));
- string->untranslatable_sections = std::move(untranslatable_sections);
+ table.string_pool.MakeRef(xmlsub_tree.style_string.str, StringPool::Context(config)));
+ string->untranslatable_sections = xmlsub_tree.untranslatable_sections;
return std::move(string);
}
if (allow_raw_value) {
// We can't parse this so return a RawString if we are allowed.
- return util::make_unique<RawString>(
- table_->string_pool.MakeRef(util::TrimWhitespace(raw_value),
- StringPool::Context(config_)));
- } else if (util::TrimWhitespace(raw_value).empty()) {
+ return util::make_unique<RawString>(table.string_pool.MakeRef(
+ util::TrimWhitespace(xmlsub_tree.raw_value), StringPool::Context(config)));
+ } else if (util::TrimWhitespace(xmlsub_tree.raw_value).empty()) {
// If the text is empty, and the value is not allowed to be a string, encode it as a @null.
return ResourceUtils::MakeNull();
}
@@ -850,6 +881,35 @@ bool ResourceParser::ParseString(xml::XmlPullParser* parser,
return true;
}
+bool ResourceParser::ParseMacro(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+ auto sub_tree = CreateFlattenSubTree(parser);
+ if (!sub_tree) {
+ return false;
+ }
+
+ if (out_resource->config != ConfigDescription::DefaultConfig()) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<macro> tags cannot be declared in configurations other than the default "
+ "configuration'");
+ return false;
+ }
+
+ auto macro = std::make_unique<Macro>();
+ macro->raw_value = std::move(sub_tree->raw_value);
+ macro->style_string = std::move(sub_tree->style_string);
+ macro->untranslatable_sections = std::move(sub_tree->untranslatable_sections);
+
+ for (const auto& decl : parser->package_decls()) {
+ macro->alias_namespaces.emplace_back(
+ Macro::Namespace{.alias = decl.prefix,
+ .package_name = decl.package.package,
+ .is_private = decl.package.private_namespace});
+ }
+
+ out_resource->value = std::move(macro);
+ return true;
+}
+
bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) {
if (options_.visibility) {
diag_->Error(DiagMessage(out_resource->source)