blob: 256af2c3da1ec719d4f329fe39a169cfa4789224 [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
Devin Mooredf93ebb2020-03-25 14:03:35 -070082AidlLocation::AidlLocation(const std::string& file, Point begin, Point end, Source source)
83 : file_(file), begin_(begin), end_(end), source_(source) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070084
85std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
Devin Moore5de18ed2020-04-02 13:52:29 -070086 os << l.file_;
87 if (l.LocationKnown()) {
88 os << ":" << l.begin_.line << "." << l.begin_.column << "-";
89 if (l.begin_.line != l.end_.line) {
90 os << l.end_.line << ".";
91 }
92 os << l.end_.column;
Steven Moreland46e9da82018-07-27 15:45:29 -070093 }
Steven Moreland46e9da82018-07-27 15:45:29 -070094 return os;
95}
96
97AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
98
Mathew Inwoodadb74672019-11-29 14:01:53 +000099std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +0000100 std::stringstream ss;
101 ss << location_.file_ << ":" << location_.begin_.line;
102 return ss.str();
103}
104
Mathew Inwoodadb74672019-11-29 14:01:53 +0000105std::string AidlNode::PrintLocation() const {
106 std::stringstream ss;
107 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
108 << location_.end_.line << ":" << location_.end_.column;
109 return ss.str();
110}
111
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700112const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
113 static const std::vector<Schema> kSchemas{
Jooyung Hand902a972020-10-23 17:32:44 +0900114 {AidlAnnotation::Type::NULLABLE, "nullable", {}, false},
115 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}, false},
Steven Morelanda7764e52020-10-27 17:29:29 +0000116 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", {}, false},
Jooyung Hand902a972020-10-23 17:32:44 +0900117 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}, false},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700118 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
119 "UnsupportedAppUsage",
120 {{"expectedSignature", "String"},
121 {"implicitMember", "String"},
122 {"maxTargetSdk", "int"},
123 {"publicAlternatives", "String"},
Jooyung Hand902a972020-10-23 17:32:44 +0900124 {"trackingBug", "long"}},
125 false},
126 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}, false},
127 {AidlAnnotation::Type::HIDE, "Hide", {}, false},
Jooyung Han5721a232020-12-24 04:34:55 +0900128 {AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}, false, {"type"}},
129 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
130 "JavaPassthrough",
131 {{"annotation", "String"}},
132 true,
133 {"annotation"}},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900134 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900135 "JavaDerive",
136 {{"toString", "boolean"}, {"equals", "boolean"}},
137 false},
Jooyung Hand902a972020-10-23 17:32:44 +0900138 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, "JavaOnlyImmutable", {}, false},
139 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", {}, false},
Jooyung Han5721a232020-12-24 04:34:55 +0900140 {AidlAnnotation::Type::DESCRIPTOR, "Descriptor", {{"value", "String"}}, false, {"value"}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700141 {AidlAnnotation::Type::RUST_DERIVE,
142 "RustDerive",
143 {{"Copy", "boolean"},
144 {"Clone", "boolean"},
145 {"PartialOrd", "boolean"},
146 {"Ord", "boolean"},
147 {"PartialEq", "boolean"},
148 {"Eq", "boolean"},
Jooyung Hand902a972020-10-23 17:32:44 +0900149 {"Hash", "boolean"}},
150 false},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900151 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700152 return kSchemas;
153}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900154
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700155std::string AidlAnnotation::TypeToString(Type type) {
156 for (const Schema& schema : AllSchemas()) {
157 if (type == schema.type) return schema.name;
158 }
159 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
160 __builtin_unreachable();
161}
Andrei Onea9445fc62019-06-27 18:11:59 +0100162
163AidlAnnotation* AidlAnnotation::Parse(
164 const AidlLocation& location, const string& name,
165 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700166 const Schema* schema = nullptr;
167 for (const Schema& a_schema : AllSchemas()) {
168 if (a_schema.name == name) {
169 schema = &a_schema;
170 }
171 }
172
173 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900174 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700175 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900176 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700177 for (const Schema& s : AllSchemas()) {
178 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900179 }
180 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700181 AIDL_ERROR(location) << stream.str();
182 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900183 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100184 if (parameter_list == nullptr) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700185 return new AidlAnnotation(location, *schema, {});
Andrei Onea9445fc62019-06-27 18:11:59 +0100186 }
187
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700188 return new AidlAnnotation(location, *schema, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900189}
190
Andrei Onea9445fc62019-06-27 18:11:59 +0100191AidlAnnotation::AidlAnnotation(
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700192 const AidlLocation& location, const Schema& schema,
Andrei Onea9445fc62019-06-27 18:11:59 +0100193 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700194 : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100195
Jooyung Han690f5842020-12-04 13:02:04 +0900196struct ConstReferenceFinder : AidlConstantValue::Visitor {
197 AidlConstantReference* found;
198 void Visit(AidlConstantValue&) override {}
199 void Visit(AidlUnaryConstExpression&) override {}
200 void Visit(AidlBinaryConstExpression&) override {}
201 void Visit(AidlConstantReference& ref) override {
202 if (!found) found = &ref;
203 }
204};
205
Andrei Onea9445fc62019-06-27 18:11:59 +0100206bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100207 for (const auto& name_and_param : parameters_) {
208 const std::string& param_name = name_and_param.first;
209 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han690f5842020-12-04 13:02:04 +0900210
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700211 auto parameter_mapping_it = schema_.supported_parameters.find(param_name);
212 if (parameter_mapping_it == schema_.supported_parameters.end()) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100213 std::ostringstream stream;
214 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700215 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100216 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700217 for (const auto& kv : schema_.supported_parameters) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100218 stream << " " << kv.first;
219 }
220 AIDL_ERROR(this) << stream.str();
221 return false;
222 }
Jooyung Han690f5842020-12-04 13:02:04 +0900223
224 ConstReferenceFinder finder;
225 param->Accept(finder);
226 if (finder.found) {
227 AIDL_ERROR(finder.found) << "Value must be a constant expression but contains reference to "
228 << finder.found->GetFieldName() << ".";
229 return false;
230 }
231
232 if (!param->CheckValid()) {
233 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
234 << GetName() << ".";
235 return false;
236 }
237
Andrei Onea9445fc62019-06-27 18:11:59 +0100238 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700239 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100240 // Assume error on empty string.
241 if (param_value == "") {
242 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
243 << GetName() << ".";
244 return false;
245 }
246 }
Jooyung Han5721a232020-12-24 04:34:55 +0900247 bool success = true;
248 for (const auto& param : schema_.required_parameters) {
249 if (parameters_.count(param) == 0) {
250 AIDL_ERROR(this) << "Missing '" << param << "' on @" << GetName() << ".";
251 success = false;
252 }
253 }
254 return success;
Andrei Onea9445fc62019-06-27 18:11:59 +0100255}
256
257std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
258 const ConstantValueDecorator& decorator) const {
259 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100260 for (const auto& name_and_param : parameters_) {
261 const std::string& param_name = name_and_param.first;
262 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Devin Mooredecaf292020-04-30 09:16:40 -0700263 if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
264 std::ostringstream stream;
265 stream << "Parameter " << param_name << " not supported ";
266 stream << "for annotation " << GetName() << ". ";
267 stream << "It must be one of:";
268 for (const auto& kv : schema_.supported_parameters) {
269 stream << " " << kv.first;
270 }
271 AIDL_ERROR(this) << stream.str();
272 continue;
273 }
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700274 AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
275 nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700276 if (!param->CheckValid()) {
277 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
278 << GetName() << ".";
Devin Mooredecaf292020-04-30 09:16:40 -0700279 continue;
Will McVickerd7d18df2019-09-12 13:40:50 -0700280 }
281
282 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100283 }
284 return raw_params;
285}
Steven Moreland46e9da82018-07-27 15:45:29 -0700286
Jooyung Han965e31d2020-11-27 12:30:16 +0900287std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700288 if (parameters_.empty()) {
289 return "@" + GetName();
290 } else {
291 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900292 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700293 param_strings.emplace_back(name + "=" + value);
294 }
295 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
296 }
297}
298
Andrei Onea9445fc62019-06-27 18:11:59 +0100299static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700300 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100301 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700302 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900303 AIDL_FATAL_IF(a.Repeatable(), a)
304 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100305 return &a;
306 }
307 }
308 return nullptr;
309}
310
Steven Moreland46e9da82018-07-27 15:45:29 -0700311AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
312
Jiyong Park68bc77a2018-07-19 19:00:45 +0900313bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700314 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900315}
316
Jiyong Park68bc77a2018-07-19 19:00:45 +0900317bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700318 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900319}
320
Steven Morelanda7764e52020-10-27 17:29:29 +0000321bool AidlAnnotatable::IsSensitiveData() const {
322 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
323}
324
Steven Morelanda57d0a62019-07-30 09:41:14 -0700325bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700326 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700327}
328
Jeongik Chad0a10272020-08-06 16:33:36 +0900329bool AidlAnnotatable::IsJavaOnlyImmutable() const {
330 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900331}
332
Devin Moorec7e47a32020-08-07 10:55:25 -0700333bool AidlAnnotatable::IsFixedSize() const {
334 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
335}
336
Andrei Onea9445fc62019-06-27 18:11:59 +0100337const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700338 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900339}
340
Andrei Homescue61feb52020-08-18 15:44:24 -0700341const AidlAnnotation* AidlAnnotatable::RustDerive() const {
342 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
343}
344
Daniel Norman716d3112019-09-10 13:11:56 -0700345const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700346 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700347 if (annotation != nullptr) {
348 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
349 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
350 const string& type = it->second;
Steven Morelande7d5d082020-05-21 20:29:02 +0000351
352 AIDL_FATAL_IF(type.size() < 2, this) << type;
353 AIDL_FATAL_IF(type[0] != '"', this) << type;
354 AIDL_FATAL_IF(type[type.length() - 1] != '"', this) << type;
355 string unquoted_type = type.substr(1, type.length() - 2);
356
Daniel Norman716d3112019-09-10 13:11:56 -0700357 AidlTypeSpecifier* type_specifier =
Jooyung Han60b2fde2020-10-29 15:12:40 +0900358 new AidlTypeSpecifier(annotation->GetLocation(), unquoted_type, false, nullptr, "");
Daniel Norman716d3112019-09-10 13:11:56 -0700359 type_specifier->Resolve(typenames);
360 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700361 }
362 }
363 return nullptr;
364}
365
Jeongik Cha88f95a82020-01-15 13:02:16 +0900366bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700367 return lang == Options::Language::JAVA &&
368 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900369}
370
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800371bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700372 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800373}
374
Jooyung Han829ec7c2020-12-02 12:07:36 +0900375bool AidlAnnotatable::JavaDerive(const std::string& method) const {
376 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
377 if (annotation != nullptr) {
378 auto params = annotation->AnnotationParams(AidlConstantValueDecorator);
379 if (auto it = params.find(method); it != params.end()) {
380 return it->second == "true";
381 }
382 }
383 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900384}
385
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900386std::string AidlAnnotatable::GetDescriptor() const {
387 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
388 if (annotation != nullptr) {
389 auto params = annotation->AnnotationParams(AidlConstantValueDecorator);
390 if (auto it = params.find("value"); it != params.end()) {
391 const string& value = it->second;
392
393 AIDL_FATAL_IF(value.size() < 2, this) << value;
394 AIDL_FATAL_IF(value[0] != '"', this) << value;
395 AIDL_FATAL_IF(value[value.length() - 1] != '"', this) << value;
396 std::string unquoted_value = value.substr(1, value.length() - 2);
397 return unquoted_value;
398 }
399 }
400 return "";
401}
402
Steven Moreland7e4b9502020-02-20 18:10:42 -0800403void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
404 if (annotations_.empty()) return;
405
406 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
407}
408
Devin Moore24f68572020-02-26 13:20:59 -0800409bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700410 std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
Andrei Onea9445fc62019-06-27 18:11:59 +0100411 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900412 // check if it is allowed for this node
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700413 if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900414 std::vector<std::string> supported_annot_strings;
415 for (AidlAnnotation::Type type : supported_annotations) {
416 supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
417 }
Devin Moore24f68572020-02-26 13:20:59 -0800418 AIDL_ERROR(this) << "'" << annotation.GetName()
419 << "' is not a supported annotation for this node. "
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700420 << "It must be one of: "
421 << android::base::Join(supported_annot_strings, ", ");
Devin Moore24f68572020-02-26 13:20:59 -0800422 return false;
423 }
Jooyung Hand902a972020-10-23 17:32:44 +0900424 // CheckValid() only if it is okay to be here
425 if (!annotation.CheckValid()) {
426 return false;
427 }
428 }
429
430 std::map<AidlAnnotation::Type, AidlLocation> declared;
431 for (const auto& annotation : GetAnnotations()) {
432 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
433 if (!inserted && !annotation.Repeatable()) {
434 AIDL_ERROR(this) << "'" << annotation.GetName()
435 << "' is repeated, but not allowed. Previous location: " << iter->second;
436 return false;
437 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100438 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700439
Andrei Onea9445fc62019-06-27 18:11:59 +0100440 return true;
441}
442
Jiyong Park68bc77a2018-07-19 19:00:45 +0900443string AidlAnnotatable::ToString() const {
444 vector<string> ret;
445 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900446 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900447 }
448 std::sort(ret.begin(), ret.end());
449 return Join(ret, " ");
450}
451
Steven Moreland46e9da82018-07-27 15:45:29 -0700452AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
453 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900454 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700455 const string& comments)
456 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900457 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700458 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700459 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900460 comments_(comments),
461 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700462
Jooyung Hand2fa0232020-10-19 02:51:41 +0900463const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700464 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900465 // Declaring array of generic type cannot happen, it is grammar error.
466 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700467
Jooyung Hand2fa0232020-10-19 02:51:41 +0900468 if (!array_base_) {
469 array_base_.reset(new AidlTypeSpecifier(*this));
470 array_base_->is_array_ = false;
471 }
472 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700473}
474
Jeongik Cha997281d2020-01-16 15:23:59 +0900475bool AidlTypeSpecifier::IsHidden() const {
476 return HasHideComment(GetComments());
477}
478
Jooyung Han965e31d2020-11-27 12:30:16 +0900479string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900480 string ret = GetName();
481 if (IsGeneric()) {
482 vector<string> arg_names;
483 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900484 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900485 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900486 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900487 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900488 if (IsArray()) {
489 ret += "[]";
490 }
491 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900492}
493
Jooyung Han965e31d2020-11-27 12:30:16 +0900494string AidlTypeSpecifier::ToString() const {
495 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900496 string annotations = AidlAnnotatable::ToString();
497 if (annotations != "") {
498 ret = annotations + " " + ret;
499 }
500 return ret;
501}
502
Daniel Norman716d3112019-09-10 13:11:56 -0700503bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000504 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700505 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
506 if (result.is_resolved) {
507 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900508 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900509 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900510 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700511 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700512}
513
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900514const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
515 return defined_type_;
516}
517
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700518std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
Devin Moore24f68572020-02-26 13:20:59 -0800519 // kHide and kUnsupportedAppUsage are both method return annotations
520 // which we don't distinguish from other type specifiers.
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700521 return {AidlAnnotation::Type::NULLABLE, AidlAnnotation::Type::UTF8_IN_CPP,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900522 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
523 AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -0800524}
525
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900526bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800527 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100528 return false;
529 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900530 if (IsGeneric()) {
531 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900532
533 auto& types = GetTypeParameters();
534 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
535 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900536 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
537 return (typenames.GetEnumDeclaration(*type_ptr)) ||
538 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
Jeongik Chae74c86d2019-12-12 16:54:03 +0900539 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700540 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900541 return false;
542 }
543 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800544 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900545 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800546 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
547 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900548 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800549 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900550 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800551 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900552 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000553 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900554 return false;
555 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900556 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
557 const string& contained_type_name = contained_type.GetName();
558 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
559 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
560 contained_type_name != "ParcelFileDescriptor") {
561 AIDL_ERROR(this) << "List<" << contained_type_name
562 << "> is not supported. List<T> supports parcelable/union, String, "
563 "IBinder, and ParcelFileDescriptor.";
564 return false;
565 }
566 } else { // Defined types
567 if (typenames.GetInterface(contained_type)) {
568 AIDL_ERROR(this) << "List<" << contained_type_name
569 << "> is not supported. List<T> supports parcelable/union, String, "
570 "IBinder, and ParcelFileDescriptor.";
571 return false;
572 }
573 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900574 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800575 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900576 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900577 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900578 return false;
579 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800580 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900581 const string& key_type = GetTypeParameters()[0]->GetName();
582 if (key_type != "String") {
583 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
584 << "'" << key_type << "'";
585 return false;
586 }
587 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800588 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900589 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800590 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900591 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800592 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900593 return false;
594 }
595 } else {
596 AIDL_ERROR(this) << type_name << " is not a generic type.";
597 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900598 }
599 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900600
Steven Moreland11cb9452020-01-21 16:56:58 -0800601 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
602 GetTypeParameters().size() == 1 &&
603 GetTypeParameters()[0]->GetName() == "String";
604 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
605 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
606 return false;
607 }
608
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900609 if (GetName() == "void") {
610 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
611 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
612 return false;
613 }
614 }
615
616 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800617 const auto defined_type = typenames.TryGetDefinedType(GetName());
618 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900619 AIDL_ERROR(this) << "Binder type cannot be an array";
620 return false;
621 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000622 if (GetName() == "ParcelableHolder") {
623 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
624 return false;
625 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900626 }
627
628 if (IsNullable()) {
629 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
630 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
631 return false;
632 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800633 const auto defined_type = typenames.TryGetDefinedType(GetName());
634 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700635 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
636 return false;
637 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900638 if (GetName() == "ParcelableHolder") {
639 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
640 return false;
641 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900642 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900643 return true;
644}
645
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900646std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700647 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900648 if (type.IsArray()) {
649 return raw_value;
650 }
651
652 if (auto defined_type = type.GetDefinedType(); defined_type) {
653 auto enum_type = defined_type->AsEnumDeclaration();
654 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
655 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
656 }
Steven Moreland860b1942018-08-16 14:59:28 -0700657 return raw_value;
658}
659
Steven Moreland46e9da82018-07-27 15:45:29 -0700660AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
661 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000662 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
663 default_user_specified_ = false;
664}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700665
Steven Moreland46e9da82018-07-27 15:45:29 -0700666AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
667 AidlTypeSpecifier* type, const std::string& name,
668 AidlConstantValue* default_value)
Jooyung Han3f347ca2020-12-01 12:41:50 +0900669 : AidlMember(location),
Steven Moreland541788d2020-05-21 22:05:52 +0000670 type_(type),
671 name_(name),
672 default_user_specified_(true),
673 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700674
Jooyung Han53fb4242020-12-17 16:03:49 +0900675bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
676 if (GetDefaultValue()) {
677 return true;
678 }
679 // null is accepted as a valid default value in all backends
680 if (GetType().IsNullable()) {
681 return true;
682 }
683 return false;
684}
685
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900686bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700687 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900688 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900689
Steven Moreland54be7bd2019-12-05 11:17:53 -0800690 if (type_->GetName() == "void") {
691 AIDL_ERROR(this) << "Declaration " << name_
692 << " is void, but declarations cannot be of void type.";
693 valid = false;
694 }
695
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900696 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700697 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700698
Steven Moreland25294322018-08-07 18:13:55 -0700699 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700700
Steven Moreland860b1942018-08-16 14:59:28 -0700701 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700702}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700703
Jooyung Hanacae85d2020-10-28 16:39:09 +0900704string AidlVariableDeclaration::GetCapitalizedName() const {
705 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
706 string str = name_;
707 str[0] = static_cast<char>(toupper(str[0]));
708 return str;
709}
710
Steven Moreland5557f1c2018-07-02 13:50:23 -0700711string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900712 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000713 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700714 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700715 }
716 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700717}
718
Jiyong Park02da7422018-07-16 16:00:26 +0900719string AidlVariableDeclaration::Signature() const {
720 return type_->Signature() + " " + name_;
721}
722
Steven Moreland860b1942018-08-16 14:59:28 -0700723std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900724 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700725 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900726 } else {
727 return "";
728 }
Steven Moreland25294322018-08-07 18:13:55 -0700729}
730
Steven Moreland46e9da82018-07-27 15:45:29 -0700731AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
732 AidlTypeSpecifier* type, const std::string& name)
733 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700734 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700735 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700736
Steven Moreland46e9da82018-07-27 15:45:29 -0700737AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
738 const std::string& name)
739 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700740 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700741 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700742
Jiyong Park02da7422018-07-16 16:00:26 +0900743string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700744 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700745 if (direction_specified_) {
746 switch(direction_) {
747 case AidlArgument::IN_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700748 ret += "in";
Casey Dahlinc378c992015-09-29 16:50:40 -0700749 break;
750 case AidlArgument::OUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700751 ret += "out";
Casey Dahlinc378c992015-09-29 16:50:40 -0700752 break;
753 case AidlArgument::INOUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700754 ret += "inout";
Casey Dahlinc378c992015-09-29 16:50:40 -0700755 break;
756 }
757 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700758 return ret;
759}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700760
Jiyong Park02da7422018-07-16 16:00:26 +0900761string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700762 if (direction_specified_) {
763 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
764 } else {
765 return AidlVariableDeclaration::ToString();
766 }
Jiyong Park02da7422018-07-16 16:00:26 +0900767}
768
Steven Moreland46e9da82018-07-27 15:45:29 -0700769AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
770
Steven Moreland46e9da82018-07-27 15:45:29 -0700771AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
772 AidlTypeSpecifier* type, const std::string& name,
773 AidlConstantValue* value)
774 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700775
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900776bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700777 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900778 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700779 valid &= value_->CheckValid();
780 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700781
Steven Morelande689da22020-11-10 02:06:30 +0000782 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900783 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
784 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700785 return false;
786 }
787
Will McVickerd7d18df2019-09-12 13:40:50 -0700788 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700789}
790
Jiyong Parka428d212018-08-29 22:26:30 +0900791string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900792 return "const " + type_->ToString() + " " + name_ + " = " +
793 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900794}
795
796string AidlConstantDeclaration::Signature() const {
797 return type_->Signature() + " " + name_;
798}
799
Steven Moreland46e9da82018-07-27 15:45:29 -0700800AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
801 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900802 const std::string& comments)
803 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
804 has_id_ = false;
805}
806
807AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
808 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900809 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700810 : AidlMember(location),
811 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700812 comments_(comments),
813 type_(type),
814 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700815 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900816 id_(id),
817 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700818 has_id_ = true;
819 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700820 for (const unique_ptr<AidlArgument>& a : arguments_) {
821 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
822 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
823 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700824}
825
Jeongik Cha997281d2020-01-16 15:23:59 +0900826bool AidlMethod::IsHidden() const {
827 return HasHideComment(GetComments());
828}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700829
Jiyong Park02da7422018-07-16 16:00:26 +0900830string AidlMethod::Signature() const {
831 vector<string> arg_signatures;
832 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900833 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900834 }
Jiyong Park309668e2018-07-28 16:55:44 +0900835 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
836}
837
838string AidlMethod::ToString() const {
839 vector<string> arg_strings;
840 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900841 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900842 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900843 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800844 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900845 if (HasId()) {
846 ret += " = " + std::to_string(GetId());
847 }
848 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900849}
850
Steven Moreland46e9da82018-07-27 15:45:29 -0700851AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900852 const std::string& comments, const std::string& package,
853 std::vector<std::unique_ptr<AidlMember>>* members)
Jiyong Park18132182020-06-08 20:24:40 +0900854 : AidlAnnotatable(location),
855 name_(name),
856 comments_(comments),
857 package_(package),
858 split_package_(package.empty() ? std::vector<std::string>()
Jooyung Han829ec7c2020-12-02 12:07:36 +0900859 : android::base::Split(package, ".")) {
860 if (members) {
861 for (auto& m : *members) {
862 if (auto constant = m->AsConstantDeclaration(); constant) {
863 constants_.emplace_back(constant);
864 } else if (auto variable = m->AsVariableDeclaration(); variable) {
865 variables_.emplace_back(variable);
866 } else if (auto method = m->AsMethod(); method) {
867 methods_.emplace_back(method);
868 } else {
869 AIDL_FATAL(*m);
870 }
871 members_.push_back(m.release());
872 }
873 delete members;
874 }
875}
Steven Moreland787b0432018-07-03 09:00:58 -0700876
Jooyung Han888c5bc2020-12-22 17:28:47 +0900877bool AidlDefinedType::CheckValid(const AidlTypenames& typenames, DiagnosticsContext&) const {
Devin Moore24f68572020-02-26 13:20:59 -0800878 if (!AidlAnnotatable::CheckValid(typenames)) {
879 return false;
880 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900881 if (!CheckValidWithMembers(typenames)) {
882 return false;
883 }
Devin Moore24f68572020-02-26 13:20:59 -0800884 return true;
885}
886
Jeongik Cha997281d2020-01-16 15:23:59 +0900887bool AidlDefinedType::IsHidden() const {
888 return HasHideComment(GetComments());
889}
890
Steven Moreland787b0432018-07-03 09:00:58 -0700891std::string AidlDefinedType::GetCanonicalName() const {
892 if (package_.empty()) {
893 return GetName();
894 }
895 return GetPackage() + "." + GetName();
896}
897
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800898void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
899 if (this->IsHidden()) {
900 AddHideComment(writer);
901 }
902 DumpAnnotations(writer);
903}
904
Jooyung Han829ec7c2020-12-02 12:07:36 +0900905bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
906 bool success = true;
907
908 for (const auto& v : GetFields()) {
909 const bool field_valid = v->CheckValid(typenames);
910 success = success && field_valid;
911 }
912
913 // field names should be unique
914 std::set<std::string> fieldnames;
915 for (const auto& v : GetFields()) {
916 bool duplicated = !fieldnames.emplace(v->GetName()).second;
917 if (duplicated) {
918 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
919 success = false;
920 }
921 }
922
923 // immutable parcelables should have immutable fields.
924 if (IsJavaOnlyImmutable()) {
925 for (const auto& v : GetFields()) {
926 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
927 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
928 << "non-immutable field named '" << v->GetName() << "'.";
929 success = false;
930 }
931 }
932 }
933
934 set<string> constant_names;
935 for (const auto& constant : GetConstantDeclarations()) {
936 if (constant_names.count(constant->GetName()) > 0) {
937 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
938 success = false;
939 }
940 constant_names.insert(constant->GetName());
941 success = success && constant->CheckValid(typenames);
942 }
943
944 return success;
945}
946
947bool AidlDefinedType::CheckValidForGetterNames() const {
948 bool success = true;
949 std::set<std::string> getters;
950 for (const auto& v : GetFields()) {
951 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
952 if (duplicated) {
953 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
954 << "' after capitalizing the first letter";
955 success = false;
956 }
957 }
958 return success;
959}
960
Jiyong Park18132182020-06-08 20:24:40 +0900961AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
962 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900963 const std::string& cpp_header, std::vector<std::string>* type_params,
964 std::vector<std::unique_ptr<AidlMember>>* members)
965 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900966 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800967 cpp_header_(cpp_header) {
968 // Strip off quotation marks if we actually have a cpp header.
969 if (cpp_header_.length() >= 2) {
970 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
971 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700972}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900973template <typename T>
974AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
975 // Copying is not supported if it has type parameters.
976 // It doesn't make a problem because only ArrayBase() makes a copy,
977 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +0000978 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900979}
980
981template <typename T>
982bool AidlParameterizable<T>::CheckValid() const {
983 return true;
984};
985
986template <>
987bool AidlParameterizable<std::string>::CheckValid() const {
988 if (!IsGeneric()) {
989 return true;
990 }
991 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
992 if (set.size() != GetTypeParameters().size()) {
993 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
994 return false;
995 }
996 return true;
997}
Casey Dahlin59401da2015-10-09 18:16:45 -0700998
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700999std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +09001000 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +09001001 AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE,
Jeongik Chad0a10272020-08-06 16:33:36 +09001002 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE};
Devin Moore24f68572020-02-26 13:20:59 -08001003}
1004
Jooyung Han888c5bc2020-12-22 17:28:47 +09001005bool AidlParcelable::CheckValid(const AidlTypenames& typenames, DiagnosticsContext& diag) const {
1006 if (!AidlDefinedType::CheckValid(typenames, diag)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001007 return false;
1008 }
Jeongik Chadf76dc72019-11-28 00:08:47 +09001009 if (!AidlParameterizable<std::string>::CheckValid()) {
1010 return false;
1011 }
Jeongik Cha82317dd2019-02-27 20:26:11 +09001012
1013 return true;
1014}
1015
Jeongik Cha997281d2020-01-16 15:23:59 +09001016void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001017 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001018 writer->Write("parcelable %s ;\n", GetName().c_str());
1019}
1020
Steven Moreland5557f1c2018-07-02 13:50:23 -07001021AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001022 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001023 const std::string& comments, std::vector<std::string>* type_params,
1024 std::vector<std::unique_ptr<AidlMember>>* members)
1025 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001026
Jeongik Cha997281d2020-01-16 15:23:59 +09001027void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001028 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001029 writer->Write("parcelable %s {\n", GetName().c_str());
1030 writer->Indent();
1031 for (const auto& field : GetFields()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001032 if (field->GetType().IsHidden()) {
1033 AddHideComment(writer);
1034 }
Jiyong Parka468e2a2018-08-29 21:25:18 +09001035 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001036 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001037 for (const auto& constdecl : GetConstantDeclarations()) {
1038 if (constdecl->GetType().IsHidden()) {
1039 AddHideComment(writer);
1040 }
1041 writer->Write("%s;\n", constdecl->ToString().c_str());
1042 }
Jiyong Park02da7422018-07-16 16:00:26 +09001043 writer->Dedent();
1044 writer->Write("}\n");
1045}
1046
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001047std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +09001048 return {AidlAnnotation::Type::VINTF_STABILITY,
1049 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
1050 AidlAnnotation::Type::HIDE,
1051 AidlAnnotation::Type::JAVA_PASSTHROUGH,
Jooyung Han90345002020-10-23 15:28:53 +09001052 AidlAnnotation::Type::JAVA_DERIVE,
Devin Moorec7e47a32020-08-07 10:55:25 -07001053 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
Andrei Homescue61feb52020-08-18 15:44:24 -07001054 AidlAnnotation::Type::FIXED_SIZE,
1055 AidlAnnotation::Type::RUST_DERIVE};
Devin Moore24f68572020-02-26 13:20:59 -08001056}
1057
Jooyung Han888c5bc2020-12-22 17:28:47 +09001058bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames,
1059 DiagnosticsContext& diag) const {
1060 if (!AidlParcelable::CheckValid(typenames, diag)) {
Devin Moore24f68572020-02-26 13:20:59 -08001061 return false;
1062 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001063
Jooyung Han59af9cc2020-10-25 21:44:14 +09001064 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001065
Jooyung Hand4057c42020-10-23 13:28:22 +09001066 if (IsFixedSize()) {
1067 for (const auto& v : GetFields()) {
1068 if (!typenames.CanBeFixedSize(v->GetType())) {
1069 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1070 << "non-fixed size field named " << v->GetName() << ".";
1071 success = false;
1072 }
1073 }
1074 }
1075
1076 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001077 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001078 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001079 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001080 }
1081 }
1082
Daniel Norman85aed542019-08-21 12:01:14 -07001083 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001084}
1085
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001086// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001087bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1088 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001089 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1090 GetName() == "IBinder") {
1091 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1092 << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001093 return false;
1094 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001095 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1096 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1097 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001098 return false;
1099 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001100 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1101 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001102 if (GetName() == "ParcelFileDescriptor") {
Andrei Homescub62afd92020-05-11 19:24:59 -07001103 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1104 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001105 return false;
1106 }
1107
Steven Morelandd59e3172020-05-11 16:42:09 -07001108 const auto defined_type = typenames.TryGetDefinedType(GetName());
1109 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Andrei Homescub62afd92020-05-11 19:24:59 -07001110 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1111 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001112 return false;
1113 }
1114 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001115 if (this->GetName() == "FileDescriptor" &&
1116 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1117 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << Options::LanguageToString(lang)
1118 << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001119 return false;
1120 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001121 if (this->IsGeneric()) {
1122 if (this->GetName() == "List") {
Jooyung Han55f96ad2020-12-13 10:08:33 +09001123 if (lang == Options::Language::NDK) {
1124 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1125 const string& contained_type_name = contained_type.GetName();
Jooyung Hane87cdd02020-12-11 16:47:35 +09001126 if (typenames.GetInterface(contained_type)) {
1127 AIDL_ERROR(this) << "List<" << contained_type_name
1128 << "> is not supported. List in NDK doesn't support interface.";
1129 return false;
1130 }
1131 if (contained_type_name == "IBinder") {
1132 AIDL_ERROR(this) << "List<" << contained_type_name
1133 << "> is not supported. List in NDK doesn't support IBinder.";
1134 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001135 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001136 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001137 }
1138 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001139
1140 if (this->IsArray()) {
1141 if (this->GetName() == "List" || this->GetName() == "Map" ||
1142 this->GetName() == "CharSequence") {
1143 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001144 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001145 }
1146 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001147
1148 if (lang != Options::Language::JAVA) {
1149 if (this->GetName() == "List" && !this->IsGeneric()) {
1150 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1151 return false;
1152 }
1153 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1154 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1155 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001156 }
1157 }
1158
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001159 return true;
1160}
1161
1162// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001163bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1164 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001165 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001166 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1167 if (unstructured_parcelable != nullptr) {
1168 if (unstructured_parcelable->GetCppHeader().empty()) {
1169 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001170 << "Unstructured parcelable must have C++ header defined.";
1171 return false;
1172 }
1173 }
1174 }
1175 return true;
1176}
1177
1178// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001179bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1180 Options::Language lang) const {
1181 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001182 return false;
1183 }
1184 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001185 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001186 return false;
1187 }
1188 }
1189 return true;
1190}
1191
Daniel Norman85aed542019-08-21 12:01:14 -07001192AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -07001193 AidlConstantValue* value, const std::string& comments)
Jooyung Han29813842020-12-08 01:28:03 +09001194 : AidlNode(location),
1195 name_(name),
1196 value_(value),
1197 comments_(comments),
1198 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001199
1200bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1201 if (GetValue() == nullptr) {
1202 return false;
1203 }
1204 if (!GetValue()->CheckValid()) {
1205 return false;
1206 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001207 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001208 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1209 return false;
1210 }
1211 return true;
1212}
1213
1214string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1215 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001216 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001217}
1218
1219AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1220 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jiyong Park18132182020-06-08 20:24:40 +09001221 const std::string& package, const std::string& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001222 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001223 enumerators_(std::move(*enumerators)) {
1224 Autofill();
1225}
Daniel Norman85aed542019-08-21 12:01:14 -07001226
1227void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
1228 backing_type_ = std::move(type);
1229}
1230
Jooyung Han29813842020-12-08 01:28:03 +09001231void AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -07001232 const AidlEnumerator* previous = nullptr;
1233 for (const auto& enumerator : enumerators_) {
1234 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001235 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001236 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001237 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001238 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001239 } else {
Jooyung Han29813842020-12-08 01:28:03 +09001240 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName(), "");
Daniel Normanb28684e2019-10-17 15:31:39 -07001241 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001242 loc, std::move(prev_value), "+",
1243 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001244 }
1245 }
1246 previous = enumerator.get();
1247 }
1248}
1249
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001250std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
1251 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::BACKING,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +09001252 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -08001253}
1254
Jooyung Han888c5bc2020-12-22 17:28:47 +09001255bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames,
1256 DiagnosticsContext& diag) const {
1257 if (!AidlDefinedType::CheckValid(typenames, diag)) {
Devin Moore24f68572020-02-26 13:20:59 -08001258 return false;
1259 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001260 if (!GetMembers().empty()) {
1261 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1262 return false;
1263 }
Daniel Norman85aed542019-08-21 12:01:14 -07001264 if (backing_type_ == nullptr) {
1265 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1266 return false;
1267 }
1268 bool success = true;
1269 for (const auto& enumerator : enumerators_) {
1270 success = success && enumerator->CheckValid(GetBackingType());
1271 }
Jooyung Han3b990182020-12-22 17:44:31 +09001272
Steven Moreland26318532020-12-23 20:08:36 +00001273 if (!success) return false; // ValueString requires valid type
1274
Jooyung Han3b990182020-12-22 17:44:31 +09001275 AIDL_FATAL_IF(GetEnumerators().empty(), this)
1276 << "The enum '" << GetName() << "' has no enumerators.";
1277
1278 const auto& first = GetEnumerators()[0];
1279 if (auto first_value = first->ValueString(GetBackingType(), AidlConstantValueDecorator);
1280 first_value != "0") {
1281 diag.Report(first->GetLocation(), DiagnosticID::enum_zero)
1282 << "The first enumerator '" << first->GetName() << "' should be 0, but it is "
1283 << first_value << ".";
1284 }
1285
Steven Moreland26318532020-12-23 20:08:36 +00001286 return true;
Daniel Norman85aed542019-08-21 12:01:14 -07001287}
1288
Jeongik Cha997281d2020-01-16 15:23:59 +09001289void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001290 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001291 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -07001292 writer->Indent();
1293 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001294 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1295 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1296 }
1297 writer->Dedent();
1298 writer->Write("}\n");
1299}
1300
Jooyung Han2946afc2020-10-05 20:29:16 +09001301AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1302 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001303 std::vector<std::string>* type_params,
1304 std::vector<std::unique_ptr<AidlMember>>* members)
1305 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001306
1307std::set<AidlAnnotation::Type> AidlUnionDecl::GetSupportedAnnotations() const {
Jooyung Hanf93b5bd2020-10-28 15:12:08 +09001308 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::HIDE,
1309 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_DERIVE,
1310 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, AidlAnnotation::Type::RUST_DERIVE};
Jooyung Han2946afc2020-10-05 20:29:16 +09001311}
1312
1313void AidlUnionDecl::Dump(CodeWriter* writer) const {
1314 DumpHeader(writer);
1315 writer->Write("union %s {\n", GetName().c_str());
1316 writer->Indent();
1317 for (const auto& field : GetFields()) {
1318 if (field->GetType().IsHidden()) {
1319 AddHideComment(writer);
1320 }
1321 writer->Write("%s;\n", field->ToString().c_str());
1322 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001323 for (const auto& constdecl : GetConstantDeclarations()) {
1324 if (constdecl->GetType().IsHidden()) {
1325 AddHideComment(writer);
1326 }
1327 writer->Write("%s;\n", constdecl->ToString().c_str());
1328 }
Jooyung Han2946afc2020-10-05 20:29:16 +09001329 writer->Dedent();
1330 writer->Write("}\n");
1331}
1332
Jooyung Han888c5bc2020-12-22 17:28:47 +09001333bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames, DiagnosticsContext& diag) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001334 // visit parents
Jooyung Han888c5bc2020-12-22 17:28:47 +09001335 if (!AidlParcelable::CheckValid(typenames, diag)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001336 return false;
1337 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001338
1339 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001340 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001341 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001342 }
1343
1344 // now, visit self!
1345 bool success = true;
1346
1347 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1348 for (const auto& v : GetFields()) {
1349 if (v->GetType().GetName() == "ParcelableHolder") {
1350 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1351 success = false;
1352 }
1353 }
1354
Jooyung Hanfe89f122020-10-14 03:49:18 +09001355 if (GetFields().empty()) {
1356 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1357 return false;
1358 }
1359
Jooyung Han53fb4242020-12-17 16:03:49 +09001360 // first member should have useful default value (implicit or explicit)
1361 const auto& first = GetFields()[0];
1362 if (!first->HasUsefulDefaultValue()) {
1363 // Most types can be initialized without a default value. For example,
1364 // interface types are inherently nullable. But, enum types should have
1365 // an explicit default value.
1366 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1367 AIDL_ERROR(first)
1368 << "The union's first member should have a useful default value. Enum types can be "
1369 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1370 return false;
1371 }
1372 // In Java, array types are initialized as null without a default value. To be sure that default
1373 // initialized unions are accepted by other backends we require arrays also have a default
1374 // value.
1375 if (first->GetType().IsArray()) {
1376 AIDL_ERROR(first)
1377 << "The union's first member should have a useful default value. Arrays can be "
1378 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1379 return false;
1380 }
1381 }
1382
Jooyung Hanfe89f122020-10-14 03:49:18 +09001383 return success;
1384}
1385
1386// TODO: we should treat every backend all the same in future.
1387bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1388 Options::Language lang) const {
1389 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1390 return false;
1391 }
1392 for (const auto& v : this->GetFields()) {
1393 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1394 return false;
1395 }
1396 }
1397 return true;
1398}
1399
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001400// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001401bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1402 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001403 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001404 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001405 return false;
1406 }
1407 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001408 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001409 return false;
1410 }
1411 }
1412 }
1413 return true;
1414}
1415
Steven Moreland46e9da82018-07-27 15:45:29 -07001416AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001417 const std::string& comments, bool oneway, const std::string& package,
1418 std::vector<std::unique_ptr<AidlMember>>* members)
1419 : AidlDefinedType(location, name, comments, package, members) {
1420 for (auto& m : GetMethods()) {
1421 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001422 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001423}
1424
Jeongik Cha997281d2020-01-16 15:23:59 +09001425void AidlInterface::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001426 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001427 writer->Write("interface %s {\n", GetName().c_str());
1428 writer->Indent();
1429 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001430 if (method->IsHidden()) {
1431 AddHideComment(writer);
1432 }
Jiyong Park309668e2018-07-28 16:55:44 +09001433 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001434 }
Jiyong Parka428d212018-08-29 22:26:30 +09001435 for (const auto& constdecl : GetConstantDeclarations()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001436 if (constdecl->GetType().IsHidden()) {
1437 AddHideComment(writer);
1438 }
Jiyong Parka428d212018-08-29 22:26:30 +09001439 writer->Write("%s;\n", constdecl->ToString().c_str());
1440 }
Jiyong Park02da7422018-07-16 16:00:26 +09001441 writer->Dedent();
1442 writer->Write("}\n");
1443}
1444
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001445std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
Steven Morelanda7764e52020-10-27 17:29:29 +00001446 return {AidlAnnotation::Type::SENSITIVE_DATA, AidlAnnotation::Type::VINTF_STABILITY,
1447 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
1448 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::DESCRIPTOR};
Devin Moore24f68572020-02-26 13:20:59 -08001449}
1450
Jooyung Han888c5bc2020-12-22 17:28:47 +09001451bool AidlInterface::CheckValid(const AidlTypenames& typenames, DiagnosticsContext& diag) const {
1452 if (!AidlDefinedType::CheckValid(typenames, diag)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001453 return false;
1454 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001455 // Has to be a pointer due to deleting copy constructor. No idea why.
1456 map<string, const AidlMethod*> method_names;
1457 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001458 if (!m->GetType().CheckValid(typenames)) {
1459 return false;
1460 }
1461
Jeongik Cha649e8a72020-03-27 17:47:40 +09001462 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1463 if (m->GetType().GetName() == "ParcelableHolder") {
1464 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1465 return false;
1466 }
Steven Morelandacd53472018-12-14 10:17:26 -08001467 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001468 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1469 return false;
1470 }
1471
1472 set<string> argument_names;
1473 for (const auto& arg : m->GetArguments()) {
1474 auto it = argument_names.find(arg->GetName());
1475 if (it != argument_names.end()) {
1476 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1477 << arg->GetName() << "'";
1478 return false;
1479 }
1480 argument_names.insert(arg->GetName());
1481
1482 if (!arg->GetType().CheckValid(typenames)) {
1483 return false;
1484 }
1485
Jeongik Cha649e8a72020-03-27 17:47:40 +09001486 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1487 if (arg->GetType().GetName() == "ParcelableHolder") {
1488 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1489 return false;
1490 }
Steven Morelandacd53472018-12-14 10:17:26 -08001491 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001492 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1493 return false;
1494 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001495
1496 const auto [can_be_out, type_aspect] = typenames.CanBeOutParameter(arg->GetType());
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001497 if (!arg->DirectionWasSpecified() && can_be_out) {
Jooyung Han965e31d2020-11-27 12:30:16 +09001498 AIDL_ERROR(arg) << "'" << arg->GetType().Signature()
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001499 << "' can be an out type, so you must declare it as in, out, or inout.";
1500 return false;
1501 }
1502
1503 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
Jooyung Han15fd6c62020-10-23 13:54:46 +09001504 AIDL_ERROR(arg) << "'" << arg->GetName() << "' can't be an " << arg->GetDirectionSpecifier()
1505 << " parameter because " << type_aspect << " can only be an in parameter.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001506 return false;
1507 }
1508
1509 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001510 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001511 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1512 return false;
1513 }
1514
1515 // Reserve a namespace for internal use
1516 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1517 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1518 return false;
1519 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001520 }
1521
1522 auto it = method_names.find(m->GetName());
1523 // prevent duplicate methods
1524 if (it == method_names.end()) {
1525 method_names[m->GetName()] = m.get();
1526 } else {
1527 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1528 AIDL_ERROR(it->second) << "previously defined here.";
1529 return false;
1530 }
1531
Paul Trautrimb77048c2020-01-21 16:39:32 +09001532 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001533 "getTransactionName(int)"};
1534
1535 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001536 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001537 return false;
1538 }
1539 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001540
1541 bool success = true;
1542 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001543 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001544 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001545 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001546 success = false;
1547 }
1548 constant_names.insert(constant->GetName());
1549 success = success && constant->CheckValid(typenames);
1550 }
1551
Jooyung Han888c5bc2020-12-22 17:28:47 +09001552 if (auto name = GetName(); name.size() < 1 || name[0] != 'I') {
1553 diag.Report(GetLocation(), DiagnosticID::interface_name)
1554 << "Interface names should start with I.";
1555 }
1556
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001557 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001558}
1559
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001560std::string AidlInterface::GetDescriptor() const {
1561 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1562 if (annotatedDescriptor != "") {
1563 return annotatedDescriptor;
1564 }
1565 return GetCanonicalName();
1566}
1567
Steven Moreland46e9da82018-07-27 15:45:29 -07001568AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1569 : AidlNode(location), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001570
1571// Resolves unresolved type name to fully qualified typename to import
1572// case #1: SimpleName --> import p.SimpleName
1573// case #2: Outer.Inner --> import p.Outer
1574// case #3: p.SimpleName --> (as is)
1575std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1576 std::string canonical_name;
1577 const auto first_dot = unresolved_name.find_first_of('.');
1578 const std::string class_name =
1579 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1580 for (const auto& import : Imports()) {
1581 const auto& fq_name = import->GetNeededClass();
1582 const auto last_dot = fq_name.find_last_of('.');
1583 const std::string imported_type_name =
1584 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1585 if (imported_type_name == class_name) {
1586 if (canonical_name != "" && canonical_name != fq_name) {
1587 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1588 return {};
1589 }
1590 canonical_name = fq_name;
1591 }
1592 }
1593 // if not found, use unresolved_name as it is
1594 if (canonical_name == "") {
1595 return unresolved_name;
1596 }
1597 return canonical_name;
Steven Moreland26318532020-12-23 20:08:36 +00001598}