| /* |
| * Copyright (C) 2021, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "preprocess.h" |
| |
| #include <android-base/strings.h> |
| |
| #include "aidl.h" |
| |
| using android::base::Join; |
| |
| namespace android { |
| namespace aidl { |
| |
| namespace { |
| // PreprocessVisitor emits |
| // - types including comments(hide/deprecated) and annotations |
| // - constant delcarations for interface/parcelable/unions |
| // - enumerators for enums |
| struct PreprocessVisitor : AidlVisitor { |
| CodeWriter& out; |
| PreprocessVisitor(CodeWriter& out) : out(out) {} |
| |
| void DumpType(const AidlDefinedType& dt, const string& type) { |
| DumpComments(dt); |
| DumpAnnotations(dt); |
| // Top-level definition emits canonical name while nested type emits "name" only. |
| if (dt.GetParentType()) { |
| out << type << " " << dt.GetName(); |
| } else { |
| out << type << " " << dt.GetCanonicalName(); |
| } |
| if (auto generic_type = dt.AsParameterizable(); generic_type && generic_type->IsGeneric()) { |
| out << "<" << Join(generic_type->GetTypeParameters(), ", ") << ">"; |
| } |
| } |
| void DumpMembers(const AidlDefinedType& dt) { |
| out << " {\n"; |
| out.Indent(); |
| for (const auto& constdecl : dt.GetConstantDeclarations()) { |
| constdecl->DispatchVisit(*this); |
| } |
| for (const auto& nested : dt.GetNestedTypes()) { |
| nested->DispatchVisit(*this); |
| } |
| out.Dedent(); |
| out << "}\n"; |
| } |
| void DumpComments(const AidlCommentable& c) { |
| const auto hidden = c.IsHidden(); |
| const auto deprecated = FindDeprecated(c.GetComments()); |
| if (hidden || deprecated) { |
| out << "/**\n"; |
| if (hidden) { |
| out << " * @hide\n"; |
| } |
| if (deprecated) { |
| out << " * @deprecated " << deprecated->note << "\n"; |
| } |
| out << " */\n"; |
| } |
| } |
| void DumpAnnotations(const AidlAnnotatable& a) { |
| auto annotations = a.ToString(); |
| if (!annotations.empty()) { |
| out << annotations << "\n"; |
| } |
| } |
| void DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c) { |
| out << c.ValueString(type, AidlConstantValueDecorator); |
| } |
| void Visit(const AidlInterface& t) override { |
| DumpType(t, "interface"); |
| DumpMembers(t); |
| } |
| void Visit(const AidlParcelable& t) override { |
| DumpType(t, "parcelable"); |
| if (const auto& cpp_header = t.GetCppHeader(); !cpp_header.empty()) { |
| out << " cpp_header " << cpp_header; |
| } |
| out << ";\n"; |
| } |
| void Visit(const AidlStructuredParcelable& t) override { |
| DumpType(t, "parcelable"); |
| DumpMembers(t); |
| } |
| void Visit(const AidlUnionDecl& t) override { |
| DumpType(t, "union"); |
| DumpMembers(t); |
| } |
| void Visit(const AidlEnumDeclaration& t) override { |
| DumpType(t, "enum"); |
| out << " {\n"; |
| out.Indent(); |
| for (const auto& e : t.GetEnumerators()) { |
| out << e->GetName() << " = "; |
| DumpConstantValue(t.GetBackingType(), *e->GetValue()); |
| out << ",\n"; |
| } |
| out.Dedent(); |
| out << "}\n"; |
| } |
| void Visit(const AidlConstantDeclaration& c) override { |
| DumpComments(c); |
| out << "const "; |
| Visit(c.GetType()); |
| out << " " << c.GetName() << " = "; |
| DumpConstantValue(c.GetType(), c.GetValue()); |
| out << ";\n"; |
| } |
| void Visit(const AidlTypeSpecifier& t) override { out << t.ToString(); } |
| }; |
| |
| } // namespace |
| |
| bool Preprocess(const Options& options, const IoDelegate& io_delegate) { |
| unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(options.OutputFile()); |
| PreprocessVisitor visitor(*writer); |
| |
| for (const auto& file : options.InputFiles()) { |
| AidlTypenames typenames; |
| auto result = |
| internals::load_and_validate_aidl(file, options, io_delegate, &typenames, nullptr); |
| if (result == AidlError::OK) { |
| const auto& doc = typenames.MainDocument(); |
| for (const auto& t : doc.DefinedTypes()) { |
| t->DispatchVisit(visitor); |
| } |
| } else { |
| return false; |
| } |
| } |
| |
| return writer->Close(); |
| } |
| |
| } // namespace aidl |
| } // namespace android |