1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "AidlHelper.h"
18 #include "CompoundType.h"
19 #include "Coordinator.h"
20 #include "EnumType.h"
21 #include "Interface.h"
22 #include "NamedType.h"
23 #include "TypeDef.h"
24
25 namespace android {
26
emitConversionNotes(Formatter & out,const NamedType & namedType)27 static void emitConversionNotes(Formatter& out, const NamedType& namedType) {
28 out << "// This is the HIDL definition of " << namedType.fqName().string() << "\n";
29 out.pushLinePrefix("// ");
30 namedType.emitHidlDefinition(out);
31 out.popLinePrefix();
32 out << "\n";
33 }
34
emitTypeDefAidlDefinition(Formatter & out,const TypeDef & typeDef)35 static void emitTypeDefAidlDefinition(Formatter& out, const TypeDef& typeDef) {
36 out << "// Cannot convert typedef " << typeDef.referencedType()->definedName() << " "
37 << typeDef.fqName().string() << " since AIDL does not support typedefs.\n";
38 emitConversionNotes(out, typeDef);
39 }
40
emitEnumAidlDefinition(Formatter & out,const EnumType & enumType)41 static void emitEnumAidlDefinition(Formatter& out, const EnumType& enumType) {
42 const ScalarType* scalar = enumType.storageType()->resolveToScalarType();
43 CHECK(scalar != nullptr) << enumType.typeName();
44
45 enumType.emitDocComment(out);
46 out << "@VintfStability\n";
47 out << "@Backing(type=\"" << AidlHelper::getAidlType(*scalar, enumType.fqName()) << "\")\n";
48 out << "enum " << AidlHelper::getAidlType(enumType, enumType.fqName()) << " ";
49
50 std::vector<const EnumValue*> values;
51 const EnumType* skippedType = nullptr;
52 for (const EnumType* type : enumType.typeChain()) {
53 if (!AidlHelper::shouldBeExpanded(enumType.fqName(), type->fqName())) {
54 skippedType = type;
55 break;
56 }
57 values.insert(values.end(), type->values().rbegin(), type->values().rend());
58 }
59 out.block([&] {
60 if (skippedType != nullptr) {
61 out << "// Not expanding values from " << skippedType->fqName().string()
62 << ". See \'-e\' argument.\n";
63 }
64 for (auto it = values.rbegin(); it != values.rend(); ++it) {
65 (*it)->emitDocComment(out);
66 out << (*it)->name();
67 if (!(*it)->isAutoFill()) {
68 out << " = " << (*it)->constExpr()->expression();
69 }
70 out << ",\n";
71 };
72 });
73 out << "\n";
74 }
75
emitCompoundTypeAidlDefinition(Formatter & out,const CompoundType & compoundType,const std::map<const NamedType *,const ProcessedCompoundType> & processedTypes)76 static void emitCompoundTypeAidlDefinition(
77 Formatter& out, const CompoundType& compoundType,
78 const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
79 // Get all of the subtypes and fields from this type and any older versions
80 // that it references.
81 const auto& it = processedTypes.find(&compoundType);
82 CHECK(it != processedTypes.end()) << "Failed to find " << compoundType.fullName();
83 const ProcessedCompoundType& processedType = it->second;
84
85 compoundType.emitDocComment(out);
86 out << "@VintfStability\n";
87 if (compoundType.style() == CompoundType::STYLE_STRUCT) {
88 out << "parcelable " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
89 } else {
90 if (compoundType.style() == CompoundType::STYLE_UNION) {
91 out << "// FIXME Any discriminators should be removed since they are automatically "
92 "added.\n";
93 }
94 out << "union " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
95 }
96 out.block([&] {
97 // Emit all nested type definitions
98 for (auto const& type : processedType.subTypes) {
99 AidlHelper::emitAidl(*type, out, processedTypes);
100 }
101 // Emit all of the fields from the processed type
102 for (auto const& fieldWithVersion : processedType.fields) {
103 fieldWithVersion.field->emitDocComment(out);
104 std::string aidlType =
105 AidlHelper::getAidlType(*fieldWithVersion.field->get(), compoundType.fqName());
106 out << aidlType << " " << fieldWithVersion.field->name() << ";\n";
107 }
108 });
109 out << "\n";
110 }
111
emitAidl(const NamedType & namedType,Formatter & out,const std::map<const NamedType *,const ProcessedCompoundType> & processedTypes)112 void AidlHelper::emitAidl(
113 const NamedType& namedType, Formatter& out,
114 const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
115 if (namedType.isTypeDef()) {
116 const TypeDef& typeDef = static_cast<const TypeDef&>(namedType);
117 emitTypeDefAidlDefinition(out, typeDef);
118 } else if (namedType.isCompoundType()) {
119 const CompoundType& compoundType = static_cast<const CompoundType&>(namedType);
120 emitCompoundTypeAidlDefinition(out, compoundType, processedTypes);
121 } else if (namedType.isEnum()) {
122 const EnumType& enumType = static_cast<const EnumType&>(namedType);
123 emitEnumAidlDefinition(out, enumType);
124 } else if (namedType.isInterface()) {
125 const Interface& iface = static_cast<const Interface&>(namedType);
126 emitAidl(iface, out, processedTypes);
127 } else {
128 out << "// TODO: Fix this " << namedType.definedName() << "\n";
129 }
130 }
131
132 } // namespace android
133