diff options
Diffstat (limited to 'tools/aapt2/ResourceParser.cpp')
-rw-r--r-- | tools/aapt2/ResourceParser.cpp | 112 |
1 files changed, 65 insertions, 47 deletions
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index a447cef6dbbb..24c60b740bc3 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -42,6 +42,10 @@ using ::android::StringPiece; using android::idmap2::policy::kPolicyStringToFlag; namespace aapt { +namespace { +constexpr const char* kPublicGroupTag = "public-group"; +constexpr const char* kStagingPublicGroupTag = "staging-public-group"; +} // namespace constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2"; @@ -102,6 +106,7 @@ struct ParsedResource { ResourceId id; Visibility::Level visibility_level = Visibility::Level::kUndefined; + bool staged_api = false; bool allow_new = false; Maybe<OverlayableItem> overlayable_item; @@ -122,6 +127,7 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed if (res->visibility_level != Visibility::Level::kUndefined) { Visibility visibility; visibility.level = res->visibility_level; + visibility.staged_api = res->staged_api; visibility.source = res->source; visibility.comment = res->comment; res_builder.SetVisibility(visibility); @@ -525,6 +531,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, {"plurals", std::mem_fn(&ResourceParser::ParsePlural)}, {"public", std::mem_fn(&ResourceParser::ParsePublic)}, {"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)}, + {"staging-public-group", std::mem_fn(&ResourceParser::ParseStagingPublicGroup)}, {"string-array", std::mem_fn(&ResourceParser::ParseStringArray)}, {"style", std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kStyle, std::placeholders::_2, std::placeholders::_3)}, @@ -653,7 +660,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, const auto bag_iter = elToBagMap.find(resource_type); if (bag_iter != elToBagMap.end()) { // Ensure we have a name (unless this is a <public-group> or <overlayable>). - if (resource_type != "public-group" && resource_type != "overlayable") { + if (resource_type != kPublicGroupTag && resource_type != kStagingPublicGroupTag && + resource_type != "overlayable") { if (!maybe_name) { diag_->Error(DiagMessage(out_resource->source) << "<" << parser->element_name() << "> missing 'name' attribute"); @@ -890,54 +898,45 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out return true; } -bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource) { - if (options_.visibility) { - diag_->Error(DiagMessage(out_resource->source) - << "<public-group> tag not allowed with --visibility flag"); - return false; - } - +template <typename Func> +bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, + const char* tag_name, IDiagnostics* diag, Func&& func) { if (out_resource->config != ConfigDescription::DefaultConfig()) { - diag_->Warn(DiagMessage(out_resource->source) - << "ignoring configuration '" << out_resource->config - << "' for <public-group> tag"); + diag->Warn(DiagMessage(out_resource->source) + << "ignoring configuration '" << out_resource->config << "' for <" << tag_name + << "> tag"); } Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type"); if (!maybe_type) { - diag_->Error(DiagMessage(out_resource->source) - << "<public-group> must have a 'type' attribute"); + diag->Error(DiagMessage(out_resource->source) + << "<" << tag_name << "> must have a 'type' attribute"); return false; } const ResourceType* parsed_type = ParseResourceType(maybe_type.value()); if (!parsed_type) { - diag_->Error(DiagMessage(out_resource->source) << "invalid resource type '" - << maybe_type.value() - << "' in <public-group>"); + diag->Error(DiagMessage(out_resource->source) + << "invalid resource type '" << maybe_type.value() << "' in <" << tag_name << ">"); return false; } - Maybe<StringPiece> maybe_id_str = - xml::FindNonEmptyAttribute(parser, "first-id"); + Maybe<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "first-id"); if (!maybe_id_str) { - diag_->Error(DiagMessage(out_resource->source) - << "<public-group> must have a 'first-id' attribute"); + diag->Error(DiagMessage(out_resource->source) + << "<" << tag_name << "> must have a 'first-id' attribute"); return false; } - Maybe<ResourceId> maybe_id = - ResourceUtils::ParseResourceId(maybe_id_str.value()); + Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(maybe_id_str.value()); if (!maybe_id) { - diag_->Error(DiagMessage(out_resource->source) << "invalid resource ID '" - << maybe_id_str.value() - << "' in <public-group>"); + diag->Error(DiagMessage(out_resource->source) + << "invalid resource ID '" << maybe_id_str.value() << "' in <" << tag_name << ">"); return false; } - ResourceId next_id = maybe_id.value(); - std::string comment; + ResourceId next_id = maybe_id.value(); bool error = false; const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { @@ -949,53 +948,72 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource continue; } - const Source item_source = source_.WithLine(parser->line_number()); + const Source item_source = out_resource->source.WithLine(parser->line_number()); const std::string& element_namespace = parser->element_namespace(); const std::string& element_name = parser->element_name(); if (element_namespace.empty() && element_name == "public") { - Maybe<StringPiece> maybe_name = - xml::FindNonEmptyAttribute(parser, "name"); + auto maybe_name = xml::FindNonEmptyAttribute(parser, "name"); if (!maybe_name) { - diag_->Error(DiagMessage(item_source) - << "<public> must have a 'name' attribute"); + diag->Error(DiagMessage(item_source) << "<public> must have a 'name' attribute"); error = true; continue; } if (xml::FindNonEmptyAttribute(parser, "id")) { - diag_->Error(DiagMessage(item_source) - << "'id' is ignored within <public-group>"); + diag->Error(DiagMessage(item_source) << "'id' is ignored within <" << tag_name << ">"); error = true; continue; } if (xml::FindNonEmptyAttribute(parser, "type")) { - diag_->Error(DiagMessage(item_source) - << "'type' is ignored within <public-group>"); + diag->Error(DiagMessage(item_source) << "'type' is ignored within <" << tag_name << ">"); error = true; continue; } - ParsedResource child_resource; - child_resource.name.type = *parsed_type; - child_resource.name.entry = maybe_name.value().to_string(); - child_resource.id = next_id; - // NOLINTNEXTLINE(bugprone-use-after-move) move+reset comment - child_resource.comment = std::move(comment); - child_resource.source = item_source; - child_resource.visibility_level = Visibility::Level::kPublic; - out_resource->child_resources.push_back(std::move(child_resource)); + ParsedResource& entry_res = out_resource->child_resources.emplace_back(ParsedResource{ + .name = ResourceName{{}, *parsed_type, maybe_name.value().to_string()}, + .source = item_source, + .id = next_id, + .comment = std::move(comment), + }); - next_id.id += 1; + // Execute group specific code. + func(entry_res, next_id); + next_id.id++; } else if (!ShouldIgnoreElement(element_namespace, element_name)) { - diag_->Error(DiagMessage(item_source) << ":" << element_name << ">"); + diag->Error(DiagMessage(item_source) << ":" << element_name << ">"); error = true; } } return !error; } +bool ResourceParser::ParseStagingPublicGroup(xml::XmlPullParser* parser, + ParsedResource* out_resource) { + return ParseGroupImpl(parser, out_resource, kStagingPublicGroupTag, diag_, + [](ParsedResource& parsed_entry, ResourceId id) { + parsed_entry.id = id; + parsed_entry.staged_api = true; + parsed_entry.visibility_level = Visibility::Level::kPublic; + }); +} + +bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource) { + if (options_.visibility) { + diag_->Error(DiagMessage(out_resource->source) + << "<" << kPublicGroupTag << "> tag not allowed with --visibility flag"); + return false; + } + + return ParseGroupImpl(parser, out_resource, kPublicGroupTag, diag_, + [](ParsedResource& parsed_entry, ResourceId id) { + parsed_entry.id = id; + parsed_entry.visibility_level = Visibility::Level::kPublic; + }); +} + bool ResourceParser::ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource) { Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type"); |