diff options
author | Adam Lesinski <adamlesinski@google.com> | 2016-03-11 09:16:43 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-03-11 09:16:44 +0000 |
commit | 330c57dbd19a064d1f5a4adb3c8ed014711b473f (patch) | |
tree | 9a795b0dbeae55273f3f3f35d842574f51102c6d /tools/aapt2/java/JavaClassGenerator.cpp | |
parent | 607c0a0a09e6543609f70eb27cc06ff44857252e (diff) | |
parent | 7656554f91b40bc93bf94c89afcad4a9a8ced884 (diff) |
Merge "AAPT2: Add descriptions of Attributes in Styleables for R.java" into nyc-dev
Diffstat (limited to 'tools/aapt2/java/JavaClassGenerator.cpp')
-rw-r--r-- | tools/aapt2/java/JavaClassGenerator.cpp | 252 |
1 files changed, 161 insertions, 91 deletions
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 <algorithm> @@ -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( + "<p>May be a reference to another resource, in the form\n" + "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n" + "attribute in the form\n" + "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\"."); + } + + if (typeMask & android::ResTable_map::TYPE_STRING) { + processor->appendComment( + "<p>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("<p>May be an integer value, such as \"<code>100</code>\"."); + } + + if (typeMask & android::ResTable_map::TYPE_BOOLEAN) { + processor->appendComment( + "<p>May be a boolean value, such as \"<code>true</code>\" or\n" + "\"<code>false</code>\"."); + } + + if (typeMask & android::ResTable_map::TYPE_COLOR) { + processor->appendComment( + "<p>May be a color value, in the form of \"<code>#<i>rgb</i></code>\",\n" + "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n" + "\"<code>#<i>aarrggbb</i></code>\"."); + } + + if (typeMask & android::ResTable_map::TYPE_FLOAT) { + processor->appendComment( + "<p>May be a floating point value, such as \"<code>1.2</code>\"."); + } + + if (typeMask & android::ResTable_map::TYPE_DIMENSION) { + processor->appendComment( + "<p>May be a dimension value, which is a floating point number appended with a\n" + "unit such as \"<code>14.5sp</code>\".\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( + "<p>May be a fractional value, which is a floating point number appended with\n" + "either % or %p, such as \"<code>14.5%</code>\".\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( + "<p>Must be one or more (separated by '|') of the following " + "constant values.</p>"); + } else { + processor->appendComment("<p>Must be one of the following constant values.</p>"); + } + + processor->appendComment("<table>\n<colgroup align=\"left\" />\n" + "<colgroup align=\"left\" />\n" + "<colgroup align=\"left\" />\n" + "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n"); + for (const Attribute::Symbol& symbol : attr->symbols) { + std::stringstream line; + line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>" + << "<td>" << std::hex << symbol.value << std::dec << "</td>" + << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>"; + processor->appendComment(line.str()); + } + processor->appendComment("</table>"); + } +} + 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> 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<ResourceName> 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 << "<table>\n" + if (!styleable->getComment().empty()) { + styleableComment << styleable->getComment() << "\n"; + } else { + styleableComment << "Attributes that can be used with a " << className << ".\n"; + } + styleableComment << + "<p>Includes the following attributes:</p>\n" + "<table>\n" + "<colgroup align=\"left\" />\n" "<colgroup align=\"left\" />\n" - "<colgroup align=\"left\">\n" "<tr><th>Attribute</th><th>Description</th></tr>\n"; + for (const auto& entry : sortedAttributes) { const ResourceName& attrName = entry.attrRef->name.value(); - styleableComment << "<tr><td><code>{@link #" << entry.fieldName << " " - << attrName.package << ":" << attrName.entry - << "}</code></td><td></td></tr>\n"; + styleableComment << "<tr><td>"; + styleableComment << "<code>{@link #" + << entry.fieldName << " " + << (!attrName.package.empty() + ? attrName.package : mContext->getCompilationPackage()) + << ":" << attrName.entry + << "}</code>"; + styleableComment << "</td>"; + + styleableComment << "<td>"; + if (entry.attribute) { + styleableComment << entry.attribute->getComment(); + } + styleableComment << "</td></tr>\n"; } styleableComment << "</table>\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( - "<p>May be a reference to another resource, in the form\n" - "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n" - "attribute in the form\n" - "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\"."); - } - - if (typeMask & android::ResTable_map::TYPE_STRING) { - processor->appendComment( - "<p>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("<p>May be an integer value, such as \"<code>100</code>\"."); - } - - if (typeMask & android::ResTable_map::TYPE_BOOLEAN) { - processor->appendComment( - "<p>May be a boolean value, such as \"<code>true</code>\" or\n" - "\"<code>false</code>\"."); - } - - if (typeMask & android::ResTable_map::TYPE_COLOR) { - processor->appendComment( - "<p>May be a color value, in the form of \"<code>#<i>rgb</i></code>\",\n" - "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n" - "\"<code>#<i>aarrggbb</i></code>\"."); - } - - if (typeMask & android::ResTable_map::TYPE_FLOAT) { - processor->appendComment( - "<p>May be a floating point value, such as \"<code>1.2</code>\"."); - } - if (typeMask & android::ResTable_map::TYPE_DIMENSION) { - processor->appendComment( - "<p>May be a dimension value, which is a floating point number appended with a\n" - "unit such as \"<code>14.5sp</code>\".\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( - "<p>May be a fractional value, which is a floating point number appended with\n" - "either % or %p, such as \"<code>14.5%</code>\".\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( - "<p>Must be one or more (separated by '|') of the following " - "constant values.</p>"); + if (!comment.empty()) { + attrProcessor.appendComment("<p>\n@attr description"); + attrProcessor.appendComment(comment); } else { - processor->appendComment("<p>Must be one of the following constant values.</p>"); + std::stringstream defaultComment; + defaultComment + << "<p>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("<table>\n<colgroup align=\"left\" />\n" - "<colgroup align=\"left\" />\n" - "<colgroup align=\"left\" />\n" - "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n"); - for (const Attribute::Symbol& symbol : attr->symbols) { - std::stringstream line; - line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>" - << "<td>" << std::hex << symbol.value << std::dec << "</td>" - << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>"; - processor->appendComment(line.str()); + attrProcessor.appendNewLine(); + + if (styleableAttr.attribute) { + addAttributeFormatDoc(&attrProcessor, styleableAttr.attribute.get()); + attrProcessor.appendNewLine(); } - processor->appendComment("</table>"); + + std::stringstream doclavaName; + doclavaName << "@attr name " << packageName << ":" << attrName.entry;; + attrProcessor.appendComment(doclavaName.str()); + outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i); } } |