diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 8e7045bd07e11..e6407332bb900 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -2255,6 +2255,9 @@ static status_t writeLayoutClasses( if (comment.size() <= 0) { comment = getAttributeComment(assets, name8); } + if (comment.contains(u"@removed")) { + continue; + } if (comment.size() > 0) { const char16_t* p = comment.string(); while (*p != 0 && *p != '.') { diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 24347a1cdc1ef..84df0b429fc5b 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -284,6 +284,13 @@ void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& package continue; } + StringPiece16 attrCommentLine = entry.symbol->attribute->getComment(); + if (attrCommentLine.contains(StringPiece16(u"@removed"))) { + // Removed attributes are public but hidden from the documentation, so don't emit + // them as part of the class documentation. + continue; + } + const ResourceName& attrName = entry.attrRef->name.value(); styleableComment << "
{@link #"
@@ -299,7 +306,6 @@ void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& package
// Only use the comment up until the first '.'. This is to stay compatible with
// the way old AAPT did it (presumably to keep it short and to avoid including
// annotations like @hide which would affect this Styleable).
- StringPiece16 attrCommentLine = entry.symbol->attribute->getComment();
auto iter = std::find(attrCommentLine.begin(), attrCommentLine.end(), u'.');
if (iter != attrCommentLine.end()) {
attrCommentLine = attrCommentLine.substr(
@@ -348,6 +354,17 @@ void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& package
continue;
}
+ StringPiece16 comment = styleableAttr.attrRef->getComment();
+ if (styleableAttr.symbol->attribute && comment.empty()) {
+ comment = styleableAttr.symbol->attribute->getComment();
+ }
+
+ if (comment.contains(StringPiece16(u"@removed"))) {
+ // Removed attributes are public but hidden from the documentation, so don't emit them
+ // as part of the class documentation.
+ continue;
+ }
+
const ResourceName& attrName = styleableAttr.attrRef->name.value();
StringPiece16 packageName = attrName.package;
@@ -360,11 +377,6 @@ void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& package
AnnotationProcessor* attrProcessor = indexMember->getCommentBuilder();
- StringPiece16 comment = styleableAttr.attrRef->getComment();
- if (styleableAttr.symbol->attribute && comment.empty()) {
- comment = styleableAttr.symbol->attribute->getComment();
- }
-
if (!comment.empty()) {
attrProcessor->appendComment("\n@attr description");
attrProcessor->appendComment(comment);
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 7d0aa83a0fb84..46266b3f3e89f 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -289,4 +289,37 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)
EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
}
+TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
+ Attribute attr(false);
+ attr.setComment(StringPiece16(u"@removed"));
+
+
+ std::unique_ptr table = test::ResourceTableBuilder()
+ .setPackageId(u"android", 0x01)
+ .addValue(u"@android:attr/one", util::make_unique(attr))
+ .build();
+
+ std::unique_ptr context = test::ContextBuilder()
+ .addSymbolSource(util::make_unique(table.get()))
+ .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+ .build();
+ JavaClassGeneratorOptions options;
+ options.useFinal = false;
+ JavaClassGenerator generator(context.get(), table.get(), options);
+ std::stringstream out;
+ ASSERT_TRUE(generator.generate(u"android", &out));
+ std::string actual = out.str();
+
+ std::cout << actual << std::endl;
+
+ EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
+ EXPECT_EQ(std::string::npos, actual.find("@attr description"));
+
+ // We should find @removed only in the attribute javadoc and not anywhere else (i.e. the class
+ // javadoc).
+ const size_t pos = actual.find("@removed");
+ EXPECT_NE(std::string::npos, pos);
+ EXPECT_EQ(std::string::npos, actual.find("@removed", pos + 1));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/util/StringPiece.h b/tools/aapt2/util/StringPiece.h
index 31deb452b53c4..f91bccc93019e 100644
--- a/tools/aapt2/util/StringPiece.h
+++ b/tools/aapt2/util/StringPiece.h
@@ -57,6 +57,7 @@ public:
bool empty() const;
std::basic_string toString() const;
+ bool contains(const BasicStringPiece& rhs) const;
int compare(const BasicStringPiece& rhs) const;
bool operator<(const BasicStringPiece& rhs) const;
bool operator>(const BasicStringPiece& rhs) const;
@@ -163,6 +164,17 @@ inline std::basic_string BasicStringPiece::toString() const {
return std::basic_string(mData, mLength);
}
+template <>
+inline bool BasicStringPiece::contains(const BasicStringPiece& rhs) const {
+ if (!mData || !rhs.mData) {
+ return false;
+ }
+ if (rhs.mLength > mLength) {
+ return false;
+ }
+ return strstr(mData, rhs.mData) != nullptr;
+}
+
template <>
inline int BasicStringPiece::compare(const BasicStringPiece& rhs) const {
const char nullStr = '\0';
@@ -185,6 +197,16 @@ inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece
+inline bool BasicStringPiece::contains(const BasicStringPiece& rhs) const {
+ if (!mData || !rhs.mData) {
+ return false;
+ }
+ if (rhs.mLength > mLength) {
+ return false;
+ }
+ return strstr16(mData, rhs.mData) != nullptr;
+}
template <>
inline int BasicStringPiece::compare(const BasicStringPiece& rhs) const {
diff --git a/tools/aapt2/util/StringPiece_test.cpp b/tools/aapt2/util/StringPiece_test.cpp
index d49b67ffa88eb..853a9a46fde82 100644
--- a/tools/aapt2/util/StringPiece_test.cpp
+++ b/tools/aapt2/util/StringPiece_test.cpp
@@ -59,4 +59,36 @@ TEST(StringPieceTest, PiecesHaveCorrectSortOrderUtf8) {
EXPECT_TRUE(StringPiece(car) > banana);
}
+TEST(StringPieceTest, ContainsOtherStringPiece) {
+ StringPiece text("I am a leaf on the wind.");
+ StringPiece startNeedle("I am");
+ StringPiece endNeedle("wind.");
+ StringPiece middleNeedle("leaf");
+ StringPiece emptyNeedle("");
+ StringPiece missingNeedle("soar");
+ StringPiece longNeedle("This string is longer than the text.");
+
+ EXPECT_TRUE(text.contains(startNeedle));
+ EXPECT_TRUE(text.contains(endNeedle));
+ EXPECT_TRUE(text.contains(middleNeedle));
+ EXPECT_TRUE(text.contains(emptyNeedle));
+ EXPECT_FALSE(text.contains(missingNeedle));
+ EXPECT_FALSE(text.contains(longNeedle));
+
+ StringPiece16 text16(u"I am a leaf on the wind.");
+ StringPiece16 startNeedle16(u"I am");
+ StringPiece16 endNeedle16(u"wind.");
+ StringPiece16 middleNeedle16(u"leaf");
+ StringPiece16 emptyNeedle16(u"");
+ StringPiece16 missingNeedle16(u"soar");
+ StringPiece16 longNeedle16(u"This string is longer than the text.");
+
+ EXPECT_TRUE(text16.contains(startNeedle16));
+ EXPECT_TRUE(text16.contains(endNeedle16));
+ EXPECT_TRUE(text16.contains(middleNeedle16));
+ EXPECT_TRUE(text16.contains(emptyNeedle16));
+ EXPECT_FALSE(text16.contains(missingNeedle16));
+ EXPECT_FALSE(text16.contains(longNeedle16));
+}
+
} // namespace aapt