Use Google3 style guide with .clang-format
Test: style change only, builds ok
Change-Id: I885180e24cb2e7b58cfb4967c3bcb40058ce4078
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index c430c46..51aed13 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -28,445 +28,488 @@
namespace aapt {
-constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
+constexpr const char* sXliffNamespaceUri =
+ "urn:oasis:names:tc:xliff:document:1.2";
/**
- * Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
+ * Returns true if the element is <skip> or <eat-comment> and can be safely
+ * ignored.
*/
-static bool shouldIgnoreElement(const StringPiece& ns, const StringPiece& name) {
- return ns.empty() && (name == "skip" || name == "eat-comment");
+static bool shouldIgnoreElement(const StringPiece& ns,
+ const StringPiece& name) {
+ return ns.empty() && (name == "skip" || name == "eat-comment");
}
static uint32_t parseFormatType(const StringPiece& piece) {
- if (piece == "reference") return android::ResTable_map::TYPE_REFERENCE;
- else if (piece == "string") return android::ResTable_map::TYPE_STRING;
- else if (piece == "integer") return android::ResTable_map::TYPE_INTEGER;
- else if (piece == "boolean") return android::ResTable_map::TYPE_BOOLEAN;
- else if (piece == "color") return android::ResTable_map::TYPE_COLOR;
- else if (piece == "float") return android::ResTable_map::TYPE_FLOAT;
- else if (piece == "dimension") return android::ResTable_map::TYPE_DIMENSION;
- else if (piece == "fraction") return android::ResTable_map::TYPE_FRACTION;
- else if (piece == "enum") return android::ResTable_map::TYPE_ENUM;
- else if (piece == "flags") return android::ResTable_map::TYPE_FLAGS;
- return 0;
+ if (piece == "reference")
+ return android::ResTable_map::TYPE_REFERENCE;
+ else if (piece == "string")
+ return android::ResTable_map::TYPE_STRING;
+ else if (piece == "integer")
+ return android::ResTable_map::TYPE_INTEGER;
+ else if (piece == "boolean")
+ return android::ResTable_map::TYPE_BOOLEAN;
+ else if (piece == "color")
+ return android::ResTable_map::TYPE_COLOR;
+ else if (piece == "float")
+ return android::ResTable_map::TYPE_FLOAT;
+ else if (piece == "dimension")
+ return android::ResTable_map::TYPE_DIMENSION;
+ else if (piece == "fraction")
+ return android::ResTable_map::TYPE_FRACTION;
+ else if (piece == "enum")
+ return android::ResTable_map::TYPE_ENUM;
+ else if (piece == "flags")
+ return android::ResTable_map::TYPE_FLAGS;
+ return 0;
}
static uint32_t parseFormatAttribute(const StringPiece& str) {
- uint32_t mask = 0;
- for (StringPiece part : util::tokenize(str, '|')) {
- StringPiece trimmedPart = util::trimWhitespace(part);
- uint32_t type = parseFormatType(trimmedPart);
- if (type == 0) {
- return 0;
- }
- mask |= type;
+ uint32_t mask = 0;
+ for (StringPiece part : util::tokenize(str, '|')) {
+ StringPiece trimmedPart = util::trimWhitespace(part);
+ uint32_t type = parseFormatType(trimmedPart);
+ if (type == 0) {
+ return 0;
}
- return mask;
+ mask |= type;
+ }
+ return mask;
}
/**
* A parsed resource ready to be added to the ResourceTable.
*/
struct ParsedResource {
- ResourceName name;
- ConfigDescription config;
- std::string product;
- Source source;
- ResourceId id;
- Maybe<SymbolState> symbolState;
- std::string comment;
- std::unique_ptr<Value> value;
- std::list<ParsedResource> childResources;
+ ResourceName name;
+ ConfigDescription config;
+ std::string product;
+ Source source;
+ ResourceId id;
+ Maybe<SymbolState> symbolState;
+ std::string comment;
+ std::unique_ptr<Value> value;
+ std::list<ParsedResource> childResources;
};
// Recursively adds resources to the ResourceTable.
-static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) {
- StringPiece trimmedComment = util::trimWhitespace(res->comment);
- if (trimmedComment.size() != res->comment.size()) {
- // Only if there was a change do we re-assign.
- res->comment = trimmedComment.toString();
- }
+static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag,
+ ParsedResource* res) {
+ StringPiece trimmedComment = util::trimWhitespace(res->comment);
+ if (trimmedComment.size() != res->comment.size()) {
+ // Only if there was a change do we re-assign.
+ res->comment = trimmedComment.toString();
+ }
- if (res->symbolState) {
- Symbol symbol;
- symbol.state = res->symbolState.value();
- symbol.source = res->source;
- symbol.comment = res->comment;
- if (!table->setSymbolState(res->name, res->id, symbol, diag)) {
- return false;
- }
+ if (res->symbolState) {
+ Symbol symbol;
+ symbol.state = res->symbolState.value();
+ symbol.source = res->source;
+ symbol.comment = res->comment;
+ if (!table->setSymbolState(res->name, res->id, symbol, diag)) {
+ return false;
}
+ }
- if (res->value) {
- // Attach the comment, source and config to the value.
- res->value->setComment(std::move(res->comment));
- res->value->setSource(std::move(res->source));
+ if (res->value) {
+ // Attach the comment, source and config to the value.
+ res->value->setComment(std::move(res->comment));
+ res->value->setSource(std::move(res->source));
- if (!table->addResource(res->name, res->id, res->config, res->product,
- std::move(res->value), diag)) {
- return false;
- }
+ if (!table->addResource(res->name, res->id, res->config, res->product,
+ std::move(res->value), diag)) {
+ return false;
}
+ }
- bool error = false;
- for (ParsedResource& child : res->childResources) {
- error |= !addResourcesToTable(table, diag, &child);
- }
- return !error;
+ bool error = false;
+ for (ParsedResource& child : res->childResources) {
+ error |= !addResourcesToTable(table, diag, &child);
+ }
+ return !error;
}
// Convenient aliases for more readable function calls.
-enum {
- kAllowRawString = true,
- kNoRawString = false
-};
+enum { kAllowRawString = true, kNoRawString = false };
-ResourceParser::ResourceParser(IDiagnostics* diag, ResourceTable* table, const Source& source,
+ResourceParser::ResourceParser(IDiagnostics* diag, ResourceTable* table,
+ const Source& source,
const ConfigDescription& config,
- const ResourceParserOptions& options) :
- mDiag(diag), mTable(table), mSource(source), mConfig(config), mOptions(options) {
-}
+ const ResourceParserOptions& options)
+ : mDiag(diag),
+ mTable(table),
+ mSource(source),
+ mConfig(config),
+ mOptions(options) {}
/**
* Build a string from XML that converts nested elements into Span objects.
*/
-bool ResourceParser::flattenXmlSubtree(xml::XmlPullParser* parser, std::string* outRawString,
+bool ResourceParser::flattenXmlSubtree(xml::XmlPullParser* parser,
+ std::string* outRawString,
StyleString* outStyleString) {
- std::vector<Span> spanStack;
+ std::vector<Span> spanStack;
- bool error = false;
- outRawString->clear();
- outStyleString->spans.clear();
- util::StringBuilder builder;
- size_t depth = 1;
- while (xml::XmlPullParser::isGoodEvent(parser->next())) {
- const xml::XmlPullParser::Event event = parser->getEvent();
- if (event == xml::XmlPullParser::Event::kEndElement) {
- if (!parser->getElementNamespace().empty()) {
- // We already warned and skipped the start element, so just skip here too
- continue;
- }
+ bool error = false;
+ outRawString->clear();
+ outStyleString->spans.clear();
+ util::StringBuilder builder;
+ size_t depth = 1;
+ while (xml::XmlPullParser::isGoodEvent(parser->next())) {
+ const xml::XmlPullParser::Event event = parser->getEvent();
+ if (event == xml::XmlPullParser::Event::kEndElement) {
+ if (!parser->getElementNamespace().empty()) {
+ // We already warned and skipped the start element, so just skip here
+ // too
+ continue;
+ }
- depth--;
- if (depth == 0) {
- break;
- }
+ depth--;
+ if (depth == 0) {
+ break;
+ }
- spanStack.back().lastChar = builder.utf16Len() - 1;
- outStyleString->spans.push_back(spanStack.back());
- spanStack.pop_back();
+ spanStack.back().lastChar = builder.utf16Len() - 1;
+ outStyleString->spans.push_back(spanStack.back());
+ spanStack.pop_back();
- } else if (event == xml::XmlPullParser::Event::kText) {
- outRawString->append(parser->getText());
- builder.append(parser->getText());
+ } else if (event == xml::XmlPullParser::Event::kText) {
+ outRawString->append(parser->getText());
+ builder.append(parser->getText());
- } else if (event == xml::XmlPullParser::Event::kStartElement) {
- if (!parser->getElementNamespace().empty()) {
- if (parser->getElementNamespace() != sXliffNamespaceUri) {
- // Only warn if this isn't an xliff namespace.
- mDiag->warn(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "skipping element '"
- << parser->getElementName()
- << "' with unknown namespace '"
- << parser->getElementNamespace()
- << "'");
- }
- continue;
- }
- depth++;
-
- // Build a span object out of the nested element.
- std::string spanName = parser->getElementName();
- const auto endAttrIter = parser->endAttributes();
- for (auto attrIter = parser->beginAttributes(); attrIter != endAttrIter; ++attrIter) {
- spanName += ";";
- spanName += attrIter->name;
- spanName += "=";
- spanName += attrIter->value;
- }
-
- if (builder.utf16Len() > std::numeric_limits<uint32_t>::max()) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "style string '" << builder.str() << "' is too long");
- error = true;
- } else {
- spanStack.push_back(Span{ spanName, static_cast<uint32_t>(builder.utf16Len()) });
- }
-
- } else if (event == xml::XmlPullParser::Event::kComment) {
- // Skip
- } else {
- assert(false);
+ } else if (event == xml::XmlPullParser::Event::kStartElement) {
+ if (!parser->getElementNamespace().empty()) {
+ if (parser->getElementNamespace() != sXliffNamespaceUri) {
+ // Only warn if this isn't an xliff namespace.
+ mDiag->warn(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "skipping element '" << parser->getElementName()
+ << "' with unknown namespace '"
+ << parser->getElementNamespace() << "'");
}
- }
- assert(spanStack.empty() && "spans haven't been fully processed");
+ continue;
+ }
+ depth++;
- outStyleString->str = builder.str();
- return !error;
+ // Build a span object out of the nested element.
+ std::string spanName = parser->getElementName();
+ const auto endAttrIter = parser->endAttributes();
+ for (auto attrIter = parser->beginAttributes(); attrIter != endAttrIter;
+ ++attrIter) {
+ spanName += ";";
+ spanName += attrIter->name;
+ spanName += "=";
+ spanName += attrIter->value;
+ }
+
+ if (builder.utf16Len() > std::numeric_limits<uint32_t>::max()) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "style string '" << builder.str() << "' is too long");
+ error = true;
+ } else {
+ spanStack.push_back(
+ Span{spanName, static_cast<uint32_t>(builder.utf16Len())});
+ }
+
+ } else if (event == xml::XmlPullParser::Event::kComment) {
+ // Skip
+ } else {
+ assert(false);
+ }
+ }
+ assert(spanStack.empty() && "spans haven't been fully processed");
+
+ outStyleString->str = builder.str();
+ return !error;
}
bool ResourceParser::parse(xml::XmlPullParser* parser) {
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip comments and text.
- continue;
- }
-
- if (!parser->getElementNamespace().empty() || parser->getElementName() != "resources") {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "root element must be <resources>");
- return false;
- }
-
- error |= !parseResources(parser);
- break;
- };
-
- if (parser->getEvent() == xml::XmlPullParser::Event::kBadDocument) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "xml parser error: " << parser->getLastError());
- return false;
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip comments and text.
+ continue;
}
- return !error;
+
+ if (!parser->getElementNamespace().empty() ||
+ parser->getElementName() != "resources") {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "root element must be <resources>");
+ return false;
+ }
+
+ error |= !parseResources(parser);
+ break;
+ };
+
+ if (parser->getEvent() == xml::XmlPullParser::Event::kBadDocument) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "xml parser error: " << parser->getLastError());
+ return false;
+ }
+ return !error;
}
bool ResourceParser::parseResources(xml::XmlPullParser* parser) {
- std::set<ResourceName> strippedResources;
+ std::set<ResourceName> strippedResources;
- bool error = false;
- std::string comment;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- const xml::XmlPullParser::Event event = parser->getEvent();
- if (event == xml::XmlPullParser::Event::kComment) {
- comment = parser->getComment();
- continue;
- }
-
- if (event == xml::XmlPullParser::Event::kText) {
- if (!util::trimWhitespace(parser->getText()).empty()) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "plain text not allowed here");
- error = true;
- }
- continue;
- }
-
- assert(event == xml::XmlPullParser::Event::kStartElement);
-
- if (!parser->getElementNamespace().empty()) {
- // Skip unknown namespace.
- continue;
- }
-
- std::string elementName = parser->getElementName();
- if (elementName == "skip" || elementName == "eat-comment") {
- comment = "";
- continue;
- }
-
- ParsedResource parsedResource;
- parsedResource.config = mConfig;
- parsedResource.source = mSource.withLine(parser->getLineNumber());
- parsedResource.comment = std::move(comment);
-
- // Extract the product name if it exists.
- if (Maybe<StringPiece> maybeProduct = xml::findNonEmptyAttribute(parser, "product")) {
- parsedResource.product = maybeProduct.value().toString();
- }
-
- // Parse the resource regardless of product.
- if (!parseResource(parser, &parsedResource)) {
- error = true;
- continue;
- }
-
- if (!addResourcesToTable(mTable, mDiag, &parsedResource)) {
- error = true;
- }
+ bool error = false;
+ std::string comment;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ const xml::XmlPullParser::Event event = parser->getEvent();
+ if (event == xml::XmlPullParser::Event::kComment) {
+ comment = parser->getComment();
+ continue;
}
- // Check that we included at least one variant of each stripped resource.
- for (const ResourceName& strippedResource : strippedResources) {
- if (!mTable->findResource(strippedResource)) {
- // Failed to find the resource.
- mDiag->error(DiagMessage(mSource) << "resource '" << strippedResource << "' "
- "was filtered out but no product variant remains");
- error = true;
- }
+ if (event == xml::XmlPullParser::Event::kText) {
+ if (!util::trimWhitespace(parser->getText()).empty()) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "plain text not allowed here");
+ error = true;
+ }
+ continue;
}
- return !error;
+ assert(event == xml::XmlPullParser::Event::kStartElement);
+
+ if (!parser->getElementNamespace().empty()) {
+ // Skip unknown namespace.
+ continue;
+ }
+
+ std::string elementName = parser->getElementName();
+ if (elementName == "skip" || elementName == "eat-comment") {
+ comment = "";
+ continue;
+ }
+
+ ParsedResource parsedResource;
+ parsedResource.config = mConfig;
+ parsedResource.source = mSource.withLine(parser->getLineNumber());
+ parsedResource.comment = std::move(comment);
+
+ // Extract the product name if it exists.
+ if (Maybe<StringPiece> maybeProduct =
+ xml::findNonEmptyAttribute(parser, "product")) {
+ parsedResource.product = maybeProduct.value().toString();
+ }
+
+ // Parse the resource regardless of product.
+ if (!parseResource(parser, &parsedResource)) {
+ error = true;
+ continue;
+ }
+
+ if (!addResourcesToTable(mTable, mDiag, &parsedResource)) {
+ error = true;
+ }
+ }
+
+ // Check that we included at least one variant of each stripped resource.
+ for (const ResourceName& strippedResource : strippedResources) {
+ if (!mTable->findResource(strippedResource)) {
+ // Failed to find the resource.
+ mDiag->error(DiagMessage(mSource)
+ << "resource '" << strippedResource
+ << "' "
+ "was filtered out but no product variant remains");
+ error = true;
+ }
+ }
+
+ return !error;
}
+bool ResourceParser::parseResource(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ struct ItemTypeFormat {
+ ResourceType type;
+ uint32_t format;
+ };
-bool ResourceParser::parseResource(xml::XmlPullParser* parser, ParsedResource* outResource) {
- struct ItemTypeFormat {
- ResourceType type;
- uint32_t format;
- };
+ using BagParseFunc = std::function<bool(ResourceParser*, xml::XmlPullParser*,
+ ParsedResource*)>;
- using BagParseFunc = std::function<bool(ResourceParser*, xml::XmlPullParser*, ParsedResource*)>;
+ static const auto elToItemMap =
+ ImmutableMap<std::string, ItemTypeFormat>::createPreSorted({
+ {"bool", {ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN}},
+ {"color", {ResourceType::kColor, android::ResTable_map::TYPE_COLOR}},
+ {"dimen",
+ {ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT |
+ android::ResTable_map::TYPE_FRACTION |
+ android::ResTable_map::TYPE_DIMENSION}},
+ {"drawable",
+ {ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR}},
+ {"fraction",
+ {ResourceType::kFraction,
+ android::ResTable_map::TYPE_FLOAT |
+ android::ResTable_map::TYPE_FRACTION |
+ android::ResTable_map::TYPE_DIMENSION}},
+ {"integer",
+ {ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER}},
+ {"string",
+ {ResourceType::kString, android::ResTable_map::TYPE_STRING}},
+ });
- static const auto elToItemMap = ImmutableMap<std::string, ItemTypeFormat>::createPreSorted({
- { "bool", { ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN } },
- { "color", { ResourceType::kColor, android::ResTable_map::TYPE_COLOR } },
- { "dimen", { ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT
- | android::ResTable_map::TYPE_FRACTION
- | android::ResTable_map::TYPE_DIMENSION } },
- { "drawable", { ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR } },
- { "fraction", { ResourceType::kFraction, android::ResTable_map::TYPE_FLOAT
- | android::ResTable_map::TYPE_FRACTION
- | android::ResTable_map::TYPE_DIMENSION } },
- { "integer", { ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER } },
- { "string", { ResourceType::kString, android::ResTable_map::TYPE_STRING } },
- });
+ static const auto elToBagMap =
+ ImmutableMap<std::string, BagParseFunc>::createPreSorted({
+ {"add-resource", std::mem_fn(&ResourceParser::parseAddResource)},
+ {"array", std::mem_fn(&ResourceParser::parseArray)},
+ {"attr", std::mem_fn(&ResourceParser::parseAttr)},
+ {"declare-styleable",
+ std::mem_fn(&ResourceParser::parseDeclareStyleable)},
+ {"integer-array", std::mem_fn(&ResourceParser::parseIntegerArray)},
+ {"java-symbol", std::mem_fn(&ResourceParser::parseSymbol)},
+ {"plurals", std::mem_fn(&ResourceParser::parsePlural)},
+ {"public", std::mem_fn(&ResourceParser::parsePublic)},
+ {"public-group", std::mem_fn(&ResourceParser::parsePublicGroup)},
+ {"string-array", std::mem_fn(&ResourceParser::parseStringArray)},
+ {"style", std::mem_fn(&ResourceParser::parseStyle)},
+ {"symbol", std::mem_fn(&ResourceParser::parseSymbol)},
+ });
- static const auto elToBagMap = ImmutableMap<std::string, BagParseFunc>::createPreSorted({
- { "add-resource", std::mem_fn(&ResourceParser::parseAddResource) },
- { "array", std::mem_fn(&ResourceParser::parseArray) },
- { "attr", std::mem_fn(&ResourceParser::parseAttr) },
- { "declare-styleable", std::mem_fn(&ResourceParser::parseDeclareStyleable) },
- { "integer-array", std::mem_fn(&ResourceParser::parseIntegerArray) },
- { "java-symbol", std::mem_fn(&ResourceParser::parseSymbol) },
- { "plurals", std::mem_fn(&ResourceParser::parsePlural) },
- { "public", std::mem_fn(&ResourceParser::parsePublic) },
- { "public-group", std::mem_fn(&ResourceParser::parsePublicGroup) },
- { "string-array", std::mem_fn(&ResourceParser::parseStringArray) },
- { "style", std::mem_fn(&ResourceParser::parseStyle) },
- { "symbol", std::mem_fn(&ResourceParser::parseSymbol) },
- });
+ std::string resourceType = parser->getElementName();
- std::string resourceType = parser->getElementName();
+ // The value format accepted for this resource.
+ uint32_t resourceFormat = 0u;
- // The value format accepted for this resource.
- uint32_t resourceFormat = 0u;
-
- if (resourceType == "item") {
- // Items have their type encoded in the type attribute.
- if (Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type")) {
- resourceType = maybeType.value().toString();
- } else {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "<item> must have a 'type' attribute");
- return false;
- }
-
- if (Maybe<StringPiece> maybeFormat = xml::findNonEmptyAttribute(parser, "format")) {
- // An explicit format for this resource was specified. The resource will retain
- // its type in its name, but the accepted value for this type is overridden.
- resourceFormat = parseFormatType(maybeFormat.value());
- if (!resourceFormat) {
- mDiag->error(DiagMessage(outResource->source)
- << "'" << maybeFormat.value() << "' is an invalid format");
- return false;
- }
- }
+ if (resourceType == "item") {
+ // Items have their type encoded in the type attribute.
+ if (Maybe<StringPiece> maybeType =
+ xml::findNonEmptyAttribute(parser, "type")) {
+ resourceType = maybeType.value().toString();
+ } else {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "<item> must have a 'type' attribute");
+ return false;
}
- // Get the name of the resource. This will be checked later, because not all
- // XML elements require a name.
- Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
-
- if (resourceType == "id") {
- if (!maybeName) {
- mDiag->error(DiagMessage(outResource->source)
- << "<" << parser->getElementName() << "> missing 'name' attribute");
- return false;
- }
-
- outResource->name.type = ResourceType::kId;
- outResource->name.entry = maybeName.value().toString();
- outResource->value = util::make_unique<Id>();
- return true;
- }
-
- const auto itemIter = elToItemMap.find(resourceType);
- if (itemIter != elToItemMap.end()) {
- // This is an item, record its type and format and start parsing.
-
- if (!maybeName) {
- mDiag->error(DiagMessage(outResource->source)
- << "<" << parser->getElementName() << "> missing 'name' attribute");
- return false;
- }
-
- outResource->name.type = itemIter->second.type;
- outResource->name.entry = maybeName.value().toString();
-
- // Only use the implicit format for this type if it wasn't overridden.
- if (!resourceFormat) {
- resourceFormat = itemIter->second.format;
- }
-
- if (!parseItem(parser, outResource, resourceFormat)) {
- return false;
- }
- return true;
- }
-
- // This might be a bag or something.
- const auto bagIter = elToBagMap.find(resourceType);
- if (bagIter != elToBagMap.end()) {
- // Ensure we have a name (unless this is a <public-group>).
- if (resourceType != "public-group") {
- if (!maybeName) {
- mDiag->error(DiagMessage(outResource->source)
- << "<" << parser->getElementName() << "> missing 'name' attribute");
- return false;
- }
-
- outResource->name.entry = maybeName.value().toString();
- }
-
- // Call the associated parse method. The type will be filled in by the
- // parse func.
- if (!bagIter->second(this, parser, outResource)) {
- return false;
- }
- return true;
- }
-
- // Try parsing the elementName (or type) as a resource. These shall only be
- // resources like 'layout' or 'xml' and they can only be references.
- const ResourceType* parsedType = parseResourceType(resourceType);
- if (parsedType) {
- if (!maybeName) {
- mDiag->error(DiagMessage(outResource->source)
- << "<" << parser->getElementName() << "> missing 'name' attribute");
- return false;
- }
-
- outResource->name.type = *parsedType;
- outResource->name.entry = maybeName.value().toString();
- outResource->value = parseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
- if (!outResource->value) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid value for type '" << *parsedType << "'. Expected a reference");
- return false;
- }
- return true;
- }
-
- mDiag->warn(DiagMessage(outResource->source)
- << "unknown resource type '" << parser->getElementName() << "'");
- return false;
-}
-
-bool ResourceParser::parseItem(xml::XmlPullParser* parser, ParsedResource* outResource,
- const uint32_t format) {
- if (format == android::ResTable_map::TYPE_STRING) {
- return parseString(parser, outResource);
- }
-
- outResource->value = parseXml(parser, format, kNoRawString);
- if (!outResource->value) {
- mDiag->error(DiagMessage(outResource->source) << "invalid " << outResource->name.type);
+ if (Maybe<StringPiece> maybeFormat =
+ xml::findNonEmptyAttribute(parser, "format")) {
+ // An explicit format for this resource was specified. The resource will
+ // retain
+ // its type in its name, but the accepted value for this type is
+ // overridden.
+ resourceFormat = parseFormatType(maybeFormat.value());
+ if (!resourceFormat) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "'" << maybeFormat.value() << "' is an invalid format");
return false;
+ }
+ }
+ }
+
+ // Get the name of the resource. This will be checked later, because not all
+ // XML elements require a name.
+ Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
+
+ if (resourceType == "id") {
+ if (!maybeName) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<" << parser->getElementName()
+ << "> missing 'name' attribute");
+ return false;
+ }
+
+ outResource->name.type = ResourceType::kId;
+ outResource->name.entry = maybeName.value().toString();
+ outResource->value = util::make_unique<Id>();
+ return true;
+ }
+
+ const auto itemIter = elToItemMap.find(resourceType);
+ if (itemIter != elToItemMap.end()) {
+ // This is an item, record its type and format and start parsing.
+
+ if (!maybeName) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<" << parser->getElementName()
+ << "> missing 'name' attribute");
+ return false;
+ }
+
+ outResource->name.type = itemIter->second.type;
+ outResource->name.entry = maybeName.value().toString();
+
+ // Only use the implicit format for this type if it wasn't overridden.
+ if (!resourceFormat) {
+ resourceFormat = itemIter->second.format;
+ }
+
+ if (!parseItem(parser, outResource, resourceFormat)) {
+ return false;
}
return true;
+ }
+
+ // This might be a bag or something.
+ const auto bagIter = elToBagMap.find(resourceType);
+ if (bagIter != elToBagMap.end()) {
+ // Ensure we have a name (unless this is a <public-group>).
+ if (resourceType != "public-group") {
+ if (!maybeName) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<" << parser->getElementName()
+ << "> missing 'name' attribute");
+ return false;
+ }
+
+ outResource->name.entry = maybeName.value().toString();
+ }
+
+ // Call the associated parse method. The type will be filled in by the
+ // parse func.
+ if (!bagIter->second(this, parser, outResource)) {
+ return false;
+ }
+ return true;
+ }
+
+ // Try parsing the elementName (or type) as a resource. These shall only be
+ // resources like 'layout' or 'xml' and they can only be references.
+ const ResourceType* parsedType = parseResourceType(resourceType);
+ if (parsedType) {
+ if (!maybeName) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<" << parser->getElementName()
+ << "> missing 'name' attribute");
+ return false;
+ }
+
+ outResource->name.type = *parsedType;
+ outResource->name.entry = maybeName.value().toString();
+ outResource->value =
+ parseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
+ if (!outResource->value) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "invalid value for type '" << *parsedType
+ << "'. Expected a reference");
+ return false;
+ }
+ return true;
+ }
+
+ mDiag->warn(DiagMessage(outResource->source)
+ << "unknown resource type '" << parser->getElementName() << "'");
+ return false;
+}
+
+bool ResourceParser::parseItem(xml::XmlPullParser* parser,
+ ParsedResource* outResource,
+ const uint32_t format) {
+ if (format == android::ResTable_map::TYPE_STRING) {
+ return parseString(parser, outResource);
+ }
+
+ outResource->value = parseXml(parser, format, kNoRawString);
+ if (!outResource->value) {
+ mDiag->error(DiagMessage(outResource->source) << "invalid "
+ << outResource->name.type);
+ return false;
+ }
+ return true;
}
/**
@@ -476,771 +519,834 @@
* an Item. If allowRawValue is false, nullptr is returned in this
* case.
*/
-std::unique_ptr<Item> ResourceParser::parseXml(xml::XmlPullParser* parser, const uint32_t typeMask,
+std::unique_ptr<Item> ResourceParser::parseXml(xml::XmlPullParser* parser,
+ const uint32_t typeMask,
const bool allowRawValue) {
- const size_t beginXmlLine = parser->getLineNumber();
+ const size_t beginXmlLine = parser->getLineNumber();
- std::string rawValue;
- StyleString styleString;
- if (!flattenXmlSubtree(parser, &rawValue, &styleString)) {
- return {};
- }
-
- if (!styleString.spans.empty()) {
- // This can only be a StyledString.
- return util::make_unique<StyledString>(
- mTable->stringPool.makeRef(styleString, StringPool::Context{ 1, mConfig }));
- }
-
- auto onCreateReference = [&](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(mSource.withLine(beginXmlLine));
- mTable->addResource(name, {}, {}, std::move(id), mDiag);
- };
-
- // Process the raw value.
- std::unique_ptr<Item> processedItem = ResourceUtils::tryParseItemForAttribute(
- rawValue, typeMask, onCreateReference);
- if (processedItem) {
- // Fix up the reference.
- if (Reference* ref = valueCast<Reference>(processedItem.get())) {
- transformReferenceFromNamespace(parser, "", ref);
- }
- return processedItem;
- }
-
- // Try making a regular string.
- if (typeMask & android::ResTable_map::TYPE_STRING) {
- // Use the trimmed, escaped string.
- return util::make_unique<String>(
- mTable->stringPool.makeRef(styleString.str, StringPool::Context{ 1, mConfig }));
- }
-
- if (allowRawValue) {
- // We can't parse this so return a RawString if we are allowed.
- return util::make_unique<RawString>(
- mTable->stringPool.makeRef(rawValue, StringPool::Context{ 1, mConfig }));
- }
+ std::string rawValue;
+ StyleString styleString;
+ if (!flattenXmlSubtree(parser, &rawValue, &styleString)) {
return {};
+ }
+
+ if (!styleString.spans.empty()) {
+ // This can only be a StyledString.
+ return util::make_unique<StyledString>(mTable->stringPool.makeRef(
+ styleString, StringPool::Context{1, mConfig}));
+ }
+
+ auto onCreateReference = [&](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(mSource.withLine(beginXmlLine));
+ mTable->addResource(name, {}, {}, std::move(id), mDiag);
+ };
+
+ // Process the raw value.
+ std::unique_ptr<Item> processedItem = ResourceUtils::tryParseItemForAttribute(
+ rawValue, typeMask, onCreateReference);
+ if (processedItem) {
+ // Fix up the reference.
+ if (Reference* ref = valueCast<Reference>(processedItem.get())) {
+ transformReferenceFromNamespace(parser, "", ref);
+ }
+ return processedItem;
+ }
+
+ // Try making a regular string.
+ if (typeMask & android::ResTable_map::TYPE_STRING) {
+ // Use the trimmed, escaped string.
+ return util::make_unique<String>(mTable->stringPool.makeRef(
+ styleString.str, StringPool::Context{1, mConfig}));
+ }
+
+ if (allowRawValue) {
+ // We can't parse this so return a RawString if we are allowed.
+ return util::make_unique<RawString>(
+ mTable->stringPool.makeRef(rawValue, StringPool::Context{1, mConfig}));
+ }
+ return {};
}
-bool ResourceParser::parseString(xml::XmlPullParser* parser, ParsedResource* outResource) {
- bool formatted = true;
- if (Maybe<StringPiece> formattedAttr = xml::findAttribute(parser, "formatted")) {
- Maybe<bool> maybeFormatted = ResourceUtils::parseBool(formattedAttr.value());
- if (!maybeFormatted) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid value for 'formatted'. Must be a boolean");
- return false;
- }
- formatted = maybeFormatted.value();
+bool ResourceParser::parseString(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ bool formatted = true;
+ if (Maybe<StringPiece> formattedAttr =
+ xml::findAttribute(parser, "formatted")) {
+ Maybe<bool> maybeFormatted =
+ ResourceUtils::parseBool(formattedAttr.value());
+ if (!maybeFormatted) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "invalid value for 'formatted'. Must be a boolean");
+ return false;
}
+ formatted = maybeFormatted.value();
+ }
- bool translateable = mOptions.translatable;
- if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
- Maybe<bool> maybeTranslateable = ResourceUtils::parseBool(translateableAttr.value());
- if (!maybeTranslateable) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid value for 'translatable'. Must be a boolean");
- return false;
- }
- translateable = maybeTranslateable.value();
+ bool translateable = mOptions.translatable;
+ if (Maybe<StringPiece> translateableAttr =
+ xml::findAttribute(parser, "translatable")) {
+ Maybe<bool> maybeTranslateable =
+ ResourceUtils::parseBool(translateableAttr.value());
+ if (!maybeTranslateable) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "invalid value for 'translatable'. Must be a boolean");
+ return false;
}
+ translateable = maybeTranslateable.value();
+ }
- outResource->value = parseXml(parser, android::ResTable_map::TYPE_STRING, kNoRawString);
- if (!outResource->value) {
- mDiag->error(DiagMessage(outResource->source) << "not a valid string");
- return false;
- }
+ outResource->value =
+ parseXml(parser, android::ResTable_map::TYPE_STRING, kNoRawString);
+ if (!outResource->value) {
+ mDiag->error(DiagMessage(outResource->source) << "not a valid string");
+ return false;
+ }
- if (String* stringValue = valueCast<String>(outResource->value.get())) {
- stringValue->setTranslateable(translateable);
+ if (String* stringValue = valueCast<String>(outResource->value.get())) {
+ stringValue->setTranslateable(translateable);
- if (formatted && translateable) {
- if (!util::verifyJavaStringFormat(*stringValue->value)) {
- DiagMessage msg(outResource->source);
- msg << "multiple substitutions specified in non-positional format; "
- "did you mean to add the formatted=\"false\" attribute?";
- if (mOptions.errorOnPositionalArguments) {
- mDiag->error(msg);
- return false;
- }
-
- mDiag->warn(msg);
- }
+ if (formatted && translateable) {
+ if (!util::verifyJavaStringFormat(*stringValue->value)) {
+ DiagMessage msg(outResource->source);
+ msg << "multiple substitutions specified in non-positional format; "
+ "did you mean to add the formatted=\"false\" attribute?";
+ if (mOptions.errorOnPositionalArguments) {
+ mDiag->error(msg);
+ return false;
}
- } else if (StyledString* stringValue = valueCast<StyledString>(outResource->value.get())) {
- stringValue->setTranslateable(translateable);
+ mDiag->warn(msg);
+ }
}
- return true;
+
+ } else if (StyledString* stringValue =
+ valueCast<StyledString>(outResource->value.get())) {
+ stringValue->setTranslateable(translateable);
+ }
+ return true;
}
-bool ResourceParser::parsePublic(xml::XmlPullParser* parser, ParsedResource* outResource) {
- Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
- if (!maybeType) {
- mDiag->error(DiagMessage(outResource->source) << "<public> must have a 'type' attribute");
- return false;
- }
+bool ResourceParser::parsePublic(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
+ if (!maybeType) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<public> must have a 'type' attribute");
+ return false;
+ }
- const ResourceType* parsedType = parseResourceType(maybeType.value());
- if (!parsedType) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid resource type '" << maybeType.value() << "' in <public>");
- return false;
- }
+ const ResourceType* parsedType = parseResourceType(maybeType.value());
+ if (!parsedType) {
+ mDiag->error(DiagMessage(outResource->source) << "invalid resource type '"
+ << maybeType.value()
+ << "' in <public>");
+ return false;
+ }
- outResource->name.type = *parsedType;
+ outResource->name.type = *parsedType;
- if (Maybe<StringPiece> maybeIdStr = xml::findNonEmptyAttribute(parser, "id")) {
- Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(maybeIdStr.value());
- if (!maybeId) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid resource ID '" << maybeId.value() << "' in <public>");
- return false;
- }
- outResource->id = maybeId.value();
- }
-
- if (*parsedType == ResourceType::kId) {
- // An ID marked as public is also the definition of an ID.
- outResource->value = util::make_unique<Id>();
- }
-
- outResource->symbolState = SymbolState::kPublic;
- return true;
-}
-
-bool ResourceParser::parsePublicGroup(xml::XmlPullParser* parser, ParsedResource* outResource) {
- Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
- if (!maybeType) {
- mDiag->error(DiagMessage(outResource->source)
- << "<public-group> must have a 'type' attribute");
- return false;
- }
-
- const ResourceType* parsedType = parseResourceType(maybeType.value());
- if (!parsedType) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid resource type '" << maybeType.value() << "' in <public-group>");
- return false;
- }
-
- Maybe<StringPiece> maybeIdStr = xml::findNonEmptyAttribute(parser, "first-id");
- if (!maybeIdStr) {
- mDiag->error(DiagMessage(outResource->source)
- << "<public-group> must have a 'first-id' attribute");
- return false;
- }
-
- Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(maybeIdStr.value());
+ if (Maybe<StringPiece> maybeIdStr =
+ xml::findNonEmptyAttribute(parser, "id")) {
+ Maybe<ResourceId> maybeId =
+ ResourceUtils::parseResourceId(maybeIdStr.value());
if (!maybeId) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid resource ID '" << maybeIdStr.value() << "' in <public-group>");
- return false;
+ mDiag->error(DiagMessage(outResource->source) << "invalid resource ID '"
+ << maybeId.value()
+ << "' in <public>");
+ return false;
}
+ outResource->id = maybeId.value();
+ }
- ResourceId nextId = maybeId.value();
+ if (*parsedType == ResourceType::kId) {
+ // An ID marked as public is also the definition of an ID.
+ outResource->value = util::make_unique<Id>();
+ }
- std::string comment;
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
- comment = util::trimWhitespace(parser->getComment()).toString();
- continue;
- } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip text.
- continue;
- }
-
- const Source itemSource = mSource.withLine(parser->getLineNumber());
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace.empty() && elementName == "public") {
- Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
- if (!maybeName) {
- mDiag->error(DiagMessage(itemSource) << "<public> must have a 'name' attribute");
- error = true;
- continue;
- }
-
- if (xml::findNonEmptyAttribute(parser, "id")) {
- mDiag->error(DiagMessage(itemSource) << "'id' is ignored within <public-group>");
- error = true;
- continue;
- }
-
- if (xml::findNonEmptyAttribute(parser, "type")) {
- mDiag->error(DiagMessage(itemSource) << "'type' is ignored within <public-group>");
- error = true;
- continue;
- }
-
- ParsedResource childResource;
- childResource.name.type = *parsedType;
- childResource.name.entry = maybeName.value().toString();
- childResource.id = nextId;
- childResource.comment = std::move(comment);
- childResource.source = itemSource;
- childResource.symbolState = SymbolState::kPublic;
- outResource->childResources.push_back(std::move(childResource));
-
- nextId.id += 1;
-
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");
- error = true;
- }
- }
- return !error;
+ outResource->symbolState = SymbolState::kPublic;
+ return true;
}
-bool ResourceParser::parseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* outResource) {
- Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
- if (!maybeType) {
- mDiag->error(DiagMessage(outResource->source)
- << "<" << parser->getElementName() << "> must have a 'type' attribute");
- return false;
- }
-
- const ResourceType* parsedType = parseResourceType(maybeType.value());
- if (!parsedType) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid resource type '" << maybeType.value()
- << "' in <" << parser->getElementName() << ">");
- return false;
- }
-
- outResource->name.type = *parsedType;
- return true;
-}
-
-bool ResourceParser::parseSymbol(xml::XmlPullParser* parser, ParsedResource* outResource) {
- if (parseSymbolImpl(parser, outResource)) {
- outResource->symbolState = SymbolState::kPrivate;
- return true;
- }
+bool ResourceParser::parsePublicGroup(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
+ if (!maybeType) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<public-group> must have a 'type' attribute");
return false;
-}
+ }
-bool ResourceParser::parseAddResource(xml::XmlPullParser* parser, ParsedResource* outResource) {
- if (parseSymbolImpl(parser, outResource)) {
- outResource->symbolState = SymbolState::kUndefined;
- return true;
- }
+ const ResourceType* parsedType = parseResourceType(maybeType.value());
+ if (!parsedType) {
+ mDiag->error(DiagMessage(outResource->source) << "invalid resource type '"
+ << maybeType.value()
+ << "' in <public-group>");
return false;
+ }
+
+ Maybe<StringPiece> maybeIdStr =
+ xml::findNonEmptyAttribute(parser, "first-id");
+ if (!maybeIdStr) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<public-group> must have a 'first-id' attribute");
+ return false;
+ }
+
+ Maybe<ResourceId> maybeId =
+ ResourceUtils::parseResourceId(maybeIdStr.value());
+ if (!maybeId) {
+ mDiag->error(DiagMessage(outResource->source) << "invalid resource ID '"
+ << maybeIdStr.value()
+ << "' in <public-group>");
+ return false;
+ }
+
+ ResourceId nextId = maybeId.value();
+
+ std::string comment;
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
+ comment = util::trimWhitespace(parser->getComment()).toString();
+ continue;
+ } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip text.
+ continue;
+ }
+
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace.empty() && elementName == "public") {
+ Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
+ if (!maybeName) {
+ mDiag->error(DiagMessage(itemSource)
+ << "<public> must have a 'name' attribute");
+ error = true;
+ continue;
+ }
+
+ if (xml::findNonEmptyAttribute(parser, "id")) {
+ mDiag->error(DiagMessage(itemSource)
+ << "'id' is ignored within <public-group>");
+ error = true;
+ continue;
+ }
+
+ if (xml::findNonEmptyAttribute(parser, "type")) {
+ mDiag->error(DiagMessage(itemSource)
+ << "'type' is ignored within <public-group>");
+ error = true;
+ continue;
+ }
+
+ ParsedResource childResource;
+ childResource.name.type = *parsedType;
+ childResource.name.entry = maybeName.value().toString();
+ childResource.id = nextId;
+ childResource.comment = std::move(comment);
+ childResource.source = itemSource;
+ childResource.symbolState = SymbolState::kPublic;
+ outResource->childResources.push_back(std::move(childResource));
+
+ nextId.id += 1;
+
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");
+ error = true;
+ }
+ }
+ return !error;
}
+bool ResourceParser::parseSymbolImpl(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
+ if (!maybeType) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "<" << parser->getElementName()
+ << "> must have a 'type' attribute");
+ return false;
+ }
-bool ResourceParser::parseAttr(xml::XmlPullParser* parser, ParsedResource* outResource) {
- return parseAttrImpl(parser, outResource, false);
+ const ResourceType* parsedType = parseResourceType(maybeType.value());
+ if (!parsedType) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "invalid resource type '" << maybeType.value() << "' in <"
+ << parser->getElementName() << ">");
+ return false;
+ }
+
+ outResource->name.type = *parsedType;
+ return true;
}
-bool ResourceParser::parseAttrImpl(xml::XmlPullParser* parser, ParsedResource* outResource,
- bool weak) {
- outResource->name.type = ResourceType::kAttr;
-
- // Attributes only end up in default configuration.
- if (outResource->config != ConfigDescription::defaultConfig()) {
- mDiag->warn(DiagMessage(outResource->source) << "ignoring configuration '"
- << outResource->config << "' for attribute " << outResource->name);
- outResource->config = ConfigDescription::defaultConfig();
- }
-
- uint32_t typeMask = 0;
-
- Maybe<StringPiece> maybeFormat = xml::findAttribute(parser, "format");
- if (maybeFormat) {
- typeMask = parseFormatAttribute(maybeFormat.value());
- if (typeMask == 0) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "invalid attribute format '" << maybeFormat.value() << "'");
- return false;
- }
- }
-
- Maybe<int32_t> maybeMin, maybeMax;
-
- if (Maybe<StringPiece> maybeMinStr = xml::findAttribute(parser, "min")) {
- StringPiece minStr = util::trimWhitespace(maybeMinStr.value());
- if (!minStr.empty()) {
- std::u16string minStr16 = util::utf8ToUtf16(minStr);
- android::Res_value value;
- if (android::ResTable::stringToInt(minStr16.data(), minStr16.size(), &value)) {
- maybeMin = static_cast<int32_t>(value.data);
- }
- }
-
- if (!maybeMin) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "invalid 'min' value '" << minStr << "'");
- return false;
- }
- }
-
- if (Maybe<StringPiece> maybeMaxStr = xml::findAttribute(parser, "max")) {
- StringPiece maxStr = util::trimWhitespace(maybeMaxStr.value());
- if (!maxStr.empty()) {
- std::u16string maxStr16 = util::utf8ToUtf16(maxStr);
- android::Res_value value;
- if (android::ResTable::stringToInt(maxStr16.data(), maxStr16.size(), &value)) {
- maybeMax = static_cast<int32_t>(value.data);
- }
- }
-
- if (!maybeMax) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "invalid 'max' value '" << maxStr << "'");
- return false;
- }
- }
-
- if ((maybeMin || maybeMax) && (typeMask & android::ResTable_map::TYPE_INTEGER) == 0) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "'min' and 'max' can only be used when format='integer'");
- return false;
- }
-
- struct SymbolComparator {
- bool operator()(const Attribute::Symbol& a, const Attribute::Symbol& b) {
- return a.symbol.name.value() < b.symbol.name.value();
- }
- };
-
- std::set<Attribute::Symbol, SymbolComparator> items;
-
- std::string comment;
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
- comment = util::trimWhitespace(parser->getComment()).toString();
- continue;
- } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip text.
- continue;
- }
-
- const Source itemSource = mSource.withLine(parser->getLineNumber());
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace.empty() && (elementName == "flag" || elementName == "enum")) {
- if (elementName == "enum") {
- if (typeMask & android::ResTable_map::TYPE_FLAGS) {
- mDiag->error(DiagMessage(itemSource)
- << "can not define an <enum>; already defined a <flag>");
- error = true;
- continue;
- }
- typeMask |= android::ResTable_map::TYPE_ENUM;
-
- } else if (elementName == "flag") {
- if (typeMask & android::ResTable_map::TYPE_ENUM) {
- mDiag->error(DiagMessage(itemSource)
- << "can not define a <flag>; already defined an <enum>");
- error = true;
- continue;
- }
- typeMask |= android::ResTable_map::TYPE_FLAGS;
- }
-
- if (Maybe<Attribute::Symbol> s = parseEnumOrFlagItem(parser, elementName)) {
- Attribute::Symbol& symbol = s.value();
- ParsedResource childResource;
- childResource.name = symbol.symbol.name.value();
- childResource.source = itemSource;
- childResource.value = util::make_unique<Id>();
- outResource->childResources.push_back(std::move(childResource));
-
- symbol.symbol.setComment(std::move(comment));
- symbol.symbol.setSource(itemSource);
-
- auto insertResult = items.insert(std::move(symbol));
- if (!insertResult.second) {
- const Attribute::Symbol& existingSymbol = *insertResult.first;
- mDiag->error(DiagMessage(itemSource)
- << "duplicate symbol '" << existingSymbol.symbol.name.value().entry
- << "'");
-
- mDiag->note(DiagMessage(existingSymbol.symbol.getSource())
- << "first defined here");
- error = true;
- }
- } else {
- error = true;
- }
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");
- error = true;
- }
-
- comment = {};
- }
-
- if (error) {
- return false;
- }
-
- std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(weak);
- attr->symbols = std::vector<Attribute::Symbol>(items.begin(), items.end());
- attr->typeMask = typeMask ? typeMask : uint32_t(android::ResTable_map::TYPE_ANY);
- if (maybeMin) {
- attr->minInt = maybeMin.value();
- }
-
- if (maybeMax) {
- attr->maxInt = maybeMax.value();
- }
- outResource->value = std::move(attr);
+bool ResourceParser::parseSymbol(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ if (parseSymbolImpl(parser, outResource)) {
+ outResource->symbolState = SymbolState::kPrivate;
return true;
+ }
+ return false;
}
-Maybe<Attribute::Symbol> ResourceParser::parseEnumOrFlagItem(xml::XmlPullParser* parser,
- const StringPiece& tag) {
- const Source source = mSource.withLine(parser->getLineNumber());
+bool ResourceParser::parseAddResource(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ if (parseSymbolImpl(parser, outResource)) {
+ outResource->symbolState = SymbolState::kUndefined;
+ return true;
+ }
+ return false;
+}
- Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
- if (!maybeName) {
- mDiag->error(DiagMessage(source) << "no attribute 'name' found for tag <" << tag << ">");
- return {};
+bool ResourceParser::parseAttr(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ return parseAttrImpl(parser, outResource, false);
+}
+
+bool ResourceParser::parseAttrImpl(xml::XmlPullParser* parser,
+ ParsedResource* outResource, bool weak) {
+ outResource->name.type = ResourceType::kAttr;
+
+ // Attributes only end up in default configuration.
+ if (outResource->config != ConfigDescription::defaultConfig()) {
+ mDiag->warn(DiagMessage(outResource->source)
+ << "ignoring configuration '" << outResource->config
+ << "' for attribute " << outResource->name);
+ outResource->config = ConfigDescription::defaultConfig();
+ }
+
+ uint32_t typeMask = 0;
+
+ Maybe<StringPiece> maybeFormat = xml::findAttribute(parser, "format");
+ if (maybeFormat) {
+ typeMask = parseFormatAttribute(maybeFormat.value());
+ if (typeMask == 0) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "invalid attribute format '" << maybeFormat.value()
+ << "'");
+ return false;
+ }
+ }
+
+ Maybe<int32_t> maybeMin, maybeMax;
+
+ if (Maybe<StringPiece> maybeMinStr = xml::findAttribute(parser, "min")) {
+ StringPiece minStr = util::trimWhitespace(maybeMinStr.value());
+ if (!minStr.empty()) {
+ std::u16string minStr16 = util::utf8ToUtf16(minStr);
+ android::Res_value value;
+ if (android::ResTable::stringToInt(minStr16.data(), minStr16.size(),
+ &value)) {
+ maybeMin = static_cast<int32_t>(value.data);
+ }
}
- Maybe<StringPiece> maybeValue = xml::findNonEmptyAttribute(parser, "value");
- if (!maybeValue) {
- mDiag->error(DiagMessage(source) << "no attribute 'value' found for tag <" << tag << ">");
- return {};
+ if (!maybeMin) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "invalid 'min' value '" << minStr << "'");
+ return false;
+ }
+ }
+
+ if (Maybe<StringPiece> maybeMaxStr = xml::findAttribute(parser, "max")) {
+ StringPiece maxStr = util::trimWhitespace(maybeMaxStr.value());
+ if (!maxStr.empty()) {
+ std::u16string maxStr16 = util::utf8ToUtf16(maxStr);
+ android::Res_value value;
+ if (android::ResTable::stringToInt(maxStr16.data(), maxStr16.size(),
+ &value)) {
+ maybeMax = static_cast<int32_t>(value.data);
+ }
}
- std::u16string value16 = util::utf8ToUtf16(maybeValue.value());
- android::Res_value val;
- if (!android::ResTable::stringToInt(value16.data(), value16.size(), &val)) {
- mDiag->error(DiagMessage(source) << "invalid value '" << maybeValue.value()
- << "' for <" << tag << ">; must be an integer");
- return {};
+ if (!maybeMax) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "invalid 'max' value '" << maxStr << "'");
+ return false;
+ }
+ }
+
+ if ((maybeMin || maybeMax) &&
+ (typeMask & android::ResTable_map::TYPE_INTEGER) == 0) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "'min' and 'max' can only be used when format='integer'");
+ return false;
+ }
+
+ struct SymbolComparator {
+ bool operator()(const Attribute::Symbol& a, const Attribute::Symbol& b) {
+ return a.symbol.name.value() < b.symbol.name.value();
+ }
+ };
+
+ std::set<Attribute::Symbol, SymbolComparator> items;
+
+ std::string comment;
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
+ comment = util::trimWhitespace(parser->getComment()).toString();
+ continue;
+ } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip text.
+ continue;
}
- return Attribute::Symbol{
- Reference(ResourceNameRef({}, ResourceType::kId, maybeName.value())), val.data };
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace.empty() &&
+ (elementName == "flag" || elementName == "enum")) {
+ if (elementName == "enum") {
+ if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+ mDiag->error(DiagMessage(itemSource)
+ << "can not define an <enum>; already defined a <flag>");
+ error = true;
+ continue;
+ }
+ typeMask |= android::ResTable_map::TYPE_ENUM;
+
+ } else if (elementName == "flag") {
+ if (typeMask & android::ResTable_map::TYPE_ENUM) {
+ mDiag->error(DiagMessage(itemSource)
+ << "can not define a <flag>; already defined an <enum>");
+ error = true;
+ continue;
+ }
+ typeMask |= android::ResTable_map::TYPE_FLAGS;
+ }
+
+ if (Maybe<Attribute::Symbol> s =
+ parseEnumOrFlagItem(parser, elementName)) {
+ Attribute::Symbol& symbol = s.value();
+ ParsedResource childResource;
+ childResource.name = symbol.symbol.name.value();
+ childResource.source = itemSource;
+ childResource.value = util::make_unique<Id>();
+ outResource->childResources.push_back(std::move(childResource));
+
+ symbol.symbol.setComment(std::move(comment));
+ symbol.symbol.setSource(itemSource);
+
+ auto insertResult = items.insert(std::move(symbol));
+ if (!insertResult.second) {
+ const Attribute::Symbol& existingSymbol = *insertResult.first;
+ mDiag->error(DiagMessage(itemSource)
+ << "duplicate symbol '"
+ << existingSymbol.symbol.name.value().entry << "'");
+
+ mDiag->note(DiagMessage(existingSymbol.symbol.getSource())
+ << "first defined here");
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");
+ error = true;
+ }
+
+ comment = {};
+ }
+
+ if (error) {
+ return false;
+ }
+
+ std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(weak);
+ attr->symbols = std::vector<Attribute::Symbol>(items.begin(), items.end());
+ attr->typeMask =
+ typeMask ? typeMask : uint32_t(android::ResTable_map::TYPE_ANY);
+ if (maybeMin) {
+ attr->minInt = maybeMin.value();
+ }
+
+ if (maybeMax) {
+ attr->maxInt = maybeMax.value();
+ }
+ outResource->value = std::move(attr);
+ return true;
+}
+
+Maybe<Attribute::Symbol> ResourceParser::parseEnumOrFlagItem(
+ xml::XmlPullParser* parser, const StringPiece& tag) {
+ const Source source = mSource.withLine(parser->getLineNumber());
+
+ Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
+ if (!maybeName) {
+ mDiag->error(DiagMessage(source) << "no attribute 'name' found for tag <"
+ << tag << ">");
+ return {};
+ }
+
+ Maybe<StringPiece> maybeValue = xml::findNonEmptyAttribute(parser, "value");
+ if (!maybeValue) {
+ mDiag->error(DiagMessage(source) << "no attribute 'value' found for tag <"
+ << tag << ">");
+ return {};
+ }
+
+ std::u16string value16 = util::utf8ToUtf16(maybeValue.value());
+ android::Res_value val;
+ if (!android::ResTable::stringToInt(value16.data(), value16.size(), &val)) {
+ mDiag->error(DiagMessage(source) << "invalid value '" << maybeValue.value()
+ << "' for <" << tag
+ << ">; must be an integer");
+ return {};
+ }
+
+ return Attribute::Symbol{
+ Reference(ResourceNameRef({}, ResourceType::kId, maybeName.value())),
+ val.data};
}
bool ResourceParser::parseStyleItem(xml::XmlPullParser* parser, Style* style) {
- const Source source = mSource.withLine(parser->getLineNumber());
+ const Source source = mSource.withLine(parser->getLineNumber());
- Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
- if (!maybeName) {
- mDiag->error(DiagMessage(source) << "<item> must have a 'name' attribute");
+ Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
+ if (!maybeName) {
+ mDiag->error(DiagMessage(source) << "<item> must have a 'name' attribute");
+ return false;
+ }
+
+ Maybe<Reference> maybeKey =
+ ResourceUtils::parseXmlAttributeName(maybeName.value());
+ if (!maybeKey) {
+ mDiag->error(DiagMessage(source) << "invalid attribute name '"
+ << maybeName.value() << "'");
+ return false;
+ }
+
+ transformReferenceFromNamespace(parser, "", &maybeKey.value());
+ maybeKey.value().setSource(source);
+
+ std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
+ if (!value) {
+ mDiag->error(DiagMessage(source) << "could not parse style item");
+ return false;
+ }
+
+ style->entries.push_back(
+ Style::Entry{std::move(maybeKey.value()), std::move(value)});
+ return true;
+}
+
+bool ResourceParser::parseStyle(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ outResource->name.type = ResourceType::kStyle;
+
+ std::unique_ptr<Style> style = util::make_unique<Style>();
+
+ Maybe<StringPiece> maybeParent = xml::findAttribute(parser, "parent");
+ if (maybeParent) {
+ // If the parent is empty, we don't have a parent, but we also don't infer
+ // either.
+ if (!maybeParent.value().empty()) {
+ std::string errStr;
+ style->parent = ResourceUtils::parseStyleParentReference(
+ maybeParent.value(), &errStr);
+ if (!style->parent) {
+ mDiag->error(DiagMessage(outResource->source) << errStr);
return false;
+ }
+
+ // Transform the namespace prefix to the actual package name, and mark the
+ // reference as
+ // private if appropriate.
+ transformReferenceFromNamespace(parser, "", &style->parent.value());
}
- Maybe<Reference> maybeKey = ResourceUtils::parseXmlAttributeName(maybeName.value());
- if (!maybeKey) {
- mDiag->error(DiagMessage(source) << "invalid attribute name '" << maybeName.value() << "'");
- return false;
+ } else {
+ // No parent was specified, so try inferring it from the style name.
+ std::string styleName = outResource->name.entry;
+ size_t pos = styleName.find_last_of(u'.');
+ if (pos != std::string::npos) {
+ style->parentInferred = true;
+ style->parent = Reference(
+ ResourceName({}, ResourceType::kStyle, styleName.substr(0, pos)));
+ }
+ }
+
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip text and comments.
+ continue;
}
- transformReferenceFromNamespace(parser, "", &maybeKey.value());
- maybeKey.value().setSource(source);
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace == "" && elementName == "item") {
+ error |= !parseStyleItem(parser, style.get());
- std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
- if (!value) {
- mDiag->error(DiagMessage(source) << "could not parse style item");
- return false;
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << ":" << elementName << ">");
+ error = true;
}
+ }
- style->entries.push_back(Style::Entry{ std::move(maybeKey.value()), std::move(value) });
- return true;
+ if (error) {
+ return false;
+ }
+
+ outResource->value = std::move(style);
+ return true;
}
-bool ResourceParser::parseStyle(xml::XmlPullParser* parser, ParsedResource* outResource) {
- outResource->name.type = ResourceType::kStyle;
-
- std::unique_ptr<Style> style = util::make_unique<Style>();
-
- Maybe<StringPiece> maybeParent = xml::findAttribute(parser, "parent");
- if (maybeParent) {
- // If the parent is empty, we don't have a parent, but we also don't infer either.
- if (!maybeParent.value().empty()) {
- std::string errStr;
- style->parent = ResourceUtils::parseStyleParentReference(maybeParent.value(), &errStr);
- if (!style->parent) {
- mDiag->error(DiagMessage(outResource->source) << errStr);
- return false;
- }
-
- // Transform the namespace prefix to the actual package name, and mark the reference as
- // private if appropriate.
- transformReferenceFromNamespace(parser, "", &style->parent.value());
- }
-
- } else {
- // No parent was specified, so try inferring it from the style name.
- std::string styleName = outResource->name.entry;
- size_t pos = styleName.find_last_of(u'.');
- if (pos != std::string::npos) {
- style->parentInferred = true;
- style->parent = Reference(ResourceName({}, ResourceType::kStyle,
- styleName.substr(0, pos)));
- }
- }
-
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip text and comments.
- continue;
- }
-
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace == "" && elementName == "item") {
- error |= !parseStyleItem(parser, style.get());
-
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << ":" << elementName << ">");
- error = true;
- }
- }
-
- if (error) {
- return false;
- }
-
- outResource->value = std::move(style);
- return true;
+bool ResourceParser::parseArray(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ return parseArrayImpl(parser, outResource, android::ResTable_map::TYPE_ANY);
}
-bool ResourceParser::parseArray(xml::XmlPullParser* parser, ParsedResource* outResource) {
- return parseArrayImpl(parser, outResource, android::ResTable_map::TYPE_ANY);
+bool ResourceParser::parseIntegerArray(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ return parseArrayImpl(parser, outResource,
+ android::ResTable_map::TYPE_INTEGER);
}
-bool ResourceParser::parseIntegerArray(xml::XmlPullParser* parser, ParsedResource* outResource) {
- return parseArrayImpl(parser, outResource, android::ResTable_map::TYPE_INTEGER);
+bool ResourceParser::parseStringArray(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ return parseArrayImpl(parser, outResource,
+ android::ResTable_map::TYPE_STRING);
}
-bool ResourceParser::parseStringArray(xml::XmlPullParser* parser, ParsedResource* outResource) {
- return parseArrayImpl(parser, outResource, android::ResTable_map::TYPE_STRING);
-}
-
-bool ResourceParser::parseArrayImpl(xml::XmlPullParser* parser, ParsedResource* outResource,
+bool ResourceParser::parseArrayImpl(xml::XmlPullParser* parser,
+ ParsedResource* outResource,
const uint32_t typeMask) {
- outResource->name.type = ResourceType::kArray;
+ outResource->name.type = ResourceType::kArray;
- std::unique_ptr<Array> array = util::make_unique<Array>();
+ std::unique_ptr<Array> array = util::make_unique<Array>();
- bool translateable = mOptions.translatable;
- if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
- Maybe<bool> maybeTranslateable = ResourceUtils::parseBool(translateableAttr.value());
- if (!maybeTranslateable) {
- mDiag->error(DiagMessage(outResource->source)
- << "invalid value for 'translatable'. Must be a boolean");
- return false;
- }
- translateable = maybeTranslateable.value();
+ bool translateable = mOptions.translatable;
+ if (Maybe<StringPiece> translateableAttr =
+ xml::findAttribute(parser, "translatable")) {
+ Maybe<bool> maybeTranslateable =
+ ResourceUtils::parseBool(translateableAttr.value());
+ if (!maybeTranslateable) {
+ mDiag->error(DiagMessage(outResource->source)
+ << "invalid value for 'translatable'. Must be a boolean");
+ return false;
}
- array->setTranslateable(translateable);
+ translateable = maybeTranslateable.value();
+ }
+ array->setTranslateable(translateable);
-
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip text and comments.
- continue;
- }
-
- const Source itemSource = mSource.withLine(parser->getLineNumber());
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace.empty() && elementName == "item") {
- std::unique_ptr<Item> item = parseXml(parser, typeMask, kNoRawString);
- if (!item) {
- mDiag->error(DiagMessage(itemSource) << "could not parse array item");
- error = true;
- continue;
- }
- item->setSource(itemSource);
- array->items.emplace_back(std::move(item));
-
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << "unknown tag <" << elementNamespace << ":" << elementName << ">");
- error = true;
- }
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip text and comments.
+ continue;
}
- if (error) {
- return false;
- }
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace.empty() && elementName == "item") {
+ std::unique_ptr<Item> item = parseXml(parser, typeMask, kNoRawString);
+ if (!item) {
+ mDiag->error(DiagMessage(itemSource) << "could not parse array item");
+ error = true;
+ continue;
+ }
+ item->setSource(itemSource);
+ array->items.emplace_back(std::move(item));
- outResource->value = std::move(array);
- return true;
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "unknown tag <" << elementNamespace << ":" << elementName
+ << ">");
+ error = true;
+ }
+ }
+
+ if (error) {
+ return false;
+ }
+
+ outResource->value = std::move(array);
+ return true;
}
-bool ResourceParser::parsePlural(xml::XmlPullParser* parser, ParsedResource* outResource) {
- outResource->name.type = ResourceType::kPlurals;
+bool ResourceParser::parsePlural(xml::XmlPullParser* parser,
+ ParsedResource* outResource) {
+ outResource->name.type = ResourceType::kPlurals;
- std::unique_ptr<Plural> plural = util::make_unique<Plural>();
+ std::unique_ptr<Plural> plural = util::make_unique<Plural>();
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Skip text and comments.
- continue;
- }
-
- const Source itemSource = mSource.withLine(parser->getLineNumber());
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace.empty() && elementName == "item") {
- Maybe<StringPiece> maybeQuantity = xml::findNonEmptyAttribute(parser, "quantity");
- if (!maybeQuantity) {
- mDiag->error(DiagMessage(itemSource) << "<item> in <plurals> requires attribute "
- << "'quantity'");
- error = true;
- continue;
- }
-
- StringPiece trimmedQuantity = util::trimWhitespace(maybeQuantity.value());
- size_t index = 0;
- if (trimmedQuantity == "zero") {
- index = Plural::Zero;
- } else if (trimmedQuantity == "one") {
- index = Plural::One;
- } else if (trimmedQuantity == "two") {
- index = Plural::Two;
- } else if (trimmedQuantity == "few") {
- index = Plural::Few;
- } else if (trimmedQuantity == "many") {
- index = Plural::Many;
- } else if (trimmedQuantity == "other") {
- index = Plural::Other;
- } else {
- mDiag->error(DiagMessage(itemSource)
- << "<item> in <plural> has invalid value '" << trimmedQuantity
- << "' for attribute 'quantity'");
- error = true;
- continue;
- }
-
- if (plural->values[index]) {
- mDiag->error(DiagMessage(itemSource)
- << "duplicate quantity '" << trimmedQuantity << "'");
- error = true;
- continue;
- }
-
- if (!(plural->values[index] = parseXml(parser, android::ResTable_map::TYPE_STRING,
- kNoRawString))) {
- error = true;
- }
- plural->values[index]->setSource(itemSource);
-
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
- << elementName << ">");
- error = true;
- }
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Skip text and comments.
+ continue;
}
- if (error) {
- return false;
- }
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace.empty() && elementName == "item") {
+ Maybe<StringPiece> maybeQuantity =
+ xml::findNonEmptyAttribute(parser, "quantity");
+ if (!maybeQuantity) {
+ mDiag->error(DiagMessage(itemSource)
+ << "<item> in <plurals> requires attribute "
+ << "'quantity'");
+ error = true;
+ continue;
+ }
- outResource->value = std::move(plural);
- return true;
+ StringPiece trimmedQuantity = util::trimWhitespace(maybeQuantity.value());
+ size_t index = 0;
+ if (trimmedQuantity == "zero") {
+ index = Plural::Zero;
+ } else if (trimmedQuantity == "one") {
+ index = Plural::One;
+ } else if (trimmedQuantity == "two") {
+ index = Plural::Two;
+ } else if (trimmedQuantity == "few") {
+ index = Plural::Few;
+ } else if (trimmedQuantity == "many") {
+ index = Plural::Many;
+ } else if (trimmedQuantity == "other") {
+ index = Plural::Other;
+ } else {
+ mDiag->error(DiagMessage(itemSource)
+ << "<item> in <plural> has invalid value '"
+ << trimmedQuantity << "' for attribute 'quantity'");
+ error = true;
+ continue;
+ }
+
+ if (plural->values[index]) {
+ mDiag->error(DiagMessage(itemSource) << "duplicate quantity '"
+ << trimmedQuantity << "'");
+ error = true;
+ continue;
+ }
+
+ if (!(plural->values[index] = parseXml(
+ parser, android::ResTable_map::TYPE_STRING, kNoRawString))) {
+ error = true;
+ }
+ plural->values[index]->setSource(itemSource);
+
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource)
+ << "unknown tag <" << elementNamespace << ":" << elementName
+ << ">");
+ error = true;
+ }
+ }
+
+ if (error) {
+ return false;
+ }
+
+ outResource->value = std::move(plural);
+ return true;
}
bool ResourceParser::parseDeclareStyleable(xml::XmlPullParser* parser,
ParsedResource* outResource) {
- outResource->name.type = ResourceType::kStyleable;
+ outResource->name.type = ResourceType::kStyleable;
- // Declare-styleable is kPrivate by default, because it technically only exists in R.java.
- outResource->symbolState = SymbolState::kPublic;
+ // Declare-styleable is kPrivate by default, because it technically only
+ // exists in R.java.
+ outResource->symbolState = SymbolState::kPublic;
- // Declare-styleable only ends up in default config;
- if (outResource->config != ConfigDescription::defaultConfig()) {
- mDiag->warn(DiagMessage(outResource->source) << "ignoring configuration '"
- << outResource->config << "' for styleable "
- << outResource->name.entry);
- outResource->config = ConfigDescription::defaultConfig();
+ // Declare-styleable only ends up in default config;
+ if (outResource->config != ConfigDescription::defaultConfig()) {
+ mDiag->warn(DiagMessage(outResource->source)
+ << "ignoring configuration '" << outResource->config
+ << "' for styleable " << outResource->name.entry);
+ outResource->config = ConfigDescription::defaultConfig();
+ }
+
+ std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+
+ std::string comment;
+ bool error = false;
+ const size_t depth = parser->getDepth();
+ while (xml::XmlPullParser::nextChildNode(parser, depth)) {
+ if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
+ comment = util::trimWhitespace(parser->getComment()).toString();
+ continue;
+ } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
+ // Ignore text.
+ continue;
}
- std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
+ const std::string& elementNamespace = parser->getElementNamespace();
+ const std::string& elementName = parser->getElementName();
+ if (elementNamespace.empty() && elementName == "attr") {
+ Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
+ if (!maybeName) {
+ mDiag->error(DiagMessage(itemSource)
+ << "<attr> tag must have a 'name' attribute");
+ error = true;
+ continue;
+ }
- std::string comment;
- bool error = false;
- const size_t depth = parser->getDepth();
- while (xml::XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() == xml::XmlPullParser::Event::kComment) {
- comment = util::trimWhitespace(parser->getComment()).toString();
- continue;
- } else if (parser->getEvent() != xml::XmlPullParser::Event::kStartElement) {
- // Ignore text.
- continue;
- }
+ // If this is a declaration, the package name may be in the name. Separate
+ // these out.
+ // Eg. <attr name="android:text" />
+ Maybe<Reference> maybeRef =
+ ResourceUtils::parseXmlAttributeName(maybeName.value());
+ if (!maybeRef) {
+ mDiag->error(DiagMessage(itemSource) << "<attr> tag has invalid name '"
+ << maybeName.value() << "'");
+ error = true;
+ continue;
+ }
- const Source itemSource = mSource.withLine(parser->getLineNumber());
- const std::string& elementNamespace = parser->getElementNamespace();
- const std::string& elementName = parser->getElementName();
- if (elementNamespace.empty() && elementName == "attr") {
- Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
- if (!maybeName) {
- mDiag->error(DiagMessage(itemSource) << "<attr> tag must have a 'name' attribute");
- error = true;
- continue;
- }
+ Reference& childRef = maybeRef.value();
+ xml::transformReferenceFromNamespace(parser, "", &childRef);
- // If this is a declaration, the package name may be in the name. Separate these out.
- // Eg. <attr name="android:text" />
- Maybe<Reference> maybeRef = ResourceUtils::parseXmlAttributeName(maybeName.value());
- if (!maybeRef) {
- mDiag->error(DiagMessage(itemSource) << "<attr> tag has invalid name '"
- << maybeName.value() << "'");
- error = true;
- continue;
- }
+ // Create the ParsedResource that will add the attribute to the table.
+ ParsedResource childResource;
+ childResource.name = childRef.name.value();
+ childResource.source = itemSource;
+ childResource.comment = std::move(comment);
- Reference& childRef = maybeRef.value();
- xml::transformReferenceFromNamespace(parser, "", &childRef);
+ if (!parseAttrImpl(parser, &childResource, true)) {
+ error = true;
+ continue;
+ }
- // Create the ParsedResource that will add the attribute to the table.
- ParsedResource childResource;
- childResource.name = childRef.name.value();
- childResource.source = itemSource;
- childResource.comment = std::move(comment);
+ // Create the reference to this attribute.
+ childRef.setComment(childResource.comment);
+ childRef.setSource(itemSource);
+ styleable->entries.push_back(std::move(childRef));
- if (!parseAttrImpl(parser, &childResource, true)) {
- error = true;
- continue;
- }
+ outResource->childResources.push_back(std::move(childResource));
- // Create the reference to this attribute.
- childRef.setComment(childResource.comment);
- childRef.setSource(itemSource);
- styleable->entries.push_back(std::move(childRef));
-
- outResource->childResources.push_back(std::move(childResource));
-
- } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
- mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
- << elementName << ">");
- error = true;
- }
-
- comment = {};
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource)
+ << "unknown tag <" << elementNamespace << ":" << elementName
+ << ">");
+ error = true;
}
- if (error) {
- return false;
- }
+ comment = {};
+ }
- outResource->value = std::move(styleable);
- return true;
+ if (error) {
+ return false;
+ }
+
+ outResource->value = std::move(styleable);
+ return true;
}
-} // namespace aapt
+} // namespace aapt