blob: 3237272c7851bdabc52835a1b0c6fd00d6fc919d [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
Jooyung Han888c5bc2020-12-22 17:28:47 +090047using android::aidl::DiagnosticID;
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}
Jeongik Cha997281d2020-01-16 15:23:59 +090072
73void AddHideComment(CodeWriter* writer) {
74 writer->Write("/* @hide */\n");
75}
76
77inline bool HasHideComment(const std::string& comment) {
78 return std::regex_search(comment, std::regex("@hide\\b"));
79}
Jeongik Cha047c5ee2019-08-07 23:16:49 +090080} // namespace
81
Steven Moreland46e9da82018-07-27 15:45:29 -070082AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
83
Mathew Inwoodadb74672019-11-29 14:01:53 +000084std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000085 std::stringstream ss;
86 ss << location_.file_ << ":" << location_.begin_.line;
87 return ss.str();
88}
89
Mathew Inwoodadb74672019-11-29 14:01:53 +000090std::string AidlNode::PrintLocation() const {
91 std::stringstream ss;
92 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
93 << location_.end_.line << ":" << location_.end_.column;
94 return ss.str();
95}
96
Jooyung Han5c2fcae2020-12-26 00:04:39 +090097static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr, ""};
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +090098static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr, ""};
Jooyung Han5c2fcae2020-12-26 00:04:39 +090099static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, ""};
100static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, ""};
101static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr, ""};
102
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700103const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
104 static const std::vector<Schema> kSchemas{
Jooyung Hand902a972020-10-23 17:32:44 +0900105 {AidlAnnotation::Type::NULLABLE, "nullable", {}, false},
106 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}, false},
Steven Morelanda7764e52020-10-27 17:29:29 +0000107 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", {}, false},
Jooyung Hand902a972020-10-23 17:32:44 +0900108 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}, false},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700109 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
110 "UnsupportedAppUsage",
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900111 {{"expectedSignature", kStringType},
112 {"implicitMember", kStringType},
113 {"maxTargetSdk", kIntType},
114 {"publicAlternatives", kStringType},
115 {"trackingBug", kLongType}},
Jooyung Hand902a972020-10-23 17:32:44 +0900116 false},
117 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}, false},
118 {AidlAnnotation::Type::HIDE, "Hide", {}, false},
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900119 {AidlAnnotation::Type::BACKING, "Backing", {{"type", kStringType}}, false, {"type"}},
Jooyung Han5721a232020-12-24 04:34:55 +0900120 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
121 "JavaPassthrough",
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900122 {{"annotation", kStringType}},
Jooyung Han5721a232020-12-24 04:34:55 +0900123 true,
124 {"annotation"}},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900125 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900126 "JavaDerive",
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900127 {{"toString", kBooleanType}, {"equals", kBooleanType}},
Jooyung Han5721a232020-12-24 04:34:55 +0900128 false},
Jooyung Hand902a972020-10-23 17:32:44 +0900129 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, "JavaOnlyImmutable", {}, false},
130 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", {}, false},
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900131 {AidlAnnotation::Type::DESCRIPTOR, "Descriptor", {{"value", kStringType}}, false, {"value"}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700132 {AidlAnnotation::Type::RUST_DERIVE,
133 "RustDerive",
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900134 {{"Copy", kBooleanType},
135 {"Clone", kBooleanType},
136 {"PartialOrd", kBooleanType},
137 {"Ord", kBooleanType},
138 {"PartialEq", kBooleanType},
139 {"Eq", kBooleanType},
140 {"Hash", kBooleanType}},
Jooyung Hand902a972020-10-23 17:32:44 +0900141 false},
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900142 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
143 "SuppressWarnings",
144 {{"value", kStringArrayType}},
145 false,
146 {"value"}},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900147 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700148 return kSchemas;
149}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900150
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700151std::string AidlAnnotation::TypeToString(Type type) {
152 for (const Schema& schema : AllSchemas()) {
153 if (type == schema.type) return schema.name;
154 }
155 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
156 __builtin_unreachable();
157}
Andrei Onea9445fc62019-06-27 18:11:59 +0100158
159AidlAnnotation* AidlAnnotation::Parse(
160 const AidlLocation& location, const string& name,
161 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700162 const Schema* schema = nullptr;
163 for (const Schema& a_schema : AllSchemas()) {
164 if (a_schema.name == name) {
165 schema = &a_schema;
166 }
167 }
168
169 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900170 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700171 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900172 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700173 for (const Schema& s : AllSchemas()) {
174 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900175 }
176 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700177 AIDL_ERROR(location) << stream.str();
178 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900179 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100180 if (parameter_list == nullptr) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700181 return new AidlAnnotation(location, *schema, {});
Andrei Onea9445fc62019-06-27 18:11:59 +0100182 }
183
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700184 return new AidlAnnotation(location, *schema, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900185}
186
Andrei Onea9445fc62019-06-27 18:11:59 +0100187AidlAnnotation::AidlAnnotation(
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700188 const AidlLocation& location, const Schema& schema,
Andrei Onea9445fc62019-06-27 18:11:59 +0100189 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700190 : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100191
Jooyung Han690f5842020-12-04 13:02:04 +0900192struct ConstReferenceFinder : AidlConstantValue::Visitor {
193 AidlConstantReference* found;
194 void Visit(AidlConstantValue&) override {}
195 void Visit(AidlUnaryConstExpression&) override {}
196 void Visit(AidlBinaryConstExpression&) override {}
197 void Visit(AidlConstantReference& ref) override {
198 if (!found) found = &ref;
199 }
200};
201
Andrei Onea9445fc62019-06-27 18:11:59 +0100202bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100203 for (const auto& name_and_param : parameters_) {
204 const std::string& param_name = name_and_param.first;
205 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han690f5842020-12-04 13:02:04 +0900206
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900207 auto it = schema_.supported_parameters.find(param_name);
208 if (it == schema_.supported_parameters.end()) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100209 std::ostringstream stream;
210 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700211 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100212 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700213 for (const auto& kv : schema_.supported_parameters) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100214 stream << " " << kv.first;
215 }
216 AIDL_ERROR(this) << stream.str();
217 return false;
218 }
Jooyung Han690f5842020-12-04 13:02:04 +0900219
220 ConstReferenceFinder finder;
221 param->Accept(finder);
222 if (finder.found) {
223 AIDL_ERROR(finder.found) << "Value must be a constant expression but contains reference to "
224 << finder.found->GetFieldName() << ".";
225 return false;
226 }
227
228 if (!param->CheckValid()) {
229 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
230 << GetName() << ".";
231 return false;
232 }
233
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900234 const std::string param_value = param->ValueString(it->second, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100235 // Assume error on empty string.
236 if (param_value == "") {
237 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
238 << GetName() << ".";
239 return false;
240 }
241 }
Jooyung Han5721a232020-12-24 04:34:55 +0900242 bool success = true;
243 for (const auto& param : schema_.required_parameters) {
244 if (parameters_.count(param) == 0) {
245 AIDL_ERROR(this) << "Missing '" << param << "' on @" << GetName() << ".";
246 success = false;
247 }
248 }
249 return success;
Andrei Onea9445fc62019-06-27 18:11:59 +0100250}
251
252std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
253 const ConstantValueDecorator& decorator) const {
254 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100255 for (const auto& name_and_param : parameters_) {
256 const std::string& param_name = name_and_param.first;
257 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Devin Mooredecaf292020-04-30 09:16:40 -0700258 if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
259 std::ostringstream stream;
260 stream << "Parameter " << param_name << " not supported ";
261 stream << "for annotation " << GetName() << ". ";
262 stream << "It must be one of:";
263 for (const auto& kv : schema_.supported_parameters) {
264 stream << " " << kv.first;
265 }
266 AIDL_ERROR(this) << stream.str();
267 continue;
268 }
Will McVickerd7d18df2019-09-12 13:40:50 -0700269 if (!param->CheckValid()) {
270 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
271 << GetName() << ".";
Devin Mooredecaf292020-04-30 09:16:40 -0700272 continue;
Will McVickerd7d18df2019-09-12 13:40:50 -0700273 }
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900274 const auto& type = schema_.supported_parameters.at(param_name);
Will McVickerd7d18df2019-09-12 13:40:50 -0700275 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100276 }
277 return raw_params;
278}
Steven Moreland46e9da82018-07-27 15:45:29 -0700279
Jooyung Han965e31d2020-11-27 12:30:16 +0900280std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700281 if (parameters_.empty()) {
282 return "@" + GetName();
283 } else {
284 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900285 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700286 param_strings.emplace_back(name + "=" + value);
287 }
288 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
289 }
290}
291
Andrei Onea9445fc62019-06-27 18:11:59 +0100292static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700293 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100294 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700295 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900296 AIDL_FATAL_IF(a.Repeatable(), a)
297 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100298 return &a;
299 }
300 }
301 return nullptr;
302}
303
Steven Moreland46e9da82018-07-27 15:45:29 -0700304AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
305
Jiyong Park68bc77a2018-07-19 19:00:45 +0900306bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700307 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900308}
309
Jiyong Park68bc77a2018-07-19 19:00:45 +0900310bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700311 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900312}
313
Steven Morelanda7764e52020-10-27 17:29:29 +0000314bool AidlAnnotatable::IsSensitiveData() const {
315 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
316}
317
Steven Morelanda57d0a62019-07-30 09:41:14 -0700318bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700319 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700320}
321
Jeongik Chad0a10272020-08-06 16:33:36 +0900322bool AidlAnnotatable::IsJavaOnlyImmutable() const {
323 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900324}
325
Devin Moorec7e47a32020-08-07 10:55:25 -0700326bool AidlAnnotatable::IsFixedSize() const {
327 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
328}
329
Andrei Onea9445fc62019-06-27 18:11:59 +0100330const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700331 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900332}
333
Andrei Homescue61feb52020-08-18 15:44:24 -0700334const AidlAnnotation* AidlAnnotatable::RustDerive() const {
335 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
336}
337
Jooyung Han672557b2020-12-24 05:18:00 +0900338const AidlAnnotation* AidlAnnotatable::BackingType() const {
339 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700340}
341
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900342std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
343 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
344 if (annot) {
345 auto names = annot->ParamValue<std::vector<std::string>>("value");
346 AIDL_FATAL_IF(!names.has_value(), this);
347 return std::move(names.value());
348 }
349 return {};
350}
351
Jeongik Cha88f95a82020-01-15 13:02:16 +0900352bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700353 return lang == Options::Language::JAVA &&
354 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900355}
356
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800357bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700358 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800359}
360
Jooyung Han829ec7c2020-12-02 12:07:36 +0900361bool AidlAnnotatable::JavaDerive(const std::string& method) const {
362 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
363 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900364 return annotation->ParamValue<bool>(method).value_or(false);
Jooyung Han829ec7c2020-12-02 12:07:36 +0900365 }
366 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900367}
368
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900369std::string AidlAnnotatable::GetDescriptor() const {
370 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
371 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900372 return annotation->ParamValue<std::string>("value").value();
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900373 }
374 return "";
375}
376
Steven Moreland7e4b9502020-02-20 18:10:42 -0800377void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
378 if (annotations_.empty()) return;
379
380 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
381}
382
Devin Moore24f68572020-02-26 13:20:59 -0800383bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700384 std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
Andrei Onea9445fc62019-06-27 18:11:59 +0100385 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900386 // check if it is allowed for this node
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700387 if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900388 std::vector<std::string> supported_annot_strings;
389 for (AidlAnnotation::Type type : supported_annotations) {
390 supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
391 }
Devin Moore24f68572020-02-26 13:20:59 -0800392 AIDL_ERROR(this) << "'" << annotation.GetName()
393 << "' is not a supported annotation for this node. "
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700394 << "It must be one of: "
395 << android::base::Join(supported_annot_strings, ", ");
Devin Moore24f68572020-02-26 13:20:59 -0800396 return false;
397 }
Jooyung Hand902a972020-10-23 17:32:44 +0900398 // CheckValid() only if it is okay to be here
399 if (!annotation.CheckValid()) {
400 return false;
401 }
402 }
403
404 std::map<AidlAnnotation::Type, AidlLocation> declared;
405 for (const auto& annotation : GetAnnotations()) {
406 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
407 if (!inserted && !annotation.Repeatable()) {
408 AIDL_ERROR(this) << "'" << annotation.GetName()
409 << "' is repeated, but not allowed. Previous location: " << iter->second;
410 return false;
411 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100412 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700413
Andrei Onea9445fc62019-06-27 18:11:59 +0100414 return true;
415}
416
Jiyong Park68bc77a2018-07-19 19:00:45 +0900417string AidlAnnotatable::ToString() const {
418 vector<string> ret;
419 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900420 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900421 }
422 std::sort(ret.begin(), ret.end());
423 return Join(ret, " ");
424}
425
Steven Moreland46e9da82018-07-27 15:45:29 -0700426AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
427 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900428 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700429 const string& comments)
430 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900431 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700432 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700433 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900434 comments_(comments),
435 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700436
Jooyung Hand2fa0232020-10-19 02:51:41 +0900437const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700438 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900439 // Declaring array of generic type cannot happen, it is grammar error.
440 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700441
Jooyung Hand2fa0232020-10-19 02:51:41 +0900442 if (!array_base_) {
443 array_base_.reset(new AidlTypeSpecifier(*this));
444 array_base_->is_array_ = false;
445 }
446 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700447}
448
Jeongik Cha997281d2020-01-16 15:23:59 +0900449bool AidlTypeSpecifier::IsHidden() const {
450 return HasHideComment(GetComments());
451}
452
Jooyung Han965e31d2020-11-27 12:30:16 +0900453string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900454 string ret = GetName();
455 if (IsGeneric()) {
456 vector<string> arg_names;
457 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900458 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900459 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900460 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900461 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900462 if (IsArray()) {
463 ret += "[]";
464 }
465 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900466}
467
Jooyung Han965e31d2020-11-27 12:30:16 +0900468string AidlTypeSpecifier::ToString() const {
469 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900470 string annotations = AidlAnnotatable::ToString();
471 if (annotations != "") {
472 ret = annotations + " " + ret;
473 }
474 return ret;
475}
476
Daniel Norman716d3112019-09-10 13:11:56 -0700477bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000478 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700479 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
480 if (result.is_resolved) {
481 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900482 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900483 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900484 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700485 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700486}
487
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900488const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
489 return defined_type_;
490}
491
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700492std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900493 // TODO(b/151102494) we don't distinguish field-level annotations from other type specifiers.
494 return {
495 AidlAnnotation::Type::NULLABLE,
496 AidlAnnotation::Type::UTF8_IN_CPP,
497 AidlAnnotation::Type::JAVA_PASSTHROUGH,
498 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, // field-level annotation
499 AidlAnnotation::Type::HIDE, // field-level annotation
500 AidlAnnotation::Type::SUPPRESS_WARNINGS, // field-level annotation
501 };
Devin Moore24f68572020-02-26 13:20:59 -0800502}
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()) {
509 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900510
511 auto& types = GetTypeParameters();
512 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
513 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900514 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
515 return (typenames.GetEnumDeclaration(*type_ptr)) ||
516 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
Jeongik Chae74c86d2019-12-12 16:54:03 +0900517 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700518 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900519 return false;
520 }
521 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800522 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900523 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800524 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
525 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900526 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800527 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900528 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800529 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900530 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000531 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900532 return false;
533 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900534 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
535 const string& contained_type_name = contained_type.GetName();
536 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
537 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
538 contained_type_name != "ParcelFileDescriptor") {
539 AIDL_ERROR(this) << "List<" << contained_type_name
540 << "> is not supported. List<T> supports parcelable/union, String, "
541 "IBinder, and ParcelFileDescriptor.";
542 return false;
543 }
544 } else { // Defined types
545 if (typenames.GetInterface(contained_type)) {
546 AIDL_ERROR(this) << "List<" << contained_type_name
547 << "> is not supported. List<T> supports parcelable/union, String, "
548 "IBinder, and ParcelFileDescriptor.";
549 return false;
550 }
551 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900552 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800553 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900554 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900555 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900556 return false;
557 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800558 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900559 const string& key_type = GetTypeParameters()[0]->GetName();
560 if (key_type != "String") {
561 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
562 << "'" << key_type << "'";
563 return false;
564 }
565 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800566 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900567 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800568 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900569 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800570 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900571 return false;
572 }
573 } else {
574 AIDL_ERROR(this) << type_name << " is not a generic type.";
575 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900576 }
577 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900578
Steven Moreland11cb9452020-01-21 16:56:58 -0800579 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
580 GetTypeParameters().size() == 1 &&
581 GetTypeParameters()[0]->GetName() == "String";
582 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
583 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
584 return false;
585 }
586
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900587 if (GetName() == "void") {
588 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
589 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
590 return false;
591 }
592 }
593
594 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800595 const auto defined_type = typenames.TryGetDefinedType(GetName());
596 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900597 AIDL_ERROR(this) << "Binder type cannot be an array";
598 return false;
599 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000600 if (GetName() == "ParcelableHolder") {
601 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
602 return false;
603 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900604 }
605
606 if (IsNullable()) {
607 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
608 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
609 return false;
610 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800611 const auto defined_type = typenames.TryGetDefinedType(GetName());
612 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700613 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
614 return false;
615 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900616 if (GetName() == "ParcelableHolder") {
617 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
618 return false;
619 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900620 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900621 return true;
622}
623
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900624std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700625 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900626 if (type.IsArray()) {
627 return raw_value;
628 }
629
630 if (auto defined_type = type.GetDefinedType(); defined_type) {
631 auto enum_type = defined_type->AsEnumDeclaration();
632 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
633 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
634 }
Steven Moreland860b1942018-08-16 14:59:28 -0700635 return raw_value;
636}
637
Steven Moreland46e9da82018-07-27 15:45:29 -0700638AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
639 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000640 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
641 default_user_specified_ = false;
642}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700643
Steven Moreland46e9da82018-07-27 15:45:29 -0700644AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
645 AidlTypeSpecifier* type, const std::string& name,
646 AidlConstantValue* default_value)
Jooyung Han3f347ca2020-12-01 12:41:50 +0900647 : AidlMember(location),
Steven Moreland541788d2020-05-21 22:05:52 +0000648 type_(type),
649 name_(name),
650 default_user_specified_(true),
651 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700652
Jooyung Han53fb4242020-12-17 16:03:49 +0900653bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
654 if (GetDefaultValue()) {
655 return true;
656 }
657 // null is accepted as a valid default value in all backends
658 if (GetType().IsNullable()) {
659 return true;
660 }
661 return false;
662}
663
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900664bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700665 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900666 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900667
Steven Moreland54be7bd2019-12-05 11:17:53 -0800668 if (type_->GetName() == "void") {
669 AIDL_ERROR(this) << "Declaration " << name_
670 << " is void, but declarations cannot be of void type.";
671 valid = false;
672 }
673
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900674 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700675 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700676
Steven Moreland25294322018-08-07 18:13:55 -0700677 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700678
Steven Moreland860b1942018-08-16 14:59:28 -0700679 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700680}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700681
Jooyung Hanacae85d2020-10-28 16:39:09 +0900682string AidlVariableDeclaration::GetCapitalizedName() const {
683 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
684 string str = name_;
685 str[0] = static_cast<char>(toupper(str[0]));
686 return str;
687}
688
Steven Moreland5557f1c2018-07-02 13:50:23 -0700689string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900690 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000691 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700692 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700693 }
694 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700695}
696
Jiyong Park02da7422018-07-16 16:00:26 +0900697string AidlVariableDeclaration::Signature() const {
698 return type_->Signature() + " " + name_;
699}
700
Steven Moreland860b1942018-08-16 14:59:28 -0700701std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900702 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700703 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900704 } else {
705 return "";
706 }
Steven Moreland25294322018-08-07 18:13:55 -0700707}
708
Steven Moreland46e9da82018-07-27 15:45:29 -0700709AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
710 AidlTypeSpecifier* type, const std::string& name)
711 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700712 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700713 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700714
Steven Moreland46e9da82018-07-27 15:45:29 -0700715AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
716 const std::string& name)
717 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700718 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700719 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700720
Jiyong Park02da7422018-07-16 16:00:26 +0900721string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700722 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700723 if (direction_specified_) {
724 switch(direction_) {
725 case AidlArgument::IN_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700726 ret += "in";
Casey Dahlinc378c992015-09-29 16:50:40 -0700727 break;
728 case AidlArgument::OUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700729 ret += "out";
Casey Dahlinc378c992015-09-29 16:50:40 -0700730 break;
731 case AidlArgument::INOUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700732 ret += "inout";
Casey Dahlinc378c992015-09-29 16:50:40 -0700733 break;
734 }
735 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700736 return ret;
737}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700738
Jiyong Park02da7422018-07-16 16:00:26 +0900739string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700740 if (direction_specified_) {
741 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
742 } else {
743 return AidlVariableDeclaration::ToString();
744 }
Jiyong Park02da7422018-07-16 16:00:26 +0900745}
746
Steven Moreland46e9da82018-07-27 15:45:29 -0700747AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
748
Steven Moreland46e9da82018-07-27 15:45:29 -0700749AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
750 AidlTypeSpecifier* type, const std::string& name,
751 AidlConstantValue* value)
752 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700753
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900754bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700755 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900756 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700757 valid &= value_->CheckValid();
758 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700759
Steven Morelande689da22020-11-10 02:06:30 +0000760 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900761 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
762 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700763 return false;
764 }
765
Will McVickerd7d18df2019-09-12 13:40:50 -0700766 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700767}
768
Jiyong Parka428d212018-08-29 22:26:30 +0900769string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900770 return "const " + type_->ToString() + " " + name_ + " = " +
771 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900772}
773
774string AidlConstantDeclaration::Signature() const {
775 return type_->Signature() + " " + name_;
776}
777
Steven Moreland46e9da82018-07-27 15:45:29 -0700778AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
779 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900780 const std::string& comments)
781 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
782 has_id_ = false;
783}
784
785AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
786 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900787 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700788 : AidlMember(location),
789 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700790 comments_(comments),
791 type_(type),
792 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700793 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900794 id_(id),
795 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700796 has_id_ = true;
797 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700798 for (const unique_ptr<AidlArgument>& a : arguments_) {
799 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
800 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
801 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700802}
803
Jeongik Cha997281d2020-01-16 15:23:59 +0900804bool AidlMethod::IsHidden() const {
805 return HasHideComment(GetComments());
806}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700807
Jiyong Park02da7422018-07-16 16:00:26 +0900808string AidlMethod::Signature() const {
809 vector<string> arg_signatures;
810 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900811 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900812 }
Jiyong Park309668e2018-07-28 16:55:44 +0900813 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
814}
815
816string AidlMethod::ToString() const {
817 vector<string> arg_strings;
818 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900819 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900820 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900821 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800822 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900823 if (HasId()) {
824 ret += " = " + std::to_string(GetId());
825 }
826 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900827}
828
Steven Moreland46e9da82018-07-27 15:45:29 -0700829AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900830 const std::string& comments, const std::string& package,
831 std::vector<std::unique_ptr<AidlMember>>* members)
Jiyong Park18132182020-06-08 20:24:40 +0900832 : AidlAnnotatable(location),
833 name_(name),
834 comments_(comments),
835 package_(package),
836 split_package_(package.empty() ? std::vector<std::string>()
Jooyung Han829ec7c2020-12-02 12:07:36 +0900837 : android::base::Split(package, ".")) {
838 if (members) {
839 for (auto& m : *members) {
840 if (auto constant = m->AsConstantDeclaration(); constant) {
841 constants_.emplace_back(constant);
842 } else if (auto variable = m->AsVariableDeclaration(); variable) {
843 variables_.emplace_back(variable);
844 } else if (auto method = m->AsMethod(); method) {
845 methods_.emplace_back(method);
846 } else {
847 AIDL_FATAL(*m);
848 }
849 members_.push_back(m.release());
850 }
851 delete members;
852 }
853}
Steven Moreland787b0432018-07-03 09:00:58 -0700854
Jooyung Han808a2a02020-12-28 16:46:54 +0900855bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800856 if (!AidlAnnotatable::CheckValid(typenames)) {
857 return false;
858 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900859 if (!CheckValidWithMembers(typenames)) {
860 return false;
861 }
Devin Moore24f68572020-02-26 13:20:59 -0800862 return true;
863}
864
Jeongik Cha997281d2020-01-16 15:23:59 +0900865bool AidlDefinedType::IsHidden() const {
866 return HasHideComment(GetComments());
867}
868
Steven Moreland787b0432018-07-03 09:00:58 -0700869std::string AidlDefinedType::GetCanonicalName() const {
870 if (package_.empty()) {
871 return GetName();
872 }
873 return GetPackage() + "." + GetName();
874}
875
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800876void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
877 if (this->IsHidden()) {
878 AddHideComment(writer);
879 }
880 DumpAnnotations(writer);
881}
882
Jooyung Han829ec7c2020-12-02 12:07:36 +0900883bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
884 bool success = true;
885
886 for (const auto& v : GetFields()) {
887 const bool field_valid = v->CheckValid(typenames);
888 success = success && field_valid;
889 }
890
891 // field names should be unique
892 std::set<std::string> fieldnames;
893 for (const auto& v : GetFields()) {
894 bool duplicated = !fieldnames.emplace(v->GetName()).second;
895 if (duplicated) {
896 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
897 success = false;
898 }
899 }
900
901 // immutable parcelables should have immutable fields.
902 if (IsJavaOnlyImmutable()) {
903 for (const auto& v : GetFields()) {
904 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
905 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
906 << "non-immutable field named '" << v->GetName() << "'.";
907 success = false;
908 }
909 }
910 }
911
912 set<string> constant_names;
913 for (const auto& constant : GetConstantDeclarations()) {
914 if (constant_names.count(constant->GetName()) > 0) {
915 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
916 success = false;
917 }
918 constant_names.insert(constant->GetName());
919 success = success && constant->CheckValid(typenames);
920 }
921
922 return success;
923}
924
925bool AidlDefinedType::CheckValidForGetterNames() const {
926 bool success = true;
927 std::set<std::string> getters;
928 for (const auto& v : GetFields()) {
929 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
930 if (duplicated) {
931 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
932 << "' after capitalizing the first letter";
933 success = false;
934 }
935 }
936 return success;
937}
938
Jiyong Park18132182020-06-08 20:24:40 +0900939AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
940 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900941 const std::string& cpp_header, std::vector<std::string>* type_params,
942 std::vector<std::unique_ptr<AidlMember>>* members)
943 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900944 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800945 cpp_header_(cpp_header) {
946 // Strip off quotation marks if we actually have a cpp header.
947 if (cpp_header_.length() >= 2) {
948 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
949 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700950}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900951template <typename T>
952AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
953 // Copying is not supported if it has type parameters.
954 // It doesn't make a problem because only ArrayBase() makes a copy,
955 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +0000956 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900957}
958
959template <typename T>
960bool AidlParameterizable<T>::CheckValid() const {
961 return true;
962};
963
964template <>
965bool AidlParameterizable<std::string>::CheckValid() const {
966 if (!IsGeneric()) {
967 return true;
968 }
969 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
970 if (set.size() != GetTypeParameters().size()) {
971 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
972 return false;
973 }
974 return true;
975}
Casey Dahlin59401da2015-10-09 18:16:45 -0700976
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700977std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900978 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900979 AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE,
Jeongik Chad0a10272020-08-06 16:33:36 +0900980 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE};
Devin Moore24f68572020-02-26 13:20:59 -0800981}
982
Jooyung Han808a2a02020-12-28 16:46:54 +0900983bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
984 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100985 return false;
986 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900987 if (!AidlParameterizable<std::string>::CheckValid()) {
988 return false;
989 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900990
991 return true;
992}
993
Jeongik Cha997281d2020-01-16 15:23:59 +0900994void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800995 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900996 writer->Write("parcelable %s ;\n", GetName().c_str());
997}
998
Steven Moreland5557f1c2018-07-02 13:50:23 -0700999AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001000 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001001 const std::string& comments, std::vector<std::string>* type_params,
1002 std::vector<std::unique_ptr<AidlMember>>* members)
1003 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001004
Jeongik Cha997281d2020-01-16 15:23:59 +09001005void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001006 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001007 writer->Write("parcelable %s {\n", GetName().c_str());
1008 writer->Indent();
1009 for (const auto& field : GetFields()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001010 if (field->GetType().IsHidden()) {
1011 AddHideComment(writer);
1012 }
Jiyong Parka468e2a2018-08-29 21:25:18 +09001013 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001014 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001015 for (const auto& constdecl : GetConstantDeclarations()) {
1016 if (constdecl->GetType().IsHidden()) {
1017 AddHideComment(writer);
1018 }
1019 writer->Write("%s;\n", constdecl->ToString().c_str());
1020 }
Jiyong Park02da7422018-07-16 16:00:26 +09001021 writer->Dedent();
1022 writer->Write("}\n");
1023}
1024
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001025std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +09001026 return {
1027 AidlAnnotation::Type::VINTF_STABILITY,
1028 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
1029 AidlAnnotation::Type::HIDE,
1030 AidlAnnotation::Type::JAVA_PASSTHROUGH,
1031 AidlAnnotation::Type::JAVA_DERIVE,
1032 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
1033 AidlAnnotation::Type::FIXED_SIZE,
1034 AidlAnnotation::Type::RUST_DERIVE,
1035 AidlAnnotation::Type::SUPPRESS_WARNINGS,
1036 };
Devin Moore24f68572020-02-26 13:20:59 -08001037}
1038
Jooyung Han808a2a02020-12-28 16:46:54 +09001039bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1040 if (!AidlParcelable::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001041 return false;
1042 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001043
Jooyung Han59af9cc2020-10-25 21:44:14 +09001044 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001045
Jooyung Hand4057c42020-10-23 13:28:22 +09001046 if (IsFixedSize()) {
1047 for (const auto& v : GetFields()) {
1048 if (!typenames.CanBeFixedSize(v->GetType())) {
1049 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1050 << "non-fixed size field named " << v->GetName() << ".";
1051 success = false;
1052 }
1053 }
1054 }
1055
1056 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001057 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001058 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001059 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001060 }
1061 }
1062
Daniel Norman85aed542019-08-21 12:01:14 -07001063 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001064}
1065
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001066// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001067bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1068 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001069 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1070 GetName() == "IBinder") {
1071 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1072 << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001073 return false;
1074 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001075 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1076 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1077 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001078 return false;
1079 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001080 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1081 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001082 if (GetName() == "ParcelFileDescriptor") {
Andrei Homescub62afd92020-05-11 19:24:59 -07001083 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1084 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001085 return false;
1086 }
1087
Steven Morelandd59e3172020-05-11 16:42:09 -07001088 const auto defined_type = typenames.TryGetDefinedType(GetName());
1089 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Andrei Homescub62afd92020-05-11 19:24:59 -07001090 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1091 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001092 return false;
1093 }
1094 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001095 if (this->GetName() == "FileDescriptor" &&
1096 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1097 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << Options::LanguageToString(lang)
1098 << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001099 return false;
1100 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001101 if (this->IsGeneric()) {
1102 if (this->GetName() == "List") {
Jooyung Han55f96ad2020-12-13 10:08:33 +09001103 if (lang == Options::Language::NDK) {
1104 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1105 const string& contained_type_name = contained_type.GetName();
Jooyung Hane87cdd02020-12-11 16:47:35 +09001106 if (typenames.GetInterface(contained_type)) {
1107 AIDL_ERROR(this) << "List<" << contained_type_name
1108 << "> is not supported. List in NDK doesn't support interface.";
1109 return false;
1110 }
1111 if (contained_type_name == "IBinder") {
1112 AIDL_ERROR(this) << "List<" << contained_type_name
1113 << "> is not supported. List in NDK doesn't support IBinder.";
1114 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001115 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001116 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001117 }
1118 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001119
1120 if (this->IsArray()) {
1121 if (this->GetName() == "List" || this->GetName() == "Map" ||
1122 this->GetName() == "CharSequence") {
1123 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001124 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001125 }
1126 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001127
1128 if (lang != Options::Language::JAVA) {
1129 if (this->GetName() == "List" && !this->IsGeneric()) {
1130 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1131 return false;
1132 }
1133 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1134 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1135 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001136 }
1137 }
1138
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001139 return true;
1140}
1141
1142// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001143bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1144 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001145 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001146 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1147 if (unstructured_parcelable != nullptr) {
1148 if (unstructured_parcelable->GetCppHeader().empty()) {
1149 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001150 << "Unstructured parcelable must have C++ header defined.";
1151 return false;
1152 }
1153 }
1154 }
1155 return true;
1156}
1157
1158// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001159bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1160 Options::Language lang) const {
1161 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001162 return false;
1163 }
1164 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001165 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001166 return false;
1167 }
1168 }
1169 return true;
1170}
1171
Daniel Norman85aed542019-08-21 12:01:14 -07001172AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -07001173 AidlConstantValue* value, const std::string& comments)
Jooyung Han29813842020-12-08 01:28:03 +09001174 : AidlNode(location),
1175 name_(name),
1176 value_(value),
1177 comments_(comments),
1178 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001179
1180bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1181 if (GetValue() == nullptr) {
1182 return false;
1183 }
1184 if (!GetValue()->CheckValid()) {
1185 return false;
1186 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001187 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001188 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1189 return false;
1190 }
1191 return true;
1192}
1193
1194string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1195 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001196 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001197}
1198
1199AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1200 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jiyong Park18132182020-06-08 20:24:40 +09001201 const std::string& package, const std::string& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001202 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001203 enumerators_(std::move(*enumerators)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001204 // Fill missing enumerator values with <prev + 1>
1205 // This can't be done in Autofill() because type/ref resolution depends on this.
1206 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1207 // resolved if A has no value set.
Daniel Normanb28684e2019-10-17 15:31:39 -07001208 const AidlEnumerator* previous = nullptr;
1209 for (const auto& enumerator : enumerators_) {
1210 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001211 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001212 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001213 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001214 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001215 } else {
Jooyung Han29813842020-12-08 01:28:03 +09001216 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName(), "");
Daniel Normanb28684e2019-10-17 15:31:39 -07001217 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001218 loc, std::move(prev_value), "+",
1219 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001220 }
1221 }
1222 previous = enumerator.get();
1223 }
1224}
1225
Jooyung Han672557b2020-12-24 05:18:00 +09001226bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1227 if (auto annot = BackingType(); annot != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001228 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1229 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
Jooyung Han672557b2020-12-24 05:18:00 +09001230 // need to call CheckValid().
1231 if (!annot->CheckValid()) {
1232 return false;
1233 }
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001234 auto type = annot->ParamValue<std::string>("type").value();
1235 backing_type_ =
1236 std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, "");
Jooyung Han672557b2020-12-24 05:18:00 +09001237 } else {
1238 // Default to byte type for enums.
1239 backing_type_ =
1240 std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, "");
1241 }
1242 // Autofill() is called after type resolution, we resolve the backing type manually.
1243 if (!backing_type_->Resolve(typenames)) {
1244 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
1245 }
1246 return true;
1247}
1248
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001249std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +09001250 return {
1251 AidlAnnotation::Type::VINTF_STABILITY,
1252 AidlAnnotation::Type::BACKING,
1253 AidlAnnotation::Type::HIDE,
1254 AidlAnnotation::Type::JAVA_PASSTHROUGH,
1255 AidlAnnotation::Type::SUPPRESS_WARNINGS,
1256 };
Devin Moore24f68572020-02-26 13:20:59 -08001257}
1258
Jooyung Han808a2a02020-12-28 16:46:54 +09001259bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1260 if (!AidlDefinedType::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001261 return false;
1262 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001263 if (!GetMembers().empty()) {
1264 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1265 return false;
1266 }
Daniel Norman85aed542019-08-21 12:01:14 -07001267 if (backing_type_ == nullptr) {
1268 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1269 return false;
1270 }
1271 bool success = true;
1272 for (const auto& enumerator : enumerators_) {
1273 success = success && enumerator->CheckValid(GetBackingType());
1274 }
Jooyung Han3b990182020-12-22 17:44:31 +09001275
Jooyung Han808a2a02020-12-28 16:46:54 +09001276 return success;
Daniel Norman85aed542019-08-21 12:01:14 -07001277}
1278
Jeongik Cha997281d2020-01-16 15:23:59 +09001279void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001280 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001281 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -07001282 writer->Indent();
1283 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001284 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1285 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1286 }
1287 writer->Dedent();
1288 writer->Write("}\n");
1289}
1290
Jooyung Han2946afc2020-10-05 20:29:16 +09001291AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1292 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001293 std::vector<std::string>* type_params,
1294 std::vector<std::unique_ptr<AidlMember>>* members)
1295 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001296
1297std::set<AidlAnnotation::Type> AidlUnionDecl::GetSupportedAnnotations() const {
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +09001298 return {
1299 AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::HIDE,
1300 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_DERIVE,
1301 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, AidlAnnotation::Type::RUST_DERIVE,
1302 AidlAnnotation::Type::SUPPRESS_WARNINGS,
1303 };
Jooyung Han2946afc2020-10-05 20:29:16 +09001304}
1305
1306void AidlUnionDecl::Dump(CodeWriter* writer) const {
1307 DumpHeader(writer);
1308 writer->Write("union %s {\n", GetName().c_str());
1309 writer->Indent();
1310 for (const auto& field : GetFields()) {
1311 if (field->GetType().IsHidden()) {
1312 AddHideComment(writer);
1313 }
1314 writer->Write("%s;\n", field->ToString().c_str());
1315 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001316 for (const auto& constdecl : GetConstantDeclarations()) {
1317 if (constdecl->GetType().IsHidden()) {
1318 AddHideComment(writer);
1319 }
1320 writer->Write("%s;\n", constdecl->ToString().c_str());
1321 }
Jooyung Han2946afc2020-10-05 20:29:16 +09001322 writer->Dedent();
1323 writer->Write("}\n");
1324}
1325
Jooyung Han808a2a02020-12-28 16:46:54 +09001326bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001327 // visit parents
Jooyung Han808a2a02020-12-28 16:46:54 +09001328 if (!AidlParcelable::CheckValid(typenames)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001329 return false;
1330 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001331
1332 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001333 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001334 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001335 }
1336
1337 // now, visit self!
1338 bool success = true;
1339
1340 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1341 for (const auto& v : GetFields()) {
1342 if (v->GetType().GetName() == "ParcelableHolder") {
1343 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1344 success = false;
1345 }
1346 }
1347
Jooyung Hanfe89f122020-10-14 03:49:18 +09001348 if (GetFields().empty()) {
1349 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1350 return false;
1351 }
1352
Jooyung Han53fb4242020-12-17 16:03:49 +09001353 // first member should have useful default value (implicit or explicit)
1354 const auto& first = GetFields()[0];
1355 if (!first->HasUsefulDefaultValue()) {
1356 // Most types can be initialized without a default value. For example,
1357 // interface types are inherently nullable. But, enum types should have
1358 // an explicit default value.
1359 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1360 AIDL_ERROR(first)
1361 << "The union's first member should have a useful default value. Enum types can be "
1362 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1363 return false;
1364 }
1365 // In Java, array types are initialized as null without a default value. To be sure that default
1366 // initialized unions are accepted by other backends we require arrays also have a default
1367 // value.
1368 if (first->GetType().IsArray()) {
1369 AIDL_ERROR(first)
1370 << "The union's first member should have a useful default value. Arrays can be "
1371 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1372 return false;
1373 }
1374 }
1375
Jooyung Hanfe89f122020-10-14 03:49:18 +09001376 return success;
1377}
1378
1379// TODO: we should treat every backend all the same in future.
1380bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1381 Options::Language lang) const {
1382 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1383 return false;
1384 }
1385 for (const auto& v : this->GetFields()) {
1386 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1387 return false;
1388 }
1389 }
1390 return true;
1391}
1392
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001393// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001394bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1395 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001396 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001397 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001398 return false;
1399 }
1400 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001401 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001402 return false;
1403 }
1404 }
1405 }
1406 return true;
1407}
1408
Steven Moreland46e9da82018-07-27 15:45:29 -07001409AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001410 const std::string& comments, bool oneway, const std::string& package,
1411 std::vector<std::unique_ptr<AidlMember>>* members)
1412 : AidlDefinedType(location, name, comments, package, members) {
1413 for (auto& m : GetMethods()) {
1414 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001415 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001416}
1417
Jeongik Cha997281d2020-01-16 15:23:59 +09001418void AidlInterface::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001419 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001420 writer->Write("interface %s {\n", GetName().c_str());
1421 writer->Indent();
1422 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001423 if (method->IsHidden()) {
1424 AddHideComment(writer);
1425 }
Jiyong Park309668e2018-07-28 16:55:44 +09001426 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001427 }
Jiyong Parka428d212018-08-29 22:26:30 +09001428 for (const auto& constdecl : GetConstantDeclarations()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001429 if (constdecl->GetType().IsHidden()) {
1430 AddHideComment(writer);
1431 }
Jiyong Parka428d212018-08-29 22:26:30 +09001432 writer->Write("%s;\n", constdecl->ToString().c_str());
1433 }
Jiyong Park02da7422018-07-16 16:00:26 +09001434 writer->Dedent();
1435 writer->Write("}\n");
1436}
1437
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001438std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +09001439 return {
1440 AidlAnnotation::Type::SENSITIVE_DATA, AidlAnnotation::Type::VINTF_STABILITY,
1441 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
1442 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::DESCRIPTOR,
1443 AidlAnnotation::Type::SUPPRESS_WARNINGS,
1444 };
Devin Moore24f68572020-02-26 13:20:59 -08001445}
1446
Jooyung Han808a2a02020-12-28 16:46:54 +09001447bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1448 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001449 return false;
1450 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001451 // Has to be a pointer due to deleting copy constructor. No idea why.
1452 map<string, const AidlMethod*> method_names;
1453 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001454 if (!m->GetType().CheckValid(typenames)) {
1455 return false;
1456 }
1457
Jeongik Cha649e8a72020-03-27 17:47:40 +09001458 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1459 if (m->GetType().GetName() == "ParcelableHolder") {
1460 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1461 return false;
1462 }
Steven Morelandacd53472018-12-14 10:17:26 -08001463 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001464 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1465 return false;
1466 }
1467
1468 set<string> argument_names;
1469 for (const auto& arg : m->GetArguments()) {
1470 auto it = argument_names.find(arg->GetName());
1471 if (it != argument_names.end()) {
1472 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1473 << arg->GetName() << "'";
1474 return false;
1475 }
1476 argument_names.insert(arg->GetName());
1477
1478 if (!arg->GetType().CheckValid(typenames)) {
1479 return false;
1480 }
1481
Jeongik Cha649e8a72020-03-27 17:47:40 +09001482 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1483 if (arg->GetType().GetName() == "ParcelableHolder") {
1484 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1485 return false;
1486 }
Steven Morelandacd53472018-12-14 10:17:26 -08001487 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001488 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1489 return false;
1490 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001491
1492 const auto [can_be_out, type_aspect] = typenames.CanBeOutParameter(arg->GetType());
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001493 if (!arg->DirectionWasSpecified() && can_be_out) {
Jooyung Han965e31d2020-11-27 12:30:16 +09001494 AIDL_ERROR(arg) << "'" << arg->GetType().Signature()
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001495 << "' can be an out type, so you must declare it as in, out, or inout.";
1496 return false;
1497 }
1498
1499 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
Jooyung Han15fd6c62020-10-23 13:54:46 +09001500 AIDL_ERROR(arg) << "'" << arg->GetName() << "' can't be an " << arg->GetDirectionSpecifier()
1501 << " parameter because " << type_aspect << " can only be an in parameter.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001502 return false;
1503 }
1504
1505 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001506 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001507 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1508 return false;
1509 }
1510
1511 // Reserve a namespace for internal use
1512 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1513 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1514 return false;
1515 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001516 }
1517
1518 auto it = method_names.find(m->GetName());
1519 // prevent duplicate methods
1520 if (it == method_names.end()) {
1521 method_names[m->GetName()] = m.get();
1522 } else {
1523 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1524 AIDL_ERROR(it->second) << "previously defined here.";
1525 return false;
1526 }
1527
Paul Trautrimb77048c2020-01-21 16:39:32 +09001528 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001529 "getTransactionName(int)"};
1530
1531 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001532 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001533 return false;
1534 }
1535 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001536
1537 bool success = true;
1538 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001539 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001540 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001541 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001542 success = false;
1543 }
1544 constant_names.insert(constant->GetName());
1545 success = success && constant->CheckValid(typenames);
1546 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001547 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001548}
1549
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001550std::string AidlInterface::GetDescriptor() const {
1551 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1552 if (annotatedDescriptor != "") {
1553 return annotatedDescriptor;
1554 }
1555 return GetCanonicalName();
1556}
1557
Steven Moreland46e9da82018-07-27 15:45:29 -07001558AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1559 : AidlNode(location), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001560
1561// Resolves unresolved type name to fully qualified typename to import
1562// case #1: SimpleName --> import p.SimpleName
1563// case #2: Outer.Inner --> import p.Outer
1564// case #3: p.SimpleName --> (as is)
1565std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1566 std::string canonical_name;
1567 const auto first_dot = unresolved_name.find_first_of('.');
1568 const std::string class_name =
1569 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1570 for (const auto& import : Imports()) {
1571 const auto& fq_name = import->GetNeededClass();
1572 const auto last_dot = fq_name.find_last_of('.');
1573 const std::string imported_type_name =
1574 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1575 if (imported_type_name == class_name) {
1576 if (canonical_name != "" && canonical_name != fq_name) {
1577 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1578 return {};
1579 }
1580 canonical_name = fq_name;
1581 }
1582 }
1583 // if not found, use unresolved_name as it is
1584 if (canonical_name == "") {
1585 return unresolved_name;
1586 }
1587 return canonical_name;
Steven Moreland26318532020-12-23 20:08:36 +00001588}
Jooyung Han808a2a02020-12-28 16:46:54 +09001589
1590void AidlVisitAll::VisitDocument(const AidlDocument& d) {
1591 for (const auto& type : d.DefinedTypes()) type->Accept(*this);
1592}
1593void AidlVisitAll::VisitInterface(const AidlInterface& i) {
1594 for (const auto& m : i.GetMembers()) m->Accept(*this);
1595}
1596void AidlVisitAll::VisitEnum(const AidlEnumDeclaration& e) {
1597 for (const auto& v : e.GetEnumerators()) v->Accept(*this);
1598}
1599void AidlVisitAll::VisitUnion(const AidlUnionDecl& u) {
1600 for (const auto& m : u.GetMembers()) m->Accept(*this);
1601}
1602void AidlVisitAll::VisitStructuredParcelable(const AidlStructuredParcelable& p) {
1603 for (const auto& m : p.GetMembers()) m->Accept(*this);
1604}
1605void AidlVisitAll::VisitUnstructuredParcelable(const AidlParcelable&) {}
1606void AidlVisitAll::VisitEnumerator(const AidlEnumerator&) {}
1607void AidlVisitAll::VisitMethod(const AidlMethod& m) {
1608 for (const auto& a : m.GetArguments()) a->Accept(*this);
1609}
1610void AidlVisitAll::VisitConstant(const AidlConstantDeclaration&) {}
1611void AidlVisitAll::VisitVariable(const AidlVariableDeclaration&) {}
1612void AidlVisitAll::VisitArgument(const AidlArgument&) {}