blob: 25a1bdb7fa382cf8f37e92f84355f13d8d0ab9c2 [file] [log] [blame]
Will McVickerefd970d2019-09-25 15:28:30 -07001/*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinskiffa16862014-01-23 18:17:42 -080017#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +090018#include "aidl_typenames.h"
Jiyong Parke5c45292020-05-26 19:06:24 +090019#include "parser.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070020
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080022#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -070023#include <string.h>
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +020024
Jiyong Park68bc77a2018-07-19 19:00:45 +090025#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +090026#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090027#include <set>
28#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070029#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090030#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070031
Steven Moreland1c4ba202018-08-09 10:49:54 -070032#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070033#include <android-base/parseint.h>
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +020034#include <android-base/result.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080035#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070036
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +020037#include "aidl.h"
Steven Moreland21780812020-09-11 01:29:45 +000038#include "aidl_language_y.h"
Jooyung Hand4fe00e2021-01-11 16:21:53 +090039#include "comments.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070040#include "logging.h"
Thiébaud Weksteen5a4db212021-09-02 17:09:34 +020041#include "permission/parser.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080042
Casey Dahlin07b9dde2015-09-10 19:13:49 -070043#ifdef _WIN32
44int isatty(int fd)
45{
46 return (fd == 0);
47}
48#endif
49
Christopher Wiley4a2884b2015-10-07 11:27:45 -070050using android::aidl::IoDelegate;
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +020051using android::base::Error;
Christopher Wileyd76067c2015-10-19 17:00:13 -070052using android::base::Join;
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +020053using android::base::Result;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080054using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070055using std::cerr;
Jiyong Park1deecc32018-07-17 01:14:41 +090056using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090057using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070058using std::string;
59using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090060using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080061
Jeongik Cha047c5ee2019-08-07 23:16:49 +090062namespace {
Jeongik Cha997281d2020-01-16 15:23:59 +090063bool IsJavaKeyword(const char* str) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +090064 static const std::vector<std::string> kJavaKeywords{
65 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
66 "char", "class", "const", "continue", "default", "do", "double",
67 "else", "enum", "extends", "final", "finally", "float", "for",
68 "goto", "if", "implements", "import", "instanceof", "int", "interface",
69 "long", "native", "new", "package", "private", "protected", "public",
70 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
71 "this", "throw", "throws", "transient", "try", "void", "volatile",
72 "while", "true", "false", "null",
73 };
74 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
75}
76} // namespace
77
Jooyung Han2b3cd2a2021-10-15 06:54:55 +090078AidlNode::~AidlNode() {
79 if (!visited_) {
80 unvisited_locations_.push_back(location_);
81 }
82}
83
84void AidlNode::ClearUnvisitedNodes() {
85 unvisited_locations_.clear();
86}
87
88const std::vector<AidlLocation>& AidlNode::GetLocationsOfUnvisitedNodes() {
89 return unvisited_locations_;
90}
91
92void AidlNode::MarkVisited() const {
93 visited_ = true;
94}
95
Jooyung Han8451a202021-01-16 03:07:06 +090096AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +090097 : location_(location), comments_(comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070098
Mathew Inwoodadb74672019-11-29 14:01:53 +000099std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +0000100 std::stringstream ss;
101 ss << location_.file_ << ":" << location_.begin_.line;
102 return ss.str();
103}
104
Mathew Inwoodadb74672019-11-29 14:01:53 +0000105std::string AidlNode::PrintLocation() const {
106 std::stringstream ss;
107 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
108 << location_.end_.line << ":" << location_.end_.column;
109 return ss.str();
110}
111
Jooyung Han2b3cd2a2021-10-15 06:54:55 +0900112std::vector<AidlLocation> AidlNode::unvisited_locations_;
113
Jooyung Han8451a202021-01-16 03:07:06 +0900114static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
115 Comments{}};
116static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
117 Comments{}};
118static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
119static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
120static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
121 Comments{}};
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900122
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700123const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
124 static const std::vector<Schema> kSchemas{
Jooyung Han01720ed2021-08-13 07:46:07 +0900125 {AidlAnnotation::Type::NULLABLE,
126 "nullable",
127 CONTEXT_TYPE_SPECIFIER,
128 {{"heap", kBooleanType}}},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900129 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
130 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
131 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700132 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
133 "UnsupportedAppUsage",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900134 CONTEXT_TYPE | CONTEXT_MEMBER,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900135 {{"expectedSignature", kStringType},
136 {"implicitMember", kStringType},
137 {"maxTargetSdk", kIntType},
138 {"publicAlternatives", kStringType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900139 {"trackingBug", kLongType}}},
140 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
141 "JavaOnlyStableParcelable",
142 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
143 {}},
144 {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
145 {AidlAnnotation::Type::BACKING,
146 "Backing",
147 CONTEXT_TYPE_ENUM,
148 {{"type", kStringType, /* required= */ true}}},
Jooyung Han5721a232020-12-24 04:34:55 +0900149 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
150 "JavaPassthrough",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900151 CONTEXT_ALL,
152 {{"annotation", kStringType, /* required= */ true}},
153 /* repeatable= */ true},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900154 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900155 "JavaDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900156 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
157 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
158 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
159 "JavaOnlyImmutable",
160 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
161 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
162 {}},
163 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
164 {AidlAnnotation::Type::DESCRIPTOR,
165 "Descriptor",
166 CONTEXT_TYPE_INTERFACE,
167 {{"value", kStringType, /* required= */ true}}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700168 {AidlAnnotation::Type::RUST_DERIVE,
169 "RustDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900170 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900171 {{"Copy", kBooleanType},
172 {"Clone", kBooleanType},
173 {"PartialOrd", kBooleanType},
174 {"Ord", kBooleanType},
175 {"PartialEq", kBooleanType},
176 {"Eq", kBooleanType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900177 {"Hash", kBooleanType}}},
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900178 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
179 "SuppressWarnings",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900180 CONTEXT_TYPE | CONTEXT_MEMBER,
181 {{"value", kStringArrayType, /* required= */ true}}},
Thiébaud Weksteene79243a2021-11-02 14:36:25 +1100182 {AidlAnnotation::Type::PERMISSION_ENFORCE,
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200183 "Enforce",
Thiébaud Weksteen133da842021-10-29 16:49:58 +1100184 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200185 {{"condition", kStringType, /* required= */ true}}},
Thiébaud Weksteene79243a2021-11-02 14:36:25 +1100186 {AidlAnnotation::Type::PERMISSION_MANUAL,
187 "PermissionManuallyEnforced",
188 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
189 {}},
190 {AidlAnnotation::Type::PERMISSION_NONE,
191 "NoPermissionRequired",
192 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
193 {}},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900194 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700195 return kSchemas;
196}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900197
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700198std::string AidlAnnotation::TypeToString(Type type) {
199 for (const Schema& schema : AllSchemas()) {
200 if (type == schema.type) return schema.name;
201 }
202 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
203 __builtin_unreachable();
204}
Andrei Onea9445fc62019-06-27 18:11:59 +0100205
Jooyung Han442cacf2021-09-13 17:44:56 +0900206std::unique_ptr<AidlAnnotation> AidlAnnotation::Parse(
Andrei Onea9445fc62019-06-27 18:11:59 +0100207 const AidlLocation& location, const string& name,
Jooyung Han442cacf2021-09-13 17:44:56 +0900208 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
Jooyung Han8451a202021-01-16 03:07:06 +0900209 const Comments& comments) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700210 const Schema* schema = nullptr;
211 for (const Schema& a_schema : AllSchemas()) {
212 if (a_schema.name == name) {
213 schema = &a_schema;
214 }
215 }
216
217 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900218 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700219 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900220 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700221 for (const Schema& s : AllSchemas()) {
222 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900223 }
224 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700225 AIDL_ERROR(location) << stream.str();
Jooyung Han442cacf2021-09-13 17:44:56 +0900226 return {};
Andrei Onea9445fc62019-06-27 18:11:59 +0100227 }
228
Jooyung Han442cacf2021-09-13 17:44:56 +0900229 return std::unique_ptr<AidlAnnotation>(
230 new AidlAnnotation(location, *schema, std::move(parameter_list), comments));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900231}
232
Jooyung Han442cacf2021-09-13 17:44:56 +0900233AidlAnnotation::AidlAnnotation(const AidlLocation& location, const Schema& schema,
234 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
235 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900236 : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100237
Jooyung Hanc5688f72021-01-05 15:41:48 +0900238struct ConstReferenceFinder : AidlVisitor {
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900239 const AidlConstantReference* found;
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900240 void Visit(const AidlConstantReference& ref) override {
Jooyung Han690f5842020-12-04 13:02:04 +0900241 if (!found) found = &ref;
242 }
Jooyung Hanc5688f72021-01-05 15:41:48 +0900243 static const AidlConstantReference* Find(const AidlConstantValue& c) {
244 ConstReferenceFinder finder;
245 VisitTopDown(finder, c);
246 return finder.found;
247 }
Jooyung Han690f5842020-12-04 13:02:04 +0900248};
249
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900250// Checks if annotation complies with the schema
251// - every parameter is known and has well-typed value.
252// - every required parameter is present.
Andrei Onea9445fc62019-06-27 18:11:59 +0100253bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100254 for (const auto& name_and_param : parameters_) {
255 const std::string& param_name = name_and_param.first;
256 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han690f5842020-12-04 13:02:04 +0900257
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900258 const ParamType* param_type = schema_.ParamType(param_name);
259 if (!param_type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100260 std::ostringstream stream;
261 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700262 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100263 stream << "It must be one of:";
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900264 for (const auto& param : schema_.parameters) {
265 stream << " " << param.name;
Andrei Onea9445fc62019-06-27 18:11:59 +0100266 }
267 AIDL_ERROR(this) << stream.str();
268 return false;
269 }
Jooyung Han690f5842020-12-04 13:02:04 +0900270
Jooyung Hanc5688f72021-01-05 15:41:48 +0900271 const auto& found = ConstReferenceFinder::Find(*param);
272 if (found) {
273 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
274 << found->GetFieldName() << ".";
Jooyung Han690f5842020-12-04 13:02:04 +0900275 return false;
276 }
277
278 if (!param->CheckValid()) {
279 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
280 << GetName() << ".";
281 return false;
282 }
283
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900284 const std::string param_value =
285 param->ValueString(param_type->type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100286 // Assume error on empty string.
287 if (param_value == "") {
288 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
289 << GetName() << ".";
290 return false;
291 }
292 }
Jooyung Han5721a232020-12-24 04:34:55 +0900293 bool success = true;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900294 for (const auto& param : schema_.parameters) {
295 if (param.required && parameters_.count(param.name) == 0) {
296 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
Jooyung Han5721a232020-12-24 04:34:55 +0900297 success = false;
298 }
299 }
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200300 if (!success) {
301 return false;
302 }
303 // For @Enforce annotations, validates the expression.
Thiébaud Weksteene79243a2021-11-02 14:36:25 +1100304 if (schema_.type == AidlAnnotation::Type::PERMISSION_ENFORCE) {
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200305 auto expr = EnforceExpression();
306 if (!expr.ok()) {
307 AIDL_ERROR(this) << "Unable to parse @Enforce annotation: " << expr.error();
308 return false;
309 }
310 }
311 return true;
312}
313
314Result<unique_ptr<perm::Expression>> AidlAnnotation::EnforceExpression() const {
315 auto perm_expr = ParamValue<std::string>("condition");
316 if (perm_expr.has_value()) {
317 return perm::Parser::Parse(perm_expr.value());
318 }
319 return Error() << "No condition parameter for @Enforce";
Andrei Onea9445fc62019-06-27 18:11:59 +0100320}
321
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900322// Checks if the annotation is applicable to the current context.
323// For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
324// nodes.
325bool AidlAnnotation::CheckContext(TargetContext context) const {
326 if (schema_.target_context & static_cast<uint32_t>(context)) {
327 return true;
328 }
329 const static map<TargetContext, string> context_name_map{
330 {CONTEXT_TYPE_INTERFACE, "interface"},
331 {CONTEXT_TYPE_ENUM, "enum"},
332 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
333 {CONTEXT_TYPE_UNION, "union"},
334 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
335 {CONTEXT_CONST, "constant"},
336 {CONTEXT_FIELD, "field"},
337 {CONTEXT_METHOD, "method"},
338 {CONTEXT_TYPE_SPECIFIER, "type"},
339 };
340 vector<string> available;
341 for (const auto& [context, name] : context_name_map) {
342 if (schema_.target_context & context) {
343 available.push_back(name);
344 }
345 }
346 AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
347 << Join(available, ", ") << "}.";
348 return false;
349}
350
Andrei Onea9445fc62019-06-27 18:11:59 +0100351std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
352 const ConstantValueDecorator& decorator) const {
353 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100354 for (const auto& name_and_param : parameters_) {
355 const std::string& param_name = name_and_param.first;
356 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900357 const ParamType* param_type = schema_.ParamType(param_name);
358 AIDL_FATAL_IF(!param_type, this);
359 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100360 }
361 return raw_params;
362}
Steven Moreland46e9da82018-07-27 15:45:29 -0700363
Jooyung Han965e31d2020-11-27 12:30:16 +0900364std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700365 if (parameters_.empty()) {
366 return "@" + GetName();
367 } else {
368 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900369 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700370 param_strings.emplace_back(name + "=" + value);
371 }
372 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
373 }
374}
375
Jooyung Hanc5688f72021-01-05 15:41:48 +0900376void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
377 for (const auto& [name, value] : parameters_) {
378 (void)name;
379 traverse(*value);
380 }
381}
382
Steven Morelanda7560e82021-10-08 16:24:39 -0700383static const AidlAnnotation* GetAnnotation(
384 const vector<std::unique_ptr<AidlAnnotation>>& annotations, AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100385 for (const auto& a : annotations) {
Steven Morelanda7560e82021-10-08 16:24:39 -0700386 if (a->GetType() == type) {
387 AIDL_FATAL_IF(a->Repeatable(), a)
Jooyung Hand902a972020-10-23 17:32:44 +0900388 << "Trying to get a single annotation when it is repeatable.";
Steven Morelanda7560e82021-10-08 16:24:39 -0700389 return a.get();
Andrei Onea9445fc62019-06-27 18:11:59 +0100390 }
391 }
392 return nullptr;
393}
394
Jooyung Han8451a202021-01-16 03:07:06 +0900395AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900396 : AidlCommentable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700397
Jiyong Park68bc77a2018-07-19 19:00:45 +0900398bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700399 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900400}
401
Jooyung Han01720ed2021-08-13 07:46:07 +0900402bool AidlAnnotatable::IsHeapNullable() const {
403 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
404 if (annot) {
405 return annot->ParamValue<bool>("heap").value_or(false);
406 }
407 return false;
408}
409
Jiyong Park68bc77a2018-07-19 19:00:45 +0900410bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700411 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900412}
413
Steven Morelanda7764e52020-10-27 17:29:29 +0000414bool AidlAnnotatable::IsSensitiveData() const {
415 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
416}
417
Steven Morelanda57d0a62019-07-30 09:41:14 -0700418bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700419 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700420}
421
Jeongik Chad0a10272020-08-06 16:33:36 +0900422bool AidlAnnotatable::IsJavaOnlyImmutable() const {
423 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900424}
425
Devin Moorec7e47a32020-08-07 10:55:25 -0700426bool AidlAnnotatable::IsFixedSize() const {
427 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
428}
429
Andrei Onea9445fc62019-06-27 18:11:59 +0100430const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700431 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900432}
433
Andrei Homescue61feb52020-08-18 15:44:24 -0700434const AidlAnnotation* AidlAnnotatable::RustDerive() const {
435 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
436}
437
Jooyung Han672557b2020-12-24 05:18:00 +0900438const AidlAnnotation* AidlAnnotatable::BackingType() const {
439 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700440}
441
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900442std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
443 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
444 if (annot) {
445 auto names = annot->ParamValue<std::vector<std::string>>("value");
446 AIDL_FATAL_IF(!names.has_value(), this);
447 return std::move(names.value());
448 }
449 return {};
450}
451
Thiébaud Weksteen5a4db212021-09-02 17:09:34 +0200452// Parses the @Enforce annotation expression.
Thiébaud Weksteen133da842021-10-29 16:49:58 +1100453std::unique_ptr<perm::Expression> AidlAnnotatable::EnforceExpression() const {
Thiébaud Weksteene79243a2021-11-02 14:36:25 +1100454 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_ENFORCE);
Thiébaud Weksteen5a4db212021-09-02 17:09:34 +0200455 if (annot) {
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200456 auto perm_expr = annot->EnforceExpression();
457 if (!perm_expr.ok()) {
458 // This should have been caught during validation.
Thiébaud Weksteen133da842021-10-29 16:49:58 +1100459 AIDL_FATAL(this) << "Unable to parse @Enforce annotation: " << perm_expr.error();
Thiébaud Weksteen5a4db212021-09-02 17:09:34 +0200460 }
Thiébaud Weksteen9ab59122021-09-20 09:37:38 +0200461 return std::move(perm_expr.value());
Thiébaud Weksteen5a4db212021-09-02 17:09:34 +0200462 }
463 return {};
464}
465
Thiébaud Weksteene79243a2021-11-02 14:36:25 +1100466bool AidlAnnotatable::IsPermissionManual() const {
467 return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_MANUAL);
468}
469
470bool AidlAnnotatable::IsPermissionNone() const {
471 return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_NONE);
472}
473
Jeongik Cha88f95a82020-01-15 13:02:16 +0900474bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700475 return lang == Options::Language::JAVA &&
476 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900477}
478
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800479bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700480 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800481}
482
Jooyung Han829ec7c2020-12-02 12:07:36 +0900483bool AidlAnnotatable::JavaDerive(const std::string& method) const {
484 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
485 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900486 return annotation->ParamValue<bool>(method).value_or(false);
Jooyung Han829ec7c2020-12-02 12:07:36 +0900487 }
488 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900489}
490
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900491std::string AidlAnnotatable::GetDescriptor() const {
492 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
493 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900494 return annotation->ParamValue<std::string>("value").value();
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900495 }
496 return "";
497}
498
Devin Moore24f68572020-02-26 13:20:59 -0800499bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100500 for (const auto& annotation : GetAnnotations()) {
Steven Morelanda7560e82021-10-08 16:24:39 -0700501 if (!annotation->CheckValid()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900502 return false;
503 }
504 }
505
506 std::map<AidlAnnotation::Type, AidlLocation> declared;
507 for (const auto& annotation : GetAnnotations()) {
Steven Morelanda7560e82021-10-08 16:24:39 -0700508 const auto& [iter, inserted] =
509 declared.emplace(annotation->GetType(), annotation->GetLocation());
510 if (!inserted && !annotation->Repeatable()) {
511 AIDL_ERROR(this) << "'" << annotation->GetName()
Jooyung Hand902a972020-10-23 17:32:44 +0900512 << "' is repeated, but not allowed. Previous location: " << iter->second;
513 return false;
514 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100515 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700516
Andrei Onea9445fc62019-06-27 18:11:59 +0100517 return true;
518}
519
Jiyong Park68bc77a2018-07-19 19:00:45 +0900520string AidlAnnotatable::ToString() const {
521 vector<string> ret;
522 for (const auto& a : annotations_) {
Steven Morelanda7560e82021-10-08 16:24:39 -0700523 ret.emplace_back(a->ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900524 }
525 std::sort(ret.begin(), ret.end());
526 return Join(ret, " ");
527}
528
Steven Moreland46e9da82018-07-27 15:45:29 -0700529AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
530 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900531 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Jooyung Han8451a202021-01-16 03:07:06 +0900532 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900533 : AidlAnnotatable(location, comments),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900534 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700535 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700536 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900537 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700538
Steven Moreland0cac8662021-10-08 16:43:29 -0700539void AidlTypeSpecifier::ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700540 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900541 // Declaring array of generic type cannot happen, it is grammar error.
542 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700543
Steven Moreland0cac8662021-10-08 16:43:29 -0700544 is_array_ = false;
545 func(*this);
546 is_array_ = true;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700547}
548
Jooyung Han965e31d2020-11-27 12:30:16 +0900549string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900550 string ret = GetName();
551 if (IsGeneric()) {
552 vector<string> arg_names;
553 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900554 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900555 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900556 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900557 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900558 if (IsArray()) {
559 ret += "[]";
560 }
561 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900562}
563
Jooyung Han965e31d2020-11-27 12:30:16 +0900564string AidlTypeSpecifier::ToString() const {
565 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900566 string annotations = AidlAnnotatable::ToString();
567 if (annotations != "") {
568 ret = annotations + " " + ret;
569 }
570 return ret;
571}
572
Jooyung Han13f1fa52021-06-11 18:06:12 +0900573// When `scope` is specified, name is resolved first based on it.
574// `scope` can be null for built-in types and fully-qualified types.
575bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames, const AidlScope* scope) {
Steven Moreland21780812020-09-11 01:29:45 +0000576 AIDL_FATAL_IF(IsResolved(), this);
Jooyung Han13f1fa52021-06-11 18:06:12 +0900577 std::string name = unresolved_name_;
578 if (scope) {
579 name = scope->ResolveName(name);
580 }
581 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(name);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700582 if (result.is_resolved) {
583 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900584 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900585 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900586 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700587 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700588}
589
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900590const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
591 return defined_type_;
592}
593
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900594bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800595 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100596 return false;
597 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900598 if (IsGeneric()) {
Jooyung Hand09a21d2021-02-15 18:56:55 +0900599 const auto& types = GetTypeParameters();
600 for (const auto& arg : types) {
601 if (!arg->CheckValid(typenames)) {
602 return false;
603 }
604 }
Jeongik Chae74c86d2019-12-12 16:54:03 +0900605
Jooyung Hand09a21d2021-02-15 18:56:55 +0900606 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900607 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
608 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900609 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
Jooyung Han1f35ef32021-02-15 19:08:05 +0900610 return !type_ptr->IsArray() &&
611 (typenames.GetEnumDeclaration(*type_ptr) ||
612 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
Jeongik Chae74c86d2019-12-12 16:54:03 +0900613 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700614 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900615 return false;
616 }
617 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800618 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900619 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800620 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
621 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900622 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800623 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900624 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800625 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900626 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000627 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900628 return false;
629 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900630 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
Jooyung Hancea89002021-02-15 17:04:04 +0900631 if (contained_type.IsArray()) {
632 AIDL_ERROR(this)
633 << "List of arrays is not supported. List<T> supports parcelable/union, String, "
634 "IBinder, and ParcelFileDescriptor.";
635 return false;
636 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900637 const string& contained_type_name = contained_type.GetName();
638 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
639 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
640 contained_type_name != "ParcelFileDescriptor") {
641 AIDL_ERROR(this) << "List<" << contained_type_name
642 << "> is not supported. List<T> supports parcelable/union, String, "
643 "IBinder, and ParcelFileDescriptor.";
644 return false;
645 }
646 } else { // Defined types
647 if (typenames.GetInterface(contained_type)) {
648 AIDL_ERROR(this) << "List<" << contained_type_name
649 << "> is not supported. List<T> supports parcelable/union, String, "
650 "IBinder, and ParcelFileDescriptor.";
651 return false;
652 }
653 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900654 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800655 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900656 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900657 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900658 return false;
659 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800660 if (num_params == 2) {
Jooyung Hanaab242a2021-02-15 19:01:15 +0900661 const string& key_type = GetTypeParameters()[0]->Signature();
Jeongik Chae48d9942020-01-02 17:39:00 +0900662 if (key_type != "String") {
663 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
664 << "'" << key_type << "'";
665 return false;
666 }
667 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800668 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900669 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800670 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900671 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800672 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900673 return false;
674 }
675 } else {
676 AIDL_ERROR(this) << type_name << " is not a generic type.";
677 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900678 }
679 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900680
Steven Moreland11cb9452020-01-21 16:56:58 -0800681 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
682 GetTypeParameters().size() == 1 &&
683 GetTypeParameters()[0]->GetName() == "String";
684 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
685 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
686 return false;
687 }
688
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900689 if (GetName() == "void") {
690 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
691 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
692 return false;
693 }
694 }
695
696 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800697 const auto defined_type = typenames.TryGetDefinedType(GetName());
698 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900699 AIDL_ERROR(this) << "Binder type cannot be an array";
700 return false;
701 }
Jooyung Han49b8f362021-10-15 10:58:02 +0900702 if (GetName() == "ParcelableHolder" || GetName() == "List" || GetName() == "Map" ||
703 GetName() == "CharSequence") {
704 AIDL_ERROR(this) << "Arrays of " << GetName() << " are not supported.";
Steven Moreland8042d2d2020-09-30 23:31:32 +0000705 return false;
706 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900707 }
708
709 if (IsNullable()) {
710 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
711 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
712 return false;
713 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800714 const auto defined_type = typenames.TryGetDefinedType(GetName());
715 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700716 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
717 return false;
718 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900719 if (GetName() == "ParcelableHolder") {
720 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
721 return false;
722 }
Jooyung Han01720ed2021-08-13 07:46:07 +0900723 if (IsHeapNullable()) {
724 if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
725 AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
726 return false;
727 }
728 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900729 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900730 return true;
731}
732
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900733std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700734 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900735 if (type.IsArray()) {
736 return raw_value;
737 }
738
739 if (auto defined_type = type.GetDefinedType(); defined_type) {
740 auto enum_type = defined_type->AsEnumDeclaration();
741 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
742 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
743 }
Steven Moreland860b1942018-08-16 14:59:28 -0700744 return raw_value;
745}
746
Steven Moreland46e9da82018-07-27 15:45:29 -0700747AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
748 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000749 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
750 default_user_specified_ = false;
751}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700752
Steven Moreland46e9da82018-07-27 15:45:29 -0700753AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
754 AidlTypeSpecifier* type, const std::string& name,
755 AidlConstantValue* default_value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900756 : AidlMember(location, type->GetComments()),
Steven Moreland541788d2020-05-21 22:05:52 +0000757 type_(type),
758 name_(name),
759 default_user_specified_(true),
760 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700761
Jooyung Han53fb4242020-12-17 16:03:49 +0900762bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
763 if (GetDefaultValue()) {
764 return true;
765 }
766 // null is accepted as a valid default value in all backends
767 if (GetType().IsNullable()) {
768 return true;
769 }
770 return false;
771}
772
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900773bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700774 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900775 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900776
Steven Moreland54be7bd2019-12-05 11:17:53 -0800777 if (type_->GetName() == "void") {
778 AIDL_ERROR(this) << "Declaration " << name_
779 << " is void, but declarations cannot be of void type.";
780 valid = false;
781 }
782
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900783 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700784 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700785
Steven Moreland25294322018-08-07 18:13:55 -0700786 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700787
Steven Moreland860b1942018-08-16 14:59:28 -0700788 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700789}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700790
Jooyung Hanacae85d2020-10-28 16:39:09 +0900791string AidlVariableDeclaration::GetCapitalizedName() const {
792 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
793 string str = name_;
794 str[0] = static_cast<char>(toupper(str[0]));
795 return str;
796}
797
Steven Moreland5557f1c2018-07-02 13:50:23 -0700798string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900799 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000800 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700801 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700802 }
803 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700804}
805
Jiyong Park02da7422018-07-16 16:00:26 +0900806string AidlVariableDeclaration::Signature() const {
807 return type_->Signature() + " " + name_;
808}
809
Steven Moreland860b1942018-08-16 14:59:28 -0700810std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900811 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700812 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900813 } else {
814 return "";
815 }
Steven Moreland25294322018-08-07 18:13:55 -0700816}
817
Jooyung Hanc5688f72021-01-05 15:41:48 +0900818void AidlVariableDeclaration::TraverseChildren(
819 std::function<void(const AidlNode&)> traverse) const {
820 traverse(GetType());
Jooyung Hanc3c739a2021-10-14 11:33:14 +0900821 if (auto default_value = GetDefaultValue(); default_value) {
822 traverse(*default_value);
Jooyung Hanc5688f72021-01-05 15:41:48 +0900823 }
824}
825
Steven Moreland46e9da82018-07-27 15:45:29 -0700826AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
827 AidlTypeSpecifier* type, const std::string& name)
828 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700829 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700830 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700831
Steven Moreland46e9da82018-07-27 15:45:29 -0700832AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
833 const std::string& name)
834 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700835 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700836 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700837
Jooyung Han020d8d12021-02-26 17:23:02 +0900838static std::string to_string(AidlArgument::Direction direction) {
839 switch (direction) {
840 case AidlArgument::IN_DIR:
841 return "in";
842 case AidlArgument::OUT_DIR:
843 return "out";
844 case AidlArgument::INOUT_DIR:
845 return "inout";
846 }
847}
848
Jiyong Park02da7422018-07-16 16:00:26 +0900849string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700850 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700851 if (direction_specified_) {
Jooyung Han020d8d12021-02-26 17:23:02 +0900852 ret = to_string(direction_);
Casey Dahlinc378c992015-09-29 16:50:40 -0700853 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700854 return ret;
855}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700856
Jiyong Park02da7422018-07-16 16:00:26 +0900857string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700858 if (direction_specified_) {
859 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
860 } else {
861 return AidlVariableDeclaration::ToString();
862 }
Jiyong Park02da7422018-07-16 16:00:26 +0900863}
864
Jooyung Han020d8d12021-02-26 17:23:02 +0900865static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
866 std::vector<std::string> out;
867 for (const auto& d : directions) {
868 out.push_back(to_string(d));
869 }
870
871 if (out.size() <= 1) { // [] => "" or [A] => "A"
872 return Join(out, "");
873 } else if (out.size() == 2) { // [A,B] => "A or B"
874 return Join(out, " or ");
875 } else { // [A,B,C] => "A, B, or C"
876 out.back() = "or " + out.back();
877 return Join(out, ", ");
878 }
879}
880
881bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
882 if (!GetType().CheckValid(typenames)) {
883 return false;
884 }
885
886 const auto& aspect = typenames.GetArgumentAspect(GetType());
887
888 if (aspect.possible_directions.size() == 0) {
889 AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
890 return false;
891 }
892
893 // when direction is not specified, "in" is assumed and should be the only possible direction
894 if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
895 AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
896 << " can be an " << FormatDirections(aspect.possible_directions)
897 << " parameter.";
898 return false;
899 }
900
901 if (aspect.possible_directions.count(GetDirection()) == 0) {
902 AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
903 << " parameter because " << aspect.name << " can only be an "
904 << FormatDirections(aspect.possible_directions) << " parameter.";
905 return false;
906 }
907
908 return true;
909}
910
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900911bool AidlCommentable::IsHidden() const {
Jooyung Han24effbf2021-01-16 10:24:03 +0900912 return android::aidl::HasHideInComments(GetComments());
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900913}
914
915bool AidlCommentable::IsDeprecated() const {
Jooyung Hand4fe00e2021-01-11 16:21:53 +0900916 return android::aidl::FindDeprecated(GetComments()).has_value();
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900917}
918
Jooyung Han8451a202021-01-16 03:07:06 +0900919AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
Jooyung Han2aedb112021-09-29 09:37:59 +0900920 : AidlAnnotatable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700921
Steven Moreland46e9da82018-07-27 15:45:29 -0700922AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
923 AidlTypeSpecifier* type, const std::string& name,
924 AidlConstantValue* value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900925 : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700926
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900927bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700928 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900929 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700930 valid &= value_->CheckValid();
931 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700932
Steven Morelande689da22020-11-10 02:06:30 +0000933 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900934 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
935 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700936 return false;
937 }
938
Will McVickerd7d18df2019-09-12 13:40:50 -0700939 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700940}
941
Jiyong Parka428d212018-08-29 22:26:30 +0900942string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900943 return "const " + type_->ToString() + " " + name_ + " = " +
944 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900945}
946
947string AidlConstantDeclaration::Signature() const {
948 return type_->Signature() + " " + name_;
949}
950
Steven Moreland46e9da82018-07-27 15:45:29 -0700951AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
952 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900953 const Comments& comments)
Jiyong Parkb034bf02018-07-30 17:44:33 +0900954 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
955 has_id_ = false;
956}
957
958AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
959 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900960 const Comments& comments, int id, bool is_user_defined)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900961 : AidlMember(location, comments),
Steven Moreland46e9da82018-07-27 15:45:29 -0700962 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700963 type_(type),
964 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700965 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900966 id_(id),
967 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700968 has_id_ = true;
969 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700970 for (const unique_ptr<AidlArgument>& a : arguments_) {
971 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
972 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
973 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700974}
975
Jiyong Park02da7422018-07-16 16:00:26 +0900976string AidlMethod::Signature() const {
977 vector<string> arg_signatures;
978 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900979 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900980 }
Jiyong Park309668e2018-07-28 16:55:44 +0900981 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
982}
983
984string AidlMethod::ToString() const {
985 vector<string> arg_strings;
986 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900987 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900988 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900989 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800990 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900991 if (HasId()) {
992 ret += " = " + std::to_string(GetId());
993 }
994 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900995}
996
Thiébaud Weksteenff6dafa2021-09-21 11:53:40 +0200997bool AidlMethod::CheckValid(const AidlTypenames& typenames) const {
998 if (!GetType().CheckValid(typenames)) {
999 return false;
1000 }
1001
1002 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1003 if (GetType().GetName() == "ParcelableHolder") {
1004 AIDL_ERROR(this) << "ParcelableHolder cannot be a return type";
1005 return false;
1006 }
1007 if (IsOneway() && GetType().GetName() != "void") {
1008 AIDL_ERROR(this) << "oneway method '" << GetName() << "' cannot return a value";
1009 return false;
1010 }
1011
1012 set<string> argument_names;
1013 for (const auto& arg : GetArguments()) {
1014 auto it = argument_names.find(arg->GetName());
1015 if (it != argument_names.end()) {
1016 AIDL_ERROR(this) << "method '" << GetName() << "' has duplicate argument name '"
1017 << arg->GetName() << "'";
1018 return false;
1019 }
1020 argument_names.insert(arg->GetName());
1021
1022 if (!arg->CheckValid(typenames)) {
1023 return false;
1024 }
1025
1026 if (IsOneway() && arg->IsOut()) {
1027 AIDL_ERROR(this) << "oneway method '" << this->GetName() << "' cannot have out parameters";
1028 return false;
1029 }
1030
1031 // check that the name doesn't match a keyword
1032 if (IsJavaKeyword(arg->GetName().c_str())) {
1033 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1034 return false;
1035 }
1036
1037 // Reserve a namespace for internal use
1038 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1039 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1040 return false;
1041 }
1042
1043 if (arg->GetType().GetName() == "void") {
1044 AIDL_ERROR(arg->GetType()) << "'void' is an invalid type for the parameter '"
1045 << arg->GetName() << "'";
1046 return false;
1047 }
1048 }
1049 return true;
1050}
1051
Steven Moreland46e9da82018-07-27 15:45:29 -07001052AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001053 const Comments& comments, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001054 std::vector<std::unique_ptr<AidlMember>>* members)
Jooyung Han2aedb112021-09-29 09:37:59 +09001055 : AidlMember(location, comments), AidlScope(this), name_(name), package_(package) {
Jooyung Han93f48f02021-06-05 00:11:16 +09001056 // adjust name/package when name is fully qualified (for preprocessed files)
1057 if (package_.empty() && name_.find('.') != std::string::npos) {
1058 // Note that this logic is absolutely wrong. Given a parcelable
1059 // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
1060 // the class is just Bar. However, this was the way it was done in the past.
1061 //
1062 // See b/17415692
1063 auto pos = name.rfind('.');
1064 // name is the last part.
1065 name_ = name.substr(pos + 1);
1066 // package is the initial parts (except the last).
1067 package_ = name.substr(0, pos);
1068 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001069 if (members) {
1070 for (auto& m : *members) {
Jooyung Hanbaa71062021-09-29 09:06:03 +09001071 if (auto constant = AidlCast<AidlConstantDeclaration>(*m); constant) {
Jooyung Han829ec7c2020-12-02 12:07:36 +09001072 constants_.emplace_back(constant);
Jooyung Hanbaa71062021-09-29 09:06:03 +09001073 } else if (auto variable = AidlCast<AidlVariableDeclaration>(*m); variable) {
Jooyung Han829ec7c2020-12-02 12:07:36 +09001074 variables_.emplace_back(variable);
Jooyung Hanbaa71062021-09-29 09:06:03 +09001075 } else if (auto method = AidlCast<AidlMethod>(*m); method) {
Jooyung Han829ec7c2020-12-02 12:07:36 +09001076 methods_.emplace_back(method);
Jooyung Han2aedb112021-09-29 09:37:59 +09001077 } else if (auto type = AidlCast<AidlDefinedType>(*m); type) {
1078 type->SetEnclosingScope(this);
1079 types_.emplace_back(type);
Jooyung Han829ec7c2020-12-02 12:07:36 +09001080 } else {
Jooyung Hanbaa71062021-09-29 09:06:03 +09001081 AIDL_FATAL(*m) << "Unknown member type.";
Jooyung Han829ec7c2020-12-02 12:07:36 +09001082 }
1083 members_.push_back(m.release());
1084 }
1085 delete members;
1086 }
1087}
Steven Moreland787b0432018-07-03 09:00:58 -07001088
Jooyung Han808a2a02020-12-28 16:46:54 +09001089bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -08001090 if (!AidlAnnotatable::CheckValid(typenames)) {
1091 return false;
1092 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001093 if (!CheckValidWithMembers(typenames)) {
1094 return false;
1095 }
Devin Moore24f68572020-02-26 13:20:59 -08001096 return true;
1097}
1098
Steven Moreland787b0432018-07-03 09:00:58 -07001099std::string AidlDefinedType::GetCanonicalName() const {
1100 if (package_.empty()) {
1101 return GetName();
1102 }
Jooyung Han2aedb112021-09-29 09:37:59 +09001103 if (auto parent = GetParentType(); parent) {
1104 return parent->GetCanonicalName() + "." + GetName();
1105 }
Steven Moreland787b0432018-07-03 09:00:58 -07001106 return GetPackage() + "." + GetName();
1107}
1108
Jooyung Han829ec7c2020-12-02 12:07:36 +09001109bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
1110 bool success = true;
1111
Jooyung Han2aedb112021-09-29 09:37:59 +09001112 for (const auto& t : GetNestedTypes()) {
1113 success = success && t->CheckValid(typenames);
1114 }
1115
Jooyung Han7fc5de02021-09-30 22:26:27 +09001116 if (auto parameterizable = AsParameterizable();
1117 parameterizable && parameterizable->IsGeneric() && !GetNestedTypes().empty()) {
1118 AIDL_ERROR(this) << "Generic types can't have nested types.";
1119 return false;
1120 }
1121
Jooyung Han2aedb112021-09-29 09:37:59 +09001122 std::set<std::string> nested_type_names;
1123 for (const auto& t : GetNestedTypes()) {
1124 bool duplicated = !nested_type_names.emplace(t->GetName()).second;
1125 if (duplicated) {
1126 AIDL_ERROR(t) << "Redefinition of '" << t->GetName() << "'.";
1127 success = false;
1128 }
1129 // nested type can't have a parent name
1130 if (t->GetName() == GetName()) {
1131 AIDL_ERROR(t) << "Nested type '" << GetName() << "' has the same name as its parent.";
1132 success = false;
1133 }
Jooyung Han2b1487d2021-09-30 09:57:01 +09001134 // Having unstructured parcelables as nested types doesn't make sense because they are defined
1135 // somewhere else in native languages (e.g. C++, Java...).
1136 if (AidlCast<AidlParcelable>(*t)) {
1137 AIDL_ERROR(t) << "'" << t->GetName()
1138 << "' is nested. Unstructured parcelables should be at the root scope.";
1139 return false;
1140 }
Jooyung Han2aedb112021-09-29 09:37:59 +09001141 }
1142
Jooyung Han8e9ae872021-10-13 02:52:25 +09001143 if (!TopologicalVisit(GetNestedTypes(), [](auto&) {})) {
1144 AIDL_ERROR(this) << GetName()
1145 << " has nested types with cyclic references. C++ and NDK backends don't "
1146 "support cyclic references.";
1147 return false;
1148 }
1149
Jooyung Han829ec7c2020-12-02 12:07:36 +09001150 for (const auto& v : GetFields()) {
1151 const bool field_valid = v->CheckValid(typenames);
1152 success = success && field_valid;
1153 }
1154
1155 // field names should be unique
1156 std::set<std::string> fieldnames;
1157 for (const auto& v : GetFields()) {
1158 bool duplicated = !fieldnames.emplace(v->GetName()).second;
1159 if (duplicated) {
1160 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
1161 success = false;
1162 }
1163 }
1164
1165 // immutable parcelables should have immutable fields.
1166 if (IsJavaOnlyImmutable()) {
1167 for (const auto& v : GetFields()) {
1168 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
1169 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
1170 << "non-immutable field named '" << v->GetName() << "'.";
1171 success = false;
1172 }
1173 }
1174 }
1175
1176 set<string> constant_names;
1177 for (const auto& constant : GetConstantDeclarations()) {
1178 if (constant_names.count(constant->GetName()) > 0) {
1179 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
1180 success = false;
1181 }
1182 constant_names.insert(constant->GetName());
1183 success = success && constant->CheckValid(typenames);
1184 }
1185
1186 return success;
1187}
1188
1189bool AidlDefinedType::CheckValidForGetterNames() const {
1190 bool success = true;
1191 std::set<std::string> getters;
1192 for (const auto& v : GetFields()) {
1193 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
1194 if (duplicated) {
1195 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
1196 << "' after capitalizing the first letter";
1197 success = false;
1198 }
1199 }
1200 return success;
1201}
1202
Jooyung Han2aedb112021-09-29 09:37:59 +09001203const AidlDefinedType* AidlDefinedType::GetParentType() const {
1204 AIDL_FATAL_IF(GetEnclosingScope() == nullptr, this) << "Scope is not set.";
1205 return AidlCast<AidlDefinedType>(GetEnclosingScope()->GetNode());
1206}
1207
Jooyung Hanf8c39632021-10-05 09:56:29 +09001208const AidlDefinedType* AidlDefinedType::GetRootType() const {
1209 const AidlDefinedType* root = this;
1210 for (auto parent = root->GetParentType(); parent; parent = parent->GetParentType()) {
1211 root = parent;
1212 }
1213 return root;
1214}
1215
Jooyung Han2aedb112021-09-29 09:37:59 +09001216// Resolve `name` in the current scope. If not found, delegate to the parent
Jooyung Han13f1fa52021-06-11 18:06:12 +09001217std::string AidlDefinedType::ResolveName(const std::string& name) const {
Jooyung Han2aedb112021-09-29 09:37:59 +09001218 // For example, in the following, t1's type Baz means x.Foo.Bar.Baz
1219 // while t2's type is y.Baz.
Jooyung Han13f1fa52021-06-11 18:06:12 +09001220 // package x;
Jooyung Han2aedb112021-09-29 09:37:59 +09001221 // import y.Baz;
Jooyung Han13f1fa52021-06-11 18:06:12 +09001222 // parcelable Foo {
1223 // parcelable Bar {
Jooyung Han2aedb112021-09-29 09:37:59 +09001224 // enum Baz { ... }
1225 // Baz t1; // -> should be x.Foo.Bar.Baz
Jooyung Han13f1fa52021-06-11 18:06:12 +09001226 // }
Jooyung Han2aedb112021-09-29 09:37:59 +09001227 // Baz t2; // -> should be y.Baz
1228 // Bar.Baz t3; // -> should be x.Foo.Bar.Baz
Jooyung Han13f1fa52021-06-11 18:06:12 +09001229 // }
1230 AIDL_FATAL_IF(!GetEnclosingScope(), this)
1231 << "Type should have an enclosing scope.(e.g. AidlDocument)";
Jooyung Han2aedb112021-09-29 09:37:59 +09001232 if (AidlTypenames::IsBuiltinTypename(name)) {
1233 return name;
1234 }
1235
1236 const auto first_dot = name.find_first_of('.');
1237 // For "Outer.Inner", we look up "Outer" in the import list.
1238 const std::string class_name =
1239 (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
1240 // Keep ".Inner", to make a fully-qualified name
1241 const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
1242
1243 // check if it is a nested type
1244 for (const auto& type : GetNestedTypes()) {
1245 if (type->GetName() == class_name) {
1246 return type->GetCanonicalName() + nested_type;
1247 }
1248 }
1249
Jooyung Han13f1fa52021-06-11 18:06:12 +09001250 return GetEnclosingScope()->ResolveName(name);
1251}
1252
Jooyung Hanbaa71062021-09-29 09:06:03 +09001253template <>
1254const AidlDefinedType* AidlCast<AidlDefinedType>(const AidlNode& node) {
1255 struct Visitor : AidlVisitor {
1256 const AidlDefinedType* defined_type = nullptr;
1257 void Visit(const AidlInterface& t) override { defined_type = &t; }
1258 void Visit(const AidlEnumDeclaration& t) override { defined_type = &t; }
1259 void Visit(const AidlStructuredParcelable& t) override { defined_type = &t; }
1260 void Visit(const AidlUnionDecl& t) override { defined_type = &t; }
1261 void Visit(const AidlParcelable& t) override { defined_type = &t; }
1262 } v;
1263 node.DispatchVisit(v);
1264 return v.defined_type;
Jooyung Han35784982021-06-29 06:26:12 +09001265}
1266
1267const AidlDocument& AidlDefinedType::GetDocument() const {
Jooyung Hanf8c39632021-10-05 09:56:29 +09001268 const AidlDefinedType* root = GetRootType();
1269 auto scope = root->GetEnclosingScope();
Jooyung Han35784982021-06-29 06:26:12 +09001270 AIDL_FATAL_IF(!scope, this) << "no scope defined.";
1271 auto doc = AidlCast<AidlDocument>(scope->GetNode());
Jooyung Hanf8c39632021-10-05 09:56:29 +09001272 AIDL_FATAL_IF(!doc, this) << "root scope is not a document.";
Jooyung Han35784982021-06-29 06:26:12 +09001273 return *doc;
1274}
1275
Jiyong Park18132182020-06-08 20:24:40 +09001276AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001277 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001278 const std::string& cpp_header, std::vector<std::string>* type_params,
1279 std::vector<std::unique_ptr<AidlMember>>* members)
1280 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +09001281 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001282 cpp_header_(cpp_header) {
1283 // Strip off quotation marks if we actually have a cpp header.
1284 if (cpp_header_.length() >= 2) {
1285 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
1286 }
Casey Dahlin59401da2015-10-09 18:16:45 -07001287}
Jeongik Chadf76dc72019-11-28 00:08:47 +09001288
1289template <typename T>
1290bool AidlParameterizable<T>::CheckValid() const {
1291 return true;
1292};
1293
1294template <>
1295bool AidlParameterizable<std::string>::CheckValid() const {
1296 if (!IsGeneric()) {
1297 return true;
1298 }
1299 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
1300 if (set.size() != GetTypeParameters().size()) {
1301 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
1302 return false;
1303 }
1304 return true;
1305}
Casey Dahlin59401da2015-10-09 18:16:45 -07001306
Jooyung Han808a2a02020-12-28 16:46:54 +09001307bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1308 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001309 return false;
1310 }
Jeongik Chadf76dc72019-11-28 00:08:47 +09001311 if (!AidlParameterizable<std::string>::CheckValid()) {
1312 return false;
1313 }
Jeongik Cha82317dd2019-02-27 20:26:11 +09001314
1315 return true;
1316}
1317
Steven Moreland5557f1c2018-07-02 13:50:23 -07001318AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001319 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han8451a202021-01-16 03:07:06 +09001320 const Comments& comments, std::vector<std::string>* type_params,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001321 std::vector<std::unique_ptr<AidlMember>>* members)
1322 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001323
Jooyung Han808a2a02020-12-28 16:46:54 +09001324bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1325 if (!AidlParcelable::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001326 return false;
1327 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001328
Jooyung Han59af9cc2020-10-25 21:44:14 +09001329 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001330
Jooyung Hand4057c42020-10-23 13:28:22 +09001331 if (IsFixedSize()) {
1332 for (const auto& v : GetFields()) {
1333 if (!typenames.CanBeFixedSize(v->GetType())) {
1334 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1335 << "non-fixed size field named " << v->GetName() << ".";
1336 success = false;
1337 }
1338 }
1339 }
1340
1341 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001342 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001343 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001344 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001345 }
1346 }
1347
Daniel Norman85aed542019-08-21 12:01:14 -07001348 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001349}
1350
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001351// TODO: we should treat every backend all the same in future.
Jooyung Hanb4997aa2021-10-16 03:26:12 +09001352bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
Andrei Homescub62afd92020-05-11 19:24:59 -07001353 if (this->GetName() == "FileDescriptor" &&
1354 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001355 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001356 return false;
1357 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001358
Devin Moore6a01ca12020-08-28 10:24:19 -07001359 if (lang != Options::Language::JAVA) {
1360 if (this->GetName() == "List" && !this->IsGeneric()) {
1361 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1362 return false;
1363 }
1364 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1365 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1366 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001367 }
1368 }
1369
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001370 return true;
1371}
1372
1373// TODO: we should treat every backend all the same in future.
Jooyung Hanb4997aa2021-10-16 03:26:12 +09001374bool AidlDefinedType::LanguageSpecificCheckValid(Options::Language lang) const {
Jooyung Han589cfb02021-09-28 17:26:04 +09001375 struct Visitor : AidlVisitor {
Jooyung Hanb4997aa2021-10-16 03:26:12 +09001376 Visitor(Options::Language lang) : lang(lang) {}
Jooyung Han589cfb02021-09-28 17:26:04 +09001377 void Visit(const AidlTypeSpecifier& type) override {
Jooyung Hanb4997aa2021-10-16 03:26:12 +09001378 success = success && type.LanguageSpecificCheckValid(lang);
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001379 }
Jooyung Han589cfb02021-09-28 17:26:04 +09001380 Options::Language lang;
1381 bool success = true;
Jooyung Hanb4997aa2021-10-16 03:26:12 +09001382 } v(lang);
Jooyung Han589cfb02021-09-28 17:26:04 +09001383 VisitTopDown(v, *this);
1384 return v.success;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001385}
1386
Daniel Norman85aed542019-08-21 12:01:14 -07001387AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001388 AidlConstantValue* value, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +09001389 : AidlCommentable(location, comments),
Jooyung Han29813842020-12-08 01:28:03 +09001390 name_(name),
1391 value_(value),
Jooyung Han29813842020-12-08 01:28:03 +09001392 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001393
1394bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1395 if (GetValue() == nullptr) {
1396 return false;
1397 }
1398 if (!GetValue()->CheckValid()) {
1399 return false;
1400 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001401 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001402 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1403 return false;
1404 }
1405 return true;
1406}
1407
1408string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1409 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001410 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001411}
1412
1413AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1414 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jooyung Han8451a202021-01-16 03:07:06 +09001415 const std::string& package, const Comments& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001416 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001417 enumerators_(std::move(*enumerators)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001418 // Fill missing enumerator values with <prev + 1>
1419 // This can't be done in Autofill() because type/ref resolution depends on this.
1420 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1421 // resolved if A has no value set.
Daniel Normanb28684e2019-10-17 15:31:39 -07001422 const AidlEnumerator* previous = nullptr;
1423 for (const auto& enumerator : enumerators_) {
1424 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001425 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001426 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001427 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001428 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001429 } else {
Jooyung Hand0c8af02021-01-06 18:08:01 +09001430 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
Daniel Normanb28684e2019-10-17 15:31:39 -07001431 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001432 loc, std::move(prev_value), "+",
1433 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001434 }
1435 }
1436 previous = enumerator.get();
1437 }
1438}
1439
Jooyung Han672557b2020-12-24 05:18:00 +09001440bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1441 if (auto annot = BackingType(); annot != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001442 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1443 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
Jooyung Han672557b2020-12-24 05:18:00 +09001444 // need to call CheckValid().
1445 if (!annot->CheckValid()) {
1446 return false;
1447 }
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001448 auto type = annot->ParamValue<std::string>("type").value();
Jooyung Hanaccd9192021-10-14 15:57:28 +09001449 backing_type_ = typenames.MakeResolvedType(annot->GetLocation(), type, false);
Jooyung Han672557b2020-12-24 05:18:00 +09001450 } else {
1451 // Default to byte type for enums.
Jooyung Hanaccd9192021-10-14 15:57:28 +09001452 backing_type_ = typenames.MakeResolvedType(GetLocation(), "byte", false);
Jooyung Han672557b2020-12-24 05:18:00 +09001453 }
Steven Morelandb248d072021-09-29 19:07:17 -07001454
1455 // we only support/test a few backing types, so make sure this is a supported
1456 // one (otherwise boolean might work, which isn't supported/tested in all
1457 // backends)
1458 static std::set<string> kBackingTypes = {"byte", "int", "long"};
1459 if (kBackingTypes.find(backing_type_->GetName()) == kBackingTypes.end()) {
1460 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName()
1461 << ". Backing type must be one of: " << Join(kBackingTypes, ", ");
1462 return false;
Jooyung Han672557b2020-12-24 05:18:00 +09001463 }
1464 return true;
1465}
1466
Jooyung Han808a2a02020-12-28 16:46:54 +09001467bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1468 if (!AidlDefinedType::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001469 return false;
1470 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001471 if (!GetMembers().empty()) {
1472 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1473 return false;
1474 }
Daniel Norman85aed542019-08-21 12:01:14 -07001475 if (backing_type_ == nullptr) {
1476 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1477 return false;
1478 }
1479 bool success = true;
1480 for (const auto& enumerator : enumerators_) {
1481 success = success && enumerator->CheckValid(GetBackingType());
1482 }
Jooyung Han3b990182020-12-22 17:44:31 +09001483
Jooyung Han808a2a02020-12-28 16:46:54 +09001484 return success;
Daniel Norman85aed542019-08-21 12:01:14 -07001485}
1486
Jooyung Han2946afc2020-10-05 20:29:16 +09001487AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001488 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001489 std::vector<std::string>* type_params,
1490 std::vector<std::unique_ptr<AidlMember>>* members)
1491 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001492
Jooyung Han808a2a02020-12-28 16:46:54 +09001493bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001494 // visit parents
Jooyung Han808a2a02020-12-28 16:46:54 +09001495 if (!AidlParcelable::CheckValid(typenames)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001496 return false;
1497 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001498
1499 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001500 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001501 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001502 }
1503
1504 // now, visit self!
1505 bool success = true;
1506
1507 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1508 for (const auto& v : GetFields()) {
1509 if (v->GetType().GetName() == "ParcelableHolder") {
1510 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1511 success = false;
1512 }
1513 }
1514
Jooyung Hanfe89f122020-10-14 03:49:18 +09001515 if (GetFields().empty()) {
1516 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1517 return false;
1518 }
1519
Jooyung Han53fb4242020-12-17 16:03:49 +09001520 // first member should have useful default value (implicit or explicit)
1521 const auto& first = GetFields()[0];
1522 if (!first->HasUsefulDefaultValue()) {
1523 // Most types can be initialized without a default value. For example,
1524 // interface types are inherently nullable. But, enum types should have
1525 // an explicit default value.
1526 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1527 AIDL_ERROR(first)
1528 << "The union's first member should have a useful default value. Enum types can be "
1529 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1530 return false;
1531 }
1532 // In Java, array types are initialized as null without a default value. To be sure that default
1533 // initialized unions are accepted by other backends we require arrays also have a default
1534 // value.
1535 if (first->GetType().IsArray()) {
1536 AIDL_ERROR(first)
1537 << "The union's first member should have a useful default value. Arrays can be "
1538 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1539 return false;
1540 }
1541 }
1542
Jooyung Hanfe89f122020-10-14 03:49:18 +09001543 return success;
1544}
1545
Steven Moreland46e9da82018-07-27 15:45:29 -07001546AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001547 const Comments& comments, bool oneway, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001548 std::vector<std::unique_ptr<AidlMember>>* members)
1549 : AidlDefinedType(location, name, comments, package, members) {
1550 for (auto& m : GetMethods()) {
1551 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001552 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001553}
1554
Jooyung Han808a2a02020-12-28 16:46:54 +09001555bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1556 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001557 return false;
1558 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001559 // Has to be a pointer due to deleting copy constructor. No idea why.
1560 map<string, const AidlMethod*> method_names;
1561 for (const auto& m : GetMethods()) {
Thiébaud Weksteenff6dafa2021-09-21 11:53:40 +02001562 if (!m->CheckValid(typenames)) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001563 return false;
1564 }
1565
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001566 auto it = method_names.find(m->GetName());
1567 // prevent duplicate methods
1568 if (it == method_names.end()) {
1569 method_names[m->GetName()] = m.get();
1570 } else {
1571 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1572 AIDL_ERROR(it->second) << "previously defined here.";
1573 return false;
1574 }
1575
Paul Trautrimb77048c2020-01-21 16:39:32 +09001576 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001577 "getTransactionName(int)"};
1578
1579 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001580 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001581 return false;
1582 }
Thiébaud Weksteene79243a2021-11-02 14:36:25 +11001583
1584 if (!CheckValidPermissionAnnotations(*m.get())) {
1585 return false;
1586 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001587 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001588
1589 bool success = true;
1590 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001591 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001592 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001593 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001594 success = false;
1595 }
1596 constant_names.insert(constant->GetName());
1597 success = success && constant->CheckValid(typenames);
1598 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001599 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001600}
1601
Thiébaud Weksteene79243a2021-11-02 14:36:25 +11001602bool AidlInterface::CheckValidPermissionAnnotations(const AidlMethod& m) const {
1603 if (IsPermissionNone() || IsPermissionManual()) {
1604 if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual() ||
1605 m.GetType().EnforceExpression()) {
1606 std::string interface_annotation = IsPermissionNone()
1607 ? "requiring no permission"
1608 : "manually implementing permission checks";
1609 AIDL_ERROR(m) << "The interface " << GetName() << " is annotated as " << interface_annotation
1610 << " but the method " << m.GetName() << " is also annotated.\n"
1611 << "Consider distributing the annotation to each method.";
1612 return false;
1613 }
1614 } else if (EnforceExpression()) {
1615 if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual()) {
1616 AIDL_ERROR(m) << "The interface " << GetName()
1617 << " enforces permissions using annotations"
1618 " but the method "
1619 << m.GetName() << " is also annotated.\n"
1620 << "Consider distributing the annotation to each method.";
1621 return false;
1622 }
1623 }
1624 return true;
1625}
1626
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001627std::string AidlInterface::GetDescriptor() const {
1628 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1629 if (annotatedDescriptor != "") {
1630 return annotatedDescriptor;
1631 }
1632 return GetCanonicalName();
1633}
1634
Jooyung Han13f1fa52021-06-11 18:06:12 +09001635AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
Jooyung Hancdf89ec2021-10-29 14:08:30 +09001636 std::set<string> imports,
Jooyung Han35784982021-06-29 06:26:12 +09001637 std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
1638 bool is_preprocessed)
Jooyung Han13f1fa52021-06-11 18:06:12 +09001639 : AidlCommentable(location, comments),
Jooyung Han35784982021-06-29 06:26:12 +09001640 AidlScope(this),
Jooyung Han13f1fa52021-06-11 18:06:12 +09001641 imports_(std::move(imports)),
Jooyung Han35784982021-06-29 06:26:12 +09001642 defined_types_(std::move(defined_types)),
1643 is_preprocessed_(is_preprocessed) {
Jooyung Han13f1fa52021-06-11 18:06:12 +09001644 for (const auto& t : defined_types_) {
1645 t->SetEnclosingScope(this);
1646 }
1647}
1648
1649// Resolves type name in the current document.
1650// - built-in types
1651// - imported types
1652// - top-level type
1653std::string AidlDocument::ResolveName(const std::string& name) const {
1654 if (AidlTypenames::IsBuiltinTypename(name)) {
1655 return name;
1656 }
1657
1658 const auto first_dot = name.find_first_of('.');
1659 // For "Outer.Inner", we look up "Outer" in the import list.
Jooyung Han29813842020-12-08 01:28:03 +09001660 const std::string class_name =
Jooyung Han13f1fa52021-06-11 18:06:12 +09001661 (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
1662 // Keep ".Inner", to make a fully-qualified name
1663 const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
1664
Jooyung Han29813842020-12-08 01:28:03 +09001665 for (const auto& import : Imports()) {
Jooyung Hancdf89ec2021-10-29 14:08:30 +09001666 if (SimpleName(import) == class_name) {
1667 return import + nested_type;
Jooyung Han29813842020-12-08 01:28:03 +09001668 }
1669 }
Jooyung Han13f1fa52021-06-11 18:06:12 +09001670
1671 // check if it is a top-level type.
1672 for (const auto& type : DefinedTypes()) {
1673 if (type->GetName() == class_name) {
1674 return type->GetCanonicalName() + nested_type;
1675 }
Jooyung Han29813842020-12-08 01:28:03 +09001676 }
Jooyung Han13f1fa52021-06-11 18:06:12 +09001677
1678 // name itself might be fully-qualified name.
1679 return name;
Steven Moreland26318532020-12-23 20:08:36 +00001680}