migrate @JavaDebug to @JavaDerive(toString=true)
This will make it easier to add a new sythetic methods in the future.
Bug: 171271915
Test: aidl_unittests / aidl_integration_test
Change-Id: I043c1320821c1821faede60fa8608ff7cc79bd6c
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index a539589..c4229b6 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -51,7 +51,7 @@
// - a new implementation might start accepting null values (add @nullable)
static const set<AidlAnnotation::Type> kIgnoreAnnotations{
AidlAnnotation::Type::NULLABLE,
- AidlAnnotation::Type::JAVA_DEBUG,
+ AidlAnnotation::Type::JAVA_DERIVE,
AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
};
set<AidlAnnotation> annotations;
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 5162960..841e730 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -132,7 +132,7 @@
{AidlAnnotation::Type::HIDE, "Hide", {}, false},
{AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}, false},
{AidlAnnotation::Type::JAVA_PASSTHROUGH, "JavaPassthrough", {{"annotation", "String"}}, true},
- {AidlAnnotation::Type::JAVA_DEBUG, "JavaDebug", {}, false},
+ {AidlAnnotation::Type::JAVA_DERIVE, "JavaDerive", {{"toString", "boolean"}}, false},
{AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, "JavaOnlyImmutable", {}, false},
{AidlAnnotation::Type::FIXED_SIZE, "FixedSize", {}, false},
{AidlAnnotation::Type::DESCRIPTOR, "Descriptor", {{"value", "String"}}, false},
@@ -338,8 +338,8 @@
return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
}
-bool AidlAnnotatable::IsJavaDebug() const {
- return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEBUG);
+const AidlAnnotation* AidlAnnotatable::JavaDerive() const {
+ return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
}
std::string AidlAnnotatable::GetDescriptor() const {
@@ -886,7 +886,7 @@
AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
AidlAnnotation::Type::HIDE,
AidlAnnotation::Type::JAVA_PASSTHROUGH,
- AidlAnnotation::Type::JAVA_DEBUG,
+ AidlAnnotation::Type::JAVA_DERIVE,
AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
AidlAnnotation::Type::FIXED_SIZE,
AidlAnnotation::Type::RUST_DERIVE};
diff --git a/aidl_language.h b/aidl_language.h
index 1e8b600..73f2d66 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -165,7 +165,7 @@
NULLABLE,
UTF8_IN_CPP,
JAVA_PASSTHROUGH,
- JAVA_DEBUG,
+ JAVA_DERIVE,
JAVA_ONLY_IMMUTABLE,
FIXED_SIZE,
DESCRIPTOR,
@@ -240,7 +240,7 @@
bool IsFixedSize() const;
bool IsStableApiParcelable(Options::Language lang) const;
bool IsHide() const;
- bool IsJavaDebug() const;
+ const AidlAnnotation* JavaDerive() const;
std::string GetDescriptor() const;
void DumpAnnotations(CodeWriter* writer) const;
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index ab98eef..a734b77 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -459,7 +459,7 @@
const string method = "package a; @nullable parcelable IFoo { String a; String b; }";
const string expected_stderr =
"ERROR: a/IFoo.aidl:1.32-37: 'nullable' is not a supported annotation for this node. "
- "It must be one of: Hide, UnsupportedAppUsage, VintfStability, JavaPassthrough, JavaDebug, "
+ "It must be one of: Hide, UnsupportedAppUsage, VintfStability, JavaPassthrough, JavaDerive, "
"JavaOnlyImmutable, FixedSize, RustDerive\n";
CaptureStderr();
EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
@@ -580,9 +580,9 @@
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
-TEST_F(AidlTest, ParsesJavaDebugAnnotation) {
+TEST_F(AidlTest, ParsesJavaDeriveAnnotation) {
io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
- @JavaDebug parcelable IFoo { int a; float b; })");
+ @JavaDerive(toString=true) parcelable IFoo { int a; float b; })");
Options java_options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
@@ -598,26 +598,37 @@
EXPECT_EQ(0, ::android::aidl::compile_aidl(ndk_options, io_delegate_));
}
-TEST_F(AidlTest, RejectsJavaDebugAnnotation) {
+TEST_F(AidlTest, RejectsJavaDeriveAnnotation) {
{
- io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDebug interface IFoo{}");
+ io_delegate_.SetFileContents("a/Foo.aidl",
+ "package a; @JavaDerive(blah=true) parcelable Foo{}");
+ Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
+ CaptureStderr();
+ EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+ const std::string expected_stderr =
+ "ERROR: a/Foo.aidl:1.11-34: Parameter blah not supported for annotation JavaDerive.";
+ EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr(expected_stderr));
+ }
+
+ {
+ io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDerive interface IFoo{}");
Options java_options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
CaptureStderr();
EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
const std::string expected_stderr =
- "ERROR: a/IFoo.aidl:1.22-32: 'JavaDebug' is not a supported annotation for this node. "
+ "ERROR: a/IFoo.aidl:1.23-33: 'JavaDerive' is not a supported annotation for this node. "
"It must be one of: Hide, UnsupportedAppUsage, VintfStability, JavaPassthrough, "
"Descriptor\n";
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
{
- io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDebug enum IFoo { A=1, }");
+ io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDerive enum IFoo { A=1, }");
Options java_options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
CaptureStderr();
EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
const std::string expected_stderr =
- "ERROR: a/IFoo.aidl:1.27-32: 'JavaDebug' is not a supported annotation for this node. "
+ "ERROR: a/IFoo.aidl:1.28-33: 'JavaDerive' is not a supported annotation for this node. "
"It must be one of: Backing, Hide, VintfStability, JavaPassthrough\n";
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
diff --git a/generate_java.cpp b/generate_java.cpp
index 9b4191e..4d2d4f3 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -41,6 +41,9 @@
using std::vector;
namespace {
+using android::aidl::java::CodeGeneratorContext;
+using android::aidl::java::ConstantValueDecorator;
+
// join two non-empty strings according to `camelCase` naming.
inline string camelcase_join(const string& a, const string& b, const AidlNode& context) {
AIDL_FATAL_IF(b.size() <= 0 || a.size() <= 0, context) << "Name cannot be empty.";
@@ -204,6 +207,44 @@
GenerateDescribeContentsHelper(out, describers);
}
}
+
+void GenerateToString(CodeWriter& out, const AidlStructuredParcelable& parcel,
+ const AidlTypenames& typenames) {
+ out << "@Override\n";
+ out << "public String toString() {\n";
+ out.Indent();
+ out << "java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(";
+ out << "\", \", \"{\", \"}\");\n";
+ for (const auto& field : parcel.GetFields()) {
+ CodeGeneratorContext ctx{
+ .writer = out,
+ .typenames = typenames,
+ .type = field->GetType(),
+ .var = field->GetName(),
+ };
+ out << "_aidl_sj.add(\"" << field->GetName() << ": \" + (";
+ ToStringFor(ctx);
+ out << "));\n";
+ }
+ out << "return \"" << parcel.GetCanonicalName() << "\" + _aidl_sj.toString() ;\n";
+ out.Dedent();
+ out << "}\n";
+}
+
+template <typename ParcelableType>
+void GenerateDerivedMethods(CodeWriter& out, const ParcelableType& parcel,
+ const AidlTypenames& typenames) {
+ if (auto java_derive = parcel.JavaDerive(); java_derive) {
+ auto synthetic_methods = java_derive->AnnotationParams(ConstantValueDecorator);
+ for (const auto& [method_name, generate] : synthetic_methods) {
+ if (generate == "true") {
+ if (method_name == "toString") {
+ GenerateToString(out, parcel, typenames);
+ }
+ }
+ }
+ }
+}
} // namespace
namespace android {
@@ -537,31 +578,8 @@
parcel_class->elements.push_back(read_or_create_method);
- if (parcel->IsJavaDebug()) {
- out.str("");
- out << "@Override\n";
- out << "public String toString() {\n";
- out << " java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(";
- out << "\", \", \"{\", \"}\");\n";
- for (const auto& field : parcel->GetFields()) {
- std::string code;
- CodeWriterPtr writer = CodeWriter::ForString(&code);
- CodeGeneratorContext context{
- .writer = *(writer.get()),
- .typenames = typenames,
- .type = field->GetType(),
- .parcel = parcel_variable->name,
- .var = field->GetName(),
- .is_classloader_created = &is_classloader_created,
- };
- ToStringFor(context);
- writer->Close();
- out << " _aidl_sj.add(\"" << field->GetName() << ": \" + (" << code << "));\n";
- }
- out << " return \"" << parcel->GetCanonicalName() << "\" + _aidl_sj.toString() ;\n";
- out << "}\n";
- parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
- }
+ auto method = CodeWriter::RunWith(GenerateDerivedMethods, *parcel, typenames);
+ parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(method));
auto describe_contents_method =
CodeWriter::RunWith(GenerateParcelableDescribeContents, *parcel, typenames);
diff --git a/tests/android/aidl/tests/GenericStructuredParcelable.aidl b/tests/android/aidl/tests/GenericStructuredParcelable.aidl
index 6e71be5..af93692 100644
--- a/tests/android/aidl/tests/GenericStructuredParcelable.aidl
+++ b/tests/android/aidl/tests/GenericStructuredParcelable.aidl
@@ -16,7 +16,7 @@
package android.aidl.tests;
-@JavaDebug
+@JavaDerive(toString=true)
parcelable GenericStructuredParcelable<T, U, B> {
int a;
int b;
diff --git a/tests/android/aidl/tests/OtherParcelableForToString.aidl b/tests/android/aidl/tests/OtherParcelableForToString.aidl
index 8bff893..f042ab5 100644
--- a/tests/android/aidl/tests/OtherParcelableForToString.aidl
+++ b/tests/android/aidl/tests/OtherParcelableForToString.aidl
@@ -16,7 +16,7 @@
package android.aidl.tests;
-@JavaDebug
+@JavaDerive(toString=true)
parcelable OtherParcelableForToString {
String field;
}
diff --git a/tests/android/aidl/tests/ParcelableForToString.aidl b/tests/android/aidl/tests/ParcelableForToString.aidl
index 3647a34..cc9440b 100644
--- a/tests/android/aidl/tests/ParcelableForToString.aidl
+++ b/tests/android/aidl/tests/ParcelableForToString.aidl
@@ -21,7 +21,7 @@
import android.aidl.tests.OtherParcelableForToString;
import android.aidl.tests.IntEnum;
-@JavaDebug
+@JavaDerive(toString=true)
parcelable ParcelableForToString {
int intValue;
int[] intArray;
diff --git a/tests/android/aidl/tests/StructuredParcelable.aidl b/tests/android/aidl/tests/StructuredParcelable.aidl
index 514d728..a50bb15 100644
--- a/tests/android/aidl/tests/StructuredParcelable.aidl
+++ b/tests/android/aidl/tests/StructuredParcelable.aidl
@@ -21,7 +21,7 @@
import android.aidl.tests.LongEnum;
import android.aidl.tests.ConstantExpressionEnum;
-@JavaDebug
+@JavaDerive(toString=true)
@RustDerive(Clone=true, PartialEq=true)
parcelable StructuredParcelable {
int[] shouldContainThreeFs;