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