1 /*
2  * Copyright (C) 2021, 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 "preprocess.h"
18 
19 #include <android-base/strings.h>
20 
21 #include "aidl.h"
22 
23 using android::base::Join;
24 
25 namespace android {
26 namespace aidl {
27 
28 namespace {
29 // PreprocessVisitor emits
30 // - types including comments(hide/deprecated) and annotations
31 // - constant delcarations for interface/parcelable/unions
32 // - enumerators for enums
33 struct PreprocessVisitor : AidlVisitor {
34   CodeWriter& out;
PreprocessVisitorandroid::aidl::__anonaede7f330111::PreprocessVisitor35   PreprocessVisitor(CodeWriter& out) : out(out) {}
36 
DumpTypeandroid::aidl::__anonaede7f330111::PreprocessVisitor37   void DumpType(const AidlDefinedType& dt, const string& type) {
38     DumpComments(dt);
39     DumpAnnotations(dt);
40     // Top-level definition emits canonical name while nested type emits "name" only.
41     if (dt.GetParentType()) {
42       out << type << " " << dt.GetName();
43     } else {
44       out << type << " " << dt.GetCanonicalName();
45     }
46     if (auto generic_type = dt.AsParameterizable(); generic_type && generic_type->IsGeneric()) {
47       out << "<" << Join(generic_type->GetTypeParameters(), ", ") << ">";
48     }
49   }
DumpMembersandroid::aidl::__anonaede7f330111::PreprocessVisitor50   void DumpMembers(const AidlDefinedType& dt) {
51     out << " {\n";
52     out.Indent();
53     for (const auto& constdecl : dt.GetConstantDeclarations()) {
54       constdecl->DispatchVisit(*this);
55     }
56     for (const auto& nested : dt.GetNestedTypes()) {
57       nested->DispatchVisit(*this);
58     }
59     out.Dedent();
60     out << "}\n";
61   }
DumpCommentsandroid::aidl::__anonaede7f330111::PreprocessVisitor62   void DumpComments(const AidlCommentable& c) {
63     const auto hidden = c.IsHidden();
64     const auto deprecated = FindDeprecated(c.GetComments());
65     if (hidden || deprecated) {
66       out << "/**\n";
67       if (hidden) {
68         out << " * @hide\n";
69       }
70       if (deprecated) {
71         out << " * @deprecated " << deprecated->note << "\n";
72       }
73       out << " */\n";
74     }
75   }
DumpAnnotationsandroid::aidl::__anonaede7f330111::PreprocessVisitor76   void DumpAnnotations(const AidlAnnotatable& a) {
77     auto annotations = a.ToString();
78     if (!annotations.empty()) {
79       out << annotations << "\n";
80     }
81   }
DumpConstantValueandroid::aidl::__anonaede7f330111::PreprocessVisitor82   void DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c) {
83     out << c.ValueString(type, AidlConstantValueDecorator);
84   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor85   void Visit(const AidlInterface& t) override {
86     DumpType(t, "interface");
87     DumpMembers(t);
88   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor89   void Visit(const AidlParcelable& t) override {
90     DumpType(t, "parcelable");
91     if (const auto& cpp_header = t.GetCppHeader(); !cpp_header.empty()) {
92       out << " cpp_header " << cpp_header;
93     }
94     if (const auto& ndk_header = t.GetNdkHeader(); !ndk_header.empty()) {
95       out << " ndk_header " << ndk_header;
96     }
97     if (const auto& rust_type = t.GetRustType(); !rust_type.empty()) {
98       out << " rust_type " << rust_type;
99     }
100     out << ";\n";
101   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor102   void Visit(const AidlStructuredParcelable& t) override {
103     DumpType(t, "parcelable");
104     DumpMembers(t);
105   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor106   void Visit(const AidlUnionDecl& t) override {
107     DumpType(t, "union");
108     DumpMembers(t);
109   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor110   void Visit(const AidlEnumDeclaration& t) override {
111     DumpType(t, "enum");
112     out << " {\n";
113     out.Indent();
114     for (const auto& e : t.GetEnumerators()) {
115       out << e->GetName() << " = ";
116       DumpConstantValue(t.GetBackingType(), *e->GetValue());
117       out << ",\n";
118     }
119     out.Dedent();
120     out << "}\n";
121   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor122   void Visit(const AidlConstantDeclaration& c) override {
123     DumpComments(c);
124     out << "const ";
125     Visit(c.GetType());
126     out << " " << c.GetName() << " = ";
127     DumpConstantValue(c.GetType(), c.GetValue());
128     out << ";\n";
129   }
Visitandroid::aidl::__anonaede7f330111::PreprocessVisitor130   void Visit(const AidlTypeSpecifier& t) override { out << t.ToString(); }
131 };
132 
133 }  // namespace
134 
Preprocess(const Options & options,const IoDelegate & io_delegate)135 bool Preprocess(const Options& options, const IoDelegate& io_delegate) {
136   unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(options.OutputFile());
137   PreprocessVisitor visitor(*writer);
138 
139   for (const auto& file : options.InputFiles()) {
140     AidlTypenames typenames;
141     auto result =
142         internals::load_and_validate_aidl(file, options, io_delegate, &typenames, nullptr);
143     if (result == AidlError::OK) {
144       const auto& doc = typenames.MainDocument();
145       for (const auto& t : doc.DefinedTypes()) {
146         t->DispatchVisit(visitor);
147       }
148     } else {
149       return false;
150     }
151   }
152 
153   return writer->Close();
154 }
155 
156 }  // namespace aidl
157 }  // namespace android
158