blob: 798dc1e9ae27e2fb86a7a19b0980eea015081dd6 [file] [log] [blame]
Will McVickerefd970d2019-09-25 15:28:30 -07001/*
2 * Copyright (C) 2015, 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
Adam Lesinskiffa16862014-01-23 18:17:42 -080017#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +090018#include "aidl_typenames.h"
Jiyong Parke5c45292020-05-26 19:06:24 +090019#include "parser.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070020
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080022#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -070023#include <string.h>
Jiyong Park68bc77a2018-07-19 19:00:45 +090024#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +090025#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090026#include <set>
27#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070028#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090029#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070030
Steven Moreland1c4ba202018-08-09 10:49:54 -070031#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070032#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080033#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070034
Steven Moreland21780812020-09-11 01:29:45 +000035#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070036#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080037
Will McVickerd7d18df2019-09-12 13:40:50 -070038#include "aidl.h"
39
Casey Dahlin07b9dde2015-09-10 19:13:49 -070040#ifdef _WIN32
41int isatty(int fd)
42{
43 return (fd == 0);
44}
45#endif
46
Christopher Wiley4a2884b2015-10-07 11:27:45 -070047using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070048using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080049using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070050using std::cerr;
Jiyong Park1deecc32018-07-17 01:14:41 +090051using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090052using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070053using std::string;
54using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090055using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080056
Jeongik Cha047c5ee2019-08-07 23:16:49 +090057namespace {
Jeongik Cha997281d2020-01-16 15:23:59 +090058bool IsJavaKeyword(const char* str) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +090059 static const std::vector<std::string> kJavaKeywords{
60 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
61 "char", "class", "const", "continue", "default", "do", "double",
62 "else", "enum", "extends", "final", "finally", "float", "for",
63 "goto", "if", "implements", "import", "instanceof", "int", "interface",
64 "long", "native", "new", "package", "private", "protected", "public",
65 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
66 "this", "throw", "throws", "transient", "try", "void", "volatile",
67 "while", "true", "false", "null",
68 };
69 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
70}
Jeongik Cha997281d2020-01-16 15:23:59 +090071
72void AddHideComment(CodeWriter* writer) {
73 writer->Write("/* @hide */\n");
74}
75
76inline bool HasHideComment(const std::string& comment) {
77 return std::regex_search(comment, std::regex("@hide\\b"));
78}
Jeongik Cha047c5ee2019-08-07 23:16:49 +090079} // namespace
80
Devin Mooredf93ebb2020-03-25 14:03:35 -070081AidlLocation::AidlLocation(const std::string& file, Point begin, Point end, Source source)
82 : file_(file), begin_(begin), end_(end), source_(source) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070083
84std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
Devin Moore5de18ed2020-04-02 13:52:29 -070085 os << l.file_;
86 if (l.LocationKnown()) {
87 os << ":" << l.begin_.line << "." << l.begin_.column << "-";
88 if (l.begin_.line != l.end_.line) {
89 os << l.end_.line << ".";
90 }
91 os << l.end_.column;
Steven Moreland46e9da82018-07-27 15:45:29 -070092 }
Steven Moreland46e9da82018-07-27 15:45:29 -070093 return os;
94}
95
96AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
97
Mathew Inwoodadb74672019-11-29 14:01:53 +000098std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000099 std::stringstream ss;
100 ss << location_.file_ << ":" << location_.begin_.line;
101 return ss.str();
102}
103
Mathew Inwoodadb74672019-11-29 14:01:53 +0000104std::string AidlNode::PrintLocation() const {
105 std::stringstream ss;
106 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
107 << location_.end_.line << ":" << location_.end_.column;
108 return ss.str();
109}
110
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700111const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
112 static const std::vector<Schema> kSchemas{
Jooyung Hand902a972020-10-23 17:32:44 +0900113 {AidlAnnotation::Type::NULLABLE, "nullable", {}, false},
114 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}, false},
115 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}, false},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700116 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
117 "UnsupportedAppUsage",
118 {{"expectedSignature", "String"},
119 {"implicitMember", "String"},
120 {"maxTargetSdk", "int"},
121 {"publicAlternatives", "String"},
Jooyung Hand902a972020-10-23 17:32:44 +0900122 {"trackingBug", "long"}},
123 false},
124 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}, false},
125 {AidlAnnotation::Type::HIDE, "Hide", {}, false},
126 {AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}, false},
127 {AidlAnnotation::Type::JAVA_PASSTHROUGH, "JavaPassthrough", {{"annotation", "String"}}, true},
Jooyung Han90345002020-10-23 15:28:53 +0900128 {AidlAnnotation::Type::JAVA_DERIVE, "JavaDerive", {{"toString", "boolean"}}, false},
Jooyung Hand902a972020-10-23 17:32:44 +0900129 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, "JavaOnlyImmutable", {}, false},
130 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", {}, false},
131 {AidlAnnotation::Type::DESCRIPTOR, "Descriptor", {{"value", "String"}}, false},
Andrei Homescue61feb52020-08-18 15:44:24 -0700132 {AidlAnnotation::Type::RUST_DERIVE,
133 "RustDerive",
134 {{"Copy", "boolean"},
135 {"Clone", "boolean"},
136 {"PartialOrd", "boolean"},
137 {"Ord", "boolean"},
138 {"PartialEq", "boolean"},
139 {"Eq", "boolean"},
Jooyung Hand902a972020-10-23 17:32:44 +0900140 {"Hash", "boolean"}},
141 false},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900142 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700143 return kSchemas;
144}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900145
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700146std::string AidlAnnotation::TypeToString(Type type) {
147 for (const Schema& schema : AllSchemas()) {
148 if (type == schema.type) return schema.name;
149 }
150 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
151 __builtin_unreachable();
152}
Andrei Onea9445fc62019-06-27 18:11:59 +0100153
154AidlAnnotation* AidlAnnotation::Parse(
155 const AidlLocation& location, const string& name,
156 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700157 const Schema* schema = nullptr;
158 for (const Schema& a_schema : AllSchemas()) {
159 if (a_schema.name == name) {
160 schema = &a_schema;
161 }
162 }
163
164 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900165 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700166 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900167 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700168 for (const Schema& s : AllSchemas()) {
169 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900170 }
171 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700172 AIDL_ERROR(location) << stream.str();
173 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900174 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100175 if (parameter_list == nullptr) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700176 return new AidlAnnotation(location, *schema, {});
Andrei Onea9445fc62019-06-27 18:11:59 +0100177 }
178
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700179 return new AidlAnnotation(location, *schema, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900180}
181
Andrei Onea9445fc62019-06-27 18:11:59 +0100182AidlAnnotation::AidlAnnotation(
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700183 const AidlLocation& location, const Schema& schema,
Andrei Onea9445fc62019-06-27 18:11:59 +0100184 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700185 : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100186
187bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100188 for (const auto& name_and_param : parameters_) {
189 const std::string& param_name = name_and_param.first;
190 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Will McVickerd7d18df2019-09-12 13:40:50 -0700191 if (!param->CheckValid()) {
192 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
193 << GetName() << ".";
194 return false;
195 }
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700196 auto parameter_mapping_it = schema_.supported_parameters.find(param_name);
197 if (parameter_mapping_it == schema_.supported_parameters.end()) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100198 std::ostringstream stream;
199 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700200 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100201 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700202 for (const auto& kv : schema_.supported_parameters) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100203 stream << " " << kv.first;
204 }
205 AIDL_ERROR(this) << stream.str();
206 return false;
207 }
208 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700209 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100210 // Assume error on empty string.
211 if (param_value == "") {
212 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
213 << GetName() << ".";
214 return false;
215 }
216 }
217 return true;
218}
219
220std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
221 const ConstantValueDecorator& decorator) const {
222 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100223 for (const auto& name_and_param : parameters_) {
224 const std::string& param_name = name_and_param.first;
225 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Devin Mooredecaf292020-04-30 09:16:40 -0700226 if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
227 std::ostringstream stream;
228 stream << "Parameter " << param_name << " not supported ";
229 stream << "for annotation " << GetName() << ". ";
230 stream << "It must be one of:";
231 for (const auto& kv : schema_.supported_parameters) {
232 stream << " " << kv.first;
233 }
234 AIDL_ERROR(this) << stream.str();
235 continue;
236 }
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700237 AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
238 nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700239 if (!param->CheckValid()) {
240 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
241 << GetName() << ".";
Devin Mooredecaf292020-04-30 09:16:40 -0700242 continue;
Will McVickerd7d18df2019-09-12 13:40:50 -0700243 }
244
245 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100246 }
247 return raw_params;
248}
Steven Moreland46e9da82018-07-27 15:45:29 -0700249
Daniel Norman37d43dd2019-09-09 17:22:34 -0700250std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
251 if (parameters_.empty()) {
252 return "@" + GetName();
253 } else {
254 vector<string> param_strings;
255 for (const auto& [name, value] : AnnotationParams(decorator)) {
256 param_strings.emplace_back(name + "=" + value);
257 }
258 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
259 }
260}
261
Andrei Onea9445fc62019-06-27 18:11:59 +0100262static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700263 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100264 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700265 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900266 AIDL_FATAL_IF(a.Repeatable(), a)
267 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100268 return &a;
269 }
270 }
271 return nullptr;
272}
273
Steven Moreland46e9da82018-07-27 15:45:29 -0700274AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
275
Jiyong Park68bc77a2018-07-19 19:00:45 +0900276bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700277 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900278}
279
Jiyong Park68bc77a2018-07-19 19:00:45 +0900280bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700281 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900282}
283
Steven Morelanda57d0a62019-07-30 09:41:14 -0700284bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700285 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700286}
287
Jeongik Chad0a10272020-08-06 16:33:36 +0900288bool AidlAnnotatable::IsJavaOnlyImmutable() const {
289 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900290}
291
Devin Moorec7e47a32020-08-07 10:55:25 -0700292bool AidlAnnotatable::IsFixedSize() const {
293 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
294}
295
Andrei Onea9445fc62019-06-27 18:11:59 +0100296const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700297 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900298}
299
Andrei Homescue61feb52020-08-18 15:44:24 -0700300const AidlAnnotation* AidlAnnotatable::RustDerive() const {
301 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
302}
303
Daniel Norman716d3112019-09-10 13:11:56 -0700304const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700305 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700306 if (annotation != nullptr) {
307 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
308 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
309 const string& type = it->second;
Steven Morelande7d5d082020-05-21 20:29:02 +0000310
311 AIDL_FATAL_IF(type.size() < 2, this) << type;
312 AIDL_FATAL_IF(type[0] != '"', this) << type;
313 AIDL_FATAL_IF(type[type.length() - 1] != '"', this) << type;
314 string unquoted_type = type.substr(1, type.length() - 2);
315
Daniel Norman716d3112019-09-10 13:11:56 -0700316 AidlTypeSpecifier* type_specifier =
Steven Morelande7d5d082020-05-21 20:29:02 +0000317 new AidlTypeSpecifier(AIDL_LOCATION_HERE, unquoted_type, false, nullptr, "");
Daniel Norman716d3112019-09-10 13:11:56 -0700318 type_specifier->Resolve(typenames);
319 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700320 }
321 }
322 return nullptr;
323}
324
Jeongik Cha88f95a82020-01-15 13:02:16 +0900325bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700326 return lang == Options::Language::JAVA &&
327 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900328}
329
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800330bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700331 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800332}
333
Jooyung Han90345002020-10-23 15:28:53 +0900334const AidlAnnotation* AidlAnnotatable::JavaDerive() const {
335 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
Jiyong Park43113fb2020-07-20 16:26:19 +0900336}
337
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900338std::string AidlAnnotatable::GetDescriptor() const {
339 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
340 if (annotation != nullptr) {
341 auto params = annotation->AnnotationParams(AidlConstantValueDecorator);
342 if (auto it = params.find("value"); it != params.end()) {
343 const string& value = it->second;
344
345 AIDL_FATAL_IF(value.size() < 2, this) << value;
346 AIDL_FATAL_IF(value[0] != '"', this) << value;
347 AIDL_FATAL_IF(value[value.length() - 1] != '"', this) << value;
348 std::string unquoted_value = value.substr(1, value.length() - 2);
349 return unquoted_value;
350 }
351 }
352 return "";
353}
354
Steven Moreland7e4b9502020-02-20 18:10:42 -0800355void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
356 if (annotations_.empty()) return;
357
358 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
359}
360
Devin Moore24f68572020-02-26 13:20:59 -0800361bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700362 std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
Andrei Onea9445fc62019-06-27 18:11:59 +0100363 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900364 // check if it is allowed for this node
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700365 if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900366 std::vector<std::string> supported_annot_strings;
367 for (AidlAnnotation::Type type : supported_annotations) {
368 supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
369 }
Devin Moore24f68572020-02-26 13:20:59 -0800370 AIDL_ERROR(this) << "'" << annotation.GetName()
371 << "' is not a supported annotation for this node. "
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700372 << "It must be one of: "
373 << android::base::Join(supported_annot_strings, ", ");
Devin Moore24f68572020-02-26 13:20:59 -0800374 return false;
375 }
Jooyung Hand902a972020-10-23 17:32:44 +0900376 // CheckValid() only if it is okay to be here
377 if (!annotation.CheckValid()) {
378 return false;
379 }
380 }
381
382 std::map<AidlAnnotation::Type, AidlLocation> declared;
383 for (const auto& annotation : GetAnnotations()) {
384 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
385 if (!inserted && !annotation.Repeatable()) {
386 AIDL_ERROR(this) << "'" << annotation.GetName()
387 << "' is repeated, but not allowed. Previous location: " << iter->second;
388 return false;
389 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100390 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700391
Andrei Onea9445fc62019-06-27 18:11:59 +0100392 return true;
393}
394
Jiyong Park68bc77a2018-07-19 19:00:45 +0900395string AidlAnnotatable::ToString() const {
396 vector<string> ret;
397 for (const auto& a : annotations_) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700398 ret.emplace_back(a.ToString(AidlConstantValueDecorator));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900399 }
400 std::sort(ret.begin(), ret.end());
401 return Join(ret, " ");
402}
403
Steven Moreland46e9da82018-07-27 15:45:29 -0700404AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
405 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900406 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700407 const string& comments)
408 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900409 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700410 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700411 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900412 comments_(comments),
413 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700414
Jooyung Hand2fa0232020-10-19 02:51:41 +0900415const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700416 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900417 // Declaring array of generic type cannot happen, it is grammar error.
418 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700419
Jooyung Hand2fa0232020-10-19 02:51:41 +0900420 if (!array_base_) {
421 array_base_.reset(new AidlTypeSpecifier(*this));
422 array_base_->is_array_ = false;
423 }
424 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700425}
426
Jeongik Cha997281d2020-01-16 15:23:59 +0900427bool AidlTypeSpecifier::IsHidden() const {
428 return HasHideComment(GetComments());
429}
430
Jiyong Park1deecc32018-07-17 01:14:41 +0900431string AidlTypeSpecifier::ToString() const {
432 string ret = GetName();
433 if (IsGeneric()) {
434 vector<string> arg_names;
435 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +0900436 arg_names.emplace_back(ta->ToString());
437 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900438 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900439 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900440 if (IsArray()) {
441 ret += "[]";
442 }
443 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900444}
445
Jiyong Park02da7422018-07-16 16:00:26 +0900446string AidlTypeSpecifier::Signature() const {
447 string ret = ToString();
448 string annotations = AidlAnnotatable::ToString();
449 if (annotations != "") {
450 ret = annotations + " " + ret;
451 }
452 return ret;
453}
454
Daniel Norman716d3112019-09-10 13:11:56 -0700455bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000456 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700457 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
458 if (result.is_resolved) {
459 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900460 split_name_ = Split(fully_qualified_name_, ".");
Jiyong Parkccf00f82018-07-17 01:39:23 +0900461 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700462 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700463}
464
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700465std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
Devin Moore24f68572020-02-26 13:20:59 -0800466 // kHide and kUnsupportedAppUsage are both method return annotations
467 // which we don't distinguish from other type specifiers.
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700468 return {AidlAnnotation::Type::NULLABLE, AidlAnnotation::Type::UTF8_IN_CPP,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900469 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
470 AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -0800471}
472
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900473bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800474 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100475 return false;
476 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900477 if (IsGeneric()) {
478 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900479
480 auto& types = GetTypeParameters();
481 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
482 if (type_name == "List" || type_name == "Map") {
483 if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
484 return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
485 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700486 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900487 return false;
488 }
489 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800490 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900491 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800492 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
493 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900494 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800495 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900496 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800497 if (num_params > 1) {
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000498 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << ToString()
499 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900500 return false;
501 }
502 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800503 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900504 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
505 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900506 return false;
507 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800508 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900509 const string& key_type = GetTypeParameters()[0]->GetName();
510 if (key_type != "String") {
511 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
512 << "'" << key_type << "'";
513 return false;
514 }
515 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800516 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900517 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800518 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900519 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800520 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900521 return false;
522 }
523 } else {
524 AIDL_ERROR(this) << type_name << " is not a generic type.";
525 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900526 }
527 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900528
Steven Moreland11cb9452020-01-21 16:56:58 -0800529 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
530 GetTypeParameters().size() == 1 &&
531 GetTypeParameters()[0]->GetName() == "String";
532 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
533 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
534 return false;
535 }
536
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900537 if (GetName() == "void") {
538 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
539 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
540 return false;
541 }
542 }
543
544 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800545 const auto defined_type = typenames.TryGetDefinedType(GetName());
546 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900547 AIDL_ERROR(this) << "Binder type cannot be an array";
548 return false;
549 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000550 if (GetName() == "ParcelableHolder") {
551 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
552 return false;
553 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900554 }
555
556 if (IsNullable()) {
557 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
558 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
559 return false;
560 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800561 const auto defined_type = typenames.TryGetDefinedType(GetName());
562 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700563 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
564 return false;
565 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900566 if (GetName() == "ParcelableHolder") {
567 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
568 return false;
569 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900570 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900571 return true;
572}
573
Steven Moreland860b1942018-08-16 14:59:28 -0700574std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
575 const std::string& raw_value) {
576 return raw_value;
577}
578
Steven Moreland46e9da82018-07-27 15:45:29 -0700579AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
580 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000581 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
582 default_user_specified_ = false;
583}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700584
Steven Moreland46e9da82018-07-27 15:45:29 -0700585AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
586 AidlTypeSpecifier* type, const std::string& name,
587 AidlConstantValue* default_value)
Steven Moreland541788d2020-05-21 22:05:52 +0000588 : AidlNode(location),
589 type_(type),
590 name_(name),
591 default_user_specified_(true),
592 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700593
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900594bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700595 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900596 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900597
Steven Moreland54be7bd2019-12-05 11:17:53 -0800598 if (type_->GetName() == "void") {
599 AIDL_ERROR(this) << "Declaration " << name_
600 << " is void, but declarations cannot be of void type.";
601 valid = false;
602 }
603
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900604 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700605 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700606
Steven Moreland25294322018-08-07 18:13:55 -0700607 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700608
Steven Moreland860b1942018-08-16 14:59:28 -0700609 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700610}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700611
Jooyung Hanacae85d2020-10-28 16:39:09 +0900612string AidlVariableDeclaration::GetCapitalizedName() const {
613 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
614 string str = name_;
615 str[0] = static_cast<char>(toupper(str[0]));
616 return str;
617}
618
Steven Moreland5557f1c2018-07-02 13:50:23 -0700619string AidlVariableDeclaration::ToString() const {
Jeongik Cha3271ffa2018-12-04 15:19:20 +0900620 string ret = type_->Signature() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000621 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700622 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700623 }
624 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700625}
626
Jiyong Park02da7422018-07-16 16:00:26 +0900627string AidlVariableDeclaration::Signature() const {
628 return type_->Signature() + " " + name_;
629}
630
Steven Moreland860b1942018-08-16 14:59:28 -0700631std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900632 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700633 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900634 } else {
635 return "";
636 }
Steven Moreland25294322018-08-07 18:13:55 -0700637}
638
Steven Moreland46e9da82018-07-27 15:45:29 -0700639AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
640 AidlTypeSpecifier* type, const std::string& name)
641 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700642 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700643 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700644
Steven Moreland46e9da82018-07-27 15:45:29 -0700645AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
646 const std::string& name)
647 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700648 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700649 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700650
Jiyong Park02da7422018-07-16 16:00:26 +0900651string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700652 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700653 if (direction_specified_) {
654 switch(direction_) {
655 case AidlArgument::IN_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700656 ret += "in";
Casey Dahlinc378c992015-09-29 16:50:40 -0700657 break;
658 case AidlArgument::OUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700659 ret += "out";
Casey Dahlinc378c992015-09-29 16:50:40 -0700660 break;
661 case AidlArgument::INOUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700662 ret += "inout";
Casey Dahlinc378c992015-09-29 16:50:40 -0700663 break;
664 }
665 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700666 return ret;
667}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700668
Jiyong Park02da7422018-07-16 16:00:26 +0900669string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700670 if (direction_specified_) {
671 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
672 } else {
673 return AidlVariableDeclaration::ToString();
674 }
Jiyong Park02da7422018-07-16 16:00:26 +0900675}
676
677std::string AidlArgument::Signature() const {
Steven Moreland46e9da82018-07-27 15:45:29 -0700678 class AidlInterface;
679 class AidlInterface;
680 class AidlParcelable;
681 class AidlStructuredParcelable;
682 class AidlParcelable;
683 class AidlStructuredParcelable;
Devin Mooreeccdb902020-03-24 16:22:40 -0700684 if (direction_specified_) {
685 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::Signature();
686 } else {
687 return AidlVariableDeclaration::Signature();
688 }
Jiyong Park02da7422018-07-16 16:00:26 +0900689}
690
Steven Moreland46e9da82018-07-27 15:45:29 -0700691AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
692
Steven Moreland46e9da82018-07-27 15:45:29 -0700693AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
694 AidlTypeSpecifier* type, const std::string& name,
695 AidlConstantValue* value)
696 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700697
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900698bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700699 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900700 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700701 valid &= value_->CheckValid();
702 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700703
Steven Moreland25294322018-08-07 18:13:55 -0700704 const static set<string> kSupportedConstTypes = {"String", "int"};
705 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
706 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700707 return false;
708 }
709
Will McVickerd7d18df2019-09-12 13:40:50 -0700710 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700711}
712
Jiyong Parka428d212018-08-29 22:26:30 +0900713string AidlConstantDeclaration::ToString() const {
714 return "const " + type_->ToString() + " " + name_ + " = " +
715 ValueString(AidlConstantValueDecorator);
716}
717
718string AidlConstantDeclaration::Signature() const {
719 return type_->Signature() + " " + name_;
720}
721
Steven Moreland46e9da82018-07-27 15:45:29 -0700722AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
723 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900724 const std::string& comments)
725 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
726 has_id_ = false;
727}
728
729AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
730 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900731 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700732 : AidlMember(location),
733 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700734 comments_(comments),
735 type_(type),
736 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700737 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900738 id_(id),
739 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700740 has_id_ = true;
741 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700742 for (const unique_ptr<AidlArgument>& a : arguments_) {
743 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
744 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
745 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700746}
747
Jeongik Cha997281d2020-01-16 15:23:59 +0900748bool AidlMethod::IsHidden() const {
749 return HasHideComment(GetComments());
750}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700751
Jiyong Park02da7422018-07-16 16:00:26 +0900752string AidlMethod::Signature() const {
753 vector<string> arg_signatures;
754 for (const auto& arg : GetArguments()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900755 arg_signatures.emplace_back(arg->GetType().ToString());
Jiyong Park02da7422018-07-16 16:00:26 +0900756 }
Jiyong Park309668e2018-07-28 16:55:44 +0900757 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
758}
759
760string AidlMethod::ToString() const {
761 vector<string> arg_strings;
762 for (const auto& arg : GetArguments()) {
763 arg_strings.emplace_back(arg->Signature());
764 }
Steven Moreland4ee68632018-12-14 15:52:46 -0800765 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
766 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900767 if (HasId()) {
768 ret += " = " + std::to_string(GetId());
769 }
770 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900771}
772
Steven Moreland46e9da82018-07-27 15:45:29 -0700773AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jiyong Park18132182020-06-08 20:24:40 +0900774 const std::string& comments, const std::string& package)
775 : AidlAnnotatable(location),
776 name_(name),
777 comments_(comments),
778 package_(package),
779 split_package_(package.empty() ? std::vector<std::string>()
780 : android::base::Split(package, ".")) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700781
Devin Moore24f68572020-02-26 13:20:59 -0800782bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
783 if (!AidlAnnotatable::CheckValid(typenames)) {
784 return false;
785 }
786
787 return true;
788}
789
Jeongik Cha997281d2020-01-16 15:23:59 +0900790bool AidlDefinedType::IsHidden() const {
791 return HasHideComment(GetComments());
792}
793
Steven Moreland787b0432018-07-03 09:00:58 -0700794std::string AidlDefinedType::GetCanonicalName() const {
795 if (package_.empty()) {
796 return GetName();
797 }
798 return GetPackage() + "." + GetName();
799}
800
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800801void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
802 if (this->IsHidden()) {
803 AddHideComment(writer);
804 }
805 DumpAnnotations(writer);
806}
807
Jiyong Park18132182020-06-08 20:24:40 +0900808AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
809 const std::string& package, const std::string& comments,
Jeongik Chadf76dc72019-11-28 00:08:47 +0900810 const std::string& cpp_header, std::vector<std::string>* type_params)
Jiyong Park18132182020-06-08 20:24:40 +0900811 : AidlDefinedType(location, name, comments, package),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900812 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800813 cpp_header_(cpp_header) {
814 // Strip off quotation marks if we actually have a cpp header.
815 if (cpp_header_.length() >= 2) {
816 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
817 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700818}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900819template <typename T>
820AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
821 // Copying is not supported if it has type parameters.
822 // It doesn't make a problem because only ArrayBase() makes a copy,
823 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +0000824 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900825}
826
827template <typename T>
828bool AidlParameterizable<T>::CheckValid() const {
829 return true;
830};
831
832template <>
833bool AidlParameterizable<std::string>::CheckValid() const {
834 if (!IsGeneric()) {
835 return true;
836 }
837 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
838 if (set.size() != GetTypeParameters().size()) {
839 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
840 return false;
841 }
842 return true;
843}
Casey Dahlin59401da2015-10-09 18:16:45 -0700844
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700845std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900846 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900847 AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE,
Jeongik Chad0a10272020-08-06 16:33:36 +0900848 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE};
Devin Moore24f68572020-02-26 13:20:59 -0800849}
850
851bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
852 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100853 return false;
854 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900855 if (!AidlParameterizable<std::string>::CheckValid()) {
856 return false;
857 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900858
859 return true;
860}
861
Jeongik Cha997281d2020-01-16 15:23:59 +0900862void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800863 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900864 writer->Write("parcelable %s ;\n", GetName().c_str());
865}
866
Jooyung Han59af9cc2020-10-25 21:44:14 +0900867bool AidlWithFields::CheckValid(const AidlParcelable& parcel,
868 const AidlTypenames& typenames) const {
869 bool success = true;
870
871 for (const auto& v : GetFields()) {
872 const bool field_valid = v->CheckValid(typenames);
873 success = success && field_valid;
874 }
875
876 // field names should be unique
877 std::set<std::string> fieldnames;
878 for (const auto& v : GetFields()) {
879 bool duplicated = !fieldnames.emplace(v->GetName()).second;
880 if (duplicated) {
881 AIDL_ERROR(v) << "'" << parcel.GetName() << "' has duplicate field name '" << v->GetName()
882 << "'";
883 success = false;
884 }
885 }
886
887 // immutable parcelables should have immutable fields.
888 if (parcel.IsJavaOnlyImmutable()) {
889 for (const auto& v : GetFields()) {
890 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
891 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << parcel.GetName() << "' has a "
892 << "non-immutable field named '" << v->GetName() << "'.";
893 success = false;
894 }
895 }
896 }
897
898 return success;
899}
900
901bool AidlWithFields::CheckValidForGetterNames(const AidlParcelable& parcel) const {
902 bool success = true;
903 std::set<std::string> getters;
904 for (const auto& v : GetFields()) {
Jooyung Hanacae85d2020-10-28 16:39:09 +0900905 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
Jooyung Han59af9cc2020-10-25 21:44:14 +0900906 if (duplicated) {
907 AIDL_ERROR(v) << "'" << parcel.GetName() << "' has duplicate field name '" << v->GetName()
908 << "' after capitalizing the first letter";
909 success = false;
910 }
911 }
912 return success;
913}
914
Steven Moreland5557f1c2018-07-02 13:50:23 -0700915AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +0900916 const AidlLocation& location, const std::string& name, const std::string& package,
Devin Moore53fc99c2020-08-12 08:07:52 -0700917 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables,
918 std::vector<std::string>* type_params)
919 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params),
Jooyung Han59af9cc2020-10-25 21:44:14 +0900920 AidlWithFields(variables) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700921
Jeongik Cha997281d2020-01-16 15:23:59 +0900922void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800923 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900924 writer->Write("parcelable %s {\n", GetName().c_str());
925 writer->Indent();
926 for (const auto& field : GetFields()) {
Jeongik Cha997281d2020-01-16 15:23:59 +0900927 if (field->GetType().IsHidden()) {
928 AddHideComment(writer);
929 }
Jiyong Parka468e2a2018-08-29 21:25:18 +0900930 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900931 }
932 writer->Dedent();
933 writer->Write("}\n");
934}
935
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700936std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900937 return {AidlAnnotation::Type::VINTF_STABILITY,
938 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
939 AidlAnnotation::Type::HIDE,
940 AidlAnnotation::Type::JAVA_PASSTHROUGH,
Jooyung Han90345002020-10-23 15:28:53 +0900941 AidlAnnotation::Type::JAVA_DERIVE,
Devin Moorec7e47a32020-08-07 10:55:25 -0700942 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
Andrei Homescue61feb52020-08-18 15:44:24 -0700943 AidlAnnotation::Type::FIXED_SIZE,
944 AidlAnnotation::Type::RUST_DERIVE};
Devin Moore24f68572020-02-26 13:20:59 -0800945}
946
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900947bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800948 if (!AidlParcelable::CheckValid(typenames)) {
949 return false;
950 }
Jooyung Han59af9cc2020-10-25 21:44:14 +0900951 if (!AidlWithFields::CheckValid(*this, typenames)) {
952 return false;
Jooyung Hand4057c42020-10-23 13:28:22 +0900953 }
Jeongik Cha13066da2020-08-06 15:43:19 +0900954
Jooyung Han59af9cc2020-10-25 21:44:14 +0900955 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +0900956
Jooyung Hand4057c42020-10-23 13:28:22 +0900957 if (IsFixedSize()) {
958 for (const auto& v : GetFields()) {
959 if (!typenames.CanBeFixedSize(v->GetType())) {
960 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
961 << "non-fixed size field named " << v->GetName() << ".";
962 success = false;
963 }
964 }
965 }
966
967 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +0900968 // Immutable parcelables provide getters
969 if (!CheckValidForGetterNames(*this)) {
970 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +0900971 }
972 }
973
Daniel Norman85aed542019-08-21 12:01:14 -0700974 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900975}
976
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900977// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -0700978bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
979 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -0700980 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
981 GetName() == "IBinder") {
982 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
983 << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +0000984 return false;
985 }
Jeongik Cha8f02a532020-10-14 00:16:28 +0900986 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
987 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
988 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +0900989 return false;
990 }
Andrei Homescub62afd92020-05-11 19:24:59 -0700991 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
992 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +0000993 if (GetName() == "ParcelFileDescriptor") {
Andrei Homescub62afd92020-05-11 19:24:59 -0700994 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
995 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +0000996 return false;
997 }
998
Steven Morelandd59e3172020-05-11 16:42:09 -0700999 const auto defined_type = typenames.TryGetDefinedType(GetName());
1000 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Andrei Homescub62afd92020-05-11 19:24:59 -07001001 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1002 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001003 return false;
1004 }
1005 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001006 if (this->GetName() == "FileDescriptor" &&
1007 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1008 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << Options::LanguageToString(lang)
1009 << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001010 return false;
1011 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001012 if (this->IsGeneric()) {
1013 if (this->GetName() == "List") {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001014 if (lang == Options::Language::CPP) {
Devin Moore2ac52f92020-03-23 15:39:36 -07001015 const string& contained_type = this->GetTypeParameters()[0]->GetName();
1016 if (!(contained_type == "String" || contained_type == "IBinder")) {
1017 AIDL_ERROR(this) << "List<" << contained_type
1018 << "> is not supported. List in cpp supports only String and IBinder.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001019 return false;
1020 }
Jeongik Cha08ca2182019-11-21 14:01:13 +09001021 } else if (lang == Options::Language::JAVA) {
1022 const string& contained_type = this->GetTypeParameters()[0]->GetName();
1023 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
1024 if (contained_type != "String" && contained_type != "IBinder" &&
1025 contained_type != "ParcelFileDescriptor") {
Devin Moore2ac52f92020-03-23 15:39:36 -07001026 AIDL_ERROR(this) << "List<" << contained_type
1027 << "> is not supported. List in Java supports only String, IBinder, "
1028 "and ParcelFileDescriptor.";
Jeongik Cha08ca2182019-11-21 14:01:13 +09001029 return false;
1030 }
1031 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001032 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001033 }
1034 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001035
1036 if (this->IsArray()) {
1037 if (this->GetName() == "List" || this->GetName() == "Map" ||
1038 this->GetName() == "CharSequence") {
1039 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001040 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001041 }
1042 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001043
1044 if (lang != Options::Language::JAVA) {
1045 if (this->GetName() == "List" && !this->IsGeneric()) {
1046 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1047 return false;
1048 }
1049 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1050 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1051 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001052 }
1053 }
1054
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001055 return true;
1056}
1057
1058// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001059bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1060 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001061 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001062 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1063 if (unstructured_parcelable != nullptr) {
1064 if (unstructured_parcelable->GetCppHeader().empty()) {
1065 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001066 << "Unstructured parcelable must have C++ header defined.";
1067 return false;
1068 }
1069 }
1070 }
1071 return true;
1072}
1073
1074// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001075bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1076 Options::Language lang) const {
1077 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001078 return false;
1079 }
1080 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001081 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001082 return false;
1083 }
1084 }
1085 return true;
1086}
1087
Daniel Norman85aed542019-08-21 12:01:14 -07001088AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -07001089 AidlConstantValue* value, const std::string& comments)
1090 : AidlNode(location), name_(name), value_(value), comments_(comments) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001091
1092bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1093 if (GetValue() == nullptr) {
1094 return false;
1095 }
1096 if (!GetValue()->CheckValid()) {
1097 return false;
1098 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001099 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001100 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1101 return false;
1102 }
1103 return true;
1104}
1105
1106string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1107 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001108 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001109}
1110
1111AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1112 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jiyong Park18132182020-06-08 20:24:40 +09001113 const std::string& package, const std::string& comments)
Daniel Norman2e4112d2019-10-03 10:22:35 -07001114 : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001115
1116void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
1117 backing_type_ = std::move(type);
1118}
1119
Steven Moreland59e53e42019-11-26 20:38:08 -08001120bool AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -07001121 const AidlEnumerator* previous = nullptr;
1122 for (const auto& enumerator : enumerators_) {
1123 if (enumerator->GetValue() == nullptr) {
1124 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001125 enumerator->SetValue(
1126 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(GetLocation(), "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001127 } else {
Steven Moreland59e53e42019-11-26 20:38:08 -08001128 auto prev_value = std::unique_ptr<AidlConstantValue>(
1129 AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
1130 if (prev_value == nullptr) {
1131 return false;
1132 }
Daniel Normanb28684e2019-10-17 15:31:39 -07001133 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Devin Mooredf93ebb2020-03-25 14:03:35 -07001134 GetLocation(), std::move(prev_value), "+",
1135 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(GetLocation(), "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001136 }
1137 }
1138 previous = enumerator.get();
1139 }
Steven Moreland59e53e42019-11-26 20:38:08 -08001140 return true;
Daniel Normanb28684e2019-10-17 15:31:39 -07001141}
1142
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001143std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
1144 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::BACKING,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +09001145 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -08001146}
1147
1148bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1149 if (!AidlDefinedType::CheckValid(typenames)) {
1150 return false;
1151 }
Daniel Norman85aed542019-08-21 12:01:14 -07001152 if (backing_type_ == nullptr) {
1153 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1154 return false;
1155 }
1156 bool success = true;
1157 for (const auto& enumerator : enumerators_) {
1158 success = success && enumerator->CheckValid(GetBackingType());
1159 }
1160 return success;
1161}
1162
Jeongik Cha997281d2020-01-16 15:23:59 +09001163void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001164 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001165 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -07001166 writer->Indent();
1167 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001168 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1169 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1170 }
1171 writer->Dedent();
1172 writer->Write("}\n");
1173}
1174
Jooyung Han2946afc2020-10-05 20:29:16 +09001175AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1176 const std::string& package, const std::string& comments,
1177 std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables,
1178 std::vector<std::string>* type_params)
1179 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params),
Jooyung Han59af9cc2020-10-25 21:44:14 +09001180 AidlWithFields(variables) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001181
1182std::set<AidlAnnotation::Type> AidlUnionDecl::GetSupportedAnnotations() const {
1183 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::HIDE,
Jooyung Han59af9cc2020-10-25 21:44:14 +09001184 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_DERIVE,
1185 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE};
Jooyung Han2946afc2020-10-05 20:29:16 +09001186}
1187
1188void AidlUnionDecl::Dump(CodeWriter* writer) const {
1189 DumpHeader(writer);
1190 writer->Write("union %s {\n", GetName().c_str());
1191 writer->Indent();
1192 for (const auto& field : GetFields()) {
1193 if (field->GetType().IsHidden()) {
1194 AddHideComment(writer);
1195 }
1196 writer->Write("%s;\n", field->ToString().c_str());
1197 }
1198 writer->Dedent();
1199 writer->Write("}\n");
1200}
1201
Jooyung Hanfe89f122020-10-14 03:49:18 +09001202bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001203 // visit parents
Jooyung Hanfe89f122020-10-14 03:49:18 +09001204 if (!AidlParcelable::CheckValid(typenames)) {
1205 return false;
1206 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001207 if (!AidlWithFields::CheckValid(*this, typenames)) {
1208 return false;
1209 }
1210
1211 // unions provide getters always
1212 if (!CheckValidForGetterNames(*this)) {
1213 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001214 }
1215
1216 // now, visit self!
1217 bool success = true;
1218
1219 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1220 for (const auto& v : GetFields()) {
1221 if (v->GetType().GetName() == "ParcelableHolder") {
1222 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1223 success = false;
1224 }
1225 }
1226
1227 // first member should have default value (implicit or explicit)
1228 if (GetFields().empty()) {
1229 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1230 return false;
1231 }
1232
1233 return success;
1234}
1235
1236// TODO: we should treat every backend all the same in future.
1237bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1238 Options::Language lang) const {
1239 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1240 return false;
1241 }
1242 for (const auto& v : this->GetFields()) {
1243 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1244 return false;
1245 }
1246 }
1247 return true;
1248}
1249
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001250// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001251bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1252 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001253 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001254 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001255 return false;
1256 }
1257 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001258 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001259 return false;
1260 }
1261 }
1262 }
1263 return true;
1264}
1265
Steven Moreland46e9da82018-07-27 15:45:29 -07001266AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001267 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001268 std::vector<std::unique_ptr<AidlMember>>* members,
Jiyong Park18132182020-06-08 20:24:40 +09001269 const std::string& package)
Steven Morelandacd53472018-12-14 10:17:26 -08001270 : AidlDefinedType(location, name, comments, package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001271 for (auto& member : *members) {
1272 AidlMember* local = member.release();
1273 AidlMethod* method = local->AsMethod();
Steven Moreland693640b2018-07-19 13:46:27 -07001274 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
1275
Steven Moreland21780812020-09-11 01:29:45 +00001276 AIDL_FATAL_IF(method != nullptr && constant != nullptr, member);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001277
1278 if (method) {
Steven Moreland8c70ba92018-12-17 10:20:31 -08001279 method->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001280 methods_.emplace_back(method);
Steven Moreland693640b2018-07-19 13:46:27 -07001281 } else if (constant) {
1282 constants_.emplace_back(constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001283 } else {
Steven Moreland46e9da82018-07-27 15:45:29 -07001284 AIDL_FATAL(this) << "Member is neither method nor constant!";
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001285 }
1286 }
1287
1288 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001289}
1290
Jeongik Cha997281d2020-01-16 15:23:59 +09001291void AidlInterface::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001292 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001293 writer->Write("interface %s {\n", GetName().c_str());
1294 writer->Indent();
1295 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001296 if (method->IsHidden()) {
1297 AddHideComment(writer);
1298 }
Jiyong Park309668e2018-07-28 16:55:44 +09001299 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001300 }
Jiyong Parka428d212018-08-29 22:26:30 +09001301 for (const auto& constdecl : GetConstantDeclarations()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001302 if (constdecl->GetType().IsHidden()) {
1303 AddHideComment(writer);
1304 }
Jiyong Parka428d212018-08-29 22:26:30 +09001305 writer->Write("%s;\n", constdecl->ToString().c_str());
1306 }
Jiyong Park02da7422018-07-16 16:00:26 +09001307 writer->Dedent();
1308 writer->Write("}\n");
1309}
1310
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001311std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
1312 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001313 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH,
1314 AidlAnnotation::Type::DESCRIPTOR};
Devin Moore24f68572020-02-26 13:20:59 -08001315}
1316
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001317bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -08001318 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001319 return false;
1320 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001321 // Has to be a pointer due to deleting copy constructor. No idea why.
1322 map<string, const AidlMethod*> method_names;
1323 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001324 if (!m->GetType().CheckValid(typenames)) {
1325 return false;
1326 }
1327
Jeongik Cha649e8a72020-03-27 17:47:40 +09001328 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1329 if (m->GetType().GetName() == "ParcelableHolder") {
1330 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1331 return false;
1332 }
Steven Morelandacd53472018-12-14 10:17:26 -08001333 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001334 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1335 return false;
1336 }
1337
1338 set<string> argument_names;
1339 for (const auto& arg : m->GetArguments()) {
1340 auto it = argument_names.find(arg->GetName());
1341 if (it != argument_names.end()) {
1342 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1343 << arg->GetName() << "'";
1344 return false;
1345 }
1346 argument_names.insert(arg->GetName());
1347
1348 if (!arg->GetType().CheckValid(typenames)) {
1349 return false;
1350 }
1351
Jeongik Cha649e8a72020-03-27 17:47:40 +09001352 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1353 if (arg->GetType().GetName() == "ParcelableHolder") {
1354 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1355 return false;
1356 }
Steven Morelandacd53472018-12-14 10:17:26 -08001357 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001358 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1359 return false;
1360 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001361
1362 const auto [can_be_out, type_aspect] = typenames.CanBeOutParameter(arg->GetType());
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001363 if (!arg->DirectionWasSpecified() && can_be_out) {
1364 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
1365 << "' can be an out type, so you must declare it as in, out, or inout.";
1366 return false;
1367 }
1368
1369 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
Jooyung Han15fd6c62020-10-23 13:54:46 +09001370 AIDL_ERROR(arg) << "'" << arg->GetName() << "' can't be an " << arg->GetDirectionSpecifier()
1371 << " parameter because " << type_aspect << " can only be an in parameter.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001372 return false;
1373 }
1374
1375 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001376 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001377 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1378 return false;
1379 }
1380
1381 // Reserve a namespace for internal use
1382 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1383 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1384 return false;
1385 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001386 }
1387
1388 auto it = method_names.find(m->GetName());
1389 // prevent duplicate methods
1390 if (it == method_names.end()) {
1391 method_names[m->GetName()] = m.get();
1392 } else {
1393 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1394 AIDL_ERROR(it->second) << "previously defined here.";
1395 return false;
1396 }
1397
Paul Trautrimb77048c2020-01-21 16:39:32 +09001398 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001399 "getTransactionName(int)"};
1400
1401 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001402 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001403 return false;
1404 }
1405 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001406
1407 bool success = true;
1408 set<string> constant_names;
1409 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1410 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001411 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001412 success = false;
1413 }
1414 constant_names.insert(constant->GetName());
1415 success = success && constant->CheckValid(typenames);
1416 }
1417
1418 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001419}
1420
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001421std::string AidlInterface::GetDescriptor() const {
1422 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1423 if (annotatedDescriptor != "") {
1424 return annotatedDescriptor;
1425 }
1426 return GetCanonicalName();
1427}
1428
Steven Moreland46e9da82018-07-27 15:45:29 -07001429AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1430 : AidlNode(location), needed_class_(needed_class) {}