blob: a36e3e239b6130935e5ef3e2c627a3cd1a78db82 [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"
Christopher Wileyf690be52015-09-14 15:19:10 -070019
Adam Lesinskiffa16862014-01-23 18:17:42 -080020#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -070022#include <string.h>
Jiyong Park68bc77a2018-07-19 19:00:45 +090023#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +090024#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090025#include <set>
26#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070027#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090028#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070029
Steven Moreland1c4ba202018-08-09 10:49:54 -070030#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070031#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080032#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070033
Dan Willemsen609ba6d2019-12-30 10:44:00 -080034#include "aidl_language_y-module.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070035#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080036
Will McVickerd7d18df2019-09-12 13:40:50 -070037#include "aidl.h"
38
Casey Dahlin07b9dde2015-09-10 19:13:49 -070039#ifdef _WIN32
40int isatty(int fd)
41{
42 return (fd == 0);
43}
44#endif
45
Christopher Wiley4a2884b2015-10-07 11:27:45 -070046using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070047using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080048using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070049using std::cerr;
50using std::endl;
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 {
58bool is_java_keyword(const char* str) {
59 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}
71} // namespace
72
Casey Dahlindd691812015-09-09 17:59:06 -070073void yylex_init(void **);
74void yylex_destroy(void *);
75void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070076int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070077YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070078void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070079
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070080AidlToken::AidlToken(const std::string& text, const std::string& comments)
81 : text_(text),
82 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070083
Steven Moreland46e9da82018-07-27 15:45:29 -070084AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
85 : file_(file), begin_(begin), end_(end) {}
86
87std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
88 os << l.file_ << ":" << 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;
93 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 Moreland92c55f12018-07-31 14:08:37 -0700111AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
Steven Morelandfdb57cd2020-01-08 20:03:30 -0800112 sHadError = true;
113
Steven Moreland92c55f12018-07-31 14:08:37 -0700114 os_ << "ERROR: ";
115}
116
Steven Morelandfdb57cd2020-01-08 20:03:30 -0800117bool AidlError::sHadError = false;
118
Jiyong Park68bc77a2018-07-19 19:00:45 +0900119static const string kNullable("nullable");
Jiyong Park68bc77a2018-07-19 19:00:45 +0900120static const string kUtf8InCpp("utf8InCpp");
Steven Morelanda57d0a62019-07-30 09:41:14 -0700121static const string kVintfStability("VintfStability");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900122static const string kUnsupportedAppUsage("UnsupportedAppUsage");
Jeongik Cha698e6af2018-12-12 14:39:55 +0900123static const string kSystemApi("SystemApi");
Jeongik Cha88f95a82020-01-15 13:02:16 +0900124static const string kJavaStableParcelable("JavaOnlyStableParcelable");
Daniel Norman85aed542019-08-21 12:01:14 -0700125static const string kBacking("Backing");
Jiyong Park68bc77a2018-07-19 19:00:45 +0900126
Andrei Onea9445fc62019-06-27 18:11:59 +0100127static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
128 {kNullable, {}},
129 {kUtf8InCpp, {}},
Steven Morelanda57d0a62019-07-30 09:41:14 -0700130 {kVintfStability, {}},
Andrei Onea9445fc62019-06-27 18:11:59 +0100131 {kUnsupportedAppUsage,
132 {{"expectedSignature", "String"},
133 {"implicitMember", "String"},
134 {"maxTargetSdk", "int"},
135 {"publicAlternatives", "String"},
136 {"trackingBug", "long"}}},
137 {kSystemApi, {}},
Jeongik Cha88f95a82020-01-15 13:02:16 +0900138 {kJavaStableParcelable, {}},
Daniel Norman85aed542019-08-21 12:01:14 -0700139 {kBacking, {{"type", "String"}}}};
Andrei Onea9445fc62019-06-27 18:11:59 +0100140
141AidlAnnotation* AidlAnnotation::Parse(
142 const AidlLocation& location, const string& name,
143 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland29db3022019-07-30 12:37:17 -0700144 if (kAnnotationParameters.find(name) == kAnnotationParameters.end()) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900145 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700146 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900147 stream << "It must be one of:";
Steven Moreland29db3022019-07-30 12:37:17 -0700148 for (const auto& kv : kAnnotationParameters) {
149 stream << " " << kv.first;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900150 }
151 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700152 AIDL_ERROR(location) << stream.str();
153 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900154 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100155 if (parameter_list == nullptr) {
156 return new AidlAnnotation(location, name);
157 }
158
159 return new AidlAnnotation(location, name, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900160}
161
Steven Moreland46e9da82018-07-27 15:45:29 -0700162AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
Andrei Onea9445fc62019-06-27 18:11:59 +0100163 : AidlAnnotation(location, name, {}) {}
164
165AidlAnnotation::AidlAnnotation(
166 const AidlLocation& location, const string& name,
167 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
168 : AidlNode(location), name_(name), parameters_(std::move(parameters)) {}
169
170bool AidlAnnotation::CheckValid() const {
171 auto supported_params_iterator = kAnnotationParameters.find(GetName());
172 if (supported_params_iterator == kAnnotationParameters.end()) {
173 AIDL_ERROR(this) << GetName() << " annotation does not have any supported parameters.";
174 return false;
175 }
176 const auto& supported_params = supported_params_iterator->second;
177 for (const auto& name_and_param : parameters_) {
178 const std::string& param_name = name_and_param.first;
179 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Will McVickerd7d18df2019-09-12 13:40:50 -0700180 if (!param->CheckValid()) {
181 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
182 << GetName() << ".";
183 return false;
184 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100185 auto parameter_mapping_it = supported_params.find(param_name);
186 if (parameter_mapping_it == supported_params.end()) {
187 std::ostringstream stream;
188 stream << "Parameter " << param_name << " not supported ";
189 stream << "for annotation " << GetName() << ".";
190 stream << "It must be one of:";
191 for (const auto& kv : supported_params) {
192 stream << " " << kv.first;
193 }
194 AIDL_ERROR(this) << stream.str();
195 return false;
196 }
197 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700198 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100199 // Assume error on empty string.
200 if (param_value == "") {
201 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
202 << GetName() << ".";
203 return false;
204 }
205 }
206 return true;
207}
208
209std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
210 const ConstantValueDecorator& decorator) const {
211 std::map<std::string, std::string> raw_params;
212 const auto& supported_params = kAnnotationParameters.at(GetName());
213 for (const auto& name_and_param : parameters_) {
214 const std::string& param_name = name_and_param.first;
215 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
216 AidlTypeSpecifier type{AIDL_LOCATION_HERE, supported_params.at(param_name), false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700217 if (!param->CheckValid()) {
218 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
219 << GetName() << ".";
220 raw_params.clear();
221 return raw_params;
222 }
223
224 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100225 }
226 return raw_params;
227}
Steven Moreland46e9da82018-07-27 15:45:29 -0700228
Daniel Norman37d43dd2019-09-09 17:22:34 -0700229std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
230 if (parameters_.empty()) {
231 return "@" + GetName();
232 } else {
233 vector<string> param_strings;
234 for (const auto& [name, value] : AnnotationParams(decorator)) {
235 param_strings.emplace_back(name + "=" + value);
236 }
237 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
238 }
239}
240
Jiyong Parka6605ab2018-11-11 14:30:21 +0900241static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900242 for (const auto& a : annotations) {
Steven Moreland3be75772018-08-20 13:27:43 -0700243 if (a.GetName() == name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900244 return true;
245 }
246 }
247 return false;
248}
249
Andrei Onea9445fc62019-06-27 18:11:59 +0100250static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
251 const string& name) {
252 for (const auto& a : annotations) {
253 if (a.GetName() == name) {
254 return &a;
255 }
256 }
257 return nullptr;
258}
259
Steven Moreland46e9da82018-07-27 15:45:29 -0700260AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
261
Jiyong Park68bc77a2018-07-19 19:00:45 +0900262bool AidlAnnotatable::IsNullable() const {
263 return HasAnnotation(annotations_, kNullable);
264}
265
Jiyong Park68bc77a2018-07-19 19:00:45 +0900266bool AidlAnnotatable::IsUtf8InCpp() const {
267 return HasAnnotation(annotations_, kUtf8InCpp);
268}
269
Steven Morelanda57d0a62019-07-30 09:41:14 -0700270bool AidlAnnotatable::IsVintfStability() const {
271 return HasAnnotation(annotations_, kVintfStability);
272}
273
Andrei Onea9445fc62019-06-27 18:11:59 +0100274const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
275 return GetAnnotation(annotations_, kUnsupportedAppUsage);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900276}
277
Daniel Norman716d3112019-09-10 13:11:56 -0700278const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700279 auto annotation = GetAnnotation(annotations_, kBacking);
280 if (annotation != nullptr) {
281 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
282 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
283 const string& type = it->second;
Daniel Norman716d3112019-09-10 13:11:56 -0700284 AidlTypeSpecifier* type_specifier =
285 new AidlTypeSpecifier(AIDL_LOCATION_HERE,
286 // Strip the quotes off the type String.
287 type.substr(1, type.length() - 2), false, nullptr, "");
288 type_specifier->Resolve(typenames);
289 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700290 }
291 }
292 return nullptr;
293}
294
Jeongik Cha698e6af2018-12-12 14:39:55 +0900295bool AidlAnnotatable::IsSystemApi() const {
296 return HasAnnotation(annotations_, kSystemApi);
297}
298
Jeongik Cha88f95a82020-01-15 13:02:16 +0900299bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
300 return HasAnnotation(annotations_, kJavaStableParcelable) && lang == Options::Language::JAVA;
Jeongik Cha82317dd2019-02-27 20:26:11 +0900301}
302
Andrei Onea9445fc62019-06-27 18:11:59 +0100303bool AidlAnnotatable::CheckValidAnnotations() const {
304 for (const auto& annotation : GetAnnotations()) {
305 if (!annotation.CheckValid()) {
306 return false;
307 }
308 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700309
Andrei Onea9445fc62019-06-27 18:11:59 +0100310 return true;
311}
312
Jiyong Park68bc77a2018-07-19 19:00:45 +0900313string AidlAnnotatable::ToString() const {
314 vector<string> ret;
315 for (const auto& a : annotations_) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700316 ret.emplace_back(a.ToString(AidlConstantValueDecorator));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900317 }
318 std::sort(ret.begin(), ret.end());
319 return Join(ret, " ");
320}
321
Steven Moreland46e9da82018-07-27 15:45:29 -0700322AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
323 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900324 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700325 const string& comments)
326 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900327 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700328 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700329 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900330 comments_(comments),
331 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700332
Steven Moreland3f658cf2018-08-20 13:40:54 -0700333AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
334 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900335 // Declaring array of generic type cannot happen, it is grammar error.
336 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700337
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800338 AidlTypeSpecifier array_base = *this;
339 array_base.is_array_ = false;
340 return array_base;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700341}
342
Jiyong Park1deecc32018-07-17 01:14:41 +0900343string AidlTypeSpecifier::ToString() const {
344 string ret = GetName();
345 if (IsGeneric()) {
346 vector<string> arg_names;
347 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +0900348 arg_names.emplace_back(ta->ToString());
349 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900350 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900351 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900352 if (IsArray()) {
353 ret += "[]";
354 }
355 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900356}
357
Jiyong Park02da7422018-07-16 16:00:26 +0900358string AidlTypeSpecifier::Signature() const {
359 string ret = ToString();
360 string annotations = AidlAnnotatable::ToString();
361 if (annotations != "") {
362 ret = annotations + " " + ret;
363 }
364 return ret;
365}
366
Daniel Norman716d3112019-09-10 13:11:56 -0700367bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland9731c632019-08-13 10:21:08 -0700368 CHECK(!IsResolved());
Jiyong Park1deecc32018-07-17 01:14:41 +0900369 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
370 if (result.second) {
371 fully_qualified_name_ = result.first;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900372 split_name_ = Split(fully_qualified_name_, ".");
Jiyong Parkccf00f82018-07-17 01:39:23 +0900373 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900374 return result.second;
Casey Dahlin70078e62015-09-30 17:01:30 -0700375}
376
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900377bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100378 if (!CheckValidAnnotations()) {
379 return false;
380 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900381 if (IsGeneric()) {
382 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900383
384 auto& types = GetTypeParameters();
385 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
386 if (type_name == "List" || type_name == "Map") {
387 if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
388 return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
389 })) {
390 AIDL_ERROR(this) << "A generic type cannot has any primitive type parameters.";
391 return false;
392 }
393 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800394 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900395 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800396 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
397 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900398 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800399 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900400 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800401 if (num_params > 1) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900402 AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
403 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900404 return false;
405 }
406 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800407 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900408 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
409 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900410 return false;
411 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800412 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900413 const string& key_type = GetTypeParameters()[0]->GetName();
414 if (key_type != "String") {
415 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
416 << "'" << key_type << "'";
417 return false;
418 }
419 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800420 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900421 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800422 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900423 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800424 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900425 return false;
426 }
427 } else {
428 AIDL_ERROR(this) << type_name << " is not a generic type.";
429 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900430 }
431 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900432
433 if (GetName() == "void") {
434 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
435 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
436 return false;
437 }
438 }
439
440 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800441 const auto defined_type = typenames.TryGetDefinedType(GetName());
442 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900443 AIDL_ERROR(this) << "Binder type cannot be an array";
444 return false;
445 }
446 }
447
448 if (IsNullable()) {
449 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
450 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
451 return false;
452 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800453 const auto defined_type = typenames.TryGetDefinedType(GetName());
454 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700455 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
456 return false;
457 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900458 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900459 return true;
460}
461
Steven Moreland860b1942018-08-16 14:59:28 -0700462std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
463 const std::string& raw_value) {
464 return raw_value;
465}
466
Steven Moreland46e9da82018-07-27 15:45:29 -0700467AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
468 AidlTypeSpecifier* type, const std::string& name)
469 : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700470
Steven Moreland46e9da82018-07-27 15:45:29 -0700471AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
472 AidlTypeSpecifier* type, const std::string& name,
473 AidlConstantValue* default_value)
474 : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700475
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900476bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700477 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900478 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900479
Steven Moreland54be7bd2019-12-05 11:17:53 -0800480 if (type_->GetName() == "void") {
481 AIDL_ERROR(this) << "Declaration " << name_
482 << " is void, but declarations cannot be of void type.";
483 valid = false;
484 }
485
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900486 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700487 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700488
Steven Moreland25294322018-08-07 18:13:55 -0700489 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700490
Steven Moreland860b1942018-08-16 14:59:28 -0700491 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700492}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700493
494string AidlVariableDeclaration::ToString() const {
Jeongik Cha3271ffa2018-12-04 15:19:20 +0900495 string ret = type_->Signature() + " " + name_;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700496 if (default_value_ != nullptr) {
Steven Moreland860b1942018-08-16 14:59:28 -0700497 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700498 }
499 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700500}
501
Jiyong Park02da7422018-07-16 16:00:26 +0900502string AidlVariableDeclaration::Signature() const {
503 return type_->Signature() + " " + name_;
504}
505
Steven Moreland860b1942018-08-16 14:59:28 -0700506std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900507 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700508 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900509 } else {
510 return "";
511 }
Steven Moreland25294322018-08-07 18:13:55 -0700512}
513
Steven Moreland46e9da82018-07-27 15:45:29 -0700514AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
515 AidlTypeSpecifier* type, const std::string& name)
516 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700517 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700518 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700519
Steven Moreland46e9da82018-07-27 15:45:29 -0700520AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
521 const std::string& name)
522 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700523 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700524 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700525
Jiyong Park02da7422018-07-16 16:00:26 +0900526string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700527 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700528 if (direction_specified_) {
529 switch(direction_) {
530 case AidlArgument::IN_DIR:
531 ret += "in ";
532 break;
533 case AidlArgument::OUT_DIR:
534 ret += "out ";
535 break;
536 case AidlArgument::INOUT_DIR:
537 ret += "inout ";
538 break;
539 }
540 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700541 return ret;
542}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700543
Jiyong Park02da7422018-07-16 16:00:26 +0900544string AidlArgument::ToString() const {
545 return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
546}
547
548std::string AidlArgument::Signature() const {
Steven Moreland46e9da82018-07-27 15:45:29 -0700549 class AidlInterface;
550 class AidlInterface;
551 class AidlParcelable;
552 class AidlStructuredParcelable;
553 class AidlParcelable;
554 class AidlStructuredParcelable;
Jiyong Park02da7422018-07-16 16:00:26 +0900555 return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
556}
557
Steven Moreland46e9da82018-07-27 15:45:29 -0700558AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
559
Steven Moreland46e9da82018-07-27 15:45:29 -0700560AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
561 AidlTypeSpecifier* type, const std::string& name,
562 AidlConstantValue* value)
563 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700564
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900565bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700566 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900567 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700568 valid &= value_->CheckValid();
569 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700570
Steven Moreland25294322018-08-07 18:13:55 -0700571 const static set<string> kSupportedConstTypes = {"String", "int"};
572 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
573 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700574 return false;
575 }
576
Will McVickerd7d18df2019-09-12 13:40:50 -0700577 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700578}
579
Jiyong Parka428d212018-08-29 22:26:30 +0900580string AidlConstantDeclaration::ToString() const {
581 return "const " + type_->ToString() + " " + name_ + " = " +
582 ValueString(AidlConstantValueDecorator);
583}
584
585string AidlConstantDeclaration::Signature() const {
586 return type_->Signature() + " " + name_;
587}
588
Steven Moreland46e9da82018-07-27 15:45:29 -0700589AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
590 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900591 const std::string& comments)
592 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
593 has_id_ = false;
594}
595
596AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
597 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900598 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700599 : AidlMember(location),
600 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700601 comments_(comments),
602 type_(type),
603 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700604 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900605 id_(id),
606 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700607 has_id_ = true;
608 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700609 for (const unique_ptr<AidlArgument>& a : arguments_) {
610 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
611 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
612 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700613}
614
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700615
Jiyong Park02da7422018-07-16 16:00:26 +0900616string AidlMethod::Signature() const {
617 vector<string> arg_signatures;
618 for (const auto& arg : GetArguments()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900619 arg_signatures.emplace_back(arg->GetType().ToString());
Jiyong Park02da7422018-07-16 16:00:26 +0900620 }
Jiyong Park309668e2018-07-28 16:55:44 +0900621 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
622}
623
624string AidlMethod::ToString() const {
625 vector<string> arg_strings;
626 for (const auto& arg : GetArguments()) {
627 arg_strings.emplace_back(arg->Signature());
628 }
Steven Moreland4ee68632018-12-14 15:52:46 -0800629 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
630 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900631 if (HasId()) {
632 ret += " = " + std::to_string(GetId());
633 }
634 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900635}
636
Steven Moreland46e9da82018-07-27 15:45:29 -0700637AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
638 const std::string& comments,
Steven Moreland787b0432018-07-03 09:00:58 -0700639 const std::vector<std::string>& package)
Steven Moreland46e9da82018-07-27 15:45:29 -0700640 : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700641
642std::string AidlDefinedType::GetPackage() const {
643 return Join(package_, '.');
644}
645
646std::string AidlDefinedType::GetCanonicalName() const {
647 if (package_.empty()) {
648 return GetName();
649 }
650 return GetPackage() + "." + GetName();
651}
652
Steven Moreland46e9da82018-07-27 15:45:29 -0700653AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900654 const std::vector<std::string>& package, const std::string& comments,
Jeongik Chadf76dc72019-11-28 00:08:47 +0900655 const std::string& cpp_header, std::vector<std::string>* type_params)
Jiyong Parka6605ab2018-11-11 14:30:21 +0900656 : AidlDefinedType(location, name->GetDotName(), comments, package),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900657 AidlParameterizable<std::string>(type_params),
Steven Moreland787b0432018-07-03 09:00:58 -0700658 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800659 cpp_header_(cpp_header) {
660 // Strip off quotation marks if we actually have a cpp header.
661 if (cpp_header_.length() >= 2) {
662 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
663 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700664}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900665template <typename T>
666AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
667 // Copying is not supported if it has type parameters.
668 // It doesn't make a problem because only ArrayBase() makes a copy,
669 // and it can be called only if a type is not generic.
670 CHECK(!other.IsGeneric());
671}
672
673template <typename T>
674bool AidlParameterizable<T>::CheckValid() const {
675 return true;
676};
677
678template <>
679bool AidlParameterizable<std::string>::CheckValid() const {
680 if (!IsGeneric()) {
681 return true;
682 }
683 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
684 if (set.size() != GetTypeParameters().size()) {
685 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
686 return false;
687 }
688 return true;
689}
Casey Dahlin59401da2015-10-09 18:16:45 -0700690
Jeongik Cha82317dd2019-02-27 20:26:11 +0900691bool AidlParcelable::CheckValid(const AidlTypenames&) const {
Jeongik Cha88f95a82020-01-15 13:02:16 +0900692 static const std::set<string> allowed{kJavaStableParcelable};
Andrei Onea9445fc62019-06-27 18:11:59 +0100693 if (!CheckValidAnnotations()) {
694 return false;
695 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900696 if (!AidlParameterizable<std::string>::CheckValid()) {
697 return false;
698 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900699 for (const auto& v : GetAnnotations()) {
700 if (allowed.find(v.GetName()) == allowed.end()) {
701 std::ostringstream stream;
702 stream << "Unstructured parcelable can contain only";
703 for (const string& kv : allowed) {
704 stream << " " << kv;
705 }
706 stream << ".";
707 AIDL_ERROR(this) << stream.str();
708 return false;
709 }
710 }
711
712 return true;
713}
714
Jiyong Park02da7422018-07-16 16:00:26 +0900715void AidlParcelable::Write(CodeWriter* writer) const {
716 writer->Write("parcelable %s ;\n", GetName().c_str());
717}
718
Steven Moreland5557f1c2018-07-02 13:50:23 -0700719AidlStructuredParcelable::AidlStructuredParcelable(
Steven Moreland46e9da82018-07-27 15:45:29 -0700720 const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900721 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
722 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
Steven Moreland46e9da82018-07-27 15:45:29 -0700723 variables_(std::move(*variables)) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700724
Jiyong Park02da7422018-07-16 16:00:26 +0900725void AidlStructuredParcelable::Write(CodeWriter* writer) const {
726 writer->Write("parcelable %s {\n", GetName().c_str());
727 writer->Indent();
728 for (const auto& field : GetFields()) {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900729 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900730 }
731 writer->Dedent();
732 writer->Write("}\n");
733}
734
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900735bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700736 bool success = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900737 for (const auto& v : GetFields()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700738 success = success && v->CheckValid(typenames);
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900739 }
Daniel Norman85aed542019-08-21 12:01:14 -0700740 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900741}
742
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900743// TODO: we should treat every backend all the same in future.
744bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
Steven Moreland04b07e12020-01-21 18:11:07 -0800745 if (lang != Options::Language::JAVA) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900746 if (this->GetName() == "List" && !this->IsGeneric()) {
Steven Moreland04b07e12020-01-21 18:11:07 -0800747 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900748 return false;
749 }
750 }
Steven Morelandc8a4ca82020-01-21 17:50:08 -0800751 if (this->GetName() == "FileDescriptor" && lang == Options::Language::NDK) {
752 AIDL_ERROR(this) << "FileDescriptor isn't supported with the NDK.";
753 return false;
754 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900755 if (this->IsGeneric()) {
756 if (this->GetName() == "List") {
757 if (this->GetTypeParameters().size() != 1) {
758 AIDL_ERROR(this) << "List must have only one type parameter.";
759 return false;
760 }
761 if (lang == Options::Language::CPP) {
762 auto& name = this->GetTypeParameters()[0]->GetName();
763 if (!(name == "String" || name == "IBinder")) {
764 AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
765 return false;
766 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900767 } else if (lang == Options::Language::JAVA) {
768 const string& contained_type = this->GetTypeParameters()[0]->GetName();
769 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
770 if (contained_type != "String" && contained_type != "IBinder" &&
771 contained_type != "ParcelFileDescriptor") {
772 AIDL_ERROR(this) << "List<" << contained_type << "> isn't supported in Java";
773 return false;
774 }
775 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900776 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900777 }
778 }
Jeongik Chab75a4512020-01-10 13:37:04 +0900779 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900780 if (lang != Options::Language::JAVA) {
Jeongik Chab75a4512020-01-10 13:37:04 +0900781 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900782 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900783 }
784 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900785 if (lang == Options::Language::JAVA) {
786 const string name = this->GetName();
787 // List[], Map[], CharSequence[] are not supported.
788 if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
789 if (name == "List" || name == "Map" || name == "CharSequence") {
790 AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
791 return false;
792 }
793 }
794 }
795
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900796 return true;
797}
798
799// TODO: we should treat every backend all the same in future.
800bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
801 if (lang != Options::Language::JAVA) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800802 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
803 if (unstructured_parcelable != nullptr) {
804 if (unstructured_parcelable->GetCppHeader().empty()) {
805 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900806 << "Unstructured parcelable must have C++ header defined.";
807 return false;
808 }
809 }
810 }
811 return true;
812}
813
814// TODO: we should treat every backend all the same in future.
815bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
816 if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
817 return false;
818 }
819 for (const auto& v : this->GetFields()) {
820 if (!v->GetType().LanguageSpecificCheckValid(lang)) {
821 return false;
822 }
823 }
824 return true;
825}
826
Daniel Norman85aed542019-08-21 12:01:14 -0700827AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700828 AidlConstantValue* value, const std::string& comments)
829 : AidlNode(location), name_(name), value_(value), comments_(comments) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700830
831bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
832 if (GetValue() == nullptr) {
833 return false;
834 }
835 if (!GetValue()->CheckValid()) {
836 return false;
837 }
Will McVickerd7d18df2019-09-12 13:40:50 -0700838 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700839 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
840 return false;
841 }
842 return true;
843}
844
845string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
846 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -0700847 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -0700848}
849
850AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
851 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700852 const std::vector<std::string>& package,
853 const std::string& comments)
854 : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700855
856void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
857 backing_type_ = std::move(type);
858}
859
Steven Moreland59e53e42019-11-26 20:38:08 -0800860bool AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -0700861 const AidlEnumerator* previous = nullptr;
862 for (const auto& enumerator : enumerators_) {
863 if (enumerator->GetValue() == nullptr) {
864 if (previous == nullptr) {
865 enumerator->SetValue(std::unique_ptr<AidlConstantValue>(
866 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "0")));
867 } else {
Steven Moreland59e53e42019-11-26 20:38:08 -0800868 auto prev_value = std::unique_ptr<AidlConstantValue>(
869 AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
870 if (prev_value == nullptr) {
871 return false;
872 }
Daniel Normanb28684e2019-10-17 15:31:39 -0700873 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Steven Moreland59e53e42019-11-26 20:38:08 -0800874 AIDL_LOCATION_HERE, std::move(prev_value), "+",
Daniel Normanb28684e2019-10-17 15:31:39 -0700875 std::unique_ptr<AidlConstantValue>(
876 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
877 }
878 }
879 previous = enumerator.get();
880 }
Steven Moreland59e53e42019-11-26 20:38:08 -0800881 return true;
Daniel Normanb28684e2019-10-17 15:31:39 -0700882}
883
Daniel Norman85aed542019-08-21 12:01:14 -0700884bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
885 if (backing_type_ == nullptr) {
886 AIDL_ERROR(this) << "Enum declaration missing backing type.";
887 return false;
888 }
889 bool success = true;
890 for (const auto& enumerator : enumerators_) {
891 success = success && enumerator->CheckValid(GetBackingType());
892 }
893 return success;
894}
895
896void AidlEnumDeclaration::Write(CodeWriter* writer) const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700897 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
898 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -0700899 writer->Indent();
900 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700901 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
902 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
903 }
904 writer->Dedent();
905 writer->Write("}\n");
906}
907
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900908// TODO: we should treat every backend all the same in future.
909bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
910 for (const auto& m : this->GetMethods()) {
911 if (!m->GetType().LanguageSpecificCheckValid(lang)) {
912 return false;
913 }
914 for (const auto& arg : m->GetArguments()) {
915 if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
916 return false;
917 }
918 }
919 }
920 return true;
921}
922
Steven Moreland46e9da82018-07-27 15:45:29 -0700923AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700924 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800925 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700926 const std::vector<std::string>& package)
Steven Morelandacd53472018-12-14 10:17:26 -0800927 : AidlDefinedType(location, name, comments, package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800928 for (auto& member : *members) {
929 AidlMember* local = member.release();
930 AidlMethod* method = local->AsMethod();
Steven Moreland693640b2018-07-19 13:46:27 -0700931 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
932
933 CHECK(method == nullptr || constant == nullptr);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800934
935 if (method) {
Steven Moreland8c70ba92018-12-17 10:20:31 -0800936 method->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800937 methods_.emplace_back(method);
Steven Moreland693640b2018-07-19 13:46:27 -0700938 } else if (constant) {
939 constants_.emplace_back(constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800940 } else {
Steven Moreland46e9da82018-07-27 15:45:29 -0700941 AIDL_FATAL(this) << "Member is neither method nor constant!";
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800942 }
943 }
944
945 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700946}
947
Jiyong Park02da7422018-07-16 16:00:26 +0900948void AidlInterface::Write(CodeWriter* writer) const {
949 writer->Write("interface %s {\n", GetName().c_str());
950 writer->Indent();
951 for (const auto& method : GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900952 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900953 }
Jiyong Parka428d212018-08-29 22:26:30 +0900954 for (const auto& constdecl : GetConstantDeclarations()) {
955 writer->Write("%s;\n", constdecl->ToString().c_str());
956 }
Jiyong Park02da7422018-07-16 16:00:26 +0900957 writer->Dedent();
958 writer->Write("}\n");
959}
960
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900961bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100962 if (!CheckValidAnnotations()) {
963 return false;
964 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900965 // Has to be a pointer due to deleting copy constructor. No idea why.
966 map<string, const AidlMethod*> method_names;
967 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900968 if (!m->GetType().CheckValid(typenames)) {
969 return false;
970 }
971
Steven Morelandacd53472018-12-14 10:17:26 -0800972 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900973 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
974 return false;
975 }
976
977 set<string> argument_names;
978 for (const auto& arg : m->GetArguments()) {
979 auto it = argument_names.find(arg->GetName());
980 if (it != argument_names.end()) {
981 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
982 << arg->GetName() << "'";
983 return false;
984 }
985 argument_names.insert(arg->GetName());
986
987 if (!arg->GetType().CheckValid(typenames)) {
988 return false;
989 }
990
Steven Morelandacd53472018-12-14 10:17:26 -0800991 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900992 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
993 return false;
994 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900995 const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
996 if (!arg->DirectionWasSpecified() && can_be_out) {
997 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
998 << "' can be an out type, so you must declare it as in, out, or inout.";
999 return false;
1000 }
1001
1002 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
1003 AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1004 return false;
1005 }
1006
1007 // check that the name doesn't match a keyword
1008 if (is_java_keyword(arg->GetName().c_str())) {
1009 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1010 return false;
1011 }
1012
1013 // Reserve a namespace for internal use
1014 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1015 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1016 return false;
1017 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001018 }
1019
1020 auto it = method_names.find(m->GetName());
1021 // prevent duplicate methods
1022 if (it == method_names.end()) {
1023 method_names[m->GetName()] = m.get();
1024 } else {
1025 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1026 AIDL_ERROR(it->second) << "previously defined here.";
1027 return false;
1028 }
1029
1030 static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
1031 "getTransactionName(int)"};
1032
1033 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1034 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
1035 return false;
1036 }
1037 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001038
1039 bool success = true;
1040 set<string> constant_names;
1041 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1042 if (constant_names.count(constant->GetName()) > 0) {
1043 LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
1044 success = false;
1045 }
1046 constant_names.insert(constant->GetName());
1047 success = success && constant->CheckValid(typenames);
1048 }
1049
1050 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001051}
1052
Steven Moreland46e9da82018-07-27 15:45:29 -07001053AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
1054 const std::string& comments)
1055 : AidlNode(location), terms_({term}), comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001056 if (term.find('.') != string::npos) {
1057 terms_ = Split(term, ".");
Steven Moreland46e9da82018-07-27 15:45:29 -07001058 for (const auto& subterm : terms_) {
1059 if (subterm.empty()) {
1060 AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001061 }
1062 }
1063 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001064}
1065
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -07001066void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001067 terms_.push_back(term);
1068}
1069
Steven Moreland46e9da82018-07-27 15:45:29 -07001070AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1071 : AidlNode(location), needed_class_(needed_class) {}
Casey Dahlin0edf3422015-10-07 12:34:59 -07001072
Steven Moreland64e29be2018-08-08 18:52:19 -07001073std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
1074 const android::aidl::IoDelegate& io_delegate,
1075 AidlTypenames& typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001076 // Make sure we can read the file first, before trashing previous state.
Steven Moreland64e29be2018-08-08 18:52:19 -07001077 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
1078 if (raw_buffer == nullptr) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001079 AIDL_ERROR(filename) << "Error while opening file for parsing";
Steven Moreland64e29be2018-08-08 18:52:19 -07001080 return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001081 }
1082
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001083 // We're going to scan this buffer in place, and yacc demands we put two
1084 // nulls at the end.
Steven Moreland64e29be2018-08-08 18:52:19 -07001085 raw_buffer->append(2u, '\0');
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001086
Steven Moreland64e29be2018-08-08 18:52:19 -07001087 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001088
Steven Moreland64e29be2018-08-08 18:52:19 -07001089 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001090
Steven Moreland64e29be2018-08-08 18:52:19 -07001091 return parser;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001092}
1093
Christopher Wiley90be4e32015-10-20 14:55:25 -07001094std::vector<std::string> Parser::Package() const {
1095 if (!package_) {
1096 return {};
1097 }
1098 return package_->GetTerms();
1099}
1100
Steven Moreland46e9da82018-07-27 15:45:29 -07001101void Parser::AddImport(AidlImport* import) {
Jiyong Park8f6ec462020-01-19 20:52:47 +09001102 for (const auto& i : imports_) {
1103 if (i->GetNeededClass() == import->GetNeededClass()) {
1104 return;
1105 }
1106 }
Steven Moreland46e9da82018-07-27 15:45:29 -07001107 imports_.emplace_back(import);
Casey Dahline2507492015-09-14 17:11:20 -07001108}
Jiyong Park1deecc32018-07-17 01:14:41 +09001109
1110bool Parser::Resolve() {
1111 bool success = true;
1112 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +09001113 if (!typespec->Resolve(typenames_)) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001114 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
Jiyong Park1deecc32018-07-17 01:14:41 +09001115 success = false;
1116 // don't stop to show more errors if any
1117 }
1118 }
1119 return success;
1120}
Steven Moreland64e29be2018-08-08 18:52:19 -07001121
1122Parser::Parser(const std::string& filename, std::string& raw_buffer,
1123 android::aidl::AidlTypenames& typenames)
1124 : filename_(filename), typenames_(typenames) {
1125 yylex_init(&scanner_);
1126 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
1127}
1128
1129Parser::~Parser() {
1130 yy_delete_buffer(buffer_, scanner_);
1131 yylex_destroy(scanner_);
1132}