blob: 5beaea1d1e4838df392229a2e0b6a2de3791797c [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 {
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
Casey Dahlindd691812015-09-09 17:59:06 -070081void yylex_init(void **);
82void yylex_destroy(void *);
83void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070084int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070085YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070086void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070087
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070088AidlToken::AidlToken(const std::string& text, const std::string& comments)
89 : text_(text),
90 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070091
Steven Moreland46e9da82018-07-27 15:45:29 -070092AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
93 : file_(file), begin_(begin), end_(end) {}
94
95std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
96 os << l.file_ << ":" << l.begin_.line << "." << l.begin_.column << "-";
97 if (l.begin_.line != l.end_.line) {
98 os << l.end_.line << ".";
99 }
100 os << l.end_.column;
101 return os;
102}
103
104AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
105
Mathew Inwoodadb74672019-11-29 14:01:53 +0000106std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +0000107 std::stringstream ss;
108 ss << location_.file_ << ":" << location_.begin_.line;
109 return ss.str();
110}
111
Mathew Inwoodadb74672019-11-29 14:01:53 +0000112std::string AidlNode::PrintLocation() const {
113 std::stringstream ss;
114 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
115 << location_.end_.line << ":" << location_.end_.column;
116 return ss.str();
117}
118
Steven Moreland92c55f12018-07-31 14:08:37 -0700119AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
Steven Morelandfdb57cd2020-01-08 20:03:30 -0800120 sHadError = true;
121
Steven Moreland92c55f12018-07-31 14:08:37 -0700122 os_ << "ERROR: ";
123}
124
Steven Morelandfdb57cd2020-01-08 20:03:30 -0800125bool AidlError::sHadError = false;
126
Jiyong Park68bc77a2018-07-19 19:00:45 +0900127static const string kNullable("nullable");
Jiyong Park68bc77a2018-07-19 19:00:45 +0900128static const string kUtf8InCpp("utf8InCpp");
Steven Morelanda57d0a62019-07-30 09:41:14 -0700129static const string kVintfStability("VintfStability");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900130static const string kUnsupportedAppUsage("UnsupportedAppUsage");
Jeongik Cha88f95a82020-01-15 13:02:16 +0900131static const string kJavaStableParcelable("JavaOnlyStableParcelable");
Makoto Onuki00be5c72020-03-04 16:57:23 -0800132static const string kHide("Hide");
Daniel Norman85aed542019-08-21 12:01:14 -0700133static const string kBacking("Backing");
Jiyong Park68bc77a2018-07-19 19:00:45 +0900134
Andrei Onea9445fc62019-06-27 18:11:59 +0100135static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
136 {kNullable, {}},
137 {kUtf8InCpp, {}},
Steven Morelanda57d0a62019-07-30 09:41:14 -0700138 {kVintfStability, {}},
Andrei Onea9445fc62019-06-27 18:11:59 +0100139 {kUnsupportedAppUsage,
140 {{"expectedSignature", "String"},
141 {"implicitMember", "String"},
142 {"maxTargetSdk", "int"},
143 {"publicAlternatives", "String"},
144 {"trackingBug", "long"}}},
Jeongik Cha88f95a82020-01-15 13:02:16 +0900145 {kJavaStableParcelable, {}},
Makoto Onuki00be5c72020-03-04 16:57:23 -0800146 {kHide, {}},
Daniel Norman85aed542019-08-21 12:01:14 -0700147 {kBacking, {{"type", "String"}}}};
Andrei Onea9445fc62019-06-27 18:11:59 +0100148
149AidlAnnotation* AidlAnnotation::Parse(
150 const AidlLocation& location, const string& name,
151 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland29db3022019-07-30 12:37:17 -0700152 if (kAnnotationParameters.find(name) == kAnnotationParameters.end()) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900153 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700154 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900155 stream << "It must be one of:";
Steven Moreland29db3022019-07-30 12:37:17 -0700156 for (const auto& kv : kAnnotationParameters) {
157 stream << " " << kv.first;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900158 }
159 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700160 AIDL_ERROR(location) << stream.str();
161 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900162 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100163 if (parameter_list == nullptr) {
164 return new AidlAnnotation(location, name);
165 }
166
167 return new AidlAnnotation(location, name, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900168}
169
Steven Moreland46e9da82018-07-27 15:45:29 -0700170AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
Andrei Onea9445fc62019-06-27 18:11:59 +0100171 : AidlAnnotation(location, name, {}) {}
172
173AidlAnnotation::AidlAnnotation(
174 const AidlLocation& location, const string& name,
175 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
176 : AidlNode(location), name_(name), parameters_(std::move(parameters)) {}
177
178bool AidlAnnotation::CheckValid() const {
179 auto supported_params_iterator = kAnnotationParameters.find(GetName());
180 if (supported_params_iterator == kAnnotationParameters.end()) {
181 AIDL_ERROR(this) << GetName() << " annotation does not have any supported parameters.";
182 return false;
183 }
184 const auto& supported_params = supported_params_iterator->second;
185 for (const auto& name_and_param : parameters_) {
186 const std::string& param_name = name_and_param.first;
187 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Will McVickerd7d18df2019-09-12 13:40:50 -0700188 if (!param->CheckValid()) {
189 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
190 << GetName() << ".";
191 return false;
192 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100193 auto parameter_mapping_it = supported_params.find(param_name);
194 if (parameter_mapping_it == supported_params.end()) {
195 std::ostringstream stream;
196 stream << "Parameter " << param_name << " not supported ";
197 stream << "for annotation " << GetName() << ".";
198 stream << "It must be one of:";
199 for (const auto& kv : supported_params) {
200 stream << " " << kv.first;
201 }
202 AIDL_ERROR(this) << stream.str();
203 return false;
204 }
205 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700206 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100207 // Assume error on empty string.
208 if (param_value == "") {
209 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
210 << GetName() << ".";
211 return false;
212 }
213 }
214 return true;
215}
216
217std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
218 const ConstantValueDecorator& decorator) const {
219 std::map<std::string, std::string> raw_params;
220 const auto& supported_params = kAnnotationParameters.at(GetName());
221 for (const auto& name_and_param : parameters_) {
222 const std::string& param_name = name_and_param.first;
223 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
224 AidlTypeSpecifier type{AIDL_LOCATION_HERE, supported_params.at(param_name), false, nullptr, ""};
Will McVickerd7d18df2019-09-12 13:40:50 -0700225 if (!param->CheckValid()) {
226 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
227 << GetName() << ".";
228 raw_params.clear();
229 return raw_params;
230 }
231
232 raw_params.emplace(param_name, param->ValueString(type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100233 }
234 return raw_params;
235}
Steven Moreland46e9da82018-07-27 15:45:29 -0700236
Daniel Norman37d43dd2019-09-09 17:22:34 -0700237std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
238 if (parameters_.empty()) {
239 return "@" + GetName();
240 } else {
241 vector<string> param_strings;
242 for (const auto& [name, value] : AnnotationParams(decorator)) {
243 param_strings.emplace_back(name + "=" + value);
244 }
245 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
246 }
247}
248
Jiyong Parka6605ab2018-11-11 14:30:21 +0900249static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900250 for (const auto& a : annotations) {
Steven Moreland3be75772018-08-20 13:27:43 -0700251 if (a.GetName() == name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900252 return true;
253 }
254 }
255 return false;
256}
257
Andrei Onea9445fc62019-06-27 18:11:59 +0100258static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
259 const string& name) {
260 for (const auto& a : annotations) {
261 if (a.GetName() == name) {
262 return &a;
263 }
264 }
265 return nullptr;
266}
267
Steven Moreland46e9da82018-07-27 15:45:29 -0700268AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
269
Jiyong Park68bc77a2018-07-19 19:00:45 +0900270bool AidlAnnotatable::IsNullable() const {
271 return HasAnnotation(annotations_, kNullable);
272}
273
Jiyong Park68bc77a2018-07-19 19:00:45 +0900274bool AidlAnnotatable::IsUtf8InCpp() const {
275 return HasAnnotation(annotations_, kUtf8InCpp);
276}
277
Steven Morelanda57d0a62019-07-30 09:41:14 -0700278bool AidlAnnotatable::IsVintfStability() const {
279 return HasAnnotation(annotations_, kVintfStability);
280}
281
Andrei Onea9445fc62019-06-27 18:11:59 +0100282const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
283 return GetAnnotation(annotations_, kUnsupportedAppUsage);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900284}
285
Daniel Norman716d3112019-09-10 13:11:56 -0700286const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700287 auto annotation = GetAnnotation(annotations_, kBacking);
288 if (annotation != nullptr) {
289 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
290 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
291 const string& type = it->second;
Daniel Norman716d3112019-09-10 13:11:56 -0700292 AidlTypeSpecifier* type_specifier =
293 new AidlTypeSpecifier(AIDL_LOCATION_HERE,
294 // Strip the quotes off the type String.
295 type.substr(1, type.length() - 2), false, nullptr, "");
296 type_specifier->Resolve(typenames);
297 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700298 }
299 }
300 return nullptr;
301}
302
Jeongik Cha88f95a82020-01-15 13:02:16 +0900303bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
304 return HasAnnotation(annotations_, kJavaStableParcelable) && lang == Options::Language::JAVA;
Jeongik Cha82317dd2019-02-27 20:26:11 +0900305}
306
Makoto Onuki00be5c72020-03-04 16:57:23 -0800307bool AidlAnnotatable::IsHide() const {
308 return HasAnnotation(annotations_, kHide);
309}
310
Steven Moreland71998bf2020-02-20 18:10:42 -0800311void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
312 if (annotations_.empty()) return;
313
314 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
315}
316
Andrei Onea9445fc62019-06-27 18:11:59 +0100317bool AidlAnnotatable::CheckValidAnnotations() const {
318 for (const auto& annotation : GetAnnotations()) {
319 if (!annotation.CheckValid()) {
320 return false;
321 }
322 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700323
Andrei Onea9445fc62019-06-27 18:11:59 +0100324 return true;
325}
326
Jiyong Park68bc77a2018-07-19 19:00:45 +0900327string AidlAnnotatable::ToString() const {
328 vector<string> ret;
329 for (const auto& a : annotations_) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700330 ret.emplace_back(a.ToString(AidlConstantValueDecorator));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900331 }
332 std::sort(ret.begin(), ret.end());
333 return Join(ret, " ");
334}
335
Steven Moreland46e9da82018-07-27 15:45:29 -0700336AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
337 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900338 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700339 const string& comments)
340 : AidlAnnotatable(location),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900341 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700342 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700343 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900344 comments_(comments),
345 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700346
Steven Moreland3f658cf2018-08-20 13:40:54 -0700347AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
348 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900349 // Declaring array of generic type cannot happen, it is grammar error.
350 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700351
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800352 AidlTypeSpecifier array_base = *this;
353 array_base.is_array_ = false;
354 return array_base;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700355}
356
Jeongik Cha997281d2020-01-16 15:23:59 +0900357bool AidlTypeSpecifier::IsHidden() const {
358 return HasHideComment(GetComments());
359}
360
Jiyong Park1deecc32018-07-17 01:14:41 +0900361string AidlTypeSpecifier::ToString() const {
362 string ret = GetName();
363 if (IsGeneric()) {
364 vector<string> arg_names;
365 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +0900366 arg_names.emplace_back(ta->ToString());
367 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900368 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900369 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900370 if (IsArray()) {
371 ret += "[]";
372 }
373 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900374}
375
Jiyong Park02da7422018-07-16 16:00:26 +0900376string AidlTypeSpecifier::Signature() const {
377 string ret = ToString();
378 string annotations = AidlAnnotatable::ToString();
379 if (annotations != "") {
380 ret = annotations + " " + ret;
381 }
382 return ret;
383}
384
Daniel Norman716d3112019-09-10 13:11:56 -0700385bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland9731c632019-08-13 10:21:08 -0700386 CHECK(!IsResolved());
Jiyong Park1deecc32018-07-17 01:14:41 +0900387 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
388 if (result.second) {
389 fully_qualified_name_ = result.first;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900390 split_name_ = Split(fully_qualified_name_, ".");
Jiyong Parkccf00f82018-07-17 01:39:23 +0900391 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900392 return result.second;
Casey Dahlin70078e62015-09-30 17:01:30 -0700393}
394
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900395bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100396 if (!CheckValidAnnotations()) {
397 return false;
398 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900399 if (IsGeneric()) {
400 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900401
402 auto& types = GetTypeParameters();
403 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
404 if (type_name == "List" || type_name == "Map") {
405 if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
406 return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
407 })) {
408 AIDL_ERROR(this) << "A generic type cannot has any primitive type parameters.";
409 return false;
410 }
411 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800412 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900413 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800414 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
415 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900416 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800417 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900418 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800419 if (num_params > 1) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900420 AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
421 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900422 return false;
423 }
424 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800425 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900426 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
427 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900428 return false;
429 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800430 if (num_params == 2) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900431 const string& key_type = GetTypeParameters()[0]->GetName();
432 if (key_type != "String") {
433 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
434 << "'" << key_type << "'";
435 return false;
436 }
437 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800438 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900439 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800440 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900441 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800442 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900443 return false;
444 }
445 } else {
446 AIDL_ERROR(this) << type_name << " is not a generic type.";
447 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900448 }
449 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900450
Steven Moreland11cb9452020-01-21 16:56:58 -0800451 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
452 GetTypeParameters().size() == 1 &&
453 GetTypeParameters()[0]->GetName() == "String";
454 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
455 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
456 return false;
457 }
458
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900459 if (GetName() == "void") {
460 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
461 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
462 return false;
463 }
464 }
465
466 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800467 const auto defined_type = typenames.TryGetDefinedType(GetName());
468 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900469 AIDL_ERROR(this) << "Binder type cannot be an array";
470 return false;
471 }
472 }
473
474 if (IsNullable()) {
475 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
476 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
477 return false;
478 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800479 const auto defined_type = typenames.TryGetDefinedType(GetName());
480 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700481 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
482 return false;
483 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900484 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900485 return true;
486}
487
Steven Moreland860b1942018-08-16 14:59:28 -0700488std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
489 const std::string& raw_value) {
490 return raw_value;
491}
492
Steven Moreland46e9da82018-07-27 15:45:29 -0700493AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
494 AidlTypeSpecifier* type, const std::string& name)
495 : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700496
Steven Moreland46e9da82018-07-27 15:45:29 -0700497AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
498 AidlTypeSpecifier* type, const std::string& name,
499 AidlConstantValue* default_value)
500 : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700501
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900502bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700503 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900504 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900505
Steven Moreland54be7bd2019-12-05 11:17:53 -0800506 if (type_->GetName() == "void") {
507 AIDL_ERROR(this) << "Declaration " << name_
508 << " is void, but declarations cannot be of void type.";
509 valid = false;
510 }
511
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900512 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700513 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700514
Steven Moreland25294322018-08-07 18:13:55 -0700515 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700516
Steven Moreland860b1942018-08-16 14:59:28 -0700517 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700518}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700519
520string AidlVariableDeclaration::ToString() const {
Jeongik Cha3271ffa2018-12-04 15:19:20 +0900521 string ret = type_->Signature() + " " + name_;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700522 if (default_value_ != nullptr) {
Steven Moreland860b1942018-08-16 14:59:28 -0700523 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700524 }
525 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700526}
527
Jiyong Park02da7422018-07-16 16:00:26 +0900528string AidlVariableDeclaration::Signature() const {
529 return type_->Signature() + " " + name_;
530}
531
Steven Moreland860b1942018-08-16 14:59:28 -0700532std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900533 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700534 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900535 } else {
536 return "";
537 }
Steven Moreland25294322018-08-07 18:13:55 -0700538}
539
Steven Moreland46e9da82018-07-27 15:45:29 -0700540AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
541 AidlTypeSpecifier* type, const std::string& name)
542 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700543 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700544 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700545
Steven Moreland46e9da82018-07-27 15:45:29 -0700546AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
547 const std::string& name)
548 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700549 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700550 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700551
Jiyong Park02da7422018-07-16 16:00:26 +0900552string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700553 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700554 if (direction_specified_) {
555 switch(direction_) {
556 case AidlArgument::IN_DIR:
557 ret += "in ";
558 break;
559 case AidlArgument::OUT_DIR:
560 ret += "out ";
561 break;
562 case AidlArgument::INOUT_DIR:
563 ret += "inout ";
564 break;
565 }
566 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700567 return ret;
568}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700569
Jiyong Park02da7422018-07-16 16:00:26 +0900570string AidlArgument::ToString() const {
571 return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
572}
573
574std::string AidlArgument::Signature() const {
Steven Moreland46e9da82018-07-27 15:45:29 -0700575 class AidlInterface;
576 class AidlInterface;
577 class AidlParcelable;
578 class AidlStructuredParcelable;
579 class AidlParcelable;
580 class AidlStructuredParcelable;
Jiyong Park02da7422018-07-16 16:00:26 +0900581 return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
582}
583
Steven Moreland46e9da82018-07-27 15:45:29 -0700584AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
585
Steven Moreland46e9da82018-07-27 15:45:29 -0700586AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
587 AidlTypeSpecifier* type, const std::string& name,
588 AidlConstantValue* value)
589 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700590
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900591bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700592 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900593 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700594 valid &= value_->CheckValid();
595 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700596
Steven Moreland25294322018-08-07 18:13:55 -0700597 const static set<string> kSupportedConstTypes = {"String", "int"};
598 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
599 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700600 return false;
601 }
602
Will McVickerd7d18df2019-09-12 13:40:50 -0700603 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700604}
605
Jiyong Parka428d212018-08-29 22:26:30 +0900606string AidlConstantDeclaration::ToString() const {
607 return "const " + type_->ToString() + " " + name_ + " = " +
608 ValueString(AidlConstantValueDecorator);
609}
610
611string AidlConstantDeclaration::Signature() const {
612 return type_->Signature() + " " + name_;
613}
614
Steven Moreland46e9da82018-07-27 15:45:29 -0700615AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
616 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900617 const std::string& comments)
618 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
619 has_id_ = false;
620}
621
622AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
623 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900624 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700625 : AidlMember(location),
626 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700627 comments_(comments),
628 type_(type),
629 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700630 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900631 id_(id),
632 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700633 has_id_ = true;
634 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700635 for (const unique_ptr<AidlArgument>& a : arguments_) {
636 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
637 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
638 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700639}
640
Jeongik Cha997281d2020-01-16 15:23:59 +0900641bool AidlMethod::IsHidden() const {
642 return HasHideComment(GetComments());
643}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700644
Jiyong Park02da7422018-07-16 16:00:26 +0900645string AidlMethod::Signature() const {
646 vector<string> arg_signatures;
647 for (const auto& arg : GetArguments()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900648 arg_signatures.emplace_back(arg->GetType().ToString());
Jiyong Park02da7422018-07-16 16:00:26 +0900649 }
Jiyong Park309668e2018-07-28 16:55:44 +0900650 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
651}
652
653string AidlMethod::ToString() const {
654 vector<string> arg_strings;
655 for (const auto& arg : GetArguments()) {
656 arg_strings.emplace_back(arg->Signature());
657 }
Steven Moreland4ee68632018-12-14 15:52:46 -0800658 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
659 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900660 if (HasId()) {
661 ret += " = " + std::to_string(GetId());
662 }
663 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900664}
665
Steven Moreland46e9da82018-07-27 15:45:29 -0700666AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
667 const std::string& comments,
Steven Moreland787b0432018-07-03 09:00:58 -0700668 const std::vector<std::string>& package)
Steven Moreland46e9da82018-07-27 15:45:29 -0700669 : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700670
671std::string AidlDefinedType::GetPackage() const {
672 return Join(package_, '.');
673}
674
Jeongik Cha997281d2020-01-16 15:23:59 +0900675bool AidlDefinedType::IsHidden() const {
676 return HasHideComment(GetComments());
677}
678
Steven Moreland787b0432018-07-03 09:00:58 -0700679std::string AidlDefinedType::GetCanonicalName() const {
680 if (package_.empty()) {
681 return GetName();
682 }
683 return GetPackage() + "." + GetName();
684}
685
Steven Moreland9f2a4332020-02-21 16:01:09 -0800686void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
687 if (this->IsHidden()) {
688 AddHideComment(writer);
689 }
690 DumpAnnotations(writer);
691}
692
Steven Moreland46e9da82018-07-27 15:45:29 -0700693AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900694 const std::vector<std::string>& package, const std::string& comments,
Jeongik Chadf76dc72019-11-28 00:08:47 +0900695 const std::string& cpp_header, std::vector<std::string>* type_params)
Jiyong Parka6605ab2018-11-11 14:30:21 +0900696 : AidlDefinedType(location, name->GetDotName(), comments, package),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900697 AidlParameterizable<std::string>(type_params),
Steven Moreland787b0432018-07-03 09:00:58 -0700698 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800699 cpp_header_(cpp_header) {
700 // Strip off quotation marks if we actually have a cpp header.
701 if (cpp_header_.length() >= 2) {
702 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
703 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700704}
Jeongik Chadf76dc72019-11-28 00:08:47 +0900705template <typename T>
706AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
707 // Copying is not supported if it has type parameters.
708 // It doesn't make a problem because only ArrayBase() makes a copy,
709 // and it can be called only if a type is not generic.
710 CHECK(!other.IsGeneric());
711}
712
713template <typename T>
714bool AidlParameterizable<T>::CheckValid() const {
715 return true;
716};
717
718template <>
719bool AidlParameterizable<std::string>::CheckValid() const {
720 if (!IsGeneric()) {
721 return true;
722 }
723 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
724 if (set.size() != GetTypeParameters().size()) {
725 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
726 return false;
727 }
728 return true;
729}
Casey Dahlin59401da2015-10-09 18:16:45 -0700730
Jeongik Cha82317dd2019-02-27 20:26:11 +0900731bool AidlParcelable::CheckValid(const AidlTypenames&) const {
Jeongik Cha88f95a82020-01-15 13:02:16 +0900732 static const std::set<string> allowed{kJavaStableParcelable};
Andrei Onea9445fc62019-06-27 18:11:59 +0100733 if (!CheckValidAnnotations()) {
734 return false;
735 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900736 if (!AidlParameterizable<std::string>::CheckValid()) {
737 return false;
738 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900739 for (const auto& v : GetAnnotations()) {
740 if (allowed.find(v.GetName()) == allowed.end()) {
741 std::ostringstream stream;
742 stream << "Unstructured parcelable can contain only";
743 for (const string& kv : allowed) {
744 stream << " " << kv;
745 }
746 stream << ".";
747 AIDL_ERROR(this) << stream.str();
748 return false;
749 }
750 }
751
752 return true;
753}
754
Jeongik Cha997281d2020-01-16 15:23:59 +0900755void AidlParcelable::Dump(CodeWriter* writer) const {
Steven Moreland9f2a4332020-02-21 16:01:09 -0800756 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900757 writer->Write("parcelable %s ;\n", GetName().c_str());
758}
759
Steven Moreland5557f1c2018-07-02 13:50:23 -0700760AidlStructuredParcelable::AidlStructuredParcelable(
Steven Moreland46e9da82018-07-27 15:45:29 -0700761 const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900762 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
763 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
Steven Moreland46e9da82018-07-27 15:45:29 -0700764 variables_(std::move(*variables)) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700765
Jeongik Cha997281d2020-01-16 15:23:59 +0900766void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
Steven Moreland9f2a4332020-02-21 16:01:09 -0800767 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900768 writer->Write("parcelable %s {\n", GetName().c_str());
769 writer->Indent();
770 for (const auto& field : GetFields()) {
Jeongik Cha997281d2020-01-16 15:23:59 +0900771 if (field->GetType().IsHidden()) {
772 AddHideComment(writer);
773 }
Jiyong Parka468e2a2018-08-29 21:25:18 +0900774 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900775 }
776 writer->Dedent();
777 writer->Write("}\n");
778}
779
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900780bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700781 bool success = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900782 for (const auto& v : GetFields()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700783 success = success && v->CheckValid(typenames);
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900784 }
Daniel Norman85aed542019-08-21 12:01:14 -0700785 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900786}
787
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900788// TODO: we should treat every backend all the same in future.
789bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
Steven Moreland04b07e12020-01-21 18:11:07 -0800790 if (lang != Options::Language::JAVA) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900791 if (this->GetName() == "List" && !this->IsGeneric()) {
Steven Moreland04b07e12020-01-21 18:11:07 -0800792 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900793 return false;
794 }
795 }
Steven Morelandc8a4ca82020-01-21 17:50:08 -0800796 if (this->GetName() == "FileDescriptor" && lang == Options::Language::NDK) {
797 AIDL_ERROR(this) << "FileDescriptor isn't supported with the NDK.";
798 return false;
799 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900800 if (this->IsGeneric()) {
801 if (this->GetName() == "List") {
802 if (this->GetTypeParameters().size() != 1) {
803 AIDL_ERROR(this) << "List must have only one type parameter.";
804 return false;
805 }
806 if (lang == Options::Language::CPP) {
807 auto& name = this->GetTypeParameters()[0]->GetName();
808 if (!(name == "String" || name == "IBinder")) {
809 AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
810 return false;
811 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900812 } else if (lang == Options::Language::JAVA) {
813 const string& contained_type = this->GetTypeParameters()[0]->GetName();
814 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
815 if (contained_type != "String" && contained_type != "IBinder" &&
816 contained_type != "ParcelFileDescriptor") {
817 AIDL_ERROR(this) << "List<" << contained_type << "> isn't supported in Java";
818 return false;
819 }
820 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900821 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900822 }
823 }
Jeongik Chab75a4512020-01-10 13:37:04 +0900824 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900825 if (lang != Options::Language::JAVA) {
Jeongik Chab75a4512020-01-10 13:37:04 +0900826 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900827 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900828 }
829 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900830 if (lang == Options::Language::JAVA) {
831 const string name = this->GetName();
832 // List[], Map[], CharSequence[] are not supported.
833 if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
834 if (name == "List" || name == "Map" || name == "CharSequence") {
835 AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
836 return false;
837 }
838 }
839 }
840
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900841 return true;
842}
843
844// TODO: we should treat every backend all the same in future.
845bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
846 if (lang != Options::Language::JAVA) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800847 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
848 if (unstructured_parcelable != nullptr) {
849 if (unstructured_parcelable->GetCppHeader().empty()) {
850 AIDL_ERROR(unstructured_parcelable)
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900851 << "Unstructured parcelable must have C++ header defined.";
852 return false;
853 }
854 }
855 }
856 return true;
857}
858
859// TODO: we should treat every backend all the same in future.
860bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
861 if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
862 return false;
863 }
864 for (const auto& v : this->GetFields()) {
865 if (!v->GetType().LanguageSpecificCheckValid(lang)) {
866 return false;
867 }
868 }
869 return true;
870}
871
Daniel Norman85aed542019-08-21 12:01:14 -0700872AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700873 AidlConstantValue* value, const std::string& comments)
874 : AidlNode(location), name_(name), value_(value), comments_(comments) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700875
876bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
877 if (GetValue() == nullptr) {
878 return false;
879 }
880 if (!GetValue()->CheckValid()) {
881 return false;
882 }
Will McVickerd7d18df2019-09-12 13:40:50 -0700883 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700884 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
885 return false;
886 }
887 return true;
888}
889
890string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
891 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -0700892 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -0700893}
894
895AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
896 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700897 const std::vector<std::string>& package,
898 const std::string& comments)
899 : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700900
901void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
902 backing_type_ = std::move(type);
903}
904
Steven Moreland59e53e42019-11-26 20:38:08 -0800905bool AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -0700906 const AidlEnumerator* previous = nullptr;
907 for (const auto& enumerator : enumerators_) {
908 if (enumerator->GetValue() == nullptr) {
909 if (previous == nullptr) {
910 enumerator->SetValue(std::unique_ptr<AidlConstantValue>(
911 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "0")));
912 } else {
Steven Moreland59e53e42019-11-26 20:38:08 -0800913 auto prev_value = std::unique_ptr<AidlConstantValue>(
914 AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
915 if (prev_value == nullptr) {
916 return false;
917 }
Daniel Normanb28684e2019-10-17 15:31:39 -0700918 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Steven Moreland59e53e42019-11-26 20:38:08 -0800919 AIDL_LOCATION_HERE, std::move(prev_value), "+",
Daniel Normanb28684e2019-10-17 15:31:39 -0700920 std::unique_ptr<AidlConstantValue>(
921 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
922 }
923 }
924 previous = enumerator.get();
925 }
Steven Moreland59e53e42019-11-26 20:38:08 -0800926 return true;
Daniel Normanb28684e2019-10-17 15:31:39 -0700927}
928
Daniel Norman85aed542019-08-21 12:01:14 -0700929bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
930 if (backing_type_ == nullptr) {
931 AIDL_ERROR(this) << "Enum declaration missing backing type.";
932 return false;
933 }
934 bool success = true;
935 for (const auto& enumerator : enumerators_) {
936 success = success && enumerator->CheckValid(GetBackingType());
937 }
938 return success;
939}
940
Jeongik Cha997281d2020-01-16 15:23:59 +0900941void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
Steven Moreland9f2a4332020-02-21 16:01:09 -0800942 DumpHeader(writer);
Daniel Norman37d43dd2019-09-09 17:22:34 -0700943 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -0700944 writer->Indent();
945 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700946 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
947 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
948 }
949 writer->Dedent();
950 writer->Write("}\n");
951}
952
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900953// TODO: we should treat every backend all the same in future.
954bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
955 for (const auto& m : this->GetMethods()) {
956 if (!m->GetType().LanguageSpecificCheckValid(lang)) {
957 return false;
958 }
959 for (const auto& arg : m->GetArguments()) {
960 if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
961 return false;
962 }
963 }
964 }
965 return true;
966}
967
Steven Moreland46e9da82018-07-27 15:45:29 -0700968AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700969 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800970 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700971 const std::vector<std::string>& package)
Steven Morelandacd53472018-12-14 10:17:26 -0800972 : AidlDefinedType(location, name, comments, package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800973 for (auto& member : *members) {
974 AidlMember* local = member.release();
975 AidlMethod* method = local->AsMethod();
Steven Moreland693640b2018-07-19 13:46:27 -0700976 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
977
978 CHECK(method == nullptr || constant == nullptr);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800979
980 if (method) {
Steven Moreland8c70ba92018-12-17 10:20:31 -0800981 method->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800982 methods_.emplace_back(method);
Steven Moreland693640b2018-07-19 13:46:27 -0700983 } else if (constant) {
984 constants_.emplace_back(constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800985 } else {
Steven Moreland46e9da82018-07-27 15:45:29 -0700986 AIDL_FATAL(this) << "Member is neither method nor constant!";
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800987 }
988 }
989
990 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700991}
992
Jeongik Cha997281d2020-01-16 15:23:59 +0900993void AidlInterface::Dump(CodeWriter* writer) const {
Steven Moreland9f2a4332020-02-21 16:01:09 -0800994 DumpHeader(writer);
Jiyong Park02da7422018-07-16 16:00:26 +0900995 writer->Write("interface %s {\n", GetName().c_str());
996 writer->Indent();
997 for (const auto& method : GetMethods()) {
Jeongik Cha997281d2020-01-16 15:23:59 +0900998 if (method->IsHidden()) {
999 AddHideComment(writer);
1000 }
Jiyong Park309668e2018-07-28 16:55:44 +09001001 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +09001002 }
Jiyong Parka428d212018-08-29 22:26:30 +09001003 for (const auto& constdecl : GetConstantDeclarations()) {
Jeongik Cha997281d2020-01-16 15:23:59 +09001004 if (constdecl->GetType().IsHidden()) {
1005 AddHideComment(writer);
1006 }
Jiyong Parka428d212018-08-29 22:26:30 +09001007 writer->Write("%s;\n", constdecl->ToString().c_str());
1008 }
Jiyong Park02da7422018-07-16 16:00:26 +09001009 writer->Dedent();
1010 writer->Write("}\n");
1011}
1012
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001013bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +01001014 if (!CheckValidAnnotations()) {
1015 return false;
1016 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001017 // Has to be a pointer due to deleting copy constructor. No idea why.
1018 map<string, const AidlMethod*> method_names;
1019 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001020 if (!m->GetType().CheckValid(typenames)) {
1021 return false;
1022 }
1023
Steven Morelandacd53472018-12-14 10:17:26 -08001024 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001025 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1026 return false;
1027 }
1028
1029 set<string> argument_names;
1030 for (const auto& arg : m->GetArguments()) {
1031 auto it = argument_names.find(arg->GetName());
1032 if (it != argument_names.end()) {
1033 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1034 << arg->GetName() << "'";
1035 return false;
1036 }
1037 argument_names.insert(arg->GetName());
1038
1039 if (!arg->GetType().CheckValid(typenames)) {
1040 return false;
1041 }
1042
Steven Morelandacd53472018-12-14 10:17:26 -08001043 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001044 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1045 return false;
1046 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001047 const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
1048 if (!arg->DirectionWasSpecified() && can_be_out) {
1049 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
1050 << "' can be an out type, so you must declare it as in, out, or inout.";
1051 return false;
1052 }
1053
1054 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
1055 AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1056 return false;
1057 }
1058
1059 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001060 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001061 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1062 return false;
1063 }
1064
1065 // Reserve a namespace for internal use
1066 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1067 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1068 return false;
1069 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001070 }
1071
1072 auto it = method_names.find(m->GetName());
1073 // prevent duplicate methods
1074 if (it == method_names.end()) {
1075 method_names[m->GetName()] = m.get();
1076 } else {
1077 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1078 AIDL_ERROR(it->second) << "previously defined here.";
1079 return false;
1080 }
1081
Paul Trautrimb77048c2020-01-21 16:39:32 +09001082 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001083 "getTransactionName(int)"};
1084
1085 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1086 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
1087 return false;
1088 }
1089 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001090
1091 bool success = true;
1092 set<string> constant_names;
1093 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1094 if (constant_names.count(constant->GetName()) > 0) {
1095 LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
1096 success = false;
1097 }
1098 constant_names.insert(constant->GetName());
1099 success = success && constant->CheckValid(typenames);
1100 }
1101
1102 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001103}
1104
Steven Moreland46e9da82018-07-27 15:45:29 -07001105AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
1106 const std::string& comments)
1107 : AidlNode(location), terms_({term}), comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001108 if (term.find('.') != string::npos) {
1109 terms_ = Split(term, ".");
Steven Moreland46e9da82018-07-27 15:45:29 -07001110 for (const auto& subterm : terms_) {
1111 if (subterm.empty()) {
1112 AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001113 }
1114 }
1115 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001116}
1117
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -07001118void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001119 terms_.push_back(term);
1120}
1121
Steven Moreland46e9da82018-07-27 15:45:29 -07001122AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1123 : AidlNode(location), needed_class_(needed_class) {}
Casey Dahlin0edf3422015-10-07 12:34:59 -07001124
Steven Moreland64e29be2018-08-08 18:52:19 -07001125std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
1126 const android::aidl::IoDelegate& io_delegate,
1127 AidlTypenames& typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001128 // Make sure we can read the file first, before trashing previous state.
Steven Moreland64e29be2018-08-08 18:52:19 -07001129 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
1130 if (raw_buffer == nullptr) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001131 AIDL_ERROR(filename) << "Error while opening file for parsing";
Steven Moreland64e29be2018-08-08 18:52:19 -07001132 return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001133 }
1134
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001135 // We're going to scan this buffer in place, and yacc demands we put two
1136 // nulls at the end.
Steven Moreland64e29be2018-08-08 18:52:19 -07001137 raw_buffer->append(2u, '\0');
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001138
Steven Moreland64e29be2018-08-08 18:52:19 -07001139 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001140
Steven Moreland64e29be2018-08-08 18:52:19 -07001141 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001142
Steven Moreland64e29be2018-08-08 18:52:19 -07001143 return parser;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001144}
1145
Christopher Wiley90be4e32015-10-20 14:55:25 -07001146std::vector<std::string> Parser::Package() const {
1147 if (!package_) {
1148 return {};
1149 }
1150 return package_->GetTerms();
1151}
1152
Steven Morelandd1039a92020-01-23 09:49:43 -08001153void Parser::AddImport(std::unique_ptr<AidlImport>&& import) {
Jiyong Park8f6ec462020-01-19 20:52:47 +09001154 for (const auto& i : imports_) {
1155 if (i->GetNeededClass() == import->GetNeededClass()) {
1156 return;
1157 }
1158 }
Steven Morelandd1039a92020-01-23 09:49:43 -08001159 imports_.emplace_back(std::move(import));
Casey Dahline2507492015-09-14 17:11:20 -07001160}
Jiyong Park1deecc32018-07-17 01:14:41 +09001161
1162bool Parser::Resolve() {
1163 bool success = true;
1164 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +09001165 if (!typespec->Resolve(typenames_)) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001166 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
Jiyong Park1deecc32018-07-17 01:14:41 +09001167 success = false;
1168 // don't stop to show more errors if any
1169 }
1170 }
1171 return success;
1172}
Steven Moreland64e29be2018-08-08 18:52:19 -07001173
1174Parser::Parser(const std::string& filename, std::string& raw_buffer,
1175 android::aidl::AidlTypenames& typenames)
1176 : filename_(filename), typenames_(typenames) {
1177 yylex_init(&scanner_);
1178 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
1179}
1180
1181Parser::~Parser() {
1182 yy_delete_buffer(buffer_, scanner_);
1183 yylex_destroy(scanner_);
1184}