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 }
74
emitCompoundTypeAidlDefinition(Formatter & out,const CompoundType & compoundType,const std::map<const NamedType *,const ProcessedCompoundType> & processedTypes)75 static void emitCompoundTypeAidlDefinition(
76 Formatter& out, const CompoundType& compoundType,
77 const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
78 // Get all of the subtypes and fields from this type and any older versions
79 // that it references.
80 const auto& it = processedTypes.find(&compoundType);
81 CHECK(it != processedTypes.end()) << "Failed to find " << compoundType.fullName();
82 const ProcessedCompoundType& processedType = it->second;
83
84 compoundType.emitDocComment(out);
85 out << "@VintfStability\n";
86 if (compoundType.style() == CompoundType::STYLE_STRUCT) {
87 out << "parcelable " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
88 } else {
89 if (compoundType.style() == CompoundType::STYLE_UNION) {
90 out << "// FIXME Any discriminators should be removed since they are automatically "
91 "added.\n";
92 }
93 out << "union " << AidlHelper::getAidlName(compoundType.fqName()) << " ";
94 }
95 out.block([&] {
96 // Emit all of the fields from the processed type
97 for (auto const& fieldWithVersion : processedType.fields) {
98 fieldWithVersion.field->emitDocComment(out);
99 std::string aidlType =
100 AidlHelper::getAidlType(*fieldWithVersion.field->get(), compoundType.fqName());
101 out << aidlType << " " << fieldWithVersion.field->name() << ";\n";
102 }
103 });
104 out << "\n\n";
105 }
106
107 // TODO: Enum/Typedef should just emit to hidl-error.log or similar
emitAidl(const NamedType & namedType,const Coordinator & coordinator,const std::map<const NamedType *,const ProcessedCompoundType> & processedTypes)108 void AidlHelper::emitAidl(
109 const NamedType& namedType, const Coordinator& coordinator,
110 const std::map<const NamedType*, const ProcessedCompoundType>& processedTypes) {
111 Formatter out = getFileWithHeader(namedType, coordinator, processedTypes);
112 if (namedType.isTypeDef()) {
113 const TypeDef& typeDef = static_cast<const TypeDef&>(namedType);
114 emitTypeDefAidlDefinition(out, typeDef);
115 } else if (namedType.isCompoundType()) {
116 const CompoundType& compoundType = static_cast<const CompoundType&>(namedType);
117 emitCompoundTypeAidlDefinition(out, compoundType, processedTypes);
118 } else if (namedType.isEnum()) {
119 const EnumType& enumType = static_cast<const EnumType&>(namedType);
120 emitEnumAidlDefinition(out, enumType);
121 } else if (namedType.isInterface()) {
122 const Interface& iface = static_cast<const Interface&>(namedType);
123 emitAidl(iface, coordinator, processedTypes);
124 } else {
125 out << "// TODO: Fix this " << namedType.definedName() << "\n";
126 }
127 }
128
129 } // namespace android
130