diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-10-30 16:31:42 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-11-02 11:53:47 -0800 |
commit | 3b4cd94034ff3e5567a2ba6da35d640ff61db4b9 (patch) | |
tree | 83c604b9a3b0d1b25769a6afd16578fd97e6effe /tools/aapt2/java | |
parent | 104e028c3a180a4a151160299ad2e1a4185d6c50 (diff) |
AAPT2: Add support for comments in R.java
Change-Id: Iaa5f3b75bf7de9dbf458fa5c452f7312989f4c4f
Diffstat (limited to 'tools/aapt2/java')
-rw-r--r-- | tools/aapt2/java/AnnotationProcessor.cpp | 30 | ||||
-rw-r--r-- | tools/aapt2/java/AnnotationProcessor.h | 3 | ||||
-rw-r--r-- | tools/aapt2/java/JavaClassGenerator.cpp | 121 | ||||
-rw-r--r-- | tools/aapt2/java/JavaClassGenerator_test.cpp | 31 |
4 files changed, 166 insertions, 19 deletions
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index 16440bcf8ad7..b36682d98bfd 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -21,16 +21,10 @@ namespace aapt { -void AnnotationProcessor::appendCommentLine(const StringPiece16& line) { +void AnnotationProcessor::appendCommentLine(const std::string& comment) { static const std::string sDeprecated = "@deprecated"; static const std::string sSystemApi = "@SystemApi"; - if (line.empty()) { - return; - } - - std::string comment = util::utf16ToUtf8(line); - if (comment.find(sDeprecated) != std::string::npos && !mDeprecated) { mDeprecated = true; if (!mAnnotations.empty()) { @@ -63,14 +57,28 @@ void AnnotationProcessor::appendCommentLine(const StringPiece16& line) { void AnnotationProcessor::appendComment(const StringPiece16& comment) { // We need to process line by line to clean-up whitespace and append prefixes. for (StringPiece16 line : util::tokenize(comment, u'\n')) { - appendCommentLine(util::trimWhitespace(line)); + line = util::trimWhitespace(line); + if (!line.empty()) { + appendCommentLine(util::utf16ToUtf8(line)); + } + } +} + +void AnnotationProcessor::appendComment(const StringPiece& comment) { + for (StringPiece line : util::tokenize(comment, '\n')) { + line = util::trimWhitespace(line); + if (!line.empty()) { + appendCommentLine(line.toString()); + } } } std::string AnnotationProcessor::buildComment() { - mComment += "\n"; - mComment += mPrefix; - mComment += " */"; + if (!mComment.empty()) { + mComment += "\n"; + mComment += mPrefix; + mComment += " */"; + } return std::move(mComment); } diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h index b47210939d06..81a6f6e42759 100644 --- a/tools/aapt2/java/AnnotationProcessor.h +++ b/tools/aapt2/java/AnnotationProcessor.h @@ -65,6 +65,7 @@ public: * we need to collect all the comments. */ void appendComment(const StringPiece16& comment); + void appendComment(const StringPiece& comment); /** * Finishes the comment and moves it to the caller. Subsequent calls to buildComment() have @@ -85,7 +86,7 @@ private: bool mDeprecated = false; bool mSystemApi = false; - void appendCommentLine(const StringPiece16& line); + void appendCommentLine(const std::string& line); }; } // namespace aapt diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 0175489cf6ea..dfd2ef6f5372 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -18,6 +18,8 @@ #include "Resource.h" #include "ResourceTable.h" #include "ResourceValues.h" +#include "ValueVisitor.h" + #include "java/AnnotationProcessor.h" #include "java/JavaClassGenerator.h" #include "util/StringPiece.h" @@ -109,13 +111,13 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen std::sort(sortedAttributes.begin(), sortedAttributes.end()); // First we emit the array containing the IDs of each attribute. - *out << " " + *out << " " << "public static final int[] " << transform(entryName) << " = {"; const size_t attrCount = sortedAttributes.size(); for (size_t i = 0; i < attrCount; i++) { if (i % kAttribsPerLine == 0) { - *out << "\n "; + *out << "\n "; } *out << sortedAttributes[i].first; @@ -123,11 +125,11 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen *out << ", "; } } - *out << "\n };\n"; + *out << "\n };\n"; // Now we emit the indices into the array. for (size_t i = 0; i < attrCount; i++) { - *out << " " + *out << " " << "public static" << finalModifier << " int " << transform(entryName); @@ -141,6 +143,85 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen } } +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::generateType(const StringPiece16& packageNameToGenerate, const ResourceTablePackage* package, const ResourceTableType* type, @@ -186,7 +267,33 @@ bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate generateStyleable(packageNameToGenerate, unmangledName, static_cast<const Styleable*>( entry->values.front().value.get()), out); } else { - *out << " " << "public static" << finalModifier + AnnotationProcessor processor(" "); + if (entry->symbolStatus.state != SymbolState::kUndefined) { + processor.appendComment(entry->symbolStatus.comment); + } + + for (const auto& configValue : entry->values) { + processor.appendComment(configValue.value->getComment()); + } + + if (!entry->values.empty()) { + if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) { + // We list out the available values for the given attribute. + addAttributeFormatDoc(&processor, attr); + } + } + + std::string comment = processor.buildComment(); + if (!comment.empty()) { + *out << comment << "\n"; + } + + std::string annotations = processor.buildAnnotations(); + if (!annotations.empty()) { + *out << annotations << "\n"; + } + + *out << " " << "public static" << finalModifier << " int " << transform(unmangledName) << " = " << id << ";\n"; } } @@ -211,11 +318,11 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate, } else { typeStr = toString(type->type); } - *out << " public static final class " << typeStr << " {\n"; + *out << " public static final class " << typeStr << " {\n"; if (!generateType(packageNameToGenerate, package.get(), type.get(), out)) { return false; } - *out << " }\n"; + *out << " }\n"; } } diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp index 3625f9c340ed..2dc387bea8b9 100644 --- a/tools/aapt2/java/JavaClassGenerator_test.cpp +++ b/tools/aapt2/java/JavaClassGenerator_test.cpp @@ -198,4 +198,35 @@ TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) { EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar =")); } +TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) { + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() + .setPackageId(u"android", 0x01) + .addSimple(u"@android:id/foo", ResourceId(0x01010000)) + .build(); + test::getValue<Id>(table.get(), u"@android:id/foo") + ->setComment(std::u16string(u"This is a comment\n@deprecated")); + + JavaClassGenerator generator(table.get(), {}); + + std::stringstream out; + ASSERT_TRUE(generator.generate(u"android", &out)); + std::string actual = out.str(); + + EXPECT_NE(std::string::npos, actual.find( + R"EOF(/** + * This is a comment + * @deprecated + */ + @Deprecated + public static final int foo = 0x01010000;)EOF")); +} + +TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) { + +} + +TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) { + +} + } // namespace aapt |