blob: 8f0c2554290fb914e6590a39098d9849c83e7e54 [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"
Jooyung Hand4fe00e2021-01-11 16:21:53 +090036#include "comments.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070037#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080038
Will McVickerd7d18df2019-09-12 13:40:50 -070039#include "aidl.h"
40
Casey Dahlin07b9dde2015-09-10 19:13:49 -070041#ifdef _WIN32
42int isatty(int fd)
43{
44 return (fd == 0);
45}
46#endif
47
Christopher Wiley4a2884b2015-10-07 11:27:45 -070048using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070049using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080050using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070051using std::cerr;
Jiyong Park1deecc32018-07-17 01:14:41 +090052using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090053using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070054using std::string;
55using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090056using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080057
Jeongik Cha047c5ee2019-08-07 23:16:49 +090058namespace {
Jeongik Cha997281d2020-01-16 15:23:59 +090059bool IsJavaKeyword(const char* str) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +090060 static const std::vector<std::string> kJavaKeywords{
61 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
62 "char", "class", "const", "continue", "default", "do", "double",
63 "else", "enum", "extends", "final", "finally", "float", "for",
64 "goto", "if", "implements", "import", "instanceof", "int", "interface",
65 "long", "native", "new", "package", "private", "protected", "public",
66 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
67 "this", "throw", "throws", "transient", "try", "void", "volatile",
68 "while", "true", "false", "null",
69 };
70 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
71}
72} // namespace
73
Jooyung Han8451a202021-01-16 03:07:06 +090074AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +090075 : location_(location), comments_(comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070076
Mathew Inwoodadb74672019-11-29 14:01:53 +000077std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000078 std::stringstream ss;
79 ss << location_.file_ << ":" << location_.begin_.line;
80 return ss.str();
81}
82
Mathew Inwoodadb74672019-11-29 14:01:53 +000083std::string AidlNode::PrintLocation() const {
84 std::stringstream ss;
85 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
86 << location_.end_.line << ":" << location_.end_.column;
87 return ss.str();
88}
89
Jooyung Han8451a202021-01-16 03:07:06 +090090static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
91 Comments{}};
92static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
93 Comments{}};
94static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
95static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
96static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
97 Comments{}};
Jooyung Han5c2fcae2020-12-26 00:04:39 +090098
Steven Moreland0cea4aa2020-04-20 21:06:02 -070099const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
100 static const std::vector<Schema> kSchemas{
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900101 {AidlAnnotation::Type::NULLABLE, "nullable", CONTEXT_TYPE_SPECIFIER, {}},
102 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
103 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
104 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700105 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
106 "UnsupportedAppUsage",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900107 CONTEXT_TYPE | CONTEXT_MEMBER,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900108 {{"expectedSignature", kStringType},
109 {"implicitMember", kStringType},
110 {"maxTargetSdk", kIntType},
111 {"publicAlternatives", kStringType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900112 {"trackingBug", kLongType}}},
113 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
114 "JavaOnlyStableParcelable",
115 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
116 {}},
117 {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
118 {AidlAnnotation::Type::BACKING,
119 "Backing",
120 CONTEXT_TYPE_ENUM,
121 {{"type", kStringType, /* required= */ true}}},
Jooyung Han5721a232020-12-24 04:34:55 +0900122 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
123 "JavaPassthrough",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900124 CONTEXT_ALL,
125 {{"annotation", kStringType, /* required= */ true}},
126 /* repeatable= */ true},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900127 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900128 "JavaDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900129 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
130 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
131 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
132 "JavaOnlyImmutable",
133 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
134 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
135 {}},
136 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
137 {AidlAnnotation::Type::DESCRIPTOR,
138 "Descriptor",
139 CONTEXT_TYPE_INTERFACE,
140 {{"value", kStringType, /* required= */ true}}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700141 {AidlAnnotation::Type::RUST_DERIVE,
142 "RustDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900143 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900144 {{"Copy", kBooleanType},
145 {"Clone", kBooleanType},
146 {"PartialOrd", kBooleanType},
147 {"Ord", kBooleanType},
148 {"PartialEq", kBooleanType},
149 {"Eq", kBooleanType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900150 {"Hash", kBooleanType}}},
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900151 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
152 "SuppressWarnings",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900153 CONTEXT_TYPE | CONTEXT_MEMBER,
154 {{"value", kStringArrayType, /* required= */ true}}},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900155 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700156 return kSchemas;
157}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900158
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700159std::string AidlAnnotation::TypeToString(Type type) {
160 for (const Schema& schema : AllSchemas()) {
161 if (type == schema.type) return schema.name;
162 }
163 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
164 __builtin_unreachable();
165}
Andrei Onea9445fc62019-06-27 18:11:59 +0100166
167AidlAnnotation* AidlAnnotation::Parse(
168 const AidlLocation& location, const string& name,
Jooyung Han6736ffb2021-01-16 10:13:40 +0900169 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list,
Jooyung Han8451a202021-01-16 03:07:06 +0900170 const Comments& comments) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700171 const Schema* schema = nullptr;
172 for (const Schema& a_schema : AllSchemas()) {
173 if (a_schema.name == name) {
174 schema = &a_schema;
175 }
176 }
177
178 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900179 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700180 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900181 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700182 for (const Schema& s : AllSchemas()) {
183 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900184 }
185 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700186 AIDL_ERROR(location) << stream.str();
187 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900188 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100189 if (parameter_list == nullptr) {
Jooyung Han6736ffb2021-01-16 10:13:40 +0900190 return new AidlAnnotation(location, *schema, {}, comments);
Andrei Onea9445fc62019-06-27 18:11:59 +0100191 }
192
Jooyung Han6736ffb2021-01-16 10:13:40 +0900193 return new AidlAnnotation(location, *schema, std::move(*parameter_list), comments);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900194}
195
Andrei Onea9445fc62019-06-27 18:11:59 +0100196AidlAnnotation::AidlAnnotation(
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700197 const AidlLocation& location, const Schema& schema,
Jooyung Han6736ffb2021-01-16 10:13:40 +0900198 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters,
Jooyung Han8451a202021-01-16 03:07:06 +0900199 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900200 : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100201
Jooyung Hanc5688f72021-01-05 15:41:48 +0900202struct ConstReferenceFinder : AidlVisitor {
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900203 const AidlConstantReference* found;
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900204 void Visit(const AidlConstantReference& ref) override {
Jooyung Han690f5842020-12-04 13:02:04 +0900205 if (!found) found = &ref;
206 }
Jooyung Hanc5688f72021-01-05 15:41:48 +0900207 static const AidlConstantReference* Find(const AidlConstantValue& c) {
208 ConstReferenceFinder finder;
209 VisitTopDown(finder, c);
210 return finder.found;
211 }
Jooyung Han690f5842020-12-04 13:02:04 +0900212};
213
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900214// Checks if annotation complies with the schema
215// - every parameter is known and has well-typed value.
216// - every required parameter is present.
Andrei Onea9445fc62019-06-27 18:11:59 +0100217bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100218 for (const auto& name_and_param : parameters_) {
219 const std::string& param_name = name_and_param.first;
220 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han690f5842020-12-04 13:02:04 +0900221
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900222 const ParamType* param_type = schema_.ParamType(param_name);
223 if (!param_type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100224 std::ostringstream stream;
225 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700226 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100227 stream << "It must be one of:";
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900228 for (const auto& param : schema_.parameters) {
229 stream << " " << param.name;
Andrei Onea9445fc62019-06-27 18:11:59 +0100230 }
231 AIDL_ERROR(this) << stream.str();
232 return false;
233 }
Jooyung Han690f5842020-12-04 13:02:04 +0900234
Jooyung Hanc5688f72021-01-05 15:41:48 +0900235 const auto& found = ConstReferenceFinder::Find(*param);
236 if (found) {
237 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
238 << found->GetFieldName() << ".";
Jooyung Han690f5842020-12-04 13:02:04 +0900239 return false;
240 }
241
242 if (!param->CheckValid()) {
243 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
244 << GetName() << ".";
245 return false;
246 }
247
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900248 const std::string param_value =
249 param->ValueString(param_type->type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100250 // Assume error on empty string.
251 if (param_value == "") {
252 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
253 << GetName() << ".";
254 return false;
255 }
256 }
Jooyung Han5721a232020-12-24 04:34:55 +0900257 bool success = true;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900258 for (const auto& param : schema_.parameters) {
259 if (param.required && parameters_.count(param.name) == 0) {
260 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
Jooyung Han5721a232020-12-24 04:34:55 +0900261 success = false;
262 }
263 }
264 return success;
Andrei Onea9445fc62019-06-27 18:11:59 +0100265}
266
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900267// Checks if the annotation is applicable to the current context.
268// For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
269// nodes.
270bool AidlAnnotation::CheckContext(TargetContext context) const {
271 if (schema_.target_context & static_cast<uint32_t>(context)) {
272 return true;
273 }
274 const static map<TargetContext, string> context_name_map{
275 {CONTEXT_TYPE_INTERFACE, "interface"},
276 {CONTEXT_TYPE_ENUM, "enum"},
277 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
278 {CONTEXT_TYPE_UNION, "union"},
279 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
280 {CONTEXT_CONST, "constant"},
281 {CONTEXT_FIELD, "field"},
282 {CONTEXT_METHOD, "method"},
283 {CONTEXT_TYPE_SPECIFIER, "type"},
284 };
285 vector<string> available;
286 for (const auto& [context, name] : context_name_map) {
287 if (schema_.target_context & context) {
288 available.push_back(name);
289 }
290 }
291 AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
292 << Join(available, ", ") << "}.";
293 return false;
294}
295
Andrei Onea9445fc62019-06-27 18:11:59 +0100296std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
297 const ConstantValueDecorator& decorator) const {
298 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100299 for (const auto& name_and_param : parameters_) {
300 const std::string& param_name = name_and_param.first;
301 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900302 const ParamType* param_type = schema_.ParamType(param_name);
303 AIDL_FATAL_IF(!param_type, this);
304 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100305 }
306 return raw_params;
307}
Steven Moreland46e9da82018-07-27 15:45:29 -0700308
Jooyung Han965e31d2020-11-27 12:30:16 +0900309std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700310 if (parameters_.empty()) {
311 return "@" + GetName();
312 } else {
313 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900314 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700315 param_strings.emplace_back(name + "=" + value);
316 }
317 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
318 }
319}
320
Jooyung Hanc5688f72021-01-05 15:41:48 +0900321void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
322 for (const auto& [name, value] : parameters_) {
323 (void)name;
324 traverse(*value);
325 }
326}
327
Andrei Onea9445fc62019-06-27 18:11:59 +0100328static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700329 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100330 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700331 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900332 AIDL_FATAL_IF(a.Repeatable(), a)
333 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100334 return &a;
335 }
336 }
337 return nullptr;
338}
339
Jooyung Han8451a202021-01-16 03:07:06 +0900340AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900341 : AidlCommentable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700342
Jiyong Park68bc77a2018-07-19 19:00:45 +0900343bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700344 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900345}
346
Jiyong Park68bc77a2018-07-19 19:00:45 +0900347bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700348 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900349}
350
Steven Morelanda7764e52020-10-27 17:29:29 +0000351bool AidlAnnotatable::IsSensitiveData() const {
352 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
353}
354
Steven Morelanda57d0a62019-07-30 09:41:14 -0700355bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700356 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700357}
358
Jeongik Chad0a10272020-08-06 16:33:36 +0900359bool AidlAnnotatable::IsJavaOnlyImmutable() const {
360 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900361}
362
Devin Moorec7e47a32020-08-07 10:55:25 -0700363bool AidlAnnotatable::IsFixedSize() const {
364 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
365}
366
Andrei Onea9445fc62019-06-27 18:11:59 +0100367const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700368 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900369}
370
Andrei Homescue61feb52020-08-18 15:44:24 -0700371const AidlAnnotation* AidlAnnotatable::RustDerive() const {
372 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
373}
374
Jooyung Han672557b2020-12-24 05:18:00 +0900375const AidlAnnotation* AidlAnnotatable::BackingType() const {
376 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700377}
378
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900379std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
380 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
381 if (annot) {
382 auto names = annot->ParamValue<std::vector<std::string>>("value");
383 AIDL_FATAL_IF(!names.has_value(), this);
384 return std::move(names.value());
385 }
386 return {};
387}
388
Jeongik Cha88f95a82020-01-15 13:02:16 +0900389bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700390 return lang == Options::Language::JAVA &&
391 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900392}
393
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800394bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700395 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800396}
397
Jooyung Han829ec7c2020-12-02 12:07:36 +0900398bool AidlAnnotatable::JavaDerive(const std::string& method) const {
399 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
400 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900401 return annotation->ParamValue<bool>(method).value_or(false);
Jooyung Han829ec7c2020-12-02 12:07:36 +0900402 }
403 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900404}
405
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900406std::string AidlAnnotatable::GetDescriptor() const {
407 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
408 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900409 return annotation->ParamValue<std::string>("value").value();
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900410 }
411 return "";
412}
413
Devin Moore24f68572020-02-26 13:20:59 -0800414bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100415 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900416 if (!annotation.CheckValid()) {
417 return false;
418 }
419 }
420
421 std::map<AidlAnnotation::Type, AidlLocation> declared;
422 for (const auto& annotation : GetAnnotations()) {
423 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
424 if (!inserted && !annotation.Repeatable()) {
425 AIDL_ERROR(this) << "'" << annotation.GetName()
426 << "' is repeated, but not allowed. Previous location: " << iter->second;
427 return false;
428 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100429 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700430
Andrei Onea9445fc62019-06-27 18:11:59 +0100431 return true;
432}
433
Jiyong Park68bc77a2018-07-19 19:00:45 +0900434string AidlAnnotatable::ToString() const {
435 vector<string> ret;
436 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900437 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900438 }
439 std::sort(ret.begin(), ret.end());
440 return Join(ret, " ");
441}
442
Steven Moreland46e9da82018-07-27 15:45:29 -0700443AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
444 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900445 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Jooyung Han8451a202021-01-16 03:07:06 +0900446 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900447 : AidlAnnotatable(location, comments),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900448 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700449 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700450 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900451 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700452
Jooyung Hand2fa0232020-10-19 02:51:41 +0900453const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700454 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900455 // Declaring array of generic type cannot happen, it is grammar error.
456 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700457
Jooyung Hand2fa0232020-10-19 02:51:41 +0900458 if (!array_base_) {
459 array_base_.reset(new AidlTypeSpecifier(*this));
460 array_base_->is_array_ = false;
461 }
462 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700463}
464
Jooyung Han965e31d2020-11-27 12:30:16 +0900465string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900466 string ret = GetName();
467 if (IsGeneric()) {
468 vector<string> arg_names;
469 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900470 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900471 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900472 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900473 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900474 if (IsArray()) {
475 ret += "[]";
476 }
477 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900478}
479
Jooyung Han965e31d2020-11-27 12:30:16 +0900480string AidlTypeSpecifier::ToString() const {
481 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900482 string annotations = AidlAnnotatable::ToString();
483 if (annotations != "") {
484 ret = annotations + " " + ret;
485 }
486 return ret;
487}
488
Daniel Norman716d3112019-09-10 13:11:56 -0700489bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000490 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700491 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
492 if (result.is_resolved) {
493 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900494 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900495 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900496 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700497 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700498}
499
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900500const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
501 return defined_type_;
502}
503
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900504bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800505 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100506 return false;
507 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900508 if (IsGeneric()) {
Jooyung Hand09a21d2021-02-15 18:56:55 +0900509 const auto& types = GetTypeParameters();
510 for (const auto& arg : types) {
511 if (!arg->CheckValid(typenames)) {
512 return false;
513 }
514 }
Jeongik Chae74c86d2019-12-12 16:54:03 +0900515
Jooyung Hand09a21d2021-02-15 18:56:55 +0900516 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900517 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
518 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900519 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
Jooyung Han1f35ef32021-02-15 19:08:05 +0900520 return !type_ptr->IsArray() &&
521 (typenames.GetEnumDeclaration(*type_ptr) ||
522 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
Jeongik Chae74c86d2019-12-12 16:54:03 +0900523 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700524 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900525 return false;
526 }
527 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800528 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900529 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800530 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
531 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900532 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800533 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900534 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800535 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900536 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000537 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900538 return false;
539 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900540 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
Jooyung Hancea89002021-02-15 17:04:04 +0900541 if (contained_type.IsArray()) {
542 AIDL_ERROR(this)
543 << "List of arrays is not supported. List<T> supports parcelable/union, String, "
544 "IBinder, and ParcelFileDescriptor.";
545 return false;
546 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900547 const string& contained_type_name = contained_type.GetName();
548 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
549 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
550 contained_type_name != "ParcelFileDescriptor") {
551 AIDL_ERROR(this) << "List<" << contained_type_name
552 << "> is not supported. List<T> supports parcelable/union, String, "
553 "IBinder, and ParcelFileDescriptor.";
554 return false;
555 }
556 } else { // Defined types
557 if (typenames.GetInterface(contained_type)) {
558 AIDL_ERROR(this) << "List<" << contained_type_name
559 << "> is not supported. List<T> supports parcelable/union, String, "
560 "IBinder, and ParcelFileDescriptor.";
561 return false;
562 }
563 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900564 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800565 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900566 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900567 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900568 return false;
569 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800570 if (num_params == 2) {
Jooyung Hanaab242a2021-02-15 19:01:15 +0900571 const string& key_type = GetTypeParameters()[0]->Signature();
Jeongik Chae48d9942020-01-02 17:39:00 +0900572 if (key_type != "String") {
573 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
574 << "'" << key_type << "'";
575 return false;
576 }
577 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800578 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900579 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800580 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900581 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800582 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900583 return false;
584 }
585 } else {
586 AIDL_ERROR(this) << type_name << " is not a generic type.";
587 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900588 }
589 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900590
Steven Moreland11cb9452020-01-21 16:56:58 -0800591 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
592 GetTypeParameters().size() == 1 &&
593 GetTypeParameters()[0]->GetName() == "String";
594 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
595 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
596 return false;
597 }
598
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900599 if (GetName() == "void") {
600 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
601 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
602 return false;
603 }
604 }
605
606 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800607 const auto defined_type = typenames.TryGetDefinedType(GetName());
608 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900609 AIDL_ERROR(this) << "Binder type cannot be an array";
610 return false;
611 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000612 if (GetName() == "ParcelableHolder") {
613 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
614 return false;
615 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900616 }
617
618 if (IsNullable()) {
619 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
620 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
621 return false;
622 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800623 const auto defined_type = typenames.TryGetDefinedType(GetName());
624 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700625 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
626 return false;
627 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900628 if (GetName() == "ParcelableHolder") {
629 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
630 return false;
631 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900632 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900633 return true;
634}
635
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900636std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700637 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900638 if (type.IsArray()) {
639 return raw_value;
640 }
641
642 if (auto defined_type = type.GetDefinedType(); defined_type) {
643 auto enum_type = defined_type->AsEnumDeclaration();
644 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
645 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
646 }
Steven Moreland860b1942018-08-16 14:59:28 -0700647 return raw_value;
648}
649
Steven Moreland46e9da82018-07-27 15:45:29 -0700650AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
651 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000652 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
653 default_user_specified_ = false;
654}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700655
Steven Moreland46e9da82018-07-27 15:45:29 -0700656AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
657 AidlTypeSpecifier* type, const std::string& name,
658 AidlConstantValue* default_value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900659 : AidlMember(location, type->GetComments()),
Steven Moreland541788d2020-05-21 22:05:52 +0000660 type_(type),
661 name_(name),
662 default_user_specified_(true),
663 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700664
Jooyung Han53fb4242020-12-17 16:03:49 +0900665bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
666 if (GetDefaultValue()) {
667 return true;
668 }
669 // null is accepted as a valid default value in all backends
670 if (GetType().IsNullable()) {
671 return true;
672 }
673 return false;
674}
675
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900676bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700677 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900678 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900679
Steven Moreland54be7bd2019-12-05 11:17:53 -0800680 if (type_->GetName() == "void") {
681 AIDL_ERROR(this) << "Declaration " << name_
682 << " is void, but declarations cannot be of void type.";
683 valid = false;
684 }
685
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900686 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700687 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700688
Steven Moreland25294322018-08-07 18:13:55 -0700689 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700690
Steven Moreland860b1942018-08-16 14:59:28 -0700691 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700692}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700693
Jooyung Hanacae85d2020-10-28 16:39:09 +0900694string AidlVariableDeclaration::GetCapitalizedName() const {
695 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
696 string str = name_;
697 str[0] = static_cast<char>(toupper(str[0]));
698 return str;
699}
700
Steven Moreland5557f1c2018-07-02 13:50:23 -0700701string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900702 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000703 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700704 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700705 }
706 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700707}
708
Jiyong Park02da7422018-07-16 16:00:26 +0900709string AidlVariableDeclaration::Signature() const {
710 return type_->Signature() + " " + name_;
711}
712
Steven Moreland860b1942018-08-16 14:59:28 -0700713std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900714 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700715 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900716 } else {
717 return "";
718 }
Steven Moreland25294322018-08-07 18:13:55 -0700719}
720
Jooyung Hanc5688f72021-01-05 15:41:48 +0900721void AidlVariableDeclaration::TraverseChildren(
722 std::function<void(const AidlNode&)> traverse) const {
723 traverse(GetType());
724 if (IsDefaultUserSpecified()) {
725 traverse(*GetDefaultValue());
726 }
727}
728
Steven Moreland46e9da82018-07-27 15:45:29 -0700729AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
730 AidlTypeSpecifier* type, const std::string& name)
731 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700732 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700733 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700734
Steven Moreland46e9da82018-07-27 15:45:29 -0700735AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
736 const std::string& name)
737 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700738 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700739 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700740
Jooyung Han020d8d12021-02-26 17:23:02 +0900741static std::string to_string(AidlArgument::Direction direction) {
742 switch (direction) {
743 case AidlArgument::IN_DIR:
744 return "in";
745 case AidlArgument::OUT_DIR:
746 return "out";
747 case AidlArgument::INOUT_DIR:
748 return "inout";
749 }
750}
751
Jiyong Park02da7422018-07-16 16:00:26 +0900752string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700753 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700754 if (direction_specified_) {
Jooyung Han020d8d12021-02-26 17:23:02 +0900755 ret = to_string(direction_);
Casey Dahlinc378c992015-09-29 16:50:40 -0700756 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700757 return ret;
758}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700759
Jiyong Park02da7422018-07-16 16:00:26 +0900760string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700761 if (direction_specified_) {
762 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
763 } else {
764 return AidlVariableDeclaration::ToString();
765 }
Jiyong Park02da7422018-07-16 16:00:26 +0900766}
767
Jooyung Han020d8d12021-02-26 17:23:02 +0900768static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
769 std::vector<std::string> out;
770 for (const auto& d : directions) {
771 out.push_back(to_string(d));
772 }
773
774 if (out.size() <= 1) { // [] => "" or [A] => "A"
775 return Join(out, "");
776 } else if (out.size() == 2) { // [A,B] => "A or B"
777 return Join(out, " or ");
778 } else { // [A,B,C] => "A, B, or C"
779 out.back() = "or " + out.back();
780 return Join(out, ", ");
781 }
782}
783
784bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
785 if (!GetType().CheckValid(typenames)) {
786 return false;
787 }
788
789 const auto& aspect = typenames.GetArgumentAspect(GetType());
790
791 if (aspect.possible_directions.size() == 0) {
792 AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
793 return false;
794 }
795
796 // when direction is not specified, "in" is assumed and should be the only possible direction
797 if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
798 AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
799 << " can be an " << FormatDirections(aspect.possible_directions)
800 << " parameter.";
801 return false;
802 }
803
804 if (aspect.possible_directions.count(GetDirection()) == 0) {
805 AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
806 << " parameter because " << aspect.name << " can only be an "
807 << FormatDirections(aspect.possible_directions) << " parameter.";
808 return false;
809 }
810
811 return true;
812}
813
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900814bool AidlCommentable::IsHidden() const {
Jooyung Han24effbf2021-01-16 10:24:03 +0900815 return android::aidl::HasHideInComments(GetComments());
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900816}
817
818bool AidlCommentable::IsDeprecated() const {
Jooyung Hand4fe00e2021-01-11 16:21:53 +0900819 return android::aidl::FindDeprecated(GetComments()).has_value();
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900820}
821
Jooyung Han8451a202021-01-16 03:07:06 +0900822AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900823 : AidlCommentable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700824
Steven Moreland46e9da82018-07-27 15:45:29 -0700825AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
826 AidlTypeSpecifier* type, const std::string& name,
827 AidlConstantValue* value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900828 : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700829
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900830bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700831 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900832 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700833 valid &= value_->CheckValid();
834 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700835
Steven Morelande689da22020-11-10 02:06:30 +0000836 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900837 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
838 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700839 return false;
840 }
841
Will McVickerd7d18df2019-09-12 13:40:50 -0700842 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700843}
844
Jiyong Parka428d212018-08-29 22:26:30 +0900845string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900846 return "const " + type_->ToString() + " " + name_ + " = " +
847 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900848}
849
850string AidlConstantDeclaration::Signature() const {
851 return type_->Signature() + " " + name_;
852}
853
Steven Moreland46e9da82018-07-27 15:45:29 -0700854AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
855 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900856 const Comments& comments)
Jiyong Parkb034bf02018-07-30 17:44:33 +0900857 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
858 has_id_ = false;
859}
860
861AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
862 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900863 const Comments& comments, int id, bool is_user_defined)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900864 : AidlMember(location, comments),
Steven Moreland46e9da82018-07-27 15:45:29 -0700865 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700866 type_(type),
867 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700868 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900869 id_(id),
870 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700871 has_id_ = true;
872 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700873 for (const unique_ptr<AidlArgument>& a : arguments_) {
874 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
875 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
876 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700877}
878
Jiyong Park02da7422018-07-16 16:00:26 +0900879string AidlMethod::Signature() const {
880 vector<string> arg_signatures;
881 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900882 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900883 }
Jiyong Park309668e2018-07-28 16:55:44 +0900884 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
885}
886
887string AidlMethod::ToString() const {
888 vector<string> arg_strings;
889 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900890 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900891 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900892 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800893 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900894 if (HasId()) {
895 ret += " = " + std::to_string(GetId());
896 }
897 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900898}
899
Steven Moreland46e9da82018-07-27 15:45:29 -0700900AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +0900901 const Comments& comments, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900902 std::vector<std::unique_ptr<AidlMember>>* members)
Jooyung Han93f48f02021-06-05 00:11:16 +0900903 : AidlAnnotatable(location, comments), name_(name), package_(package) {
904 // adjust name/package when name is fully qualified (for preprocessed files)
905 if (package_.empty() && name_.find('.') != std::string::npos) {
906 // Note that this logic is absolutely wrong. Given a parcelable
907 // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
908 // the class is just Bar. However, this was the way it was done in the past.
909 //
910 // See b/17415692
911 auto pos = name.rfind('.');
912 // name is the last part.
913 name_ = name.substr(pos + 1);
914 // package is the initial parts (except the last).
915 package_ = name.substr(0, pos);
916 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900917 if (members) {
918 for (auto& m : *members) {
919 if (auto constant = m->AsConstantDeclaration(); constant) {
920 constants_.emplace_back(constant);
921 } else if (auto variable = m->AsVariableDeclaration(); variable) {
922 variables_.emplace_back(variable);
923 } else if (auto method = m->AsMethod(); method) {
924 methods_.emplace_back(method);
925 } else {
926 AIDL_FATAL(*m);
927 }
928 members_.push_back(m.release());
929 }
930 delete members;
931 }
932}
Steven Moreland787b0432018-07-03 09:00:58 -0700933
Jooyung Han808a2a02020-12-28 16:46:54 +0900934bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800935 if (!AidlAnnotatable::CheckValid(typenames)) {
936 return false;
937 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900938 if (!CheckValidWithMembers(typenames)) {
939 return false;
940 }
Devin Moore24f68572020-02-26 13:20:59 -0800941 return true;
942}
943
Steven Moreland787b0432018-07-03 09:00:58 -0700944std::string AidlDefinedType::GetCanonicalName() const {
945 if (package_.empty()) {
946 return GetName();
947 }
948 return GetPackage() + "." + GetName();
949}
950
Jooyung Han829ec7c2020-12-02 12:07:36 +0900951bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
952 bool success = true;
953
954 for (const auto& v : GetFields()) {
955 const bool field_valid = v->CheckValid(typenames);
956 success = success && field_valid;
957 }
958
959 // field names should be unique
960 std::set<std::string> fieldnames;
961 for (const auto& v : GetFields()) {
962 bool duplicated = !fieldnames.emplace(v->GetName()).second;
963 if (duplicated) {
964 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
965 success = false;
966 }
967 }
968
969 // immutable parcelables should have immutable fields.
970 if (IsJavaOnlyImmutable()) {
971 for (const auto& v : GetFields()) {
972 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
973 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
974 << "non-immutable field named '" << v->GetName() << "'.";
975 success = false;
976 }
977 }
978 }
979
980 set<string> constant_names;
981 for (const auto& constant : GetConstantDeclarations()) {
982 if (constant_names.count(constant->GetName()) > 0) {
983 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
984 success = false;
985 }
986 constant_names.insert(constant->GetName());
987 success = success && constant->CheckValid(typenames);
988 }
989
990 return success;
991}
992
993bool AidlDefinedType::CheckValidForGetterNames() const {
994 bool success = true;
995 std::set<std::string> getters;
996 for (const auto& v : GetFields()) {
997 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
998 if (duplicated) {
999 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
1000 << "' after capitalizing the first letter";
1001 success = false;
1002 }
1003 }
1004 return success;
1005}
1006
Jiyong Park18132182020-06-08 20:24:40 +09001007AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001008 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001009 const std::string& cpp_header, std::vector<std::string>* type_params,
1010 std::vector<std::unique_ptr<AidlMember>>* members)
1011 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +09001012 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001013 cpp_header_(cpp_header) {
1014 // Strip off quotation marks if we actually have a cpp header.
1015 if (cpp_header_.length() >= 2) {
1016 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
1017 }
Casey Dahlin59401da2015-10-09 18:16:45 -07001018}
Jeongik Chadf76dc72019-11-28 00:08:47 +09001019template <typename T>
1020AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
1021 // Copying is not supported if it has type parameters.
1022 // It doesn't make a problem because only ArrayBase() makes a copy,
1023 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +00001024 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +09001025}
1026
1027template <typename T>
1028bool AidlParameterizable<T>::CheckValid() const {
1029 return true;
1030};
1031
1032template <>
1033bool AidlParameterizable<std::string>::CheckValid() const {
1034 if (!IsGeneric()) {
1035 return true;
1036 }
1037 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
1038 if (set.size() != GetTypeParameters().size()) {
1039 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
1040 return false;
1041 }
1042 return true;
1043}
Casey Dahlin59401da2015-10-09 18:16:45 -07001044
Jooyung Han808a2a02020-12-28 16:46:54 +09001045bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1046 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001047 return false;
1048 }
Jeongik Chadf76dc72019-11-28 00:08:47 +09001049 if (!AidlParameterizable<std::string>::CheckValid()) {
1050 return false;
1051 }
Jeongik Cha82317dd2019-02-27 20:26:11 +09001052
1053 return true;
1054}
1055
Steven Moreland5557f1c2018-07-02 13:50:23 -07001056AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001057 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han8451a202021-01-16 03:07:06 +09001058 const Comments& comments, std::vector<std::string>* type_params,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001059 std::vector<std::unique_ptr<AidlMember>>* members)
1060 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001061
Jooyung Han808a2a02020-12-28 16:46:54 +09001062bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1063 if (!AidlParcelable::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001064 return false;
1065 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001066
Jooyung Han59af9cc2020-10-25 21:44:14 +09001067 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001068
Jooyung Hand4057c42020-10-23 13:28:22 +09001069 if (IsFixedSize()) {
1070 for (const auto& v : GetFields()) {
1071 if (!typenames.CanBeFixedSize(v->GetType())) {
1072 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1073 << "non-fixed size field named " << v->GetName() << ".";
1074 success = false;
1075 }
1076 }
1077 }
1078
1079 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001080 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001081 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001082 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001083 }
1084 }
1085
Daniel Norman85aed542019-08-21 12:01:14 -07001086 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001087}
1088
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001089// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001090bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1091 Options::Language lang) const {
Jooyung Hand09a21d2021-02-15 18:56:55 +09001092 if (IsGeneric()) {
1093 const auto& types = GetTypeParameters();
1094 for (const auto& arg : types) {
1095 if (!arg->LanguageSpecificCheckValid(typenames, lang)) {
1096 return false;
1097 }
1098 }
1099 }
1100
Andrei Homescub62afd92020-05-11 19:24:59 -07001101 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1102 GetName() == "IBinder") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001103 AIDL_ERROR(this) << "The " << to_string(lang) << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001104 return false;
1105 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001106 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1107 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1108 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001109 return false;
1110 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001111 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1112 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001113 if (GetName() == "ParcelFileDescriptor") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001114 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001115 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001116 return false;
1117 }
1118
Steven Morelandd59e3172020-05-11 16:42:09 -07001119 const auto defined_type = typenames.TryGetDefinedType(GetName());
1120 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001121 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001122 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001123 return false;
1124 }
1125 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001126 if (this->GetName() == "FileDescriptor" &&
1127 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001128 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001129 return false;
1130 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001131 if (this->IsGeneric()) {
1132 if (this->GetName() == "List") {
Jooyung Han55f96ad2020-12-13 10:08:33 +09001133 if (lang == Options::Language::NDK) {
1134 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1135 const string& contained_type_name = contained_type.GetName();
Jooyung Hane87cdd02020-12-11 16:47:35 +09001136 if (typenames.GetInterface(contained_type)) {
1137 AIDL_ERROR(this) << "List<" << contained_type_name
1138 << "> is not supported. List in NDK doesn't support interface.";
1139 return false;
1140 }
1141 if (contained_type_name == "IBinder") {
1142 AIDL_ERROR(this) << "List<" << contained_type_name
1143 << "> is not supported. List in NDK doesn't support IBinder.";
1144 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001145 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001146 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001147 }
1148 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001149
1150 if (this->IsArray()) {
1151 if (this->GetName() == "List" || this->GetName() == "Map" ||
1152 this->GetName() == "CharSequence") {
1153 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001154 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001155 }
1156 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001157
1158 if (lang != Options::Language::JAVA) {
1159 if (this->GetName() == "List" && !this->IsGeneric()) {
1160 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1161 return false;
1162 }
1163 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1164 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1165 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001166 }
1167 }
1168
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001169 return true;
1170}
1171
1172// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001173bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1174 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001175 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001176 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1177 if (unstructured_parcelable != nullptr) {
1178 if (unstructured_parcelable->GetCppHeader().empty()) {
1179 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001180 << "Unstructured parcelable must have C++ header defined.";
1181 return false;
1182 }
1183 }
1184 }
1185 return true;
1186}
1187
1188// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001189bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1190 Options::Language lang) const {
1191 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001192 return false;
1193 }
1194 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001195 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001196 return false;
1197 }
1198 }
1199 return true;
1200}
1201
Daniel Norman85aed542019-08-21 12:01:14 -07001202AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001203 AidlConstantValue* value, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +09001204 : AidlCommentable(location, comments),
Jooyung Han29813842020-12-08 01:28:03 +09001205 name_(name),
1206 value_(value),
Jooyung Han29813842020-12-08 01:28:03 +09001207 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001208
1209bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1210 if (GetValue() == nullptr) {
1211 return false;
1212 }
1213 if (!GetValue()->CheckValid()) {
1214 return false;
1215 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001216 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001217 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1218 return false;
1219 }
1220 return true;
1221}
1222
1223string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1224 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001225 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001226}
1227
1228AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1229 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jooyung Han8451a202021-01-16 03:07:06 +09001230 const std::string& package, const Comments& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001231 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001232 enumerators_(std::move(*enumerators)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001233 // Fill missing enumerator values with <prev + 1>
1234 // This can't be done in Autofill() because type/ref resolution depends on this.
1235 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1236 // resolved if A has no value set.
Daniel Normanb28684e2019-10-17 15:31:39 -07001237 const AidlEnumerator* previous = nullptr;
1238 for (const auto& enumerator : enumerators_) {
1239 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001240 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001241 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001242 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001243 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001244 } else {
Jooyung Hand0c8af02021-01-06 18:08:01 +09001245 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
Daniel Normanb28684e2019-10-17 15:31:39 -07001246 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001247 loc, std::move(prev_value), "+",
1248 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001249 }
1250 }
1251 previous = enumerator.get();
1252 }
1253}
1254
Jooyung Han672557b2020-12-24 05:18:00 +09001255bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1256 if (auto annot = BackingType(); annot != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001257 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1258 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
Jooyung Han672557b2020-12-24 05:18:00 +09001259 // need to call CheckValid().
1260 if (!annot->CheckValid()) {
1261 return false;
1262 }
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001263 auto type = annot->ParamValue<std::string>("type").value();
1264 backing_type_ =
Jooyung Han8451a202021-01-16 03:07:06 +09001265 std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, Comments{});
Jooyung Han672557b2020-12-24 05:18:00 +09001266 } else {
1267 // Default to byte type for enums.
1268 backing_type_ =
Jooyung Han8451a202021-01-16 03:07:06 +09001269 std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, Comments{});
Jooyung Han672557b2020-12-24 05:18:00 +09001270 }
1271 // Autofill() is called after type resolution, we resolve the backing type manually.
1272 if (!backing_type_->Resolve(typenames)) {
1273 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
1274 }
1275 return true;
1276}
1277
Jooyung Han808a2a02020-12-28 16:46:54 +09001278bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1279 if (!AidlDefinedType::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001280 return false;
1281 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001282 if (!GetMembers().empty()) {
1283 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1284 return false;
1285 }
Daniel Norman85aed542019-08-21 12:01:14 -07001286 if (backing_type_ == nullptr) {
1287 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1288 return false;
1289 }
1290 bool success = true;
1291 for (const auto& enumerator : enumerators_) {
1292 success = success && enumerator->CheckValid(GetBackingType());
1293 }
Jooyung Han3b990182020-12-22 17:44:31 +09001294
Jooyung Han808a2a02020-12-28 16:46:54 +09001295 return success;
Daniel Norman85aed542019-08-21 12:01:14 -07001296}
1297
Jooyung Han2946afc2020-10-05 20:29:16 +09001298AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001299 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001300 std::vector<std::string>* type_params,
1301 std::vector<std::unique_ptr<AidlMember>>* members)
1302 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001303
Jooyung Han808a2a02020-12-28 16:46:54 +09001304bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001305 // visit parents
Jooyung Han808a2a02020-12-28 16:46:54 +09001306 if (!AidlParcelable::CheckValid(typenames)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001307 return false;
1308 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001309
1310 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001311 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001312 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001313 }
1314
1315 // now, visit self!
1316 bool success = true;
1317
1318 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1319 for (const auto& v : GetFields()) {
1320 if (v->GetType().GetName() == "ParcelableHolder") {
1321 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1322 success = false;
1323 }
1324 }
1325
Jooyung Hanfe89f122020-10-14 03:49:18 +09001326 if (GetFields().empty()) {
1327 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1328 return false;
1329 }
1330
Jooyung Han53fb4242020-12-17 16:03:49 +09001331 // first member should have useful default value (implicit or explicit)
1332 const auto& first = GetFields()[0];
1333 if (!first->HasUsefulDefaultValue()) {
1334 // Most types can be initialized without a default value. For example,
1335 // interface types are inherently nullable. But, enum types should have
1336 // an explicit default value.
1337 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1338 AIDL_ERROR(first)
1339 << "The union's first member should have a useful default value. Enum types can be "
1340 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1341 return false;
1342 }
1343 // In Java, array types are initialized as null without a default value. To be sure that default
1344 // initialized unions are accepted by other backends we require arrays also have a default
1345 // value.
1346 if (first->GetType().IsArray()) {
1347 AIDL_ERROR(first)
1348 << "The union's first member should have a useful default value. Arrays can be "
1349 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1350 return false;
1351 }
1352 }
1353
Jooyung Hanfe89f122020-10-14 03:49:18 +09001354 return success;
1355}
1356
1357// TODO: we should treat every backend all the same in future.
1358bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1359 Options::Language lang) const {
1360 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1361 return false;
1362 }
1363 for (const auto& v : this->GetFields()) {
1364 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1365 return false;
1366 }
1367 }
1368 return true;
1369}
1370
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001371// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001372bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1373 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001374 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001375 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001376 return false;
1377 }
1378 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001379 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001380 return false;
1381 }
1382 }
1383 }
1384 return true;
1385}
1386
Steven Moreland46e9da82018-07-27 15:45:29 -07001387AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001388 const Comments& comments, bool oneway, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001389 std::vector<std::unique_ptr<AidlMember>>* members)
1390 : AidlDefinedType(location, name, comments, package, members) {
1391 for (auto& m : GetMethods()) {
1392 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001393 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001394}
1395
Jooyung Han808a2a02020-12-28 16:46:54 +09001396bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1397 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001398 return false;
1399 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001400 // Has to be a pointer due to deleting copy constructor. No idea why.
1401 map<string, const AidlMethod*> method_names;
1402 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001403 if (!m->GetType().CheckValid(typenames)) {
1404 return false;
1405 }
1406
Jeongik Cha649e8a72020-03-27 17:47:40 +09001407 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1408 if (m->GetType().GetName() == "ParcelableHolder") {
1409 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1410 return false;
1411 }
Steven Morelandacd53472018-12-14 10:17:26 -08001412 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001413 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1414 return false;
1415 }
1416
1417 set<string> argument_names;
1418 for (const auto& arg : m->GetArguments()) {
1419 auto it = argument_names.find(arg->GetName());
1420 if (it != argument_names.end()) {
1421 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1422 << arg->GetName() << "'";
1423 return false;
1424 }
1425 argument_names.insert(arg->GetName());
1426
Jooyung Han020d8d12021-02-26 17:23:02 +09001427 if (!arg->CheckValid(typenames)) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001428 return false;
1429 }
1430
Steven Morelandacd53472018-12-14 10:17:26 -08001431 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001432 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1433 return false;
1434 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001435
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001436 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001437 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001438 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1439 return false;
1440 }
1441
1442 // Reserve a namespace for internal use
1443 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1444 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1445 return false;
1446 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001447 }
1448
1449 auto it = method_names.find(m->GetName());
1450 // prevent duplicate methods
1451 if (it == method_names.end()) {
1452 method_names[m->GetName()] = m.get();
1453 } else {
1454 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1455 AIDL_ERROR(it->second) << "previously defined here.";
1456 return false;
1457 }
1458
Paul Trautrimb77048c2020-01-21 16:39:32 +09001459 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001460 "getTransactionName(int)"};
1461
1462 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001463 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001464 return false;
1465 }
1466 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001467
1468 bool success = true;
1469 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001470 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001471 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001472 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001473 success = false;
1474 }
1475 constant_names.insert(constant->GetName());
1476 success = success && constant->CheckValid(typenames);
1477 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001478 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001479}
1480
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001481std::string AidlInterface::GetDescriptor() const {
1482 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1483 if (annotatedDescriptor != "") {
1484 return annotatedDescriptor;
1485 }
1486 return GetCanonicalName();
1487}
1488
Jooyung Han132cf802021-01-15 02:17:32 +09001489AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class,
Jooyung Han8451a202021-01-16 03:07:06 +09001490 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +09001491 : AidlNode(location, comments), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001492
1493// Resolves unresolved type name to fully qualified typename to import
1494// case #1: SimpleName --> import p.SimpleName
1495// case #2: Outer.Inner --> import p.Outer
1496// case #3: p.SimpleName --> (as is)
1497std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1498 std::string canonical_name;
1499 const auto first_dot = unresolved_name.find_first_of('.');
1500 const std::string class_name =
1501 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1502 for (const auto& import : Imports()) {
1503 const auto& fq_name = import->GetNeededClass();
1504 const auto last_dot = fq_name.find_last_of('.');
1505 const std::string imported_type_name =
1506 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1507 if (imported_type_name == class_name) {
1508 if (canonical_name != "" && canonical_name != fq_name) {
1509 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1510 return {};
1511 }
1512 canonical_name = fq_name;
1513 }
1514 }
1515 // if not found, use unresolved_name as it is
1516 if (canonical_name == "") {
1517 return unresolved_name;
1518 }
1519 return canonical_name;
Steven Moreland26318532020-12-23 20:08:36 +00001520}