blob: 92571ade64f7b1db01ea96909552c56cc8923c62 [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
338 AidlTypeSpecifier arrayBase = *this;
339 arrayBase.is_array_ = false;
340 return arrayBase;
341}
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 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900394 const auto definedType = typenames.TryGetDefinedType(type_name);
395 const auto parameterizable =
396 definedType != nullptr ? definedType->AsParameterizable() : nullptr;
397 const bool isUserDefinedGenericType =
398 parameterizable != nullptr && parameterizable->IsGeneric();
399 const size_t num = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900400 if (type_name == "List") {
401 if (num > 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") {
407 if (num != 0 && num != 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 }
Jeongik Chae48d9942020-01-02 17:39:00 +0900412 if (num == 2) {
413 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 }
Jeongik Chadf76dc72019-11-28 00:08:47 +0900420 } else if (isUserDefinedGenericType) {
421 const size_t allowed = parameterizable->GetTypeParameters().size();
422 if (num != allowed) {
423 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
424 << num;
425 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()) {
441 const auto definedType = typenames.TryGetDefinedType(GetName());
442 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
443 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 }
Daniel Normanee8674f2019-09-20 16:07:00 -0700453 const auto definedType = typenames.TryGetDefinedType(GetName());
454 if (definedType != nullptr && definedType->AsEnumDeclaration() != nullptr && !IsArray()) {
455 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 {
745 if (lang == Options::Language::CPP) {
746 if (this->GetName() == "List" && !this->IsGeneric()) {
747 AIDL_ERROR(this) << "List without type isn't supported in cpp.";
748 return false;
749 }
750 }
751 if (this->IsGeneric()) {
752 if (this->GetName() == "List") {
753 if (this->GetTypeParameters().size() != 1) {
754 AIDL_ERROR(this) << "List must have only one type parameter.";
755 return false;
756 }
757 if (lang == Options::Language::CPP) {
758 auto& name = this->GetTypeParameters()[0]->GetName();
759 if (!(name == "String" || name == "IBinder")) {
760 AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
761 return false;
762 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900763 } else if (lang == Options::Language::JAVA) {
764 const string& contained_type = this->GetTypeParameters()[0]->GetName();
765 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
766 if (contained_type != "String" && contained_type != "IBinder" &&
767 contained_type != "ParcelFileDescriptor") {
768 AIDL_ERROR(this) << "List<" << contained_type << "> isn't supported in Java";
769 return false;
770 }
771 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900772 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900773 }
774 }
Jeongik Chab75a4512020-01-10 13:37:04 +0900775 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900776 if (lang != Options::Language::JAVA) {
Jeongik Chab75a4512020-01-10 13:37:04 +0900777 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
Jeongik Chabb55b5e2020-01-07 23:11:26 +0900778 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900779 }
780 }
Jeongik Cha08ca2182019-11-21 14:01:13 +0900781 if (lang == Options::Language::JAVA) {
782 const string name = this->GetName();
783 // List[], Map[], CharSequence[] are not supported.
784 if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
785 if (name == "List" || name == "Map" || name == "CharSequence") {
786 AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
787 return false;
788 }
789 }
790 }
791
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900792 return true;
793}
794
795// TODO: we should treat every backend all the same in future.
796bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
797 if (lang != Options::Language::JAVA) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900798 const AidlParcelable* unstructuredParcelable = this->AsUnstructuredParcelable();
799 if (unstructuredParcelable != nullptr) {
800 if (unstructuredParcelable->GetCppHeader().empty()) {
801 AIDL_ERROR(unstructuredParcelable)
802 << "Unstructured parcelable must have C++ header defined.";
803 return false;
804 }
805 }
806 }
807 return true;
808}
809
810// TODO: we should treat every backend all the same in future.
811bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
812 if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
813 return false;
814 }
815 for (const auto& v : this->GetFields()) {
816 if (!v->GetType().LanguageSpecificCheckValid(lang)) {
817 return false;
818 }
819 }
820 return true;
821}
822
Daniel Norman85aed542019-08-21 12:01:14 -0700823AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700824 AidlConstantValue* value, const std::string& comments)
825 : AidlNode(location), name_(name), value_(value), comments_(comments) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700826
827bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
828 if (GetValue() == nullptr) {
829 return false;
830 }
831 if (!GetValue()->CheckValid()) {
832 return false;
833 }
Will McVickerd7d18df2019-09-12 13:40:50 -0700834 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700835 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
836 return false;
837 }
838 return true;
839}
840
841string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
842 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -0700843 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -0700844}
845
846AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
847 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Daniel Norman2e4112d2019-10-03 10:22:35 -0700848 const std::vector<std::string>& package,
849 const std::string& comments)
850 : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
Daniel Norman85aed542019-08-21 12:01:14 -0700851
852void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
853 backing_type_ = std::move(type);
854}
855
Steven Moreland59e53e42019-11-26 20:38:08 -0800856bool AidlEnumDeclaration::Autofill() {
Daniel Normanb28684e2019-10-17 15:31:39 -0700857 const AidlEnumerator* previous = nullptr;
858 for (const auto& enumerator : enumerators_) {
859 if (enumerator->GetValue() == nullptr) {
860 if (previous == nullptr) {
861 enumerator->SetValue(std::unique_ptr<AidlConstantValue>(
862 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "0")));
863 } else {
Steven Moreland59e53e42019-11-26 20:38:08 -0800864 auto prev_value = std::unique_ptr<AidlConstantValue>(
865 AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
866 if (prev_value == nullptr) {
867 return false;
868 }
Daniel Normanb28684e2019-10-17 15:31:39 -0700869 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Steven Moreland59e53e42019-11-26 20:38:08 -0800870 AIDL_LOCATION_HERE, std::move(prev_value), "+",
Daniel Normanb28684e2019-10-17 15:31:39 -0700871 std::unique_ptr<AidlConstantValue>(
872 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
873 }
874 }
875 previous = enumerator.get();
876 }
Steven Moreland59e53e42019-11-26 20:38:08 -0800877 return true;
Daniel Normanb28684e2019-10-17 15:31:39 -0700878}
879
Daniel Norman85aed542019-08-21 12:01:14 -0700880bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
881 if (backing_type_ == nullptr) {
882 AIDL_ERROR(this) << "Enum declaration missing backing type.";
883 return false;
884 }
885 bool success = true;
886 for (const auto& enumerator : enumerators_) {
887 success = success && enumerator->CheckValid(GetBackingType());
888 }
889 return success;
890}
891
892void AidlEnumDeclaration::Write(CodeWriter* writer) const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700893 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
894 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -0700895 writer->Indent();
896 for (const auto& enumerator : GetEnumerators()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700897 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
898 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
899 }
900 writer->Dedent();
901 writer->Write("}\n");
902}
903
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900904// TODO: we should treat every backend all the same in future.
905bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
906 for (const auto& m : this->GetMethods()) {
907 if (!m->GetType().LanguageSpecificCheckValid(lang)) {
908 return false;
909 }
910 for (const auto& arg : m->GetArguments()) {
911 if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
912 return false;
913 }
914 }
915 }
916 return true;
917}
918
Steven Moreland46e9da82018-07-27 15:45:29 -0700919AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700920 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800921 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700922 const std::vector<std::string>& package)
Steven Morelandacd53472018-12-14 10:17:26 -0800923 : AidlDefinedType(location, name, comments, package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800924 for (auto& member : *members) {
925 AidlMember* local = member.release();
926 AidlMethod* method = local->AsMethod();
Steven Moreland693640b2018-07-19 13:46:27 -0700927 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
928
929 CHECK(method == nullptr || constant == nullptr);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800930
931 if (method) {
Steven Moreland8c70ba92018-12-17 10:20:31 -0800932 method->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800933 methods_.emplace_back(method);
Steven Moreland693640b2018-07-19 13:46:27 -0700934 } else if (constant) {
935 constants_.emplace_back(constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800936 } else {
Steven Moreland46e9da82018-07-27 15:45:29 -0700937 AIDL_FATAL(this) << "Member is neither method nor constant!";
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800938 }
939 }
940
941 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700942}
943
Jiyong Park02da7422018-07-16 16:00:26 +0900944void AidlInterface::Write(CodeWriter* writer) const {
945 writer->Write("interface %s {\n", GetName().c_str());
946 writer->Indent();
947 for (const auto& method : GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900948 writer->Write("%s;\n", method->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900949 }
Jiyong Parka428d212018-08-29 22:26:30 +0900950 for (const auto& constdecl : GetConstantDeclarations()) {
951 writer->Write("%s;\n", constdecl->ToString().c_str());
952 }
Jiyong Park02da7422018-07-16 16:00:26 +0900953 writer->Dedent();
954 writer->Write("}\n");
955}
956
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900957bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100958 if (!CheckValidAnnotations()) {
959 return false;
960 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900961 // Has to be a pointer due to deleting copy constructor. No idea why.
962 map<string, const AidlMethod*> method_names;
963 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900964 if (!m->GetType().CheckValid(typenames)) {
965 return false;
966 }
967
Steven Morelandacd53472018-12-14 10:17:26 -0800968 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900969 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
970 return false;
971 }
972
973 set<string> argument_names;
974 for (const auto& arg : m->GetArguments()) {
975 auto it = argument_names.find(arg->GetName());
976 if (it != argument_names.end()) {
977 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
978 << arg->GetName() << "'";
979 return false;
980 }
981 argument_names.insert(arg->GetName());
982
983 if (!arg->GetType().CheckValid(typenames)) {
984 return false;
985 }
986
Steven Morelandacd53472018-12-14 10:17:26 -0800987 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900988 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
989 return false;
990 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900991 const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
992 if (!arg->DirectionWasSpecified() && can_be_out) {
993 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
994 << "' can be an out type, so you must declare it as in, out, or inout.";
995 return false;
996 }
997
998 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
999 AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1000 return false;
1001 }
1002
1003 // check that the name doesn't match a keyword
1004 if (is_java_keyword(arg->GetName().c_str())) {
1005 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1006 return false;
1007 }
1008
1009 // Reserve a namespace for internal use
1010 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1011 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1012 return false;
1013 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001014 }
1015
1016 auto it = method_names.find(m->GetName());
1017 // prevent duplicate methods
1018 if (it == method_names.end()) {
1019 method_names[m->GetName()] = m.get();
1020 } else {
1021 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1022 AIDL_ERROR(it->second) << "previously defined here.";
1023 return false;
1024 }
1025
1026 static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
1027 "getTransactionName(int)"};
1028
1029 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1030 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
1031 return false;
1032 }
1033 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001034
1035 bool success = true;
1036 set<string> constant_names;
1037 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1038 if (constant_names.count(constant->GetName()) > 0) {
1039 LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
1040 success = false;
1041 }
1042 constant_names.insert(constant->GetName());
1043 success = success && constant->CheckValid(typenames);
1044 }
1045
1046 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001047}
1048
Steven Moreland46e9da82018-07-27 15:45:29 -07001049AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
1050 const std::string& comments)
1051 : AidlNode(location), terms_({term}), comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001052 if (term.find('.') != string::npos) {
1053 terms_ = Split(term, ".");
Steven Moreland46e9da82018-07-27 15:45:29 -07001054 for (const auto& subterm : terms_) {
1055 if (subterm.empty()) {
1056 AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001057 }
1058 }
1059 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001060}
1061
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -07001062void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001063 terms_.push_back(term);
1064}
1065
Steven Moreland46e9da82018-07-27 15:45:29 -07001066AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1067 : AidlNode(location), needed_class_(needed_class) {}
Casey Dahlin0edf3422015-10-07 12:34:59 -07001068
Steven Moreland64e29be2018-08-08 18:52:19 -07001069std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
1070 const android::aidl::IoDelegate& io_delegate,
1071 AidlTypenames& typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001072 // Make sure we can read the file first, before trashing previous state.
Steven Moreland64e29be2018-08-08 18:52:19 -07001073 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
1074 if (raw_buffer == nullptr) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001075 AIDL_ERROR(filename) << "Error while opening file for parsing";
Steven Moreland64e29be2018-08-08 18:52:19 -07001076 return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001077 }
1078
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001079 // We're going to scan this buffer in place, and yacc demands we put two
1080 // nulls at the end.
Steven Moreland64e29be2018-08-08 18:52:19 -07001081 raw_buffer->append(2u, '\0');
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001082
Steven Moreland64e29be2018-08-08 18:52:19 -07001083 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001084
Steven Moreland64e29be2018-08-08 18:52:19 -07001085 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001086
Steven Moreland64e29be2018-08-08 18:52:19 -07001087 return parser;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001088}
1089
Christopher Wiley90be4e32015-10-20 14:55:25 -07001090std::vector<std::string> Parser::Package() const {
1091 if (!package_) {
1092 return {};
1093 }
1094 return package_->GetTerms();
1095}
1096
Steven Moreland46e9da82018-07-27 15:45:29 -07001097void Parser::AddImport(AidlImport* import) {
1098 imports_.emplace_back(import);
Casey Dahline2507492015-09-14 17:11:20 -07001099}
Jiyong Park1deecc32018-07-17 01:14:41 +09001100
1101bool Parser::Resolve() {
1102 bool success = true;
1103 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +09001104 if (!typespec->Resolve(typenames_)) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001105 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
Jiyong Park1deecc32018-07-17 01:14:41 +09001106 success = false;
1107 // don't stop to show more errors if any
1108 }
1109 }
1110 return success;
1111}
Steven Moreland64e29be2018-08-08 18:52:19 -07001112
1113Parser::Parser(const std::string& filename, std::string& raw_buffer,
1114 android::aidl::AidlTypenames& typenames)
1115 : filename_(filename), typenames_(typenames) {
1116 yylex_init(&scanner_);
1117 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
1118}
1119
1120Parser::~Parser() {
1121 yy_delete_buffer(buffer_, scanner_);
1122 yylex_destroy(scanner_);
1123}