blob: ed01066a10aa097f3427de34760590157f3c1573 [file] [log] [blame]
Will McVickerefd970d2019-09-25 15:28:30 -07001/*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinskiffa16862014-01-23 18:17:42 -080017#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +090018#include "aidl_typenames.h"
Jiyong Parke5c45292020-05-26 19:06:24 +090019#include "parser.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070020
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080022#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -070023#include <string.h>
Jiyong Park68bc77a2018-07-19 19:00:45 +090024#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +090025#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090026#include <set>
27#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070028#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090029#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070030
Steven Moreland1c4ba202018-08-09 10:49:54 -070031#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070032#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080033#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070034
Steven Moreland21780812020-09-11 01:29:45 +000035#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070036#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080037
Will McVickerd7d18df2019-09-12 13:40:50 -070038#include "aidl.h"
39
Casey Dahlin07b9dde2015-09-10 19:13:49 -070040#ifdef _WIN32
41int isatty(int fd)
42{
43 return (fd == 0);
44}
45#endif
46
Christopher Wiley4a2884b2015-10-07 11:27:45 -070047using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070048using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080049using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070050using std::cerr;
Jiyong Park1deecc32018-07-17 01:14:41 +090051using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090052using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070053using std::string;
54using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090055using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080056
Jeongik Cha047c5ee2019-08-07 23:16:49 +090057namespace {
Jeongik Cha997281d2020-01-16 15:23:59 +090058bool IsJavaKeyword(const char* str) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +090059 static const std::vector<std::string> kJavaKeywords{
60 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
61 "char", "class", "const", "continue", "default", "do", "double",
62 "else", "enum", "extends", "final", "finally", "float", "for",
63 "goto", "if", "implements", "import", "instanceof", "int", "interface",
64 "long", "native", "new", "package", "private", "protected", "public",
65 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
66 "this", "throw", "throws", "transient", "try", "void", "volatile",
67 "while", "true", "false", "null",
68 };
69 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
70}
Jeongik Cha997281d2020-01-16 15:23:59 +090071
72void AddHideComment(CodeWriter* writer) {
73 writer->Write("/* @hide */\n");
74}
75
76inline bool HasHideComment(const std::string& comment) {
77 return std::regex_search(comment, std::regex("@hide\\b"));
78}
Jeongik Cha047c5ee2019-08-07 23:16:49 +090079} // namespace
80
Devin Mooredf93ebb2020-03-25 14:03:35 -070081AidlLocation::AidlLocation(const std::string& file, Point begin, Point end, Source source)
82 : file_(file), begin_(begin), end_(end), source_(source) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070083
84std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
Devin Moore5de18ed2020-04-02 13:52:29 -070085 os << l.file_;
86 if (l.LocationKnown()) {
87 os << ":" << l.begin_.line << "." << l.begin_.column << "-";
88 if (l.begin_.line != l.end_.line) {
89 os << l.end_.line << ".";
90 }
91 os << l.end_.column;
Steven Moreland46e9da82018-07-27 15:45:29 -070092 }
Steven Moreland46e9da82018-07-27 15:45:29 -070093 return os;
94}
95
96AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
97
Mathew Inwoodadb74672019-11-29 14:01:53 +000098std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000099 std::stringstream ss;
100 ss << location_.file_ << ":" << location_.begin_.line;
101 return ss.str();
102}
103
Mathew Inwoodadb74672019-11-29 14:01:53 +0000104std::string AidlNode::PrintLocation() const {
105 std::stringstream ss;
106 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
107 << location_.end_.line << ":" << location_.end_.column;
108 return ss.str();
109}
110
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700111const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
112 static const std::vector<Schema> kSchemas{
Jooyung Hand902a972020-10-23 17:32:44 +0900113 {AidlAnnotation::Type::NULLABLE, "nullable", {}, false},
114 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}, false},
Steven Morelanda7764e52020-10-27 17:29:29 +0000115 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", {}, false},
Jooyung Hand902a972020-10-23 17:32:44 +0900116 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}, false},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700117 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
118 "UnsupportedAppUsage",
119 {{"expectedSignature", "String"},
120 {"implicitMember", "String"},
121 {"maxTargetSdk", "int"},
122 {"publicAlternatives", "String"},
Jooyung Hand902a972020-10-23 17:32:44 +0900123 {"trackingBug", "long"}},
124 false},
125 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}, false},
126 {AidlAnnotation::Type::HIDE, "Hide", {}, false},
127 {AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}, false},
128 {AidlAnnotation::Type::JAVA_PASSTHROUGH, "JavaPassthrough", {{"annotation", "String"}}, true},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900129 {AidlAnnotation::Type::JAVA_DERIVE,
130 "JavaDerive",
131 {{"toString", "boolean"},
132 {"equals", "boolean"}},
133 false},
Jooyung Hand902a972020-10-23 17:32:44 +0900134 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, "JavaOnlyImmutable", {}, false},
135 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", {}, false},
136 {AidlAnnotation::Type::DESCRIPTOR, "Descriptor", {{"value", "String"}}, false},
Andrei Homescue61feb52020-08-18 15:44:24 -0700137 {AidlAnnotation::Type::RUST_DERIVE,
138 "RustDerive",
139 {{"Copy", "boolean"},
140 {"Clone", "boolean"},
141 {"PartialOrd", "boolean"},
142 {"Ord", "boolean"},
143 {"PartialEq", "boolean"},
144 {"Eq", "boolean"},
Jooyung Hand902a972020-10-23 17:32:44 +0900145 {"Hash", "boolean"}},
146 false},
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
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700207 auto parameter_mapping_it = schema_.supported_parameters.find(param_name);
208 if (parameter_mapping_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
Andrei Onea9445fc62019-06-27 18:11:59 +0100234 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700235 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100236 // Assume error on empty string.
237 if (param_value == "") {
238 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
239 << GetName() << ".";
240 return false;
241 }
242 }
243 return true;
244}
245
246std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
247 const ConstantValueDecorator& decorator) const {
248 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100249 for (const auto& name_and_param : parameters_) {
250 const std::string& param_name = name_and_param.first;
251 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Devin Mooredecaf292020-04-30 09:16:40 -0700252 if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
253 std::ostringstream stream;
254 stream << "Parameter " << param_name << " not supported ";
255 stream << "for annotation " << GetName() << ". ";
256 stream << "It must be one of:";
257 for (const auto& kv : schema_.supported_parameters) {
258 stream << " " << kv.first;
259 }
260 AIDL_ERROR(this) << stream.str();
261 continue;
262 }
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700263 AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
264 nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700265 if (!param->CheckValid()) {
266 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
267 << GetName() << ".";
Devin Mooredecaf292020-04-30 09:16:40 -0700268 continue;
Will McVickerd7d18df2019-09-12 13:40:50 -0700269 }
270
271 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100272 }
273 return raw_params;
274}
Steven Moreland46e9da82018-07-27 15:45:29 -0700275
Jooyung Han965e31d2020-11-27 12:30:16 +0900276std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700277 if (parameters_.empty()) {
278 return "@" + GetName();
279 } else {
280 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900281 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700282 param_strings.emplace_back(name + "=" + value);
283 }
284 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
285 }
286}
287
Andrei Onea9445fc62019-06-27 18:11:59 +0100288static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700289 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100290 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700291 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900292 AIDL_FATAL_IF(a.Repeatable(), a)
293 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100294 return &a;
295 }
296 }
297 return nullptr;
298}
299
Steven Moreland46e9da82018-07-27 15:45:29 -0700300AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
301
Jiyong Park68bc77a2018-07-19 19:00:45 +0900302bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700303 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900304}
305
Jiyong Park68bc77a2018-07-19 19:00:45 +0900306bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700307 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900308}
309
Steven Morelanda7764e52020-10-27 17:29:29 +0000310bool AidlAnnotatable::IsSensitiveData() const {
311 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
312}
313
Steven Morelanda57d0a62019-07-30 09:41:14 -0700314bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700315 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700316}
317
Jeongik Chad0a10272020-08-06 16:33:36 +0900318bool AidlAnnotatable::IsJavaOnlyImmutable() const {
319 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900320}
321
Devin Moorec7e47a32020-08-07 10:55:25 -0700322bool AidlAnnotatable::IsFixedSize() const {
323 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
324}
325
Andrei Onea9445fc62019-06-27 18:11:59 +0100326const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700327 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900328}
329
Andrei Homescue61feb52020-08-18 15:44:24 -0700330const AidlAnnotation* AidlAnnotatable::RustDerive() const {
331 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
332}
333
Daniel Norman716d3112019-09-10 13:11:56 -0700334const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700335 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700336 if (annotation != nullptr) {
337 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
338 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
339 const string& type = it->second;
Steven Morelande7d5d082020-05-21 20:29:02 +0000340
341 AIDL_FATAL_IF(type.size() < 2, this) << type;
342 AIDL_FATAL_IF(type[0] != '"', this) << type;
343 AIDL_FATAL_IF(type[type.length() - 1] != '"', this) << type;
344 string unquoted_type = type.substr(1, type.length() - 2);
345
Daniel Norman716d3112019-09-10 13:11:56 -0700346 AidlTypeSpecifier* type_specifier =
Jooyung Han60b2fde2020-10-29 15:12:40 +0900347 new AidlTypeSpecifier(annotation->GetLocation(), unquoted_type, false, nullptr, "");
Daniel Norman716d3112019-09-10 13:11:56 -0700348 type_specifier->Resolve(typenames);
349 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700350 }
351 }
352 return nullptr;
353}
354
Jeongik Cha88f95a82020-01-15 13:02:16 +0900355bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700356 return lang == Options::Language::JAVA &&
357 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900358}
359
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800360bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700361 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800362}
363
Jooyung Han829ec7c2020-12-02 12:07:36 +0900364bool AidlAnnotatable::JavaDerive(const std::string& method) const {
365 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
366 if (annotation != nullptr) {
367 auto params = annotation->AnnotationParams(AidlConstantValueDecorator);
368 if (auto it = params.find(method); it != params.end()) {
369 return it->second == "true";
370 }
371 }
372 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900373}
374
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900375std::string AidlAnnotatable::GetDescriptor() const {
376 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
377 if (annotation != nullptr) {
378 auto params = annotation->AnnotationParams(AidlConstantValueDecorator);
379 if (auto it = params.find("value"); it != params.end()) {
380 const string& value = it->second;
381
382 AIDL_FATAL_IF(value.size() < 2, this) << value;
383 AIDL_FATAL_IF(value[0] != '"', this) << value;
384 AIDL_FATAL_IF(value[value.length() - 1] != '"', this) << value;
385 std::string unquoted_value = value.substr(1, value.length() - 2);
386 return unquoted_value;
387 }
388 }
389 return "";
390}
391
Steven Moreland7e4b9502020-02-20 18:10:42 -0800392void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
393 if (annotations_.empty()) return;
394
395 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
396}
397
Devin Moore24f68572020-02-26 13:20:59 -0800398bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700399 std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
Andrei Onea9445fc62019-06-27 18:11:59 +0100400 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900401 // check if it is allowed for this node
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700402 if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900403 std::vector<std::string> supported_annot_strings;
404 for (AidlAnnotation::Type type : supported_annotations) {
405 supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
406 }
Devin Moore24f68572020-02-26 13:20:59 -0800407 AIDL_ERROR(this) << "'" << annotation.GetName()
408 << "' is not a supported annotation for this node. "
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700409 << "It must be one of: "
410 << android::base::Join(supported_annot_strings, ", ");
Devin Moore24f68572020-02-26 13:20:59 -0800411 return false;
412 }
Jooyung Hand902a972020-10-23 17:32:44 +0900413 // CheckValid() only if it is okay to be here
414 if (!annotation.CheckValid()) {
415 return false;
416 }
417 }
418
419 std::map<AidlAnnotation::Type, AidlLocation> declared;
420 for (const auto& annotation : GetAnnotations()) {
421 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
422 if (!inserted && !annotation.Repeatable()) {
423 AIDL_ERROR(this) << "'" << annotation.GetName()
424 << "' is repeated, but not allowed. Previous location: " << iter->second;
425 return false;
426 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100427 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700428
Andrei Onea9445fc62019-06-27 18:11:59 +0100429 return true;
430}
431
Jiyong Park68bc77a2018-07-19 19:00:45 +0900432string AidlAnnotatable::ToString() const {
433 vector<string> ret;
434 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900435 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900436 }
437 std::sort(ret.begin(), ret.end());
438 return Join(ret, " ");
439}
440
Steven Moreland46e9da82018-07-27 15:45:29 -0700441AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
442 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900443 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700444 const string& comments)
445 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900446 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700447 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700448 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900449 comments_(comments),
450 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700451
Jooyung Hand2fa0232020-10-19 02:51:41 +0900452const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700453 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900454 // Declaring array of generic type cannot happen, it is grammar error.
455 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700456
Jooyung Hand2fa0232020-10-19 02:51:41 +0900457 if (!array_base_) {
458 array_base_.reset(new AidlTypeSpecifier(*this));
459 array_base_->is_array_ = false;
460 }
461 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700462}
463
Jeongik Cha997281d2020-01-16 15:23:59 +0900464bool AidlTypeSpecifier::IsHidden() const {
465 return HasHideComment(GetComments());
466}
467
Jooyung Han965e31d2020-11-27 12:30:16 +0900468string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900469 string ret = GetName();
470 if (IsGeneric()) {
471 vector<string> arg_names;
472 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900473 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900474 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900475 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900476 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900477 if (IsArray()) {
478 ret += "[]";
479 }
480 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900481}
482
Jooyung Han965e31d2020-11-27 12:30:16 +0900483string AidlTypeSpecifier::ToString() const {
484 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900485 string annotations = AidlAnnotatable::ToString();
486 if (annotations != "") {
487 ret = annotations + " " + ret;
488 }
489 return ret;
490}
491
Daniel Norman716d3112019-09-10 13:11:56 -0700492bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland21780812020-09-11 01:29:45 +0000493 AIDL_FATAL_IF(IsResolved(), this);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700494 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
495 if (result.is_resolved) {
496 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900497 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900498 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900499 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700500 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700501}
502
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900503const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
504 return defined_type_;
505}
506
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700507std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
Devin Moore24f68572020-02-26 13:20:59 -0800508 // kHide and kUnsupportedAppUsage are both method return annotations
509 // which we don't distinguish from other type specifiers.
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700510 return {AidlAnnotation::Type::NULLABLE, AidlAnnotation::Type::UTF8_IN_CPP,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900511 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
512 AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -0800513}
514
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900515bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800516 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100517 return false;
518 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900519 if (IsGeneric()) {
520 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900521
522 auto& types = GetTypeParameters();
523 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
524 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900525 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
526 return (typenames.GetEnumDeclaration(*type_ptr)) ||
527 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
Jeongik Chae74c86d2019-12-12 16:54:03 +0900528 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700529 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900530 return false;
531 }
532 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800533 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900534 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800535 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
536 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900537 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800538 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900539 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800540 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900541 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000542 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900543 return false;
544 }
545 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800546 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900547 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900548 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900549 return false;
550 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800551 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900552 const string& key_type = GetTypeParameters()[0]->GetName();
553 if (key_type != "String") {
554 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
555 << "'" << key_type << "'";
556 return false;
557 }
558 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800559 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900560 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800561 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900562 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800563 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900564 return false;
565 }
566 } else {
567 AIDL_ERROR(this) << type_name << " is not a generic type.";
568 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900569 }
570 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900571
Steven Moreland11cb9452020-01-21 16:56:58 -0800572 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
573 GetTypeParameters().size() == 1 &&
574 GetTypeParameters()[0]->GetName() == "String";
575 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
576 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
577 return false;
578 }
579
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900580 if (GetName() == "void") {
581 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
582 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
583 return false;
584 }
585 }
586
587 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800588 const auto defined_type = typenames.TryGetDefinedType(GetName());
589 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900590 AIDL_ERROR(this) << "Binder type cannot be an array";
591 return false;
592 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000593 if (GetName() == "ParcelableHolder") {
594 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
595 return false;
596 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900597 }
598
599 if (IsNullable()) {
600 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
601 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
602 return false;
603 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800604 const auto defined_type = typenames.TryGetDefinedType(GetName());
605 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700606 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
607 return false;
608 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900609 if (GetName() == "ParcelableHolder") {
610 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
611 return false;
612 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900613 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900614 return true;
615}
616
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900617std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700618 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900619 if (type.IsArray()) {
620 return raw_value;
621 }
622
623 if (auto defined_type = type.GetDefinedType(); defined_type) {
624 auto enum_type = defined_type->AsEnumDeclaration();
625 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
626 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
627 }
Steven Moreland860b1942018-08-16 14:59:28 -0700628 return raw_value;
629}
630
Steven Moreland46e9da82018-07-27 15:45:29 -0700631AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
632 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000633 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
634 default_user_specified_ = false;
635}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700636
Steven Moreland46e9da82018-07-27 15:45:29 -0700637AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
638 AidlTypeSpecifier* type, const std::string& name,
639 AidlConstantValue* default_value)
Jooyung Han3f347ca2020-12-01 12:41:50 +0900640 : AidlMember(location),
Steven Moreland541788d2020-05-21 22:05:52 +0000641 type_(type),
642 name_(name),
643 default_user_specified_(true),
644 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700645
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900646bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700647 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900648 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900649
Steven Moreland54be7bd2019-12-05 11:17:53 -0800650 if (type_->GetName() == "void") {
651 AIDL_ERROR(this) << "Declaration " << name_
652 << " is void, but declarations cannot be of void type.";
653 valid = false;
654 }
655
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900656 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700657 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700658
Steven Moreland25294322018-08-07 18:13:55 -0700659 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700660
Steven Moreland860b1942018-08-16 14:59:28 -0700661 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700662}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700663
Jooyung Hanacae85d2020-10-28 16:39:09 +0900664string AidlVariableDeclaration::GetCapitalizedName() const {
665 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
666 string str = name_;
667 str[0] = static_cast<char>(toupper(str[0]));
668 return str;
669}
670
Steven Moreland5557f1c2018-07-02 13:50:23 -0700671string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900672 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000673 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700674 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700675 }
676 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700677}
678
Jiyong Park02da7422018-07-16 16:00:26 +0900679string AidlVariableDeclaration::Signature() const {
680 return type_->Signature() + " " + name_;
681}
682
Steven Moreland860b1942018-08-16 14:59:28 -0700683std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900684 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700685 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900686 } else {
687 return "";
688 }
Steven Moreland25294322018-08-07 18:13:55 -0700689}
690
Steven Moreland46e9da82018-07-27 15:45:29 -0700691AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
692 AidlTypeSpecifier* type, const std::string& name)
693 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700694 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700695 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700696
Steven Moreland46e9da82018-07-27 15:45:29 -0700697AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
698 const std::string& name)
699 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700700 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700701 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700702
Jiyong Park02da7422018-07-16 16:00:26 +0900703string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700704 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700705 if (direction_specified_) {
706 switch(direction_) {
707 case AidlArgument::IN_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700708 ret += "in";
Casey Dahlinc378c992015-09-29 16:50:40 -0700709 break;
710 case AidlArgument::OUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700711 ret += "out";
Casey Dahlinc378c992015-09-29 16:50:40 -0700712 break;
713 case AidlArgument::INOUT_DIR:
Devin Mooreeccdb902020-03-24 16:22:40 -0700714 ret += "inout";
Casey Dahlinc378c992015-09-29 16:50:40 -0700715 break;
716 }
717 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700718 return ret;
719}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700720
Jiyong Park02da7422018-07-16 16:00:26 +0900721string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700722 if (direction_specified_) {
723 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
724 } else {
725 return AidlVariableDeclaration::ToString();
726 }
Jiyong Park02da7422018-07-16 16:00:26 +0900727}
728
Steven Moreland46e9da82018-07-27 15:45:29 -0700729AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
730
Steven Moreland46e9da82018-07-27 15:45:29 -0700731AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
732 AidlTypeSpecifier* type, const std::string& name,
733 AidlConstantValue* value)
734 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700735
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900736bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700737 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900738 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700739 valid &= value_->CheckValid();
740 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700741
Steven Morelande689da22020-11-10 02:06:30 +0000742 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900743 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
744 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700745 return false;
746 }
747
Will McVickerd7d18df2019-09-12 13:40:50 -0700748 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700749}
750
Jiyong Parka428d212018-08-29 22:26:30 +0900751string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900752 return "const " + type_->ToString() + " " + name_ + " = " +
753 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900754}
755
756string AidlConstantDeclaration::Signature() const {
757 return type_->Signature() + " " + name_;
758}
759
Steven Moreland46e9da82018-07-27 15:45:29 -0700760AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
761 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900762 const std::string& comments)
763 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
764 has_id_ = false;
765}
766
767AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
768 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900769 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700770 : AidlMember(location),
771 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700772 comments_(comments),
773 type_(type),
774 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700775 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900776 id_(id),
777 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700778 has_id_ = true;
779 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700780 for (const unique_ptr<AidlArgument>& a : arguments_) {
781 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
782 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
783 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700784}
785
Jeongik Cha997281d2020-01-16 15:23:59 +0900786bool AidlMethod::IsHidden() const {
787 return HasHideComment(GetComments());
788}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700789
Jiyong Park02da7422018-07-16 16:00:26 +0900790string AidlMethod::Signature() const {
791 vector<string> arg_signatures;
792 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900793 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900794 }
Jiyong Park309668e2018-07-28 16:55:44 +0900795 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
796}
797
798string AidlMethod::ToString() const {
799 vector<string> arg_strings;
800 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900801 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900802 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900803 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800804 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900805 if (HasId()) {
806 ret += " = " + std::to_string(GetId());
807 }
808 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900809}
810
Steven Moreland46e9da82018-07-27 15:45:29 -0700811AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900812 const std::string& comments, const std::string& package,
813 std::vector<std::unique_ptr<AidlMember>>* members)
Jiyong Park18132182020-06-08 20:24:40 +0900814 : AidlAnnotatable(location),
815 name_(name),
816 comments_(comments),
817 package_(package),
818 split_package_(package.empty() ? std::vector<std::string>()
Jooyung Han829ec7c2020-12-02 12:07:36 +0900819 : android::base::Split(package, ".")) {
820 if (members) {
821 for (auto& m : *members) {
822 if (auto constant = m->AsConstantDeclaration(); constant) {
823 constants_.emplace_back(constant);
824 } else if (auto variable = m->AsVariableDeclaration(); variable) {
825 variables_.emplace_back(variable);
826 } else if (auto method = m->AsMethod(); method) {
827 methods_.emplace_back(method);
828 } else {
829 AIDL_FATAL(*m);
830 }
831 members_.push_back(m.release());
832 }
833 delete members;
834 }
835}
Steven Moreland787b0432018-07-03 09:00:58 -0700836
Devin Moore24f68572020-02-26 13:20:59 -0800837bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
838 if (!AidlAnnotatable::CheckValid(typenames)) {
839 return false;
840 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900841 if (!CheckValidWithMembers(typenames)) {
842 return false;
843 }
Devin Moore24f68572020-02-26 13:20:59 -0800844 return true;
845}
846
Jeongik Cha997281d2020-01-16 15:23:59 +0900847bool AidlDefinedType::IsHidden() const {
848 return HasHideComment(GetComments());
849}
850
Steven Moreland787b0432018-07-03 09:00:58 -0700851std::string AidlDefinedType::GetCanonicalName() const {
852 if (package_.empty()) {
853 return GetName();
854 }
855 return GetPackage() + "." + GetName();
856}
857
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800858void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
859 if (this->IsHidden()) {
860 AddHideComment(writer);
861 }
862 DumpAnnotations(writer);
863}
864
Jooyung Han829ec7c2020-12-02 12:07:36 +0900865bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
866 bool success = true;
867
868 for (const auto& v : GetFields()) {
869 const bool field_valid = v->CheckValid(typenames);
870 success = success && field_valid;
871 }
872
873 // field names should be unique
874 std::set<std::string> fieldnames;
875 for (const auto& v : GetFields()) {
876 bool duplicated = !fieldnames.emplace(v->GetName()).second;
877 if (duplicated) {
878 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
879 success = false;
880 }
881 }
882
883 // immutable parcelables should have immutable fields.
884 if (IsJavaOnlyImmutable()) {
885 for (const auto& v : GetFields()) {
886 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
887 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
888 << "non-immutable field named '" << v->GetName() << "'.";
889 success = false;
890 }
891 }
892 }
893
894 set<string> constant_names;
895 for (const auto& constant : GetConstantDeclarations()) {
896 if (constant_names.count(constant->GetName()) > 0) {
897 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
898 success = false;
899 }
900 constant_names.insert(constant->GetName());
901 success = success && constant->CheckValid(typenames);
902 }
903
904 return success;
905}
906
907bool AidlDefinedType::CheckValidForGetterNames() const {
908 bool success = true;
909 std::set<std::string> getters;
910 for (const auto& v : GetFields()) {
911 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
912 if (duplicated) {
913 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
914 << "' after capitalizing the first letter";
915 success = false;
916 }
917 }
918 return success;
919}
920
Jiyong Park18132182020-06-08 20:24:40 +0900921AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
922 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900923 const std::string& cpp_header, std::vector<std::string>* type_params,
924 std::vector<std::unique_ptr<AidlMember>>* members)
925 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900926 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800927 cpp_header_(cpp_header) {
928 // Strip off quotation marks if we actually have a cpp header.
929 if (cpp_header_.length() >= 2) {
930 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
931 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700932}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900933template <typename T>
934AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
935 // Copying is not supported if it has type parameters.
936 // It doesn't make a problem because only ArrayBase() makes a copy,
937 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +0000938 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900939}
940
941template <typename T>
942bool AidlParameterizable<T>::CheckValid() const {
943 return true;
944};
945
946template <>
947bool AidlParameterizable<std::string>::CheckValid() const {
948 if (!IsGeneric()) {
949 return true;
950 }
951 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
952 if (set.size() != GetTypeParameters().size()) {
953 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
954 return false;
955 }
956 return true;
957}
Casey Dahlin59401da2015-10-09 18:16:45 -0700958
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700959std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900960 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900961 AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE,
Jeongik Chad0a10272020-08-06 16:33:36 +0900962 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE};
Devin Moore24f68572020-02-26 13:20:59 -0800963}
964
965bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
966 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100967 return false;
968 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900969 if (!AidlParameterizable<std::string>::CheckValid()) {
970 return false;
971 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900972
973 return true;
974}
975
Jeongik Cha997281d2020-01-16 15:23:59 +0900976void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800977 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900978 writer->Write("parcelable %s ;\n", GetName().c_str());
979}
980
Steven Moreland5557f1c2018-07-02 13:50:23 -0700981AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +0900982 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900983 const std::string& comments, std::vector<std::string>* type_params,
984 std::vector<std::unique_ptr<AidlMember>>* members)
985 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700986
Jeongik Cha997281d2020-01-16 15:23:59 +0900987void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -0800988 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900989 writer->Write("parcelable %s {\n", GetName().c_str());
990 writer->Indent();
991 for (const auto& field : GetFields()) {
Jeongik Cha997281d2020-01-16 15:23:59 +0900992 if (field->GetType().IsHidden()) {
993 AddHideComment(writer);
994 }
Jiyong Parka468e2a2018-08-29 21:25:18 +0900995 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900996 }
Jooyung Han3f347ca2020-12-01 12:41:50 +0900997 for (const auto& constdecl : GetConstantDeclarations()) {
998 if (constdecl->GetType().IsHidden()) {
999 AddHideComment(writer);
1000 }
1001 writer->Write("%s;\n", constdecl->ToString().c_str());
1002 }
Jiyong Park02da7422018-07-16 16:00:26 +09001003 writer->Dedent();
1004 writer->Write("}\n");
1005}
1006
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001007std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
Jeongik Cha36f76c32020-07-28 00:25:52 +09001008 return {AidlAnnotation::Type::VINTF_STABILITY,
1009 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
1010 AidlAnnotation::Type::HIDE,
1011 AidlAnnotation::Type::JAVA_PASSTHROUGH,
Jooyung Han90345002020-10-23 15:28:53 +09001012 AidlAnnotation::Type::JAVA_DERIVE,
Devin Moorec7e47a32020-08-07 10:55:25 -07001013 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
Andrei Homescue61feb52020-08-18 15:44:24 -07001014 AidlAnnotation::Type::FIXED_SIZE,
1015 AidlAnnotation::Type::RUST_DERIVE};
Devin Moore24f68572020-02-26 13:20:59 -08001016}
1017
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001018bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -08001019 if (!AidlParcelable::CheckValid(typenames)) {
1020 return false;
1021 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001022
Jooyung Han59af9cc2020-10-25 21:44:14 +09001023 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001024
Jooyung Hand4057c42020-10-23 13:28:22 +09001025 if (IsFixedSize()) {
1026 for (const auto& v : GetFields()) {
1027 if (!typenames.CanBeFixedSize(v->GetType())) {
1028 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1029 << "non-fixed size field named " << v->GetName() << ".";
1030 success = false;
1031 }
1032 }
1033 }
1034
1035 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001036 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001037 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001038 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001039 }
1040 }
1041
Daniel Norman85aed542019-08-21 12:01:14 -07001042 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001043}
1044
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001045// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001046bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1047 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001048 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1049 GetName() == "IBinder") {
1050 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1051 << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001052 return false;
1053 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001054 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1055 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1056 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001057 return false;
1058 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001059 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1060 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001061 if (GetName() == "ParcelFileDescriptor") {
Andrei Homescub62afd92020-05-11 19:24:59 -07001062 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1063 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001064 return false;
1065 }
1066
Steven Morelandd59e3172020-05-11 16:42:09 -07001067 const auto defined_type = typenames.TryGetDefinedType(GetName());
1068 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Andrei Homescub62afd92020-05-11 19:24:59 -07001069 AIDL_ERROR(this) << "The " << Options::LanguageToString(lang)
1070 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001071 return false;
1072 }
1073 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001074 if (this->GetName() == "FileDescriptor" &&
1075 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1076 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << Options::LanguageToString(lang)
1077 << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001078 return false;
1079 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001080 if (this->IsGeneric()) {
1081 if (this->GetName() == "List") {
Jooyung Hane87cdd02020-12-11 16:47:35 +09001082 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1083 const string& contained_type_name = contained_type.GetName();
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001084 if (lang == Options::Language::CPP) {
Jooyung Hane87cdd02020-12-11 16:47:35 +09001085 if (!(contained_type_name == "String" || contained_type_name == "IBinder")) {
1086 AIDL_ERROR(this) << "List<" << contained_type_name
Devin Moore2ac52f92020-03-23 15:39:36 -07001087 << "> is not supported. List in cpp supports only String and IBinder.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001088 return false;
1089 }
Jeongik Cha08ca2182019-11-21 14:01:13 +09001090 } else if (lang == Options::Language::JAVA) {
Jooyung Hane87cdd02020-12-11 16:47:35 +09001091 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
1092 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
1093 contained_type_name != "ParcelFileDescriptor") {
1094 AIDL_ERROR(this) << "List<" << contained_type_name
Devin Moore2ac52f92020-03-23 15:39:36 -07001095 << "> is not supported. List in Java supports only String, IBinder, "
1096 "and ParcelFileDescriptor.";
Jeongik Cha08ca2182019-11-21 14:01:13 +09001097 return false;
1098 }
Jooyung Hane87cdd02020-12-11 16:47:35 +09001099 } else { // Defined types
1100 if (typenames.GetInterface(contained_type)) {
1101 AIDL_ERROR(this) << "List<" << contained_type_name
1102 << "> is not supported. List in Java supports only String, IBinder, "
1103 "and ParcelFileDescriptor.";
1104 return false;
1105 }
1106 }
1107 } else if (lang == Options::Language::NDK) {
1108 if (typenames.GetInterface(contained_type)) {
1109 AIDL_ERROR(this) << "List<" << contained_type_name
1110 << "> is not supported. List in NDK doesn't support interface.";
1111 return false;
1112 }
1113 if (contained_type_name == "IBinder") {
1114 AIDL_ERROR(this) << "List<" << contained_type_name
1115 << "> is not supported. List in NDK doesn't support IBinder.";
1116 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001117 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001118 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001119 }
1120 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001121
1122 if (this->IsArray()) {
1123 if (this->GetName() == "List" || this->GetName() == "Map" ||
1124 this->GetName() == "CharSequence") {
1125 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001126 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001127 }
1128 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001129
1130 if (lang != Options::Language::JAVA) {
1131 if (this->GetName() == "List" && !this->IsGeneric()) {
1132 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1133 return false;
1134 }
1135 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1136 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1137 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001138 }
1139 }
1140
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001141 return true;
1142}
1143
1144// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001145bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1146 Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001147 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -08001148 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1149 if (unstructured_parcelable != nullptr) {
1150 if (unstructured_parcelable->GetCppHeader().empty()) {
1151 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001152 << "Unstructured parcelable must have C++ header defined.";
1153 return false;
1154 }
1155 }
1156 }
1157 return true;
1158}
1159
1160// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001161bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1162 Options::Language lang) const {
1163 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001164 return false;
1165 }
1166 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001167 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001168 return false;
1169 }
1170 }
1171 return true;
1172}
1173
Daniel Norman85aed542019-08-21 12:01:14 -07001174AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -07001175 AidlConstantValue* value, const std::string& comments)
Jooyung Han29813842020-12-08 01:28:03 +09001176 : AidlNode(location),
1177 name_(name),
1178 value_(value),
1179 comments_(comments),
1180 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001181
1182bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1183 if (GetValue() == nullptr) {
1184 return false;
1185 }
1186 if (!GetValue()->CheckValid()) {
1187 return false;
1188 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001189 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001190 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1191 return false;
1192 }
1193 return true;
1194}
1195
1196string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1197 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001198 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001199}
1200
1201AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1202 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jiyong Park18132182020-06-08 20:24:40 +09001203 const std::string& package, const std::string& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001204 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001205 enumerators_(std::move(*enumerators)) {
1206 Autofill();
1207}
Daniel Norman85aed542019-08-21 12:01:14 -07001208
1209void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
1210 backing_type_ = std::move(type);
1211}
1212
Jooyung Han29813842020-12-08 01:28:03 +09001213void AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -07001214 const AidlEnumerator* previous = nullptr;
1215 for (const auto& enumerator : enumerators_) {
1216 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001217 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001218 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001219 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001220 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001221 } else {
Jooyung Han29813842020-12-08 01:28:03 +09001222 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName(), "");
Daniel Normanb28684e2019-10-17 15:31:39 -07001223 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001224 loc, std::move(prev_value), "+",
1225 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001226 }
1227 }
1228 previous = enumerator.get();
1229 }
1230}
1231
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001232std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
1233 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::BACKING,
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +09001234 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH};
Devin Moore24f68572020-02-26 13:20:59 -08001235}
1236
1237bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1238 if (!AidlDefinedType::CheckValid(typenames)) {
1239 return false;
1240 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001241 if (!GetMembers().empty()) {
1242 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1243 return false;
1244 }
Daniel Norman85aed542019-08-21 12:01:14 -07001245 if (backing_type_ == nullptr) {
1246 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1247 return false;
1248 }
1249 bool success = true;
1250 for (const auto& enumerator : enumerators_) {
1251 success = success && enumerator->CheckValid(GetBackingType());
1252 }
1253 return success;
1254}
1255
Jeongik Cha997281d2020-01-16 15:23:59 +09001256void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001257 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001258 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -07001259 writer->Indent();
1260 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001261 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1262 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1263 }
1264 writer->Dedent();
1265 writer->Write("}\n");
1266}
1267
Jooyung Han2946afc2020-10-05 20:29:16 +09001268AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1269 const std::string& package, const std::string& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001270 std::vector<std::string>* type_params,
1271 std::vector<std::unique_ptr<AidlMember>>* members)
1272 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001273
1274std::set<AidlAnnotation::Type> AidlUnionDecl::GetSupportedAnnotations() const {
Jooyung Hanf93b5bd2020-10-28 15:12:08 +09001275 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::HIDE,
1276 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::JAVA_DERIVE,
1277 AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE, AidlAnnotation::Type::RUST_DERIVE};
Jooyung Han2946afc2020-10-05 20:29:16 +09001278}
1279
1280void AidlUnionDecl::Dump(CodeWriter* writer) const {
1281 DumpHeader(writer);
1282 writer->Write("union %s {\n", GetName().c_str());
1283 writer->Indent();
1284 for (const auto& field : GetFields()) {
1285 if (field->GetType().IsHidden()) {
1286 AddHideComment(writer);
1287 }
1288 writer->Write("%s;\n", field->ToString().c_str());
1289 }
Jooyung Han3f347ca2020-12-01 12:41:50 +09001290 for (const auto& constdecl : GetConstantDeclarations()) {
1291 if (constdecl->GetType().IsHidden()) {
1292 AddHideComment(writer);
1293 }
1294 writer->Write("%s;\n", constdecl->ToString().c_str());
1295 }
Jooyung Han2946afc2020-10-05 20:29:16 +09001296 writer->Dedent();
1297 writer->Write("}\n");
1298}
1299
Jooyung Hanfe89f122020-10-14 03:49:18 +09001300bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001301 // visit parents
Jooyung Hanfe89f122020-10-14 03:49:18 +09001302 if (!AidlParcelable::CheckValid(typenames)) {
1303 return false;
1304 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001305
1306 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001307 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001308 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001309 }
1310
1311 // now, visit self!
1312 bool success = true;
1313
1314 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1315 for (const auto& v : GetFields()) {
1316 if (v->GetType().GetName() == "ParcelableHolder") {
1317 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1318 success = false;
1319 }
1320 }
1321
1322 // first member should have default value (implicit or explicit)
1323 if (GetFields().empty()) {
1324 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1325 return false;
1326 }
1327
1328 return success;
1329}
1330
1331// TODO: we should treat every backend all the same in future.
1332bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1333 Options::Language lang) const {
1334 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1335 return false;
1336 }
1337 for (const auto& v : this->GetFields()) {
1338 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1339 return false;
1340 }
1341 }
1342 return true;
1343}
1344
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001345// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001346bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1347 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001348 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001349 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001350 return false;
1351 }
1352 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001353 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001354 return false;
1355 }
1356 }
1357 }
1358 return true;
1359}
1360
Steven Moreland46e9da82018-07-27 15:45:29 -07001361AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001362 const std::string& comments, bool oneway, const std::string& package,
1363 std::vector<std::unique_ptr<AidlMember>>* members)
1364 : AidlDefinedType(location, name, comments, package, members) {
1365 for (auto& m : GetMethods()) {
1366 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001367 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001368}
1369
Jeongik Cha997281d2020-01-16 15:23:59 +09001370void AidlInterface::Dump(CodeWriter* writer) const {
Steven Morelanda5d9c5c2020-02-21 16:01:09 -08001371 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +09001372 writer->Write("interface %s {\n", GetName().c_str());
1373 writer->Indent();
1374 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001375 if (method->IsHidden()) {
1376 AddHideComment(writer);
1377 }
Jiyong Park309668e2018-07-28 16:55:44 +09001378 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001379 }
Jiyong Parka428d212018-08-29 22:26:30 +09001380 for (const auto& constdecl : GetConstantDeclarations()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001381 if (constdecl->GetType().IsHidden()) {
1382 AddHideComment(writer);
1383 }
Jiyong Parka428d212018-08-29 22:26:30 +09001384 writer->Write("%s;\n", constdecl->ToString().c_str());
1385 }
Jiyong Park02da7422018-07-16 16:00:26 +09001386 writer->Dedent();
1387 writer->Write("}\n");
1388}
1389
Steven Moreland0cea4aa2020-04-20 21:06:02 -07001390std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
Steven Morelanda7764e52020-10-27 17:29:29 +00001391 return {AidlAnnotation::Type::SENSITIVE_DATA, AidlAnnotation::Type::VINTF_STABILITY,
1392 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
1393 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::DESCRIPTOR};
Devin Moore24f68572020-02-26 13:20:59 -08001394}
1395
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001396bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -08001397 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001398 return false;
1399 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001400 // Has to be a pointer due to deleting copy constructor. No idea why.
1401 map<string, const AidlMethod*> method_names;
1402 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001403 if (!m->GetType().CheckValid(typenames)) {
1404 return false;
1405 }
1406
Jeongik Cha649e8a72020-03-27 17:47:40 +09001407 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1408 if (m->GetType().GetName() == "ParcelableHolder") {
1409 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1410 return false;
1411 }
Steven Morelandacd53472018-12-14 10:17:26 -08001412 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001413 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1414 return false;
1415 }
1416
1417 set<string> argument_names;
1418 for (const auto& arg : m->GetArguments()) {
1419 auto it = argument_names.find(arg->GetName());
1420 if (it != argument_names.end()) {
1421 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1422 << arg->GetName() << "'";
1423 return false;
1424 }
1425 argument_names.insert(arg->GetName());
1426
1427 if (!arg->GetType().CheckValid(typenames)) {
1428 return false;
1429 }
1430
Jeongik Cha649e8a72020-03-27 17:47:40 +09001431 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1432 if (arg->GetType().GetName() == "ParcelableHolder") {
1433 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1434 return false;
1435 }
Steven Morelandacd53472018-12-14 10:17:26 -08001436 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001437 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1438 return false;
1439 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001440
1441 const auto [can_be_out, type_aspect] = typenames.CanBeOutParameter(arg->GetType());
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001442 if (!arg->DirectionWasSpecified() && can_be_out) {
Jooyung Han965e31d2020-11-27 12:30:16 +09001443 AIDL_ERROR(arg) << "'" << arg->GetType().Signature()
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001444 << "' can be an out type, so you must declare it as in, out, or inout.";
1445 return false;
1446 }
1447
1448 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
Jooyung Han15fd6c62020-10-23 13:54:46 +09001449 AIDL_ERROR(arg) << "'" << arg->GetName() << "' can't be an " << arg->GetDirectionSpecifier()
1450 << " parameter because " << type_aspect << " can only be an in parameter.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001451 return false;
1452 }
1453
1454 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001455 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001456 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1457 return false;
1458 }
1459
1460 // Reserve a namespace for internal use
1461 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1462 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1463 return false;
1464 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001465 }
1466
1467 auto it = method_names.find(m->GetName());
1468 // prevent duplicate methods
1469 if (it == method_names.end()) {
1470 method_names[m->GetName()] = m.get();
1471 } else {
1472 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1473 AIDL_ERROR(it->second) << "previously defined here.";
1474 return false;
1475 }
1476
Paul Trautrimb77048c2020-01-21 16:39:32 +09001477 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001478 "getTransactionName(int)"};
1479
1480 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001481 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001482 return false;
1483 }
1484 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001485
1486 bool success = true;
1487 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001488 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001489 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001490 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001491 success = false;
1492 }
1493 constant_names.insert(constant->GetName());
1494 success = success && constant->CheckValid(typenames);
1495 }
1496
1497 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001498}
1499
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001500std::string AidlInterface::GetDescriptor() const {
1501 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1502 if (annotatedDescriptor != "") {
1503 return annotatedDescriptor;
1504 }
1505 return GetCanonicalName();
1506}
1507
Steven Moreland46e9da82018-07-27 15:45:29 -07001508AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1509 : AidlNode(location), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001510
1511// Resolves unresolved type name to fully qualified typename to import
1512// case #1: SimpleName --> import p.SimpleName
1513// case #2: Outer.Inner --> import p.Outer
1514// case #3: p.SimpleName --> (as is)
1515std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1516 std::string canonical_name;
1517 const auto first_dot = unresolved_name.find_first_of('.');
1518 const std::string class_name =
1519 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1520 for (const auto& import : Imports()) {
1521 const auto& fq_name = import->GetNeededClass();
1522 const auto last_dot = fq_name.find_last_of('.');
1523 const std::string imported_type_name =
1524 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1525 if (imported_type_name == class_name) {
1526 if (canonical_name != "" && canonical_name != fq_name) {
1527 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1528 return {};
1529 }
1530 canonical_name = fq_name;
1531 }
1532 }
1533 // if not found, use unresolved_name as it is
1534 if (canonical_name == "") {
1535 return unresolved_name;
1536 }
1537 return canonical_name;
1538}