summaryrefslogtreecommitdiff
path: root/tools/aapt2/java
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-10-30 16:31:42 -0700
committerAdam Lesinski <adamlesinski@google.com>2015-11-02 11:53:47 -0800
commit3b4cd94034ff3e5567a2ba6da35d640ff61db4b9 (patch)
tree83c604b9a3b0d1b25769a6afd16578fd97e6effe /tools/aapt2/java
parent104e028c3a180a4a151160299ad2e1a4185d6c50 (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.cpp30
-rw-r--r--tools/aapt2/java/AnnotationProcessor.h3
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp121
-rw-r--r--tools/aapt2/java/JavaClassGenerator_test.cpp31
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