From 7656554f91b40bc93bf94c89afcad4a9a8ced884 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Thu, 10 Mar 2016 21:55:04 -0800 Subject: AAPT2: Add descriptions of Attributes in Styleables for R.java Change-Id: I69e7b73cbdfe4baf502348397435c501ae29ff5e --- tools/aapt2/java/JavaClassGenerator.cpp | 252 ++++++++++++++++++++------------ 1 file changed, 161 insertions(+), 91 deletions(-) (limited to 'tools/aapt2/java/JavaClassGenerator.cpp') diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 1076ffe1b01d..01330dc6b5a1 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -23,6 +23,7 @@ #include "java/AnnotationProcessor.h" #include "java/ClassDefinitionWriter.h" #include "java/JavaClassGenerator.h" +#include "process/SymbolTable.h" #include "util/StringPiece.h" #include @@ -33,8 +34,9 @@ namespace aapt { -JavaClassGenerator::JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options) : - mTable(table), mOptions(options) { +JavaClassGenerator::JavaClassGenerator(IAaptContext* context, ResourceTable* table, + const JavaClassGeneratorOptions& options) : + mContext(context), mTable(table), mOptions(options) { } static void generateHeader(const StringPiece16& packageNameToGenerate, std::ostream* out) { @@ -103,6 +105,85 @@ static std::string transformNestedAttr(const ResourceNameRef& attrName, return output; } +static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) { + const uint32_t typeMask = attr->typeMask; + if (typeMask & android::ResTable_map::TYPE_REFERENCE) { + processor->appendComment( + "

May be a reference to another resource, in the form\n" + "\"@[+][package:]type/name\" or a theme\n" + "attribute in the form\n" + "\"?[package:]type/name\"."); + } + + if (typeMask & android::ResTable_map::TYPE_STRING) { + processor->appendComment( + "

May be a string value, using '\\\\;' to escape characters such as\n" + "'\\\\n' or '\\\\uxxxx' for a unicode character;"); + } + + if (typeMask & android::ResTable_map::TYPE_INTEGER) { + processor->appendComment("

May be an integer value, such as \"100\"."); + } + + if (typeMask & android::ResTable_map::TYPE_BOOLEAN) { + processor->appendComment( + "

May be a boolean value, such as \"true\" or\n" + "\"false\"."); + } + + if (typeMask & android::ResTable_map::TYPE_COLOR) { + processor->appendComment( + "

May be a color value, in the form of \"#rgb\",\n" + "\"#argb\", \"#rrggbb#aarrggbb\"."); + } + + if (typeMask & android::ResTable_map::TYPE_FLOAT) { + processor->appendComment( + "

May be a floating point value, such as \"1.2\"."); + } + + if (typeMask & android::ResTable_map::TYPE_DIMENSION) { + processor->appendComment( + "

May be a dimension value, which is a floating point number appended with a\n" + "unit such as \"14.5sp\".\n" + "Available units are: px (pixels), dp (density-independent pixels),\n" + "sp (scaled pixels based on preferred font size), in (inches), and\n" + "mm (millimeters)."); + } + + if (typeMask & android::ResTable_map::TYPE_FRACTION) { + processor->appendComment( + "

May be a fractional value, which is a floating point number appended with\n" + "either % or %p, such as \"14.5%\".\n" + "The % suffix always means a percentage of the base size;\n" + "the optional %p suffix provides a size relative to some parent container."); + } + + if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) { + if (typeMask & android::ResTable_map::TYPE_FLAGS) { + processor->appendComment( + "

Must be one or more (separated by '|') of the following " + "constant values.

"); + } else { + processor->appendComment("

Must be one of the following constant values.

"); + } + + processor->appendComment("\n\n" + "\n" + "\n" + "\n"); + for (const Attribute::Symbol& symbol : attr->symbols) { + std::stringstream line; + line << "" + << "" + << ""; + processor->appendComment(line.str()); + } + processor->appendComment("
ConstantValueDescription
" << symbol.symbol.name.value().entry << "" << std::hex << symbol.value << std::dec << "" << util::trimWhitespace(symbol.symbol.getComment()) << "
"); + } +} + bool JavaClassGenerator::skipSymbol(SymbolState state) { switch (mOptions.types) { case JavaClassGeneratorOptions::SymbolTypes::kAll: @@ -117,6 +198,7 @@ bool JavaClassGenerator::skipSymbol(SymbolState state) { struct StyleableAttr { const Reference* attrRef; + std::shared_ptr attribute; std::string fieldName; }; @@ -148,8 +230,29 @@ void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outC assert((!mOptions.useFinal || attr.id) && "no ID set for Styleable entry"); assert(attr.name && "no name set for Styleable entry"); - sortedAttributes.emplace_back(StyleableAttr{ - &attr, transformNestedAttr(attr.name.value(), className, packageNameToGenerate) }); + StyleableAttr styleableAttr = {}; + styleableAttr.attrRef = &attr; + styleableAttr.fieldName = transformNestedAttr(attr.name.value(), className, + packageNameToGenerate); + + Reference mangledReference; + mangledReference.id = attr.id; + mangledReference.name = attr.name; + if (mangledReference.name.value().package.empty()) { + mangledReference.name.value().package = mContext->getCompilationPackage(); + } + + if (Maybe mangledName = + mContext->getNameMangler()->mangleName(mangledReference.name.value())) { + mangledReference.name = mangledName; + } + + const SymbolTable::Symbol* symbol = mContext->getExternalSymbols()->findByReference( + mangledReference); + if (symbol) { + styleableAttr.attribute = symbol->attribute; + } + sortedAttributes.push_back(std::move(styleableAttr)); } std::sort(sortedAttributes.begin(), sortedAttributes.end(), lessStyleableAttr); @@ -159,16 +262,34 @@ void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outC // Build the comment string for the Styleable. It includes details about the // child attributes. std::stringstream styleableComment; - styleableComment << "Attributes that can be used with a " << className << ".\n"; - styleableComment << "\n" + if (!styleable->getComment().empty()) { + styleableComment << styleable->getComment() << "\n"; + } else { + styleableComment << "Attributes that can be used with a " << className << ".\n"; + } + styleableComment << + "

Includes the following attributes:

\n" + "
\n" + "\n" "\n" - "\n" "\n"; + for (const auto& entry : sortedAttributes) { const ResourceName& attrName = entry.attrRef->name.value(); - styleableComment << "\n"; + styleableComment << ""; + + styleableComment << "\n"; } styleableComment << "
AttributeDescription
{@link #" << entry.fieldName << " " - << attrName.package << ":" << attrName.entry - << "}
"; + styleableComment << "{@link #" + << entry.fieldName << " " + << (!attrName.package.empty() + ? attrName.package : mContext->getCompilationPackage()) + << ":" << attrName.entry + << "}"; + styleableComment << ""; + if (entry.attribute) { + styleableComment << entry.attribute->getComment(); + } + styleableComment << "
\n"; for (const auto& entry : sortedAttributes) { @@ -189,96 +310,45 @@ void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outC // Now we emit the indices into the array. for (size_t i = 0; i < attrCount; i++) { - const ResourceName& attrName = sortedAttributes[i].attrRef->name.value(); + const StyleableAttr& styleableAttr = sortedAttributes[i]; + const ResourceName& attrName = styleableAttr.attrRef->name.value(); - AnnotationProcessor attrProcessor; - std::stringstream doclavaComments; - doclavaComments << "@attr name "; - if (!attrName.package.empty()) { - doclavaComments << attrName.package << ":"; + StringPiece16 packageName = attrName.package; + if (packageName.empty()) { + packageName = mContext->getCompilationPackage(); } - doclavaComments << attrName.entry; - attrProcessor.appendComment(doclavaComments.str()); - outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i); - } -} - -static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) { - const uint32_t typeMask = attr->typeMask; - if (typeMask & android::ResTable_map::TYPE_REFERENCE) { - processor->appendComment( - "

May be a reference to another resource, in the form\n" - "\"@[+][package:]type/name\" or a theme\n" - "attribute in the form\n" - "\"?[package:]type/name\"."); - } - - if (typeMask & android::ResTable_map::TYPE_STRING) { - processor->appendComment( - "

May be a string value, using '\\\\;' to escape characters such as\n" - "'\\\\n' or '\\\\uxxxx' for a unicode character;"); - } - - if (typeMask & android::ResTable_map::TYPE_INTEGER) { - processor->appendComment("

May be an integer value, such as \"100\"."); - } - - if (typeMask & android::ResTable_map::TYPE_BOOLEAN) { - processor->appendComment( - "

May be a boolean value, such as \"true\" or\n" - "\"false\"."); - } - - if (typeMask & android::ResTable_map::TYPE_COLOR) { - processor->appendComment( - "

May be a color value, in the form of \"#rgb\",\n" - "\"#argb\", \"#rrggbb#aarrggbb\"."); - } - - if (typeMask & android::ResTable_map::TYPE_FLOAT) { - processor->appendComment( - "

May be a floating point value, such as \"1.2\"."); - } - if (typeMask & android::ResTable_map::TYPE_DIMENSION) { - processor->appendComment( - "

May be a dimension value, which is a floating point number appended with a\n" - "unit such as \"14.5sp\".\n" - "Available units are: px (pixels), dp (density-independent pixels),\n" - "sp (scaled pixels based on preferred font size), in (inches), and\n" - "mm (millimeters)."); - } + AnnotationProcessor attrProcessor; - if (typeMask & android::ResTable_map::TYPE_FRACTION) { - processor->appendComment( - "

May be a fractional value, which is a floating point number appended with\n" - "either % or %p, such as \"14.5%\".\n" - "The % suffix always means a percentage of the base size;\n" - "the optional %p suffix provides a size relative to some parent container."); - } + StringPiece16 comment = styleableAttr.attrRef->getComment(); + if (styleableAttr.attribute && comment.empty()) { + comment = styleableAttr.attribute->getComment(); + } - if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) { - if (typeMask & android::ResTable_map::TYPE_FLAGS) { - processor->appendComment( - "

Must be one or more (separated by '|') of the following " - "constant values.

"); + if (!comment.empty()) { + attrProcessor.appendComment("

\n@attr description"); + attrProcessor.appendComment(comment); } else { - processor->appendComment("

Must be one of the following constant values.

"); + std::stringstream defaultComment; + defaultComment + << "

This symbol is the offset where the " + << "{@link " << packageName << ".R.attr#" << transform(attrName.entry) << "}\n" + << "attribute's value can be found in the " + << "{@link #" << className << "} array."; + attrProcessor.appendComment(defaultComment.str()); } - processor->appendComment("\n\n" - "\n" - "\n" - "\n"); - for (const Attribute::Symbol& symbol : attr->symbols) { - std::stringstream line; - line << "" - << "" - << ""; - processor->appendComment(line.str()); + attrProcessor.appendNewLine(); + + if (styleableAttr.attribute) { + addAttributeFormatDoc(&attrProcessor, styleableAttr.attribute.get()); + attrProcessor.appendNewLine(); } - processor->appendComment("
ConstantValueDescription
" << symbol.symbol.name.value().entry << "" << std::hex << symbol.value << std::dec << "" << util::trimWhitespace(symbol.symbol.getComment()) << "
"); + + std::stringstream doclavaName; + doclavaName << "@attr name " << packageName << ":" << attrName.entry;; + attrProcessor.appendComment(doclavaName.str()); + outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i); } } -- cgit v1.2.3