diff options
Diffstat (limited to 'tools/aapt2/ResourceParser.cpp')
-rw-r--r-- | tools/aapt2/ResourceParser.cpp | 110 |
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) |