blob: aac32f380b267e9509a21186dba3bbae29200948 [file] [log] [blame]
Adam Lesinskiffa16862014-01-23 18:17:42 -08001#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +09002#include "aidl_typenames.h"
Christopher Wileyf690be52015-09-14 15:19:10 -07003
Adam Lesinskiffa16862014-01-23 18:17:42 -08004#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -08005#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -07006#include <string.h>
Jiyong Park68bc77a2018-07-19 19:00:45 +09007#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +09008#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +09009#include <set>
10#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070011#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090012#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070013
Steven Moreland1c4ba202018-08-09 10:49:54 -070014#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070015#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080016#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070017
Ying Wang3000e752016-01-11 18:05:59 -080018#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070019#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080020
Casey Dahlin07b9dde2015-09-10 19:13:49 -070021#ifdef _WIN32
22int isatty(int fd)
23{
24 return (fd == 0);
25}
26#endif
27
Christopher Wiley4a2884b2015-10-07 11:27:45 -070028using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070029using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080030using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070031using std::cerr;
32using std::endl;
Jiyong Park1deecc32018-07-17 01:14:41 +090033using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090034using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070035using std::string;
36using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090037using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080038
Jeongik Cha047c5ee2019-08-07 23:16:49 +090039namespace {
40bool is_java_keyword(const char* str) {
41 static const std::vector<std::string> kJavaKeywords{
42 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
43 "char", "class", "const", "continue", "default", "do", "double",
44 "else", "enum", "extends", "final", "finally", "float", "for",
45 "goto", "if", "implements", "import", "instanceof", "int", "interface",
46 "long", "native", "new", "package", "private", "protected", "public",
47 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
48 "this", "throw", "throws", "transient", "try", "void", "volatile",
49 "while", "true", "false", "null",
50 };
51 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
52}
53} // namespace
54
Casey Dahlindd691812015-09-09 17:59:06 -070055void yylex_init(void **);
56void yylex_destroy(void *);
57void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070058int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070059YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070060void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070061
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070062AidlToken::AidlToken(const std::string& text, const std::string& comments)
63 : text_(text),
64 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070065
Steven Moreland46e9da82018-07-27 15:45:29 -070066AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
67 : file_(file), begin_(begin), end_(end) {}
68
69std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
70 os << l.file_ << ":" << l.begin_.line << "." << l.begin_.column << "-";
71 if (l.begin_.line != l.end_.line) {
72 os << l.end_.line << ".";
73 }
74 os << l.end_.column;
75 return os;
76}
77
78AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
79
Andrei Onea8714b022019-02-01 18:55:54 +000080std::string AidlNode::PrintLocation() const {
81 std::stringstream ss;
82 ss << location_.file_ << ":" << location_.begin_.line;
83 return ss.str();
84}
85
Steven Moreland92c55f12018-07-31 14:08:37 -070086AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
87 os_ << "ERROR: ";
88}
89
Jiyong Park68bc77a2018-07-19 19:00:45 +090090static const string kNullable("nullable");
Jiyong Park68bc77a2018-07-19 19:00:45 +090091static const string kUtf8InCpp("utf8InCpp");
Steven Morelanda57d0a62019-07-30 09:41:14 -070092static const string kVintfStability("VintfStability");
Jiyong Parka6605ab2018-11-11 14:30:21 +090093static const string kUnsupportedAppUsage("UnsupportedAppUsage");
Jeongik Cha698e6af2018-12-12 14:39:55 +090094static const string kSystemApi("SystemApi");
Jeongik Cha82317dd2019-02-27 20:26:11 +090095static const string kStableParcelable("JavaOnlyStableParcelable");
Daniel Norman85aed542019-08-21 12:01:14 -070096static const string kBacking("Backing");
Jiyong Park68bc77a2018-07-19 19:00:45 +090097
Andrei Onea9445fc62019-06-27 18:11:59 +010098static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
99 {kNullable, {}},
100 {kUtf8InCpp, {}},
Steven Morelanda57d0a62019-07-30 09:41:14 -0700101 {kVintfStability, {}},
Andrei Onea9445fc62019-06-27 18:11:59 +0100102 {kUnsupportedAppUsage,
103 {{"expectedSignature", "String"},
104 {"implicitMember", "String"},
105 {"maxTargetSdk", "int"},
106 {"publicAlternatives", "String"},
107 {"trackingBug", "long"}}},
108 {kSystemApi, {}},
Daniel Norman85aed542019-08-21 12:01:14 -0700109 {kStableParcelable, {}},
110 {kBacking, {{"type", "String"}}}};
Andrei Onea9445fc62019-06-27 18:11:59 +0100111
112AidlAnnotation* AidlAnnotation::Parse(
113 const AidlLocation& location, const string& name,
114 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
Steven Moreland29db3022019-07-30 12:37:17 -0700115 if (kAnnotationParameters.find(name) == kAnnotationParameters.end()) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900116 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700117 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900118 stream << "It must be one of:";
Steven Moreland29db3022019-07-30 12:37:17 -0700119 for (const auto& kv : kAnnotationParameters) {
120 stream << " " << kv.first;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900121 }
122 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700123 AIDL_ERROR(location) << stream.str();
124 return nullptr;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900125 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100126 if (parameter_list == nullptr) {
127 return new AidlAnnotation(location, name);
128 }
129
130 return new AidlAnnotation(location, name, std::move(*parameter_list));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900131}
132
Steven Moreland46e9da82018-07-27 15:45:29 -0700133AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
Andrei Onea9445fc62019-06-27 18:11:59 +0100134 : AidlAnnotation(location, name, {}) {}
135
136AidlAnnotation::AidlAnnotation(
137 const AidlLocation& location, const string& name,
138 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
139 : AidlNode(location), name_(name), parameters_(std::move(parameters)) {}
140
141bool AidlAnnotation::CheckValid() const {
142 auto supported_params_iterator = kAnnotationParameters.find(GetName());
143 if (supported_params_iterator == kAnnotationParameters.end()) {
144 AIDL_ERROR(this) << GetName() << " annotation does not have any supported parameters.";
145 return false;
146 }
147 const auto& supported_params = supported_params_iterator->second;
148 for (const auto& name_and_param : parameters_) {
149 const std::string& param_name = name_and_param.first;
150 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
151 auto parameter_mapping_it = supported_params.find(param_name);
152 if (parameter_mapping_it == supported_params.end()) {
153 std::ostringstream stream;
154 stream << "Parameter " << param_name << " not supported ";
155 stream << "for annotation " << GetName() << ".";
156 stream << "It must be one of:";
157 for (const auto& kv : supported_params) {
158 stream << " " << kv.first;
159 }
160 AIDL_ERROR(this) << stream.str();
161 return false;
162 }
163 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
164 const std::string param_value = param->As(type, AidlConstantValueDecorator);
165 // Assume error on empty string.
166 if (param_value == "") {
167 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
168 << GetName() << ".";
169 return false;
170 }
171 }
172 return true;
173}
174
175std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
176 const ConstantValueDecorator& decorator) const {
177 std::map<std::string, std::string> raw_params;
178 const auto& supported_params = kAnnotationParameters.at(GetName());
179 for (const auto& name_and_param : parameters_) {
180 const std::string& param_name = name_and_param.first;
181 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
182 AidlTypeSpecifier type{AIDL_LOCATION_HERE, supported_params.at(param_name), false, nullptr, ""};
183 raw_params.emplace(param_name, param->As(type, decorator));
184 }
185 return raw_params;
186}
Steven Moreland46e9da82018-07-27 15:45:29 -0700187
Daniel Norman37d43dd2019-09-09 17:22:34 -0700188std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
189 if (parameters_.empty()) {
190 return "@" + GetName();
191 } else {
192 vector<string> param_strings;
193 for (const auto& [name, value] : AnnotationParams(decorator)) {
194 param_strings.emplace_back(name + "=" + value);
195 }
196 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
197 }
198}
199
Jiyong Parka6605ab2018-11-11 14:30:21 +0900200static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900201 for (const auto& a : annotations) {
Steven Moreland3be75772018-08-20 13:27:43 -0700202 if (a.GetName() == name) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900203 return true;
204 }
205 }
206 return false;
207}
208
Andrei Onea9445fc62019-06-27 18:11:59 +0100209static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
210 const string& name) {
211 for (const auto& a : annotations) {
212 if (a.GetName() == name) {
213 return &a;
214 }
215 }
216 return nullptr;
217}
218
Steven Moreland46e9da82018-07-27 15:45:29 -0700219AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
220
Jiyong Park68bc77a2018-07-19 19:00:45 +0900221bool AidlAnnotatable::IsNullable() const {
222 return HasAnnotation(annotations_, kNullable);
223}
224
Jiyong Park68bc77a2018-07-19 19:00:45 +0900225bool AidlAnnotatable::IsUtf8InCpp() const {
226 return HasAnnotation(annotations_, kUtf8InCpp);
227}
228
Steven Morelanda57d0a62019-07-30 09:41:14 -0700229bool AidlAnnotatable::IsVintfStability() const {
230 return HasAnnotation(annotations_, kVintfStability);
231}
232
Andrei Onea9445fc62019-06-27 18:11:59 +0100233const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
234 return GetAnnotation(annotations_, kUnsupportedAppUsage);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900235}
236
Daniel Norman716d3112019-09-10 13:11:56 -0700237const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700238 auto annotation = GetAnnotation(annotations_, kBacking);
239 if (annotation != nullptr) {
240 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
241 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
242 const string& type = it->second;
Daniel Norman716d3112019-09-10 13:11:56 -0700243 AidlTypeSpecifier* type_specifier =
244 new AidlTypeSpecifier(AIDL_LOCATION_HERE,
245 // Strip the quotes off the type String.
246 type.substr(1, type.length() - 2), false, nullptr, "");
247 type_specifier->Resolve(typenames);
248 return type_specifier;
Daniel Norman85aed542019-08-21 12:01:14 -0700249 }
250 }
251 return nullptr;
252}
253
Jeongik Cha698e6af2018-12-12 14:39:55 +0900254bool AidlAnnotatable::IsSystemApi() const {
255 return HasAnnotation(annotations_, kSystemApi);
256}
257
Jeongik Cha82317dd2019-02-27 20:26:11 +0900258bool AidlAnnotatable::IsStableParcelable() const {
259 return HasAnnotation(annotations_, kStableParcelable);
260}
261
Andrei Onea9445fc62019-06-27 18:11:59 +0100262bool AidlAnnotatable::CheckValidAnnotations() const {
263 for (const auto& annotation : GetAnnotations()) {
264 if (!annotation.CheckValid()) {
265 return false;
266 }
267 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700268
Andrei Onea9445fc62019-06-27 18:11:59 +0100269 return true;
270}
271
Jiyong Park68bc77a2018-07-19 19:00:45 +0900272string AidlAnnotatable::ToString() const {
273 vector<string> ret;
274 for (const auto& a : annotations_) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700275 ret.emplace_back(a.ToString(AidlConstantValueDecorator));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900276 }
277 std::sort(ret.begin(), ret.end());
278 return Join(ret, " ");
279}
280
Steven Moreland46e9da82018-07-27 15:45:29 -0700281AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
282 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900283 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Steven Moreland46e9da82018-07-27 15:45:29 -0700284 const string& comments)
285 : AidlAnnotatable(location),
286 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700287 is_array_(is_array),
Jiyong Park1deecc32018-07-17 01:14:41 +0900288 type_params_(type_params),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900289 comments_(comments),
290 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700291
Steven Moreland3f658cf2018-08-20 13:40:54 -0700292AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
293 AIDL_FATAL_IF(!is_array_, this);
294
295 AidlTypeSpecifier arrayBase = *this;
296 arrayBase.is_array_ = false;
297 return arrayBase;
298}
299
Jiyong Park1deecc32018-07-17 01:14:41 +0900300string AidlTypeSpecifier::ToString() const {
301 string ret = GetName();
302 if (IsGeneric()) {
303 vector<string> arg_names;
304 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +0900305 arg_names.emplace_back(ta->ToString());
306 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900307 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900308 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900309 if (IsArray()) {
310 ret += "[]";
311 }
312 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900313}
314
Jiyong Park02da7422018-07-16 16:00:26 +0900315string AidlTypeSpecifier::Signature() const {
316 string ret = ToString();
317 string annotations = AidlAnnotatable::ToString();
318 if (annotations != "") {
319 ret = annotations + " " + ret;
320 }
321 return ret;
322}
323
Daniel Norman716d3112019-09-10 13:11:56 -0700324bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
Steven Moreland9731c632019-08-13 10:21:08 -0700325 CHECK(!IsResolved());
Jiyong Park1deecc32018-07-17 01:14:41 +0900326 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
327 if (result.second) {
328 fully_qualified_name_ = result.first;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900329 split_name_ = Split(fully_qualified_name_, ".");
Jiyong Parkccf00f82018-07-17 01:39:23 +0900330 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900331 return result.second;
Casey Dahlin70078e62015-09-30 17:01:30 -0700332}
333
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900334bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100335 if (!CheckValidAnnotations()) {
336 return false;
337 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900338 if (IsGeneric()) {
339 const string& type_name = GetName();
340 const int num = GetTypeParameters().size();
341 if (type_name == "List") {
342 if (num > 1) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900343 AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
344 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900345 return false;
346 }
347 } else if (type_name == "Map") {
348 if (num != 0 && num != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900349 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
350 << "'" << ToString() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900351 return false;
352 }
353 }
354 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900355
356 if (GetName() == "void") {
357 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
358 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
359 return false;
360 }
361 }
362
363 if (IsArray()) {
364 const auto definedType = typenames.TryGetDefinedType(GetName());
365 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
366 AIDL_ERROR(this) << "Binder type cannot be an array";
367 return false;
368 }
Daniel Norman716d3112019-09-10 13:11:56 -0700369 if (definedType != nullptr && definedType->AsEnumDeclaration() != nullptr) {
370 // TODO(b/123321528): Support arrays of enums.
371 AIDL_ERROR(this) << "Enum type cannot be an array";
372 return false;
373 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900374 }
375
376 if (IsNullable()) {
377 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
378 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
379 return false;
380 }
381 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900382 return true;
383}
384
Steven Moreland860b1942018-08-16 14:59:28 -0700385std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
386 const std::string& raw_value) {
387 return raw_value;
388}
389
Steven Moreland46e9da82018-07-27 15:45:29 -0700390AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
391 AidlTypeSpecifier* type, const std::string& name)
392 : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700393
Steven Moreland46e9da82018-07-27 15:45:29 -0700394AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
395 AidlTypeSpecifier* type, const std::string& name,
396 AidlConstantValue* default_value)
397 : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700398
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900399bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700400 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900401 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900402
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900403 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700404 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700405
Steven Moreland25294322018-08-07 18:13:55 -0700406 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700407
Steven Moreland860b1942018-08-16 14:59:28 -0700408 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700409}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700410
411string AidlVariableDeclaration::ToString() const {
Jeongik Cha3271ffa2018-12-04 15:19:20 +0900412 string ret = type_->Signature() + " " + name_;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700413 if (default_value_ != nullptr) {
Steven Moreland860b1942018-08-16 14:59:28 -0700414 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700415 }
416 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700417}
418
Jiyong Park02da7422018-07-16 16:00:26 +0900419string AidlVariableDeclaration::Signature() const {
420 return type_->Signature() + " " + name_;
421}
422
Steven Moreland860b1942018-08-16 14:59:28 -0700423std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900424 if (default_value_ != nullptr) {
425 return GetDefaultValue()->As(GetType(), decorator);
426 } else {
427 return "";
428 }
Steven Moreland25294322018-08-07 18:13:55 -0700429}
430
Steven Moreland46e9da82018-07-27 15:45:29 -0700431AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
432 AidlTypeSpecifier* type, const std::string& name)
433 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700434 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700435 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700436
Steven Moreland46e9da82018-07-27 15:45:29 -0700437AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
438 const std::string& name)
439 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700440 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700441 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700442
Jiyong Park02da7422018-07-16 16:00:26 +0900443string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700444 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700445 if (direction_specified_) {
446 switch(direction_) {
447 case AidlArgument::IN_DIR:
448 ret += "in ";
449 break;
450 case AidlArgument::OUT_DIR:
451 ret += "out ";
452 break;
453 case AidlArgument::INOUT_DIR:
454 ret += "inout ";
455 break;
456 }
457 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700458 return ret;
459}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700460
Jiyong Park02da7422018-07-16 16:00:26 +0900461string AidlArgument::ToString() const {
462 return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
463}
464
465std::string AidlArgument::Signature() const {
Steven Moreland46e9da82018-07-27 15:45:29 -0700466 class AidlInterface;
467 class AidlInterface;
468 class AidlParcelable;
469 class AidlStructuredParcelable;
470 class AidlParcelable;
471 class AidlStructuredParcelable;
Jiyong Park02da7422018-07-16 16:00:26 +0900472 return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
473}
474
Steven Moreland46e9da82018-07-27 15:45:29 -0700475AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
476
Steven Moreland46e9da82018-07-27 15:45:29 -0700477AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
478 const std::string& checked_value)
Steven Moreland1c4ba202018-08-09 10:49:54 -0700479 : AidlNode(location), type_(type), value_(checked_value) {
480 CHECK(!value_.empty() || type_ == Type::ERROR);
Steven Moreland860b1942018-08-16 14:59:28 -0700481 CHECK(type_ != Type::ARRAY);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700482}
Steven Moreland693640b2018-07-19 13:46:27 -0700483
Steven Moreland860b1942018-08-16 14:59:28 -0700484AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
485 std::vector<std::unique_ptr<AidlConstantValue>>* values)
486 : AidlNode(location), type_(type), values_(std::move(*values)) {}
487
Steven Moreland25294322018-08-07 18:13:55 -0700488static bool isValidLiteralChar(char c) {
489 return !(c <= 0x1f || // control characters are < 0x20
490 c >= 0x7f || // DEL is 0x7f
491 c == '\\'); // Disallow backslashes for future proofing.
Steven Moreland693640b2018-07-19 13:46:27 -0700492}
493
Steven Moreland25294322018-08-07 18:13:55 -0700494AidlConstantValue* AidlConstantValue::Boolean(const AidlLocation& location, bool value) {
495 return new AidlConstantValue(location, Type::BOOLEAN, value ? "true" : "false");
496}
497
498AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location, char value) {
499 if (!isValidLiteralChar(value)) {
500 AIDL_ERROR(location) << "Invalid character literal " << value;
Steven Moreland46e9da82018-07-27 15:45:29 -0700501 return new AidlConstantValue(location, Type::ERROR, "");
Steven Moreland693640b2018-07-19 13:46:27 -0700502 }
Steven Moreland25294322018-08-07 18:13:55 -0700503 return new AidlConstantValue(location, Type::CHARACTER, std::string("'") + value + "'");
Steven Moreland693640b2018-07-19 13:46:27 -0700504}
505
Steven Moreland1c4ba202018-08-09 10:49:54 -0700506AidlConstantValue* AidlConstantValue::Floating(const AidlLocation& location,
507 const std::string& value) {
508 return new AidlConstantValue(location, Type::FLOATING, value);
509}
510
Steven Moreland25294322018-08-07 18:13:55 -0700511AidlConstantValue* AidlConstantValue::Hex(const AidlLocation& location, const std::string& value) {
512 return new AidlConstantValue(location, Type::HEXIDECIMAL, value);
513}
514
515AidlConstantValue* AidlConstantValue::Integral(const AidlLocation& location,
516 const std::string& value) {
517 return new AidlConstantValue(location, Type::INTEGRAL, value);
518}
519
Steven Moreland860b1942018-08-16 14:59:28 -0700520AidlConstantValue* AidlConstantValue::Array(
521 const AidlLocation& location, std::vector<std::unique_ptr<AidlConstantValue>>* values) {
522 return new AidlConstantValue(location, Type::ARRAY, values);
523}
524
Steven Moreland25294322018-08-07 18:13:55 -0700525AidlConstantValue* AidlConstantValue::String(const AidlLocation& location,
526 const std::string& value) {
Steven Moreland693640b2018-07-19 13:46:27 -0700527 for (size_t i = 0; i < value.length(); ++i) {
Steven Moreland25294322018-08-07 18:13:55 -0700528 if (!isValidLiteralChar(value[i])) {
Steven Moreland46e9da82018-07-27 15:45:29 -0700529 AIDL_ERROR(location) << "Found invalid character at index " << i << " in string constant '"
530 << value << "'";
531 return new AidlConstantValue(location, Type::ERROR, "");
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700532 }
533 }
Steven Moreland693640b2018-07-19 13:46:27 -0700534
Steven Moreland46e9da82018-07-27 15:45:29 -0700535 return new AidlConstantValue(location, Type::STRING, value);
Steven Moreland693640b2018-07-19 13:46:27 -0700536}
537
Steven Moreland25294322018-08-07 18:13:55 -0700538bool AidlConstantValue::CheckValid() const {
539 // error always logged during creation
540 return type_ != AidlConstantValue::Type::ERROR;
541}
542
Steven Moreland1c4ba202018-08-09 10:49:54 -0700543static string TrimIfSuffix(const string& str, const string& suffix) {
544 if (str.size() > suffix.size() &&
545 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix)) {
546 return str.substr(0, str.size() - suffix.size());
547 }
548 return str;
549}
550
Steven Moreland860b1942018-08-16 14:59:28 -0700551string AidlConstantValue::As(const AidlTypeSpecifier& type,
552 const ConstantValueDecorator& decorator) const {
553 if (type.IsGeneric()) {
554 AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
555 return "";
556 }
557
558 const std::string& type_string = type.GetName();
559
560 if ((type_ == Type::ARRAY) != type.IsArray()) {
561 goto mismatch_error;
562 }
Steven Moreland25294322018-08-07 18:13:55 -0700563
564 switch (type_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700565 case AidlConstantValue::Type::ARRAY: {
566 vector<string> raw_values;
567 raw_values.reserve(values_.size());
568
569 bool success = true;
570 for (const auto& value : values_) {
571 const AidlTypeSpecifier& array_base = type.ArrayBase();
572 const std::string raw_value = value->As(array_base, decorator);
573
574 success &= !raw_value.empty();
575 raw_values.push_back(decorator(array_base, raw_value));
576 }
577 if (!success) {
578 AIDL_ERROR(this) << "Default value must be a literal array of " << type_string << ".";
579 return "";
580 }
581 return decorator(type, "{" + Join(raw_values, ", ") + "}");
582 }
Steven Moreland1c4ba202018-08-09 10:49:54 -0700583 case AidlConstantValue::Type::BOOLEAN:
Steven Moreland860b1942018-08-16 14:59:28 -0700584 if (type_string == "boolean") return decorator(type, value_);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700585 goto mismatch_error;
586 case AidlConstantValue::Type::CHARACTER:
Steven Moreland860b1942018-08-16 14:59:28 -0700587 if (type_string == "char") return decorator(type, value_);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700588 goto mismatch_error;
589 case AidlConstantValue::Type::FLOATING: {
590 bool is_float_literal = value_.back() == 'f';
591 const std::string raw_value = TrimIfSuffix(value_, "f");
592
593 if (type_string == "double") {
594 double parsed_value;
595 if (!android::base::ParseDouble(raw_value, &parsed_value)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700596 return decorator(type, std::to_string(parsed_value));
Steven Moreland25294322018-08-07 18:13:55 -0700597 }
Steven Moreland1c4ba202018-08-09 10:49:54 -0700598 if (is_float_literal && type_string == "float") {
599 float parsed_value;
600 if (!android::base::ParseFloat(raw_value, &parsed_value)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700601 return decorator(type, std::to_string(parsed_value) + "f");
Steven Moreland25294322018-08-07 18:13:55 -0700602 }
603 goto mismatch_error;
Steven Moreland1c4ba202018-08-09 10:49:54 -0700604 }
Steven Moreland25294322018-08-07 18:13:55 -0700605 case AidlConstantValue::Type::HEXIDECIMAL:
606 // For historical reasons, a hexidecimal int needs to have the specified bits interpreted
607 // as the signed type, so the other types are made consistent with it.
608 if (type_string == "byte") {
609 uint8_t unsigned_value;
610 if (!android::base::ParseUint<uint8_t>(value_, &unsigned_value)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700611 return decorator(type, std::to_string((int8_t)unsigned_value));
Steven Moreland25294322018-08-07 18:13:55 -0700612 }
613 if (type_string == "int") {
614 uint32_t unsigned_value;
615 if (!android::base::ParseUint<uint32_t>(value_, &unsigned_value)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700616 return decorator(type, std::to_string((int32_t)unsigned_value));
Steven Moreland25294322018-08-07 18:13:55 -0700617 }
618 if (type_string == "long") {
619 uint64_t unsigned_value;
620 if (!android::base::ParseUint<uint64_t>(value_, &unsigned_value)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700621 return decorator(type, std::to_string((int64_t)unsigned_value));
Steven Moreland25294322018-08-07 18:13:55 -0700622 }
623 goto mismatch_error;
Steven Moreland1c4ba202018-08-09 10:49:54 -0700624 case AidlConstantValue::Type::INTEGRAL:
625 if (type_string == "byte") {
626 if (!android::base::ParseInt<int8_t>(value_, nullptr)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700627 return decorator(type, value_);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700628 }
629 if (type_string == "int") {
630 if (!android::base::ParseInt<int32_t>(value_, nullptr)) goto parse_error;
Steven Moreland860b1942018-08-16 14:59:28 -0700631 return decorator(type, value_);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700632 }
633 if (type_string == "long") {
634 if (!android::base::ParseInt<int64_t>(value_, nullptr)) goto parse_error;
Daniel Norman37d43dd2019-09-09 17:22:34 -0700635 return decorator(type, value_);
Steven Moreland1c4ba202018-08-09 10:49:54 -0700636 }
Steven Moreland25294322018-08-07 18:13:55 -0700637 goto mismatch_error;
638 case AidlConstantValue::Type::STRING:
Steven Moreland860b1942018-08-16 14:59:28 -0700639 if (type_string == "String") return decorator(type, value_);
Steven Moreland25294322018-08-07 18:13:55 -0700640 goto mismatch_error;
641 default:
642 AIDL_FATAL(this) << "Unrecognized constant value type";
643 }
644
645mismatch_error:
Steven Moreland860b1942018-08-16 14:59:28 -0700646 AIDL_ERROR(this) << "Expecting type " << type_string << " but constant is " << ToString(type_);
Steven Moreland25294322018-08-07 18:13:55 -0700647 return "";
648parse_error:
649 AIDL_ERROR(this) << "Could not parse " << value_ << " as " << type_string;
650 return "";
651}
652
653string AidlConstantValue::ToString(Type type) {
654 switch (type) {
Steven Moreland860b1942018-08-16 14:59:28 -0700655 case Type::ARRAY:
656 return "a literal array";
Steven Moreland25294322018-08-07 18:13:55 -0700657 case Type::BOOLEAN:
658 return "a literal boolean";
659 case Type::CHARACTER:
660 return "a literal char";
Steven Moreland1c4ba202018-08-09 10:49:54 -0700661 case Type::FLOATING:
662 return "a floating-point literal";
663 case Type::HEXIDECIMAL:
664 return "a hexidecimal literal";
Steven Moreland25294322018-08-07 18:13:55 -0700665 case Type::INTEGRAL:
666 return "an integral literal";
667 case Type::STRING:
668 return "a literal string";
669 case Type::ERROR:
670 LOG(FATAL) << "aidl internal error: error type failed to halt program";
Wei Wang35b7bb62018-10-09 13:06:12 -0700671 return "";
Steven Moreland25294322018-08-07 18:13:55 -0700672 default:
673 LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
674 return ""; // not reached
675 }
Steven Moreland693640b2018-07-19 13:46:27 -0700676}
677
Steven Moreland46e9da82018-07-27 15:45:29 -0700678AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
679 AidlTypeSpecifier* type, const std::string& name,
680 AidlConstantValue* value)
681 : AidlMember(location), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700682
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900683bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700684 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900685 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700686 valid &= value_->CheckValid();
687 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700688
Steven Moreland25294322018-08-07 18:13:55 -0700689 const static set<string> kSupportedConstTypes = {"String", "int"};
690 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
691 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700692 return false;
693 }
694
Steven Moreland860b1942018-08-16 14:59:28 -0700695 return !ValueString(AidlConstantValueDecorator).empty();
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700696}
697
Jiyong Parka428d212018-08-29 22:26:30 +0900698string AidlConstantDeclaration::ToString() const {
699 return "const " + type_->ToString() + " " + name_ + " = " +
700 ValueString(AidlConstantValueDecorator);
701}
702
703string AidlConstantDeclaration::Signature() const {
704 return type_->Signature() + " " + name_;
705}
706
Steven Moreland46e9da82018-07-27 15:45:29 -0700707AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
708 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900709 const std::string& comments)
710 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
711 has_id_ = false;
712}
713
714AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
715 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jiyong Parkb034bf02018-07-30 17:44:33 +0900716 const std::string& comments, int id, bool is_user_defined)
Steven Moreland46e9da82018-07-27 15:45:29 -0700717 : AidlMember(location),
718 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700719 comments_(comments),
720 type_(type),
721 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700722 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900723 id_(id),
724 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700725 has_id_ = true;
726 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700727 for (const unique_ptr<AidlArgument>& a : arguments_) {
728 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
729 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
730 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700731}
732
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700733
Jiyong Park02da7422018-07-16 16:00:26 +0900734string AidlMethod::Signature() const {
735 vector<string> arg_signatures;
736 for (const auto& arg : GetArguments()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900737 arg_signatures.emplace_back(arg->GetType().ToString());
Jiyong Park02da7422018-07-16 16:00:26 +0900738 }
Jiyong Park309668e2018-07-28 16:55:44 +0900739 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
740}
741
742string AidlMethod::ToString() const {
743 vector<string> arg_strings;
744 for (const auto& arg : GetArguments()) {
745 arg_strings.emplace_back(arg->Signature());
746 }
Steven Moreland4ee68632018-12-14 15:52:46 -0800747 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
748 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900749 if (HasId()) {
750 ret += " = " + std::to_string(GetId());
751 }
752 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900753}
754
Steven Moreland46e9da82018-07-27 15:45:29 -0700755AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
756 const std::string& comments,
Steven Moreland787b0432018-07-03 09:00:58 -0700757 const std::vector<std::string>& package)
Steven Moreland46e9da82018-07-27 15:45:29 -0700758 : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700759
760std::string AidlDefinedType::GetPackage() const {
761 return Join(package_, '.');
762}
763
764std::string AidlDefinedType::GetCanonicalName() const {
765 if (package_.empty()) {
766 return GetName();
767 }
768 return GetPackage() + "." + GetName();
769}
770
Steven Moreland46e9da82018-07-27 15:45:29 -0700771AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900772 const std::vector<std::string>& package, const std::string& comments,
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800773 const std::string& cpp_header)
Jiyong Parka6605ab2018-11-11 14:30:21 +0900774 : AidlDefinedType(location, name->GetDotName(), comments, package),
Steven Moreland787b0432018-07-03 09:00:58 -0700775 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800776 cpp_header_(cpp_header) {
777 // Strip off quotation marks if we actually have a cpp header.
778 if (cpp_header_.length() >= 2) {
779 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
780 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700781}
782
Jeongik Cha82317dd2019-02-27 20:26:11 +0900783bool AidlParcelable::CheckValid(const AidlTypenames&) const {
784 static const std::set<string> allowed{kStableParcelable};
Andrei Onea9445fc62019-06-27 18:11:59 +0100785 if (!CheckValidAnnotations()) {
786 return false;
787 }
Jeongik Cha82317dd2019-02-27 20:26:11 +0900788 for (const auto& v : GetAnnotations()) {
789 if (allowed.find(v.GetName()) == allowed.end()) {
790 std::ostringstream stream;
791 stream << "Unstructured parcelable can contain only";
792 for (const string& kv : allowed) {
793 stream << " " << kv;
794 }
795 stream << ".";
796 AIDL_ERROR(this) << stream.str();
797 return false;
798 }
799 }
800
801 return true;
802}
803
Jiyong Park02da7422018-07-16 16:00:26 +0900804void AidlParcelable::Write(CodeWriter* writer) const {
805 writer->Write("parcelable %s ;\n", GetName().c_str());
806}
807
Steven Moreland5557f1c2018-07-02 13:50:23 -0700808AidlStructuredParcelable::AidlStructuredParcelable(
Steven Moreland46e9da82018-07-27 15:45:29 -0700809 const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
Jiyong Parka6605ab2018-11-11 14:30:21 +0900810 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
811 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
Steven Moreland46e9da82018-07-27 15:45:29 -0700812 variables_(std::move(*variables)) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700813
Jiyong Park02da7422018-07-16 16:00:26 +0900814void AidlStructuredParcelable::Write(CodeWriter* writer) const {
815 writer->Write("parcelable %s {\n", GetName().c_str());
816 writer->Indent();
817 for (const auto& field : GetFields()) {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900818 writer->Write("%s;\n", field->ToString().c_str());
Jiyong Park02da7422018-07-16 16:00:26 +0900819 }
820 writer->Dedent();
821 writer->Write("}\n");
822}
823
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900824bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
Daniel Norman85aed542019-08-21 12:01:14 -0700825 bool success = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900826 for (const auto& v : GetFields()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700827 success = success && v->CheckValid(typenames);
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900828 }
Daniel Norman85aed542019-08-21 12:01:14 -0700829 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900830}
831
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900832// TODO: we should treat every backend all the same in future.
833bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
834 if (lang == Options::Language::CPP) {
835 if (this->GetName() == "List" && !this->IsGeneric()) {
836 AIDL_ERROR(this) << "List without type isn't supported in cpp.";
837 return false;
838 }
839 }
840 if (this->IsGeneric()) {
841 if (this->GetName() == "List") {
842 if (this->GetTypeParameters().size() != 1) {
843 AIDL_ERROR(this) << "List must have only one type parameter.";
844 return false;
845 }
846 if (lang == Options::Language::CPP) {
847 auto& name = this->GetTypeParameters()[0]->GetName();
848 if (!(name == "String" || name == "IBinder")) {
849 AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
850 return false;
851 }
852 } else if (lang == Options::Language::NDK) {
853 AIDL_ERROR(this) << "NDK backend does not support List yet.";
854 return false;
855 }
856
857 } else if (this->GetName() == "Map") {
858 if (lang != Options::Language::JAVA) {
859 AIDL_ERROR(this) << "Currently, only Java backend supports Map.";
860 return false;
861 }
862 }
863 }
864 return true;
865}
866
867// TODO: we should treat every backend all the same in future.
868bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
869 if (lang != Options::Language::JAVA) {
870 if (this->IsStableParcelable()) {
871 AIDL_ERROR(this) << "@JavaOnlyStableParcelable supports only Java target.";
872 return false;
873 }
874 const AidlParcelable* unstructuredParcelable = this->AsUnstructuredParcelable();
875 if (unstructuredParcelable != nullptr) {
876 if (unstructuredParcelable->GetCppHeader().empty()) {
877 AIDL_ERROR(unstructuredParcelable)
878 << "Unstructured parcelable must have C++ header defined.";
879 return false;
880 }
881 }
882 }
883 return true;
884}
885
886// TODO: we should treat every backend all the same in future.
887bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
888 if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
889 return false;
890 }
891 for (const auto& v : this->GetFields()) {
892 if (!v->GetType().LanguageSpecificCheckValid(lang)) {
893 return false;
894 }
895 }
896 return true;
897}
898
Daniel Norman85aed542019-08-21 12:01:14 -0700899AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
900 AidlConstantValue* value)
901 : AidlNode(location), name_(name), value_(value) {}
902
903bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
904 if (GetValue() == nullptr) {
905 return false;
906 }
907 if (!GetValue()->CheckValid()) {
908 return false;
909 }
910 if (GetValue()->As(enum_backing_type, AidlConstantValueDecorator).empty()) {
911 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
912 return false;
913 }
914 return true;
915}
916
917string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
918 const ConstantValueDecorator& decorator) const {
919 return GetValue()->As(backing_type, decorator);
920}
921
922AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
923 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
924 const std::vector<std::string>& package)
925 : AidlDefinedType(location, name, "", package), enumerators_(std::move(*enumerators)) {}
926
927void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
928 backing_type_ = std::move(type);
929}
930
931bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
932 if (backing_type_ == nullptr) {
933 AIDL_ERROR(this) << "Enum declaration missing backing type.";
934 return false;
935 }
936 bool success = true;
937 for (const auto& enumerator : enumerators_) {
938 success = success && enumerator->CheckValid(GetBackingType());
939 }
940 return success;
941}
942
943void AidlEnumDeclaration::Write(CodeWriter* writer) const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700944 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
945 writer->Write("enum %s {\n", GetName().c_str());
Daniel Norman85aed542019-08-21 12:01:14 -0700946 writer->Indent();
947 for (const auto& enumerator : GetEnumerators()) {
948 // TODO(b/123321528): After autofilling is supported, determine if we want
949 // to leave out the assigned value for enumerators that were autofilled.
950 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
951 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
952 }
953 writer->Dedent();
954 writer->Write("}\n");
955}
956
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900957// TODO: we should treat every backend all the same in future.
958bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
959 for (const auto& m : this->GetMethods()) {
960 if (!m->GetType().LanguageSpecificCheckValid(lang)) {
961 return false;
962 }
963 for (const auto& arg : m->GetArguments()) {
964 if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
965 return false;
966 }
967 }
968 }
969 return true;
970}
971
Steven Moreland46e9da82018-07-27 15:45:29 -0700972AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700973 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800974 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700975 const std::vector<std::string>& package)
Steven Morelandacd53472018-12-14 10:17:26 -0800976 : AidlDefinedType(location, name, comments, package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800977 for (auto& member : *members) {
978 AidlMember* local = member.release();
979 AidlMethod* method = local->AsMethod();
Steven Moreland693640b2018-07-19 13:46:27 -0700980 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
981
982 CHECK(method == nullptr || constant == nullptr);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800983
984 if (method) {
Steven Moreland8c70ba92018-12-17 10:20:31 -0800985 method->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800986 methods_.emplace_back(method);
Steven Moreland693640b2018-07-19 13:46:27 -0700987 } else if (constant) {
988 constants_.emplace_back(constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800989 } else {
Steven Moreland46e9da82018-07-27 15:45:29 -0700990 AIDL_FATAL(this) << "Member is neither method nor constant!";
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800991 }
992 }
993
994 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700995}
996
Jiyong Park02da7422018-07-16 16:00:26 +0900997void AidlInterface::Write(CodeWriter* writer) const {
998 writer->Write("interface %s {\n", GetName().c_str());
999 writer->Indent();
1000 for (const auto& method : GetMethods()) {
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()) {
1004 writer->Write("%s;\n", constdecl->ToString().c_str());
1005 }
Jiyong Park02da7422018-07-16 16:00:26 +09001006 writer->Dedent();
1007 writer->Write("}\n");
1008}
1009
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001010bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
Andrei Onea9445fc62019-06-27 18:11:59 +01001011 if (!CheckValidAnnotations()) {
1012 return false;
1013 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001014 // Has to be a pointer due to deleting copy constructor. No idea why.
1015 map<string, const AidlMethod*> method_names;
1016 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001017 if (!m->GetType().CheckValid(typenames)) {
1018 return false;
1019 }
1020
Steven Morelandacd53472018-12-14 10:17:26 -08001021 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001022 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1023 return false;
1024 }
1025
1026 set<string> argument_names;
1027 for (const auto& arg : m->GetArguments()) {
1028 auto it = argument_names.find(arg->GetName());
1029 if (it != argument_names.end()) {
1030 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1031 << arg->GetName() << "'";
1032 return false;
1033 }
1034 argument_names.insert(arg->GetName());
1035
1036 if (!arg->GetType().CheckValid(typenames)) {
1037 return false;
1038 }
1039
Steven Morelandacd53472018-12-14 10:17:26 -08001040 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001041 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1042 return false;
1043 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001044 const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
1045 if (!arg->DirectionWasSpecified() && can_be_out) {
1046 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
1047 << "' can be an out type, so you must declare it as in, out, or inout.";
1048 return false;
1049 }
1050
1051 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
1052 AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1053 return false;
1054 }
1055
1056 // check that the name doesn't match a keyword
1057 if (is_java_keyword(arg->GetName().c_str())) {
1058 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1059 return false;
1060 }
1061
1062 // Reserve a namespace for internal use
1063 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1064 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1065 return false;
1066 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001067 }
1068
1069 auto it = method_names.find(m->GetName());
1070 // prevent duplicate methods
1071 if (it == method_names.end()) {
1072 method_names[m->GetName()] = m.get();
1073 } else {
1074 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1075 AIDL_ERROR(it->second) << "previously defined here.";
1076 return false;
1077 }
1078
1079 static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
1080 "getTransactionName(int)"};
1081
1082 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1083 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
1084 return false;
1085 }
1086 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001087
1088 bool success = true;
1089 set<string> constant_names;
1090 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1091 if (constant_names.count(constant->GetName()) > 0) {
1092 LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
1093 success = false;
1094 }
1095 constant_names.insert(constant->GetName());
1096 success = success && constant->CheckValid(typenames);
1097 }
1098
1099 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001100}
1101
Steven Moreland46e9da82018-07-27 15:45:29 -07001102AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
1103 const std::string& comments)
1104 : AidlNode(location), terms_({term}), comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001105 if (term.find('.') != string::npos) {
1106 terms_ = Split(term, ".");
Steven Moreland46e9da82018-07-27 15:45:29 -07001107 for (const auto& subterm : terms_) {
1108 if (subterm.empty()) {
1109 AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001110 }
1111 }
1112 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001113}
1114
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -07001115void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -07001116 terms_.push_back(term);
1117}
1118
Steven Moreland46e9da82018-07-27 15:45:29 -07001119AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1120 : AidlNode(location), needed_class_(needed_class) {}
Casey Dahlin0edf3422015-10-07 12:34:59 -07001121
Steven Moreland64e29be2018-08-08 18:52:19 -07001122std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
1123 const android::aidl::IoDelegate& io_delegate,
1124 AidlTypenames& typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001125 // Make sure we can read the file first, before trashing previous state.
Steven Moreland64e29be2018-08-08 18:52:19 -07001126 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
1127 if (raw_buffer == nullptr) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001128 AIDL_ERROR(filename) << "Error while opening file for parsing";
Steven Moreland64e29be2018-08-08 18:52:19 -07001129 return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001130 }
1131
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001132 // We're going to scan this buffer in place, and yacc demands we put two
1133 // nulls at the end.
Steven Moreland64e29be2018-08-08 18:52:19 -07001134 raw_buffer->append(2u, '\0');
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001135
Steven Moreland64e29be2018-08-08 18:52:19 -07001136 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001137
Steven Moreland64e29be2018-08-08 18:52:19 -07001138 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001139
Steven Moreland64e29be2018-08-08 18:52:19 -07001140 return parser;
Christopher Wiley4a2884b2015-10-07 11:27:45 -07001141}
1142
Christopher Wiley90be4e32015-10-20 14:55:25 -07001143std::vector<std::string> Parser::Package() const {
1144 if (!package_) {
1145 return {};
1146 }
1147 return package_->GetTerms();
1148}
1149
Steven Moreland46e9da82018-07-27 15:45:29 -07001150void Parser::AddImport(AidlImport* import) {
1151 imports_.emplace_back(import);
Casey Dahline2507492015-09-14 17:11:20 -07001152}
Jiyong Park1deecc32018-07-17 01:14:41 +09001153
1154bool Parser::Resolve() {
1155 bool success = true;
1156 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +09001157 if (!typespec->Resolve(typenames_)) {
Steven Moreland46e9da82018-07-27 15:45:29 -07001158 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
Jiyong Park1deecc32018-07-17 01:14:41 +09001159 success = false;
1160 // don't stop to show more errors if any
1161 }
1162 }
1163 return success;
1164}
Steven Moreland64e29be2018-08-08 18:52:19 -07001165
1166Parser::Parser(const std::string& filename, std::string& raw_buffer,
1167 android::aidl::AidlTypenames& typenames)
1168 : filename_(filename), typenames_(typenames) {
1169 yylex_init(&scanner_);
1170 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
1171}
1172
1173Parser::~Parser() {
1174 yy_delete_buffer(buffer_, scanner_);
1175 yylex_destroy(scanner_);
1176}