blob: 1016d760977db2db736592a99679f0de1f202b8b [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}
Jooyung Han720253d2021-01-05 19:13:17 +090079
80inline bool HasDeprecatedComment(const std::string& comment) {
81 return std::regex_search(comment, std::regex("@deprecated\\b"));
82}
Jeongik Cha047c5ee2019-08-07 23:16:49 +090083} // namespace
84
Steven Moreland46e9da82018-07-27 15:45:29 -070085AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
86
Mathew Inwoodadb74672019-11-29 14:01:53 +000087std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000088 std::stringstream ss;
89 ss << location_.file_ << ":" << location_.begin_.line;
90 return ss.str();
91}
92
Mathew Inwoodadb74672019-11-29 14:01:53 +000093std::string AidlNode::PrintLocation() const {
94 std::stringstream ss;
95 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
96 << location_.end_.line << ":" << location_.end_.column;
97 return ss.str();
98}
99
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900100static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr, ""};
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900101static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr, ""};
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900102static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, ""};
103static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, ""};
104static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr, ""};
105
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700106const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
107 static const std::vector<Schema> kSchemas{
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900108 {AidlAnnotation::Type::NULLABLE, "nullable", CONTEXT_TYPE_SPECIFIER, {}},
109 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
110 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
111 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700112 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
113 "UnsupportedAppUsage",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900114 CONTEXT_TYPE | CONTEXT_MEMBER,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900115 {{"expectedSignature", kStringType},
116 {"implicitMember", kStringType},
117 {"maxTargetSdk", kIntType},
118 {"publicAlternatives", kStringType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900119 {"trackingBug", kLongType}}},
120 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
121 "JavaOnlyStableParcelable",
122 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
123 {}},
124 {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
125 {AidlAnnotation::Type::BACKING,
126 "Backing",
127 CONTEXT_TYPE_ENUM,
128 {{"type", kStringType, /* required= */ true}}},
Jooyung Han5721a232020-12-24 04:34:55 +0900129 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
130 "JavaPassthrough",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900131 CONTEXT_ALL,
132 {{"annotation", kStringType, /* required= */ true}},
133 /* repeatable= */ true},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900134 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900135 "JavaDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900136 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
137 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
138 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
139 "JavaOnlyImmutable",
140 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
141 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
142 {}},
143 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
144 {AidlAnnotation::Type::DESCRIPTOR,
145 "Descriptor",
146 CONTEXT_TYPE_INTERFACE,
147 {{"value", kStringType, /* required= */ true}}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700148 {AidlAnnotation::Type::RUST_DERIVE,
149 "RustDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900150 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900151 {{"Copy", kBooleanType},
152 {"Clone", kBooleanType},
153 {"PartialOrd", kBooleanType},
154 {"Ord", kBooleanType},
155 {"PartialEq", kBooleanType},
156 {"Eq", kBooleanType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900157 {"Hash", kBooleanType}}},
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900158 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
159 "SuppressWarnings",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900160 CONTEXT_TYPE | CONTEXT_MEMBER,
161 {{"value", kStringArrayType, /* required= */ true}}},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900162 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700163 return kSchemas;
164}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900165
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700166std::string AidlAnnotation::TypeToString(Type type) {
167 for (const Schema& schema : AllSchemas()) {
168 if (type == schema.type) return schema.name;
169 }
170 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
171 __builtin_unreachable();
172}
Andrei Onea9445fc62019-06-27 18:11:59 +0100173
174AidlAnnotation* AidlAnnotation::Parse(
175 const AidlLocation& location, const string& name,
176 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700177 const Schema* schema = nullptr;
178 for (const Schema& a_schema : AllSchemas()) {
179 if (a_schema.name == name) {
180 schema = &a_schema;
181 }
182 }
183
184 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900185 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700186 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900187 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700188 for (const Schema& s : AllSchemas()) {
189 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900190 }
191 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700192 AIDL_ERROR(location) << stream.str();
193 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900194 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100195 if (parameter_list == nullptr) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700196 return new AidlAnnotation(location, *schema, {});
Andrei Onea9445fc62019-06-27 18:11:59 +0100197 }
198
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700199 return new AidlAnnotation(location, *schema, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900200}
201
Andrei Onea9445fc62019-06-27 18:11:59 +0100202AidlAnnotation::AidlAnnotation(
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700203 const AidlLocation& location, const Schema& schema,
Andrei Onea9445fc62019-06-27 18:11:59 +0100204 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700205 : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100206
Jooyung Hanc5688f72021-01-05 15:41:48 +0900207struct ConstReferenceFinder : AidlVisitor {
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900208 const AidlConstantReference* found;
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900209 void Visit(const AidlConstantReference& ref) override {
Jooyung Han690f5842020-12-04 13:02:04 +0900210 if (!found) found = &ref;
211 }
Jooyung Hanc5688f72021-01-05 15:41:48 +0900212 static const AidlConstantReference* Find(const AidlConstantValue& c) {
213 ConstReferenceFinder finder;
214 VisitTopDown(finder, c);
215 return finder.found;
216 }
Jooyung Han690f5842020-12-04 13:02:04 +0900217};
218
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900219// Checks if annotation complies with the schema
220// - every parameter is known and has well-typed value.
221// - every required parameter is present.
Andrei Onea9445fc62019-06-27 18:11:59 +0100222bool AidlAnnotation::CheckValid() const {
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;
Jooyung Han690f5842020-12-04 13:02:04 +0900226
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900227 const ParamType* param_type = schema_.ParamType(param_name);
228 if (!param_type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100229 std::ostringstream stream;
230 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700231 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100232 stream << "It must be one of:";
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900233 for (const auto& param : schema_.parameters) {
234 stream << " " << param.name;
Andrei Onea9445fc62019-06-27 18:11:59 +0100235 }
236 AIDL_ERROR(this) << stream.str();
237 return false;
238 }
Jooyung Han690f5842020-12-04 13:02:04 +0900239
Jooyung Hanc5688f72021-01-05 15:41:48 +0900240 const auto& found = ConstReferenceFinder::Find(*param);
241 if (found) {
242 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
243 << found->GetFieldName() << ".";
Jooyung Han690f5842020-12-04 13:02:04 +0900244 return false;
245 }
246
247 if (!param->CheckValid()) {
248 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
249 << GetName() << ".";
250 return false;
251 }
252
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900253 const std::string param_value =
254 param->ValueString(param_type->type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100255 // Assume error on empty string.
256 if (param_value == "") {
257 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
258 << GetName() << ".";
259 return false;
260 }
261 }
Jooyung Han5721a232020-12-24 04:34:55 +0900262 bool success = true;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900263 for (const auto& param : schema_.parameters) {
264 if (param.required && parameters_.count(param.name) == 0) {
265 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
Jooyung Han5721a232020-12-24 04:34:55 +0900266 success = false;
267 }
268 }
269 return success;
Andrei Onea9445fc62019-06-27 18:11:59 +0100270}
271
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900272// Checks if the annotation is applicable to the current context.
273// For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
274// nodes.
275bool AidlAnnotation::CheckContext(TargetContext context) const {
276 if (schema_.target_context & static_cast<uint32_t>(context)) {
277 return true;
278 }
279 const static map<TargetContext, string> context_name_map{
280 {CONTEXT_TYPE_INTERFACE, "interface"},
281 {CONTEXT_TYPE_ENUM, "enum"},
282 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
283 {CONTEXT_TYPE_UNION, "union"},
284 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
285 {CONTEXT_CONST, "constant"},
286 {CONTEXT_FIELD, "field"},
287 {CONTEXT_METHOD, "method"},
288 {CONTEXT_TYPE_SPECIFIER, "type"},
289 };
290 vector<string> available;
291 for (const auto& [context, name] : context_name_map) {
292 if (schema_.target_context & context) {
293 available.push_back(name);
294 }
295 }
296 AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
297 << Join(available, ", ") << "}.";
298 return false;
299}
300
Andrei Onea9445fc62019-06-27 18:11:59 +0100301std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
302 const ConstantValueDecorator& decorator) const {
303 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100304 for (const auto& name_and_param : parameters_) {
305 const std::string& param_name = name_and_param.first;
306 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900307 const ParamType* param_type = schema_.ParamType(param_name);
308 AIDL_FATAL_IF(!param_type, this);
309 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100310 }
311 return raw_params;
312}
Steven Moreland46e9da82018-07-27 15:45:29 -0700313
Jooyung Han965e31d2020-11-27 12:30:16 +0900314std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700315 if (parameters_.empty()) {
316 return "@" + GetName();
317 } else {
318 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900319 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700320 param_strings.emplace_back(name + "=" + value);
321 }
322 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
323 }
324}
325
Jooyung Hanc5688f72021-01-05 15:41:48 +0900326void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
327 for (const auto& [name, value] : parameters_) {
328 (void)name;
329 traverse(*value);
330 }
331}
332
Andrei Onea9445fc62019-06-27 18:11:59 +0100333static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700334 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100335 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700336 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900337 AIDL_FATAL_IF(a.Repeatable(), a)
338 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100339 return &a;
340 }
341 }
342 return nullptr;
343}
344
Steven Moreland46e9da82018-07-27 15:45:29 -0700345AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
346
Jiyong Park68bc77a2018-07-19 19:00:45 +0900347bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700348 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900349}
350
Jiyong Park68bc77a2018-07-19 19:00:45 +0900351bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700352 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900353}
354
Steven Morelanda7764e52020-10-27 17:29:29 +0000355bool AidlAnnotatable::IsSensitiveData() const {
356 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
357}
358
Steven Morelanda57d0a62019-07-30 09:41:14 -0700359bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700360 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700361}
362
Jeongik Chad0a10272020-08-06 16:33:36 +0900363bool AidlAnnotatable::IsJavaOnlyImmutable() const {
364 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900365}
366
Devin Moorec7e47a32020-08-07 10:55:25 -0700367bool AidlAnnotatable::IsFixedSize() const {
368 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
369}
370
Andrei Onea9445fc62019-06-27 18:11:59 +0100371const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700372 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900373}
374
Andrei Homescue61feb52020-08-18 15:44:24 -0700375const AidlAnnotation* AidlAnnotatable::RustDerive() const {
376 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
377}
378
Jooyung Han672557b2020-12-24 05:18:00 +0900379const AidlAnnotation* AidlAnnotatable::BackingType() const {
380 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700381}
382
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900383std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
384 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
385 if (annot) {
386 auto names = annot->ParamValue<std::vector<std::string>>("value");
387 AIDL_FATAL_IF(!names.has_value(), this);
388 return std::move(names.value());
389 }
390 return {};
391}
392
Jeongik Cha88f95a82020-01-15 13:02:16 +0900393bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700394 return lang == Options::Language::JAVA &&
395 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900396}
397
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800398bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700399 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800400}
401
Jooyung Han829ec7c2020-12-02 12:07:36 +0900402bool AidlAnnotatable::JavaDerive(const std::string& method) const {
403 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
404 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900405 return annotation->ParamValue<bool>(method).value_or(false);
Jooyung Han829ec7c2020-12-02 12:07:36 +0900406 }
407 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900408}
409
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900410std::string AidlAnnotatable::GetDescriptor() const {
411 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
412 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900413 return annotation->ParamValue<std::string>("value").value();
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900414 }
415 return "";
416}
417
Steven Moreland7e4b9502020-02-20 18:10:42 -0800418void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
419 if (annotations_.empty()) return;
420
421 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
422}
423
Devin Moore24f68572020-02-26 13:20:59 -0800424bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100425 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900426 if (!annotation.CheckValid()) {
427 return false;
428 }
429 }
430
431 std::map<AidlAnnotation::Type, AidlLocation> declared;
432 for (const auto& annotation : GetAnnotations()) {
433 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
434 if (!inserted && !annotation.Repeatable()) {
435 AIDL_ERROR(this) << "'" << annotation.GetName()
436 << "' is repeated, but not allowed. Previous location: " << iter->second;
437 return false;
438 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100439 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700440
Andrei Onea9445fc62019-06-27 18:11:59 +0100441 return true;
442}
443
Jiyong Park68bc77a2018-07-19 19:00:45 +0900444string AidlAnnotatable::ToString() const {
445 vector<string> ret;
446 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900447 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900448 }
449 std::sort(ret.begin(), ret.end());
450 return Join(ret, " ");
451}
452
Steven Moreland46e9da82018-07-27 15:45:29 -0700453AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
454 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900455 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700456 const string& comments)
457 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900458 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700459 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700460 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900461 comments_(comments),
462 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700463
Jooyung Hand2fa0232020-10-19 02:51:41 +0900464const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700465 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900466 // Declaring array of generic type cannot happen, it is grammar error.
467 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700468
Jooyung Hand2fa0232020-10-19 02:51:41 +0900469 if (!array_base_) {
470 array_base_.reset(new AidlTypeSpecifier(*this));
471 array_base_->is_array_ = false;
472 }
473 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700474}
475
Jooyung Han965e31d2020-11-27 12:30:16 +0900476string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900477 string ret = GetName();
478 if (IsGeneric()) {
479 vector<string> arg_names;
480 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900481 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900482 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900483 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900484 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900485 if (IsArray()) {
486 ret += "[]";
487 }
488 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900489}
490
Jooyung Han965e31d2020-11-27 12:30:16 +0900491string AidlTypeSpecifier::ToString() const {
492 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900493 string annotations = AidlAnnotatable::ToString();
494 if (annotations != "") {
495 ret = annotations + " " + ret;
496 }
497 return ret;
498}
499
Daniel Norman716d3112019-09-10 13:11:56 -0700500bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000501 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700502 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
503 if (result.is_resolved) {
504 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900505 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900506 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900507 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700508 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700509}
510
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900511const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
512 return defined_type_;
513}
514
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900515bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800516 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100517 return false;
518 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900519 if (IsGeneric()) {
520 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900521
522 auto& types = GetTypeParameters();
523 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
524 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900525 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
526 return (typenames.GetEnumDeclaration(*type_ptr)) ||
527 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
Jeongik Chae74c86d2019-12-12 16:54:03 +0900528 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700529 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900530 return false;
531 }
532 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800533 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900534 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800535 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
536 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900537 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800538 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900539 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800540 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900541 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000542 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900543 return false;
544 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900545 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
546 const string& contained_type_name = contained_type.GetName();
547 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
548 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
549 contained_type_name != "ParcelFileDescriptor") {
550 AIDL_ERROR(this) << "List<" << contained_type_name
551 << "> is not supported. List<T> supports parcelable/union, String, "
552 "IBinder, and ParcelFileDescriptor.";
553 return false;
554 }
555 } else { // Defined types
556 if (typenames.GetInterface(contained_type)) {
557 AIDL_ERROR(this) << "List<" << contained_type_name
558 << "> is not supported. List<T> supports parcelable/union, String, "
559 "IBinder, and ParcelFileDescriptor.";
560 return false;
561 }
562 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900563 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800564 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900565 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900566 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900567 return false;
568 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800569 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900570 const string& key_type = GetTypeParameters()[0]->GetName();
571 if (key_type != "String") {
572 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
573 << "'" << key_type << "'";
574 return false;
575 }
576 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800577 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900578 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800579 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900580 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800581 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900582 return false;
583 }
584 } else {
585 AIDL_ERROR(this) << type_name << " is not a generic type.";
586 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900587 }
588 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900589
Steven Moreland11cb9452020-01-21 16:56:58 -0800590 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
591 GetTypeParameters().size() == 1 &&
592 GetTypeParameters()[0]->GetName() == "String";
593 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
594 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
595 return false;
596 }
597
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900598 if (GetName() == "void") {
599 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
600 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
601 return false;
602 }
603 }
604
605 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800606 const auto defined_type = typenames.TryGetDefinedType(GetName());
607 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900608 AIDL_ERROR(this) << "Binder type cannot be an array";
609 return false;
610 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000611 if (GetName() == "ParcelableHolder") {
612 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
613 return false;
614 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900615 }
616
617 if (IsNullable()) {
618 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
619 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
620 return false;
621 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800622 const auto defined_type = typenames.TryGetDefinedType(GetName());
623 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700624 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
625 return false;
626 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900627 if (GetName() == "ParcelableHolder") {
628 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
629 return false;
630 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900631 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900632 return true;
633}
634
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900635std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700636 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900637 if (type.IsArray()) {
638 return raw_value;
639 }
640
641 if (auto defined_type = type.GetDefinedType(); defined_type) {
642 auto enum_type = defined_type->AsEnumDeclaration();
643 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
644 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
645 }
Steven Moreland860b1942018-08-16 14:59:28 -0700646 return raw_value;
647}
648
Steven Moreland46e9da82018-07-27 15:45:29 -0700649AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
650 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000651 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
652 default_user_specified_ = false;
653}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700654
Steven Moreland46e9da82018-07-27 15:45:29 -0700655AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
656 AidlTypeSpecifier* type, const std::string& name,
657 AidlConstantValue* default_value)
Jooyung Han3f347ca2020-12-01 12:41:50 +0900658 : AidlMember(location),
Steven Moreland541788d2020-05-21 22:05:52 +0000659 type_(type),
660 name_(name),
661 default_user_specified_(true),
662 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700663
Jooyung Han53fb4242020-12-17 16:03:49 +0900664bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
665 if (GetDefaultValue()) {
666 return true;
667 }
668 // null is accepted as a valid default value in all backends
669 if (GetType().IsNullable()) {
670 return true;
671 }
672 return false;
673}
674
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900675bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700676 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900677 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900678
Steven Moreland54be7bd2019-12-05 11:17:53 -0800679 if (type_->GetName() == "void") {
680 AIDL_ERROR(this) << "Declaration " << name_
681 << " is void, but declarations cannot be of void type.";
682 valid = false;
683 }
684
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900685 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700686 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700687
Steven Moreland25294322018-08-07 18:13:55 -0700688 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700689
Steven Moreland860b1942018-08-16 14:59:28 -0700690 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700691}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700692
Jooyung Hanacae85d2020-10-28 16:39:09 +0900693string AidlVariableDeclaration::GetCapitalizedName() const {
694 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
695 string str = name_;
696 str[0] = static_cast<char>(toupper(str[0]));
697 return str;
698}
699
Steven Moreland5557f1c2018-07-02 13:50:23 -0700700string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900701 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000702 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700703 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700704 }
705 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700706}
707
Jiyong Park02da7422018-07-16 16:00:26 +0900708string AidlVariableDeclaration::Signature() const {
709 return type_->Signature() + " " + name_;
710}
711
Steven Moreland860b1942018-08-16 14:59:28 -0700712std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900713 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700714 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900715 } else {
716 return "";
717 }
Steven Moreland25294322018-08-07 18:13:55 -0700718}
719
Jooyung Hanc5688f72021-01-05 15:41:48 +0900720void AidlVariableDeclaration::TraverseChildren(
721 std::function<void(const AidlNode&)> traverse) const {
722 traverse(GetType());
723 if (IsDefaultUserSpecified()) {
724 traverse(*GetDefaultValue());
725 }
726}
727
Steven Moreland46e9da82018-07-27 15:45:29 -0700728AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
729 AidlTypeSpecifier* type, const std::string& name)
730 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700731 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700732 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700733
Steven Moreland46e9da82018-07-27 15:45:29 -0700734AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
735 const std::string& name)
736 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700737 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700738 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700739
Jiyong Park02da7422018-07-16 16:00:26 +0900740string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700741 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700742 if (direction_specified_) {
743 switch(direction_) {
744 case AidlArgument::IN_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700745 ret += "in";
Casey Dahlinc378c992015-09-29 16:50:40 -0700746 break;
747 case AidlArgument::OUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700748 ret += "out";
Casey Dahlinc378c992015-09-29 16:50:40 -0700749 break;
750 case AidlArgument::INOUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700751 ret += "inout";
Casey Dahlinc378c992015-09-29 16:50:40 -0700752 break;
753 }
754 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700755 return ret;
756}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700757
Jiyong Park02da7422018-07-16 16:00:26 +0900758string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700759 if (direction_specified_) {
760 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
761 } else {
762 return AidlVariableDeclaration::ToString();
763 }
Jiyong Park02da7422018-07-16 16:00:26 +0900764}
765
Steven Moreland46e9da82018-07-27 15:45:29 -0700766AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
767
Steven Moreland46e9da82018-07-27 15:45:29 -0700768AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
769 AidlTypeSpecifier* type, const std::string& name,
770 AidlConstantValue* value)
771 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700772
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900773bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700774 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900775 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700776 valid &= value_->CheckValid();
777 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700778
Steven Morelande689da22020-11-10 02:06:30 +0000779 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900780 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
781 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700782 return false;
783 }
784
Will McVickerd7d18df2019-09-12 13:40:50 -0700785 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700786}
787
Jiyong Parka428d212018-08-29 22:26:30 +0900788string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900789 return "const " + type_->ToString() + " " + name_ + " = " +
790 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900791}
792
793string AidlConstantDeclaration::Signature() const {
794 return type_->Signature() + " " + name_;
795}
796
Steven Moreland46e9da82018-07-27 15:45:29 -0700797AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
798 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900799 const std::string& comments)
800 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
801 has_id_ = false;
802}
803
804AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
805 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900806 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700807 : AidlMember(location),
808 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700809 comments_(comments),
810 type_(type),
811 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700812 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900813 id_(id),
814 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700815 has_id_ = true;
816 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700817 for (const unique_ptr<AidlArgument>& a : arguments_) {
818 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
819 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
820 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700821}
822
Jooyung Han720253d2021-01-05 19:13:17 +0900823bool AidlMember::IsHidden() const {
Jeongik Cha997281d2020-01-16 15:23:59 +0900824 return HasHideComment(GetComments());
825}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700826
Jooyung Han720253d2021-01-05 19:13:17 +0900827bool AidlMember::IsDeprecated() const {
828 return HasDeprecatedComment(GetComments());
829}
830
Jiyong Park02da7422018-07-16 16:00:26 +0900831string AidlMethod::Signature() const {
832 vector<string> arg_signatures;
833 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900834 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900835 }
Jiyong Park309668e2018-07-28 16:55:44 +0900836 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
837}
838
839string AidlMethod::ToString() const {
840 vector<string> arg_strings;
841 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900842 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900843 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900844 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800845 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900846 if (HasId()) {
847 ret += " = " + std::to_string(GetId());
848 }
849 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900850}
851
Steven Moreland46e9da82018-07-27 15:45:29 -0700852AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900853 const std::string& comments, const std::string& package,
854 std::vector<std::unique_ptr<AidlMember>>* members)
Jiyong Park18132182020-06-08 20:24:40 +0900855 : AidlAnnotatable(location),
856 name_(name),
857 comments_(comments),
858 package_(package),
859 split_package_(package.empty() ? std::vector<std::string>()
Jooyung Han829ec7c2020-12-02 12:07:36 +0900860 : android::base::Split(package, ".")) {
861 if (members) {
862 for (auto& m : *members) {
863 if (auto constant = m->AsConstantDeclaration(); constant) {
864 constants_.emplace_back(constant);
865 } else if (auto variable = m->AsVariableDeclaration(); variable) {
866 variables_.emplace_back(variable);
867 } else if (auto method = m->AsMethod(); method) {
868 methods_.emplace_back(method);
869 } else {
870 AIDL_FATAL(*m);
871 }
872 members_.push_back(m.release());
873 }
874 delete members;
875 }
876}
Steven Moreland787b0432018-07-03 09:00:58 -0700877
Jooyung Han808a2a02020-12-28 16:46:54 +0900878bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800879 if (!AidlAnnotatable::CheckValid(typenames)) {
880 return false;
881 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900882 if (!CheckValidWithMembers(typenames)) {
883 return false;
884 }
Devin Moore24f68572020-02-26 13:20:59 -0800885 return true;
886}
887
Jeongik Cha997281d2020-01-16 15:23:59 +0900888bool AidlDefinedType::IsHidden() const {
889 return HasHideComment(GetComments());
890}
891
Jooyung Han720253d2021-01-05 19:13:17 +0900892bool AidlDefinedType::IsDeprecated() const {
893 return HasDeprecatedComment(GetComments());
894}
895
Steven Moreland787b0432018-07-03 09:00:58 -0700896std::string AidlDefinedType::GetCanonicalName() const {
897 if (package_.empty()) {
898 return GetName();
899 }
900 return GetPackage() + "." + GetName();
901}
902
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800903void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
904 if (this->IsHidden()) {
905 AddHideComment(writer);
906 }
907 DumpAnnotations(writer);
908}
909
Jooyung Han829ec7c2020-12-02 12:07:36 +0900910bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
911 bool success = true;
912
913 for (const auto& v : GetFields()) {
914 const bool field_valid = v->CheckValid(typenames);
915 success = success && field_valid;
916 }
917
918 // field names should be unique
919 std::set<std::string> fieldnames;
920 for (const auto& v : GetFields()) {
921 bool duplicated = !fieldnames.emplace(v->GetName()).second;
922 if (duplicated) {
923 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
924 success = false;
925 }
926 }
927
928 // immutable parcelables should have immutable fields.
929 if (IsJavaOnlyImmutable()) {
930 for (const auto& v : GetFields()) {
931 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
932 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
933 << "non-immutable field named '" << v->GetName() << "'.";
934 success = false;
935 }
936 }
937 }
938
939 set<string> constant_names;
940 for (const auto& constant : GetConstantDeclarations()) {
941 if (constant_names.count(constant->GetName()) > 0) {
942 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
943 success = false;
944 }
945 constant_names.insert(constant->GetName());
946 success = success && constant->CheckValid(typenames);
947 }
948
949 return success;
950}
951
952bool AidlDefinedType::CheckValidForGetterNames() const {
953 bool success = true;
954 std::set<std::string> getters;
955 for (const auto& v : GetFields()) {
956 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
957 if (duplicated) {
958 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
959 << "' after capitalizing the first letter";
960 success = false;
961 }
962 }
963 return success;
964}
965
Jiyong Park18132182020-06-08 20:24:40 +0900966AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
967 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900968 const std::string& cpp_header, std::vector<std::string>* type_params,
969 std::vector<std::unique_ptr<AidlMember>>* members)
970 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900971 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800972 cpp_header_(cpp_header) {
973 // Strip off quotation marks if we actually have a cpp header.
974 if (cpp_header_.length() >= 2) {
975 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
976 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700977}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900978template <typename T>
979AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
980 // Copying is not supported if it has type parameters.
981 // It doesn't make a problem because only ArrayBase() makes a copy,
982 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +0000983 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900984}
985
986template <typename T>
987bool AidlParameterizable<T>::CheckValid() const {
988 return true;
989};
990
991template <>
992bool AidlParameterizable<std::string>::CheckValid() const {
993 if (!IsGeneric()) {
994 return true;
995 }
996 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
997 if (set.size() != GetTypeParameters().size()) {
998 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
999 return false;
1000 }
1001 return true;
1002}
Casey Dahlin59401da2015-10-09 18:16:45 -07001003
Jooyung Han808a2a02020-12-28 16:46:54 +09001004bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1005 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001006 return false;
1007 }
Jeongik Chadf76dc72019-11-28 00:08:47 +09001008 if (!AidlParameterizable<std::string>::CheckValid()) {
1009 return false;
1010 }
Jeongik Cha82317dd2019-02-27 20:26:11 +09001011
1012 return true;
1013}
1014
Jeongik Cha997281d2020-01-16 15:23:59 +09001015void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001016 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001017 writer->Write("parcelable %s ;\n", GetName().c_str());
1018}
1019
Steven Moreland5557f1c2018-07-02 13:50:23 -07001020AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001021 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001022 const std::string& comments, std::vector<std::string>* type_params,
1023 std::vector<std::unique_ptr<AidlMember>>* members)
1024 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001025
Jeongik Cha997281d2020-01-16 15:23:59 +09001026void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001027 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001028 writer->Write("parcelable %s {\n", GetName().c_str());
1029 writer->Indent();
1030 for (const auto& field : GetFields()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001031 if (field->IsHidden()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001032 AddHideComment(writer);
1033 }
Jiyong Parka468e2a2018-08-29 21:25:18 +09001034 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001035 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001036 for (const auto& constdecl : GetConstantDeclarations()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001037 if (constdecl->IsHidden()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001038 AddHideComment(writer);
1039 }
1040 writer->Write("%s;\n", constdecl->ToString().c_str());
1041 }
Jiyong Park02da7422018-07-16 16:00:26 +09001042 writer->Dedent();
1043 writer->Write("}\n");
1044}
1045
Jooyung Han808a2a02020-12-28 16:46:54 +09001046bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1047 if (!AidlParcelable::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001048 return false;
1049 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001050
Jooyung Han59af9cc2020-10-25 21:44:14 +09001051 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001052
Jooyung Hand4057c42020-10-23 13:28:22 +09001053 if (IsFixedSize()) {
1054 for (const auto& v : GetFields()) {
1055 if (!typenames.CanBeFixedSize(v->GetType())) {
1056 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1057 << "non-fixed size field named " << v->GetName() << ".";
1058 success = false;
1059 }
1060 }
1061 }
1062
1063 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001064 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001065 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001066 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001067 }
1068 }
1069
Daniel Norman85aed542019-08-21 12:01:14 -07001070 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001071}
1072
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001073// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001074bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1075 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001076 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1077 GetName() == "IBinder") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001078 AIDL_ERROR(this) << "The " << to_string(lang) << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001079 return false;
1080 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001081 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1082 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1083 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001084 return false;
1085 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001086 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1087 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001088 if (GetName() == "ParcelFileDescriptor") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001089 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001090 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001091 return false;
1092 }
1093
Steven Morelandd59e3172020-05-11 16:42:09 -07001094 const auto defined_type = typenames.TryGetDefinedType(GetName());
1095 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001096 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001097 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001098 return false;
1099 }
1100 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001101 if (this->GetName() == "FileDescriptor" &&
1102 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001103 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001104 return false;
1105 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001106 if (this->IsGeneric()) {
1107 if (this->GetName() == "List") {
Jooyung Han55f96ad2020-12-13 10:08:33 +09001108 if (lang == Options::Language::NDK) {
1109 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1110 const string& contained_type_name = contained_type.GetName();
Jooyung Hane87cdd02020-12-11 16:47:35 +09001111 if (typenames.GetInterface(contained_type)) {
1112 AIDL_ERROR(this) << "List<" << contained_type_name
1113 << "> is not supported. List in NDK doesn't support interface.";
1114 return false;
1115 }
1116 if (contained_type_name == "IBinder") {
1117 AIDL_ERROR(this) << "List<" << contained_type_name
1118 << "> is not supported. List in NDK doesn't support IBinder.";
1119 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001120 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001121 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001122 }
1123 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001124
1125 if (this->IsArray()) {
1126 if (this->GetName() == "List" || this->GetName() == "Map" ||
1127 this->GetName() == "CharSequence") {
1128 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001129 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001130 }
1131 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001132
1133 if (lang != Options::Language::JAVA) {
1134 if (this->GetName() == "List" && !this->IsGeneric()) {
1135 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1136 return false;
1137 }
1138 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1139 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1140 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001141 }
1142 }
1143
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001144 return true;
1145}
1146
1147// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001148bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1149 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001150 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001151 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1152 if (unstructured_parcelable != nullptr) {
1153 if (unstructured_parcelable->GetCppHeader().empty()) {
1154 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001155 << "Unstructured parcelable must have C++ header defined.";
1156 return false;
1157 }
1158 }
1159 }
1160 return true;
1161}
1162
1163// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001164bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1165 Options::Language lang) const {
1166 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001167 return false;
1168 }
1169 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001170 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001171 return false;
1172 }
1173 }
1174 return true;
1175}
1176
Daniel Norman85aed542019-08-21 12:01:14 -07001177AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -07001178 AidlConstantValue* value, const std::string& comments)
Jooyung Han29813842020-12-08 01:28:03 +09001179 : AidlNode(location),
1180 name_(name),
1181 value_(value),
1182 comments_(comments),
1183 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001184
1185bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1186 if (GetValue() == nullptr) {
1187 return false;
1188 }
1189 if (!GetValue()->CheckValid()) {
1190 return false;
1191 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001192 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001193 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1194 return false;
1195 }
1196 return true;
1197}
1198
1199string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1200 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001201 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001202}
1203
1204AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1205 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jiyong Park18132182020-06-08 20:24:40 +09001206 const std::string& package, const std::string& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001207 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001208 enumerators_(std::move(*enumerators)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001209 // Fill missing enumerator values with <prev + 1>
1210 // This can't be done in Autofill() because type/ref resolution depends on this.
1211 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1212 // resolved if A has no value set.
Daniel Normanb28684e2019-10-17 15:31:39 -07001213 const AidlEnumerator* previous = nullptr;
1214 for (const auto& enumerator : enumerators_) {
1215 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001216 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001217 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001218 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001219 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001220 } else {
Jooyung Hand0c8af02021-01-06 18:08:01 +09001221 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
Daniel Normanb28684e2019-10-17 15:31:39 -07001222 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001223 loc, std::move(prev_value), "+",
1224 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001225 }
1226 }
1227 previous = enumerator.get();
1228 }
1229}
1230
Jooyung Han672557b2020-12-24 05:18:00 +09001231bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1232 if (auto annot = BackingType(); annot != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001233 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1234 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
Jooyung Han672557b2020-12-24 05:18:00 +09001235 // need to call CheckValid().
1236 if (!annot->CheckValid()) {
1237 return false;
1238 }
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001239 auto type = annot->ParamValue<std::string>("type").value();
1240 backing_type_ =
1241 std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, "");
Jooyung Han672557b2020-12-24 05:18:00 +09001242 } else {
1243 // Default to byte type for enums.
1244 backing_type_ =
1245 std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, "");
1246 }
1247 // Autofill() is called after type resolution, we resolve the backing type manually.
1248 if (!backing_type_->Resolve(typenames)) {
1249 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
1250 }
1251 return true;
1252}
1253
Jooyung Han808a2a02020-12-28 16:46:54 +09001254bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1255 if (!AidlDefinedType::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001256 return false;
1257 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001258 if (!GetMembers().empty()) {
1259 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1260 return false;
1261 }
Daniel Norman85aed542019-08-21 12:01:14 -07001262 if (backing_type_ == nullptr) {
1263 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1264 return false;
1265 }
1266 bool success = true;
1267 for (const auto& enumerator : enumerators_) {
1268 success = success && enumerator->CheckValid(GetBackingType());
1269 }
Jooyung Han3b990182020-12-22 17:44:31 +09001270
Jooyung Han808a2a02020-12-28 16:46:54 +09001271 return success;
Daniel Norman85aed542019-08-21 12:01:14 -07001272}
1273
Jeongik Cha997281d2020-01-16 15:23:59 +09001274void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001275 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001276 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -07001277 writer->Indent();
1278 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001279 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1280 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1281 }
1282 writer->Dedent();
1283 writer->Write("}\n");
1284}
1285
Jooyung Han2946afc2020-10-05 20:29:16 +09001286AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1287 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001288 std::vector<std::string>* type_params,
1289 std::vector<std::unique_ptr<AidlMember>>* members)
1290 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001291
Jooyung Han2946afc2020-10-05 20:29:16 +09001292void AidlUnionDecl::Dump(CodeWriter* writer) const {
1293 DumpHeader(writer);
1294 writer->Write("union %s {\n", GetName().c_str());
1295 writer->Indent();
1296 for (const auto& field : GetFields()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001297 if (field->IsHidden()) {
Jooyung Han2946afc2020-10-05 20:29:16 +09001298 AddHideComment(writer);
1299 }
1300 writer->Write("%s;\n", field->ToString().c_str());
1301 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001302 for (const auto& constdecl : GetConstantDeclarations()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001303 if (constdecl->IsHidden()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001304 AddHideComment(writer);
1305 }
1306 writer->Write("%s;\n", constdecl->ToString().c_str());
1307 }
Jooyung Han2946afc2020-10-05 20:29:16 +09001308 writer->Dedent();
1309 writer->Write("}\n");
1310}
1311
Jooyung Han808a2a02020-12-28 16:46:54 +09001312bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001313 // visit parents
Jooyung Han808a2a02020-12-28 16:46:54 +09001314 if (!AidlParcelable::CheckValid(typenames)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001315 return false;
1316 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001317
1318 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001319 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001320 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001321 }
1322
1323 // now, visit self!
1324 bool success = true;
1325
1326 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1327 for (const auto& v : GetFields()) {
1328 if (v->GetType().GetName() == "ParcelableHolder") {
1329 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1330 success = false;
1331 }
1332 }
1333
Jooyung Hanfe89f122020-10-14 03:49:18 +09001334 if (GetFields().empty()) {
1335 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1336 return false;
1337 }
1338
Jooyung Han53fb4242020-12-17 16:03:49 +09001339 // first member should have useful default value (implicit or explicit)
1340 const auto& first = GetFields()[0];
1341 if (!first->HasUsefulDefaultValue()) {
1342 // Most types can be initialized without a default value. For example,
1343 // interface types are inherently nullable. But, enum types should have
1344 // an explicit default value.
1345 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1346 AIDL_ERROR(first)
1347 << "The union's first member should have a useful default value. Enum types can be "
1348 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1349 return false;
1350 }
1351 // In Java, array types are initialized as null without a default value. To be sure that default
1352 // initialized unions are accepted by other backends we require arrays also have a default
1353 // value.
1354 if (first->GetType().IsArray()) {
1355 AIDL_ERROR(first)
1356 << "The union's first member should have a useful default value. Arrays can be "
1357 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1358 return false;
1359 }
1360 }
1361
Jooyung Hanfe89f122020-10-14 03:49:18 +09001362 return success;
1363}
1364
1365// TODO: we should treat every backend all the same in future.
1366bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1367 Options::Language lang) const {
1368 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1369 return false;
1370 }
1371 for (const auto& v : this->GetFields()) {
1372 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1373 return false;
1374 }
1375 }
1376 return true;
1377}
1378
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001379// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001380bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1381 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001382 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001383 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001384 return false;
1385 }
1386 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001387 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001388 return false;
1389 }
1390 }
1391 }
1392 return true;
1393}
1394
Steven Moreland46e9da82018-07-27 15:45:29 -07001395AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001396 const std::string& comments, bool oneway, const std::string& package,
1397 std::vector<std::unique_ptr<AidlMember>>* members)
1398 : AidlDefinedType(location, name, comments, package, members) {
1399 for (auto& m : GetMethods()) {
1400 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001401 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001402}
1403
Jeongik Cha997281d2020-01-16 15:23:59 +09001404void AidlInterface::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001405 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001406 writer->Write("interface %s {\n", GetName().c_str());
1407 writer->Indent();
1408 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001409 if (method->IsHidden()) {
1410 AddHideComment(writer);
1411 }
Jiyong Park309668e2018-07-28 16:55:44 +09001412 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001413 }
Jiyong Parka428d212018-08-29 22:26:30 +09001414 for (const auto& constdecl : GetConstantDeclarations()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001415 if (constdecl->IsHidden()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001416 AddHideComment(writer);
1417 }
Jiyong Parka428d212018-08-29 22:26:30 +09001418 writer->Write("%s;\n", constdecl->ToString().c_str());
1419 }
Jiyong Park02da7422018-07-16 16:00:26 +09001420 writer->Dedent();
1421 writer->Write("}\n");
1422}
1423
Jooyung Han808a2a02020-12-28 16:46:54 +09001424bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1425 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001426 return false;
1427 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001428 // Has to be a pointer due to deleting copy constructor. No idea why.
1429 map<string, const AidlMethod*> method_names;
1430 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001431 if (!m->GetType().CheckValid(typenames)) {
1432 return false;
1433 }
1434
Jeongik Cha649e8a72020-03-27 17:47:40 +09001435 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1436 if (m->GetType().GetName() == "ParcelableHolder") {
1437 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1438 return false;
1439 }
Steven Morelandacd53472018-12-14 10:17:26 -08001440 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001441 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1442 return false;
1443 }
1444
1445 set<string> argument_names;
1446 for (const auto& arg : m->GetArguments()) {
1447 auto it = argument_names.find(arg->GetName());
1448 if (it != argument_names.end()) {
1449 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1450 << arg->GetName() << "'";
1451 return false;
1452 }
1453 argument_names.insert(arg->GetName());
1454
1455 if (!arg->GetType().CheckValid(typenames)) {
1456 return false;
1457 }
1458
Jeongik Cha649e8a72020-03-27 17:47:40 +09001459 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1460 if (arg->GetType().GetName() == "ParcelableHolder") {
1461 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1462 return false;
1463 }
Steven Morelandacd53472018-12-14 10:17:26 -08001464 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001465 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1466 return false;
1467 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001468
1469 const auto [can_be_out, type_aspect] = typenames.CanBeOutParameter(arg->GetType());
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001470 if (!arg->DirectionWasSpecified() && can_be_out) {
Jooyung Han965e31d2020-11-27 12:30:16 +09001471 AIDL_ERROR(arg) << "'" << arg->GetType().Signature()
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001472 << "' can be an out type, so you must declare it as in, out, or inout.";
1473 return false;
1474 }
1475
1476 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
Jooyung Han15fd6c62020-10-23 13:54:46 +09001477 AIDL_ERROR(arg) << "'" << arg->GetName() << "' can't be an " << arg->GetDirectionSpecifier()
1478 << " parameter because " << type_aspect << " can only be an in parameter.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001479 return false;
1480 }
1481
1482 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001483 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001484 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1485 return false;
1486 }
1487
1488 // Reserve a namespace for internal use
1489 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1490 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1491 return false;
1492 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001493 }
1494
1495 auto it = method_names.find(m->GetName());
1496 // prevent duplicate methods
1497 if (it == method_names.end()) {
1498 method_names[m->GetName()] = m.get();
1499 } else {
1500 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1501 AIDL_ERROR(it->second) << "previously defined here.";
1502 return false;
1503 }
1504
Paul Trautrimb77048c2020-01-21 16:39:32 +09001505 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001506 "getTransactionName(int)"};
1507
1508 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001509 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001510 return false;
1511 }
1512 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001513
1514 bool success = true;
1515 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001516 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001517 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001518 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001519 success = false;
1520 }
1521 constant_names.insert(constant->GetName());
1522 success = success && constant->CheckValid(typenames);
1523 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001524 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001525}
1526
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001527std::string AidlInterface::GetDescriptor() const {
1528 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1529 if (annotatedDescriptor != "") {
1530 return annotatedDescriptor;
1531 }
1532 return GetCanonicalName();
1533}
1534
Steven Moreland46e9da82018-07-27 15:45:29 -07001535AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1536 : AidlNode(location), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001537
1538// Resolves unresolved type name to fully qualified typename to import
1539// case #1: SimpleName --> import p.SimpleName
1540// case #2: Outer.Inner --> import p.Outer
1541// case #3: p.SimpleName --> (as is)
1542std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1543 std::string canonical_name;
1544 const auto first_dot = unresolved_name.find_first_of('.');
1545 const std::string class_name =
1546 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1547 for (const auto& import : Imports()) {
1548 const auto& fq_name = import->GetNeededClass();
1549 const auto last_dot = fq_name.find_last_of('.');
1550 const std::string imported_type_name =
1551 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1552 if (imported_type_name == class_name) {
1553 if (canonical_name != "" && canonical_name != fq_name) {
1554 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1555 return {};
1556 }
1557 canonical_name = fq_name;
1558 }
1559 }
1560 // if not found, use unresolved_name as it is
1561 if (canonical_name == "") {
1562 return unresolved_name;
1563 }
1564 return canonical_name;
Steven Moreland26318532020-12-23 20:08:36 +00001565}