diff options
Diffstat (limited to 'tools/aapt2/link/TableMerger.cpp')
-rw-r--r-- | tools/aapt2/link/TableMerger.cpp | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index e819f51a5634..d777e22fa4b7 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -101,8 +101,18 @@ static bool MergeType(IAaptContext* context, const Source& src, ResourceTableTyp return true; } -static bool MergeEntry(IAaptContext* context, const Source& src, bool overlay, - ResourceEntry* dst_entry, ResourceEntry* src_entry) { +static bool MergeEntry(IAaptContext* context, const Source& src, + ResourceEntry* dst_entry, ResourceEntry* src_entry, + bool strict_visibility) { + if (strict_visibility + && dst_entry->visibility.level != Visibility::Level::kUndefined + && src_entry->visibility.level != dst_entry->visibility.level) { + context->GetDiagnostics()->Error( + DiagMessage(src) << "cannot merge resource '" << dst_entry->name << "' with conflicting visibilities: " + << "public and private"); + return false; + } + // Copy over the strongest visibility. if (src_entry->visibility.level > dst_entry->visibility.level) { // Only copy the ID if the source is public, or else the ID is meaningless. @@ -124,17 +134,35 @@ static bool MergeEntry(IAaptContext* context, const Source& src, bool overlay, dst_entry->allow_new = std::move(src_entry->allow_new); } - if (src_entry->overlayable) { - if (dst_entry->overlayable && !overlay) { - context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable.value().source) - << "duplicate overlayable declaration for resource '" - << src_entry->name << "'"); - context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable.value().source) - << "previous declaration here"); - return false; + for (auto& src_overlayable : src_entry->overlayable_declarations) { + for (auto& dst_overlayable : dst_entry->overlayable_declarations) { + // An overlayable resource cannot be declared twice with the same policy + if (src_overlayable.policy == dst_overlayable.policy) { + context->GetDiagnostics()->Error(DiagMessage(src_overlayable.source) + << "duplicate overlayable declaration for resource '" + << src_entry->name << "'"); + context->GetDiagnostics()->Error(DiagMessage(dst_overlayable.source) + << "previous declaration here"); + return false; + } + + // An overlayable resource cannot be declared once with a policy and without a policy because + // the policy becomes unused + if (!src_overlayable.policy || !dst_overlayable.policy) { + context->GetDiagnostics()->Error(DiagMessage(src_overlayable.source) + << "overlayable resource '" << src_entry->name + << "' declared once with a policy and once with no " + << "policy"); + context->GetDiagnostics()->Error(DiagMessage(dst_overlayable.source) + << "previous declaration here"); + return false; + } } - dst_entry->overlayable = std::move(src_entry->overlayable); } + + dst_entry->overlayable_declarations.insert(dst_entry->overlayable_declarations.end(), + src_entry->overlayable_declarations.begin(), + src_entry->overlayable_declarations.end()); return true; } @@ -234,7 +262,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, continue; } - if (!MergeEntry(context_, src, overlay, dst_entry, src_entry.get())) { + if (!MergeEntry(context_, src, dst_entry, src_entry.get(), options_.strict_visibility)) { error = true; continue; } @@ -271,8 +299,17 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, dst_config_value->value = std::move(new_file_ref); } else { + Maybe<std::string> original_comment = (dst_config_value->value) + ? dst_config_value->value->GetComment() : Maybe<std::string>(); + dst_config_value->value = std::unique_ptr<Value>( src_config_value->value->Clone(&master_table_->string_pool)); + + // Keep the comment from the original resource and ignore all comments from overlaying + // resources + if (overlay && original_comment) { + dst_config_value->value->SetComment(original_comment.value()); + } } } } |