diff options
author | Jooyung Han <jooyung@google.com> | 2020-10-15 16:41:38 +0900 |
---|---|---|
committer | Jooyung Han <jooyung@google.com> | 2020-10-18 09:25:52 +0900 |
commit | 97945de2f0749ee1e1c4086582be2f89aab37ec8 (patch) | |
tree | 4c3e9a68f1e20890574e22ba2e7e54f6d1a3e7f5 | |
parent | 14004ed5555139f95c7fa2f5b592d1db9993baf8 (diff) | |
download | aidl-97945de2f0749ee1e1c4086582be2f89aab37ec8.tar.gz |
fix format for union output (C++/Java)
- spacing between members
- use C++-style casting instead of C-style
- rename C++ internal names to use underscore prefix
e.g. template <typename _Tp> ..
- and fix a silly mistake (hard-coded constructor Union)
Bug: 150948558
Test: aidl_unittests / aidl_integration_test
Change-Id: Id2bc916760dbd0f0f5257996be135df5c8474931
-rw-r--r-- | aidl_unittest.cpp | 152 | ||||
-rw-r--r-- | generate_cpp.cpp | 80 | ||||
-rw-r--r-- | generate_java.cpp | 50 |
3 files changed, 158 insertions, 124 deletions
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp index 470b09d0..ddfa0a5c 100644 --- a/aidl_unittest.cpp +++ b/aidl_unittest.cpp @@ -2709,73 +2709,76 @@ namespace a { class Foo : public ::android::Parcelable { public: - inline bool operator!=([[maybe_unused]] const Foo& rhs) const { - return _value!=rhs._value; + inline bool operator!=(const Foo& rhs) const { + return _value != rhs._value; } - inline bool operator<([[maybe_unused]] const Foo& rhs) const { - return _value<rhs._value; + inline bool operator<(const Foo& rhs) const { + return _value < rhs._value; } - inline bool operator<=([[maybe_unused]] const Foo& rhs) const { - return _value<=rhs._value; + inline bool operator<=(const Foo& rhs) const { + return _value <= rhs._value; } - inline bool operator==([[maybe_unused]] const Foo& rhs) const { - return _value==rhs._value; + inline bool operator==(const Foo& rhs) const { + return _value == rhs._value; } - inline bool operator>([[maybe_unused]] const Foo& rhs) const { - return _value>rhs._value; + inline bool operator>(const Foo& rhs) const { + return _value > rhs._value; } - inline bool operator>=([[maybe_unused]] const Foo& rhs) const { - return _value>=rhs._value; + inline bool operator>=(const Foo& rhs) const { + return _value >= rhs._value; } + enum Tag : int32_t { - // int[] ns - ns = 0, - // a.ByteEnum e - e, + ns = 0, // int[] ns; + e, // a.ByteEnum e; }; + template<typename _Tp> - static constexpr bool not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Foo>; + static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Foo>; Foo() : _value(std::in_place_index<ns>, ::std::vector<int32_t>({42})) { } - Foo(const Foo& other) = default; - Foo(Foo&& other) = default; + Foo(const Foo&) = default; + Foo(Foo&&) = default; Foo& operator=(const Foo&) = default; Foo& operator=(Foo&&) = default; - template <typename T, std::enable_if_t<not_self<T>, int> = 0> - constexpr Foo(T&& arg) - : _value(std::forward<T>(arg)) {} - template <typename... T> - constexpr explicit Foo(T&&... args) - : _value(std::forward<T>(args)...) {} - template <Tag tag, typename... T> - static Foo make(T&&... args) { - return Foo(std::in_place_index<tag>, std::forward<T>(args)...); + template <typename _Tp, std::enable_if_t<_not_self<_Tp>, int> = 0> + constexpr Foo(_Tp&& _arg) + : _value(std::forward<_Tp>(_arg)) {} + + template <typename... _Tp> + constexpr explicit Foo(_Tp&&... _args) + : _value(std::forward<_Tp>(_args)...) {} + + template <Tag _tag, typename... _Tp> + static Foo make(_Tp&&... _args) { + return Foo(std::in_place_index<_tag>, std::forward<_Tp>(_args)...); } - template <Tag tag, typename T, typename... U> - static Foo make(std::initializer_list<T> il, U&&... args) { - return Foo(std::in_place_index<tag>, std::move(il), std::forward<U>(args)...); + + template <Tag _tag, typename _Tp, typename... _Up> + static Foo make(std::initializer_list<_Tp> _il, _Up&&... _args) { + return Foo(std::in_place_index<_tag>, std::move(_il), std::forward<_Up>(_args)...); } Tag getTag() const { - return (Tag)_value.index(); + return static_cast<Tag>(_value.index()); } - template <Tag tag> + template <Tag _tag> const auto& get() const { - if (getTag() != tag) { abort(); } - return std::get<tag>(_value); + if (getTag() != _tag) { abort(); } + return std::get<_tag>(_value); } - template <Tag tag> + template <Tag _tag> auto& get() { - if (getTag() != tag) { abort(); } - return std::get<tag>(_value); + if (getTag() != _tag) { abort(); } + return std::get<_tag>(_value); } - template <Tag tag, typename... T> - void set(T&&... args) { - _value.emplace<tag>(std::forward<T>(args)...); + template <Tag _tag, typename... _Tp> + void set(_Tp&&... _args) { + _value.emplace<_tag>(std::forward<_Tp>(_args)...); } ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) override final; @@ -2785,7 +2788,7 @@ public: return DESCIPTOR; } private: - std::variant<::std::vector<int32_t>,::a::ByteEnum> _value; + std::variant<::std::vector<int32_t>, ::a::ByteEnum> _value; }; // class Foo } // namespace a @@ -2834,9 +2837,9 @@ package a; public final class Foo implements android.os.Parcelable { - // tags union fields - public final static int ns = 0; // int[] - public final static int e = 1; // a.ByteEnum + // tags for union fields + public final static int ns = 0; // int[] ns; + public final static int e = 1; // a.ByteEnum e; private int _tag; private Object _value; @@ -2845,9 +2848,11 @@ public final class Foo implements android.os.Parcelable { int[] value = {42}; _set(ns, value); } + private Foo(android.os.Parcel _aidl_parcel) { readFromParcel(_aidl_parcel); } + private Foo(int tag, Object value) { _set(tag, value); } @@ -2856,28 +2861,32 @@ public final class Foo implements android.os.Parcelable { return _tag; } - // int[] ns + // int[] ns; public static Foo ns(int[] _value) { return new Foo(ns, _value); } + public int[] getNs() { _assertTag(ns); return (int[]) _value; } + public void setNs(int[] _value) { _set(ns, _value); } - // a.ByteEnum e + // a.ByteEnum e; public static Foo e(byte _value) { return new Foo(e, _value); } + public byte getE() { _assertTag(e); return (byte) _value; } + public void setE(byte _value) { _set(e, _value); } @@ -2885,13 +2894,14 @@ public final class Foo implements android.os.Parcelable { public static final android.os.Parcelable.Creator<Foo> CREATOR = new android.os.Parcelable.Creator<Foo>() { @Override public Foo createFromParcel(android.os.Parcel _aidl_source) { - return new Union(_aidl_source); + return new Foo(_aidl_source); } @Override public Foo[] newArray(int _aidl_size) { return new Foo[_aidl_size]; } }; + @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) { _aidl_parcel.writeInt(_tag); @@ -2904,6 +2914,7 @@ public final class Foo implements android.os.Parcelable { break; } } + public void readFromParcel(android.os.Parcel _aidl_parcel) { int _aidl_tag; _aidl_tag = _aidl_parcel.readInt(); @@ -2921,6 +2932,7 @@ public final class Foo implements android.os.Parcelable { } throw new RuntimeException("union: out of range: " + _aidl_tag); } + @Override public int describeContents() { return 0; @@ -2931,6 +2943,7 @@ public final class Foo implements android.os.Parcelable { throw new IllegalStateException("bad access: " + _tagString(tag) + ", " + _tagString(getTag()) + " is available."); } } + private String _tagString(int _tag) { switch (_tag) { case ns: return "ns"; @@ -2938,6 +2951,7 @@ public final class Foo implements android.os.Parcelable { } throw new IllegalStateException("unknown field: " + _tag); } + private void _set(int tag, Object value) { this._tag = tag; this._value = value; @@ -2945,8 +2959,9 @@ public final class Foo implements android.os.Parcelable { } )"; -TEST_F(AidlTest, UnionExample) { - io_delegate_.SetFileContents("a/Foo.aidl", R"( +struct AidlUnionTest : ::testing::Test { + void SetUp() override { + io_delegate_.SetFileContents("a/Foo.aidl", R"( package a; import a.ByteEnum; union Foo { @@ -2954,32 +2969,47 @@ union Foo { ByteEnum e; } )"); - io_delegate_.SetFileContents("a/ByteEnum.aidl", R"( + io_delegate_.SetFileContents("a/ByteEnum.aidl", R"( package a; @Backing(type="byte") enum ByteEnum { a, b, c } )"); - - auto EXPECT_COMPILE_OUTPUT = [&](string lang, auto output) { - auto opts = Options::From("aidl a/Foo.aidl -I . --out=out --header_out=out --lang=" + lang); + } + FakeIoDelegate io_delegate_; + void Compile(string lang) { + string command = "aidl --structured -I. -o out --lang=" + lang; + if (lang == "cpp" || lang == "ndk") { + command += " -h out"; + } + command += " a/Foo.aidl"; + auto opts = Options::From(command); CaptureStderr(); auto ret = ::android::aidl::compile_aidl(opts, io_delegate_); auto err = GetCapturedStderr(); EXPECT_EQ(0, ret) << err; - for (const auto& [path, expected] : output) { + } + void EXPECT_COMPILE_OUTPUTS(const map<string, string>& outputs) { + for (const auto& [path, expected] : outputs) { string actual; EXPECT_TRUE(io_delegate_.GetWrittenContents(path, &actual)) << path << " not found."; EXPECT_EQ(expected, actual); } - }; + } +}; + +TEST_F(AidlUnionTest, Example_Cpp) { + Compile("cpp"); + EXPECT_COMPILE_OUTPUTS( + map<string, string>({{"out/a/Foo.cpp", kUnionExampleExpectedOutputCppSource}, + {"out/a/Foo.h", kUnionExampleExpectedOutputCppHeader}})); +} - EXPECT_COMPILE_OUTPUT( - "cpp", map<string, string>({{"out/a/Foo.cpp", kUnionExampleExpectedOutputCppSource}, - {"out/a/Foo.h", kUnionExampleExpectedOutputCppHeader}})); - EXPECT_COMPILE_OUTPUT("java", - map<string, string>({{"out/a/Foo.java", kUnionExampleExpectedOutputJava}})); +TEST_F(AidlUnionTest, Example_Java) { + Compile("java"); + EXPECT_COMPILE_OUTPUTS( + map<string, string>({{"out/a/Foo.java", kUnionExampleExpectedOutputJava}})); // TODO(b/170784707) NDK // TODO(b/170689477) Rust } diff --git a/generate_cpp.cpp b/generate_cpp.cpp index 447c6fca..ad323522 100644 --- a/generate_cpp.cpp +++ b/generate_cpp.cpp @@ -1155,15 +1155,18 @@ struct ParcelableTraits<AidlUnionDecl> { const AidlTypenames& typenames) { AidlTypeSpecifier tag_type(AIDL_LOCATION_HERE, "int", /* is_array= */ false, /* type_params= */ nullptr, /* comments= */ ""); - auto enum_tag = - std::make_unique<Enum>("Tag", CppNameOf(tag_type, typenames), /* is_class= */ false); + tag_type.Resolve(typenames); + + std::ostringstream out; + out << "enum Tag : " << CppNameOf(tag_type, typenames) << " {\n"; bool is_first = true; for (const auto& f : decl.GetFields()) { - auto raw_decl = f->Signature(); - enum_tag->AddValue(f->GetName(), is_first ? "0" : "", "// " + raw_decl); + out << " " << f->GetName() << (is_first ? " = 0" : "") << ", // " << f->Signature() + << ";\n"; is_first = false; } - clazz.AddPublic(std::move(enum_tag)); + out << "};\n\n"; + clazz.AddPublic(std::make_unique<LiteralDecl>(out.str())); const auto& name = decl.GetName(); @@ -1176,62 +1179,62 @@ struct ParcelableTraits<AidlUnionDecl> { auto helper_methods = vector<string>{ // type classification "template<typename _Tp>\n" - "static constexpr bool not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, " + name + ">;\n\n", + "static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, " + name + ">;\n\n", // default ctor inits with the first member's default value name + "() : _value(std::in_place_index<" + first_name + ">, " + first_value + ") { }\n", // other ctors with default implementation - name + "(const " + name + "& other) = default;\n", - name + "(" + name + "&& other) = default;\n", + name + "(const " + name + "&) = default;\n", + name + "(" + name + "&&) = default;\n", name + "& operator=(const " + name + "&) = default;\n", name + "& operator=(" + name + "&&) = default;\n\n", // conversion ctor from value - "template <typename T, std::enable_if_t<not_self<T>, int> = 0>\n" - "constexpr " + name + "(T&& arg)\n" - " : _value(std::forward<T>(arg)) {}\n", + "template <typename _Tp, std::enable_if_t<_not_self<_Tp>, int> = 0>\n" + "constexpr " + name + "(_Tp&& _arg)\n" + " : _value(std::forward<_Tp>(_arg)) {}\n\n", // ctor to support in-place construction using in_place_index/in_place_type - "template <typename... T>\n" - "constexpr explicit " + name + "(T&&... args)\n" - " : _value(std::forward<T>(args)...) {}\n", + "template <typename... _Tp>\n" + "constexpr explicit " + name + "(_Tp&&... _args)\n" + " : _value(std::forward<_Tp>(_args)...) {}\n\n", // value ctor: make<tag>(args...) - "template <Tag tag, typename... T>\n" - "static " + name + " make(T&&... args) {\n" - " return " + name + "(std::in_place_index<tag>, std::forward<T>(args)...);\n" - "}\n", + "template <Tag _tag, typename... _Tp>\n" + "static " + name + " make(_Tp&&... _args) {\n" + " return " + name + "(std::in_place_index<_tag>, std::forward<_Tp>(_args)...);\n" + "}\n\n", // value ctor: make<tag>({initializer_list}) - "template <Tag tag, typename T, typename... U>\n" - "static " + name + " make(std::initializer_list<T> il, U&&... args) {\n" - " return " + name + "(std::in_place_index<tag>, std::move(il), std::forward<U>(args)...);\n" + "template <Tag _tag, typename _Tp, typename... _Up>\n" + "static " + name + " make(std::initializer_list<_Tp> _il, _Up&&... _args) {\n" + " return " + name + "(std::in_place_index<_tag>, std::move(_il), std::forward<_Up>(_args)...);\n" "}\n\n", // getTag "Tag getTag() const {\n" - " return (Tag)_value.index();\n" + " return static_cast<Tag>(_value.index());\n" "}\n\n", // const-getter - "template <Tag tag>\n" + "template <Tag _tag>\n" "const auto& get() const {\n" - " if (getTag() != tag) { abort(); }\n" - " return std::get<tag>(_value);\n" + " if (getTag() != _tag) { abort(); }\n" + " return std::get<_tag>(_value);\n" "}\n\n", // getter - "template <Tag tag>\n" + "template <Tag _tag>\n" "auto& get() {\n" - " if (getTag() != tag) { abort(); }\n" - " return std::get<tag>(_value);\n" + " if (getTag() != _tag) { abort(); }\n" + " return std::get<_tag>(_value);\n" "}\n\n", // setter - "template <Tag tag, typename... T>\n" - "void set(T&&... args) {\n" - " _value.emplace<tag>(std::forward<T>(args)...);\n" + "template <Tag _tag, typename... _Tp>\n" + "void set(_Tp&&... _args) {\n" + " _value.emplace<_tag>(std::forward<_Tp>(_args)...);\n" "}\n\n", }; // clang-format on @@ -1244,7 +1247,7 @@ struct ParcelableTraits<AidlUnionDecl> { field_types.push_back(CppNameOf(f->GetType(), typenames)); } clazz.AddPrivate( - std::make_unique<LiteralDecl>("std::variant<" + Join(field_types, ",") + "> _value;\n")); + std::make_unique<LiteralDecl>("std::variant<" + Join(field_types, ", ") + "> _value;\n")); } static void GenReadFromParcel(const AidlUnionDecl& parcel, const AidlTypenames& typenames, StatementBlock* read_block) { @@ -1336,15 +1339,16 @@ std::unique_ptr<Document> BuildParcelHeader(const AidlTypenames& typenames, cons set<string> operators = {"<", ">", "==", ">=", "<=", "!="}; string lhs = Traits::GetComparable(parcel, ""); string rhs = Traits::GetComparable(parcel, "rhs."); + bool is_empty = parcel.GetFields().empty(); + std::ostringstream operator_code; for (const auto& op : operators) { - std::ostringstream operator_code; - operator_code << "inline bool operator" << op << "([[maybe_unused]] const " << parcel.GetName() - << "& rhs) const {\n" - << " return " << lhs << op << rhs << ";\n" + operator_code << "inline bool operator" << op << "(const " << parcel.GetName() << "&" + << (is_empty ? "" : " rhs") << ") const {\n" + << " return " << lhs << " " << op << " " << rhs << ";\n" << "}\n"; - - parcel_class->AddPublic(std::make_unique<LiteralDecl>(operator_code.str())); } + operator_code << "\n"; + parcel_class->AddPublic(std::make_unique<LiteralDecl>(operator_code.str())); Traits::AddFields(*parcel_class, parcel, typenames); diff --git a/generate_java.cpp b/generate_java.cpp index daf4147b..aeeea816 100644 --- a/generate_java.cpp +++ b/generate_java.cpp @@ -470,11 +470,11 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out.Indent(); size_t tag_index = 0; - out << "// tags union fields\n"; + out << "// tags for union fields\n"; for (const auto& variable : decl->GetFields()) { - auto raw_type = variable->GetType().ToString(); + auto signature = variable->Signature() + ";"; out << "public final static " + tag_type + " " + variable->GetName() + " = " + - std::to_string(tag_index++) + "; // " + raw_type + "\n"; + std::to_string(tag_index++) + "; // " + signature + "\n"; } out << "\n"; @@ -493,35 +493,35 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out << first_type + " value = " << (first_value.empty() ? "null" : first_value) << ";\n"; out << "_set(" + first_field->GetName() + ", value);\n"; out.Dedent(); - out << "}\n"; + out << "}\n\n"; + // ctor(Parcel) out << "private " + clazz + "(android.os.Parcel _aidl_parcel) {\n"; out << " readFromParcel(_aidl_parcel);\n"; - out << "}\n"; + out << "}\n\n"; + // ctor(tag, value) out << "private " + clazz + "(" + tag_type + " tag, Object value) {\n"; out << " _set(tag, value);\n"; - out << "}\n"; - out << "\n"; + out << "}\n\n"; // getTag() out << "public " + tag_type + " " + "getTag() {\n"; out << " return " + tag_name + ";\n"; - out << "}\n"; - out << "\n"; + out << "}\n\n"; // value ctor, getter, setter for each field for (const auto& variable : decl->GetFields()) { auto var_name = variable->GetName(); auto var_type = JavaSignatureOf(variable->GetType(), typenames); - auto raw_type = variable->GetType().ToString(); - out << "// " + raw_type + " " + var_name + "\n"; + out << "// " + variable->Signature() + ";\n"; // value ctor out << variable->GetType().GetComments() + "\n"; out << "public static " + clazz + " " + var_name + "(" + var_type + " " + value_name + ") {\n"; out << " return new " + clazz + "(" + var_name + ", " + value_name + ");\n"; - out << "}\n"; + out << "}\n\n"; + // getter if (variable->GetType().IsGeneric()) { out << "@SuppressWarnings(\"unchecked\")\n"; @@ -529,33 +529,32 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out << "public " + var_type + " " + getter_name(*variable) + "() {\n"; out << " _assertTag(" + var_name + ");\n"; out << " return (" + var_type + ") " + value_name + ";\n"; - out << "}\n"; + out << "}\n\n"; + // setter out << "public void " + setter_name(*variable) + "(" + var_type + " " + value_name + ") {\n"; out << " _set(" + var_name + ", " + value_name + ");\n"; - out << "}\n"; - out << "\n"; + out << "}\n\n"; } if (decl->IsVintfStability()) { out << "@Override\n"; out << "public final int getStability() {\n"; out << " return android.os.Parcelable.PARCELABLE_STABILITY_VINTF;\n"; - out << "}\n"; - out << "\n"; + out << "}\n\n"; } out << "public static final android.os.Parcelable.Creator<" << clazz << "> CREATOR = " << "new android.os.Parcelable.Creator<" << clazz << ">() {\n"; out << " @Override\n"; out << " public " << clazz << " createFromParcel(android.os.Parcel _aidl_source) {\n"; - out << " return new Union(_aidl_source);\n"; // to avoid unnecessary allocation of "default" + out << " return new " << clazz << "(_aidl_source);\n"; out << " }\n"; out << " @Override\n"; out << " public " << clazz << "[] newArray(int _aidl_size) {\n"; out << " return new " << clazz << "[_aidl_size];\n"; out << " }\n"; - out << "};\n"; + out << "};\n\n"; auto write_to_parcel = [&](const AidlTypeSpecifier& type, std::string name, std::string parcel) { string code; @@ -584,7 +583,7 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out << " break;\n"; } out << " }\n"; - out << "}\n"; + out << "}\n\n"; // keep this across different fields in order to create the classloader // at most once. @@ -621,13 +620,12 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena } out << " }\n"; out << " throw new RuntimeException(\"union: out of range: \" + _aidl_tag);\n"; - out << "}\n"; + out << "}\n\n"; out << "@Override\n"; out << "public int describeContents() {\n"; out << " return 0;\n"; - out << "}\n"; - out << "\n"; + out << "}\n\n"; // helper: _assertTag out << "private void _assertTag(" + tag_type + " tag) {\n"; @@ -635,7 +633,8 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out << " throw new IllegalStateException(\"bad access: \" + _tagString(tag) + \", \" + " "_tagString(getTag()) + \" is available.\");\n"; out << " }\n"; - out << "}\n"; + out << "}\n\n"; + // helper: _tagString out << "private String _tagString(" + tag_type + " " + tag_name + ") {\n"; out << " switch (" + tag_name + ") {\n"; @@ -645,7 +644,8 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena } out << " }\n"; out << " throw new IllegalStateException(\"unknown field: \" + " + tag_name + ");\n"; - out << "}\n"; + out << "}\n\n"; + // helper: _set out << "private void _set(" + tag_type + " tag, Object value) {\n"; out << " this." + tag_name + " = tag;\n"; |