1 /*
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
17 #include "aidl_language.h"
18 #include "aidl_typenames.h"
19 #include "parser.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <algorithm>
26 #include <iostream>
27 #include <set>
28 #include <sstream>
29 #include <string>
30 #include <utility>
31
32 #include <android-base/parsedouble.h>
33 #include <android-base/parseint.h>
34 #include <android-base/result.h>
35 #include <android-base/strings.h>
36
37 #include "aidl.h"
38 #include "aidl_language_y.h"
39 #include "comments.h"
40 #include "logging.h"
41 #include "permission.h"
42
43 #ifdef _WIN32
isatty(int fd)44 int isatty(int fd)
45 {
46 return (fd == 0);
47 }
48 #endif
49
50 using android::aidl::IoDelegate;
51 using android::base::Error;
52 using android::base::Join;
53 using android::base::Result;
54 using android::base::Split;
55 using std::cerr;
56 using std::pair;
57 using std::set;
58 using std::string;
59 using std::unique_ptr;
60 using std::vector;
61
62 namespace {
IsJavaKeyword(const char * str)63 bool IsJavaKeyword(const char* str) {
64 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
~AidlNode()78 AidlNode::~AidlNode() {
79 if (!visited_) {
80 unvisited_locations_.push_back(location_);
81 }
82 }
83
ClearUnvisitedNodes()84 void AidlNode::ClearUnvisitedNodes() {
85 unvisited_locations_.clear();
86 }
87
GetLocationsOfUnvisitedNodes()88 const std::vector<AidlLocation>& AidlNode::GetLocationsOfUnvisitedNodes() {
89 return unvisited_locations_;
90 }
91
MarkVisited() const92 void AidlNode::MarkVisited() const {
93 visited_ = true;
94 }
95
AidlNode(const AidlLocation & location,const Comments & comments)96 AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
97 : location_(location), comments_(comments) {}
98
PrintLine() const99 std::string AidlNode::PrintLine() const {
100 std::stringstream ss;
101 ss << location_.file_ << ":" << location_.begin_.line;
102 return ss.str();
103 }
104
PrintLocation() const105 std::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
112 std::vector<AidlLocation> AidlNode::unvisited_locations_;
113
114 static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", /*array=*/std::nullopt,
115 nullptr, Comments{}};
116 static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", DynamicArray{},
117 nullptr, Comments{}};
118 static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", /*array=*/std::nullopt, nullptr,
119 Comments{}};
120 static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", /*array=*/std::nullopt,
121 nullptr, Comments{}};
122 static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", /*array=*/std::nullopt,
123 nullptr, Comments{}};
124
AllSchemas()125 const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
126 static const std::vector<Schema> kSchemas{
127 {AidlAnnotation::Type::NULLABLE,
128 "nullable",
129 CONTEXT_TYPE_SPECIFIER,
130 {{"heap", kBooleanType}}},
131 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
132 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
133 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
134 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
135 "UnsupportedAppUsage",
136 CONTEXT_TYPE | CONTEXT_MEMBER,
137 {{"expectedSignature", kStringType},
138 {"implicitMember", kStringType},
139 {"maxTargetSdk", kIntType},
140 {"publicAlternatives", kStringType},
141 {"trackingBug", kLongType}}},
142 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
143 "JavaOnlyStableParcelable",
144 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
145 {}},
146 {AidlAnnotation::Type::NDK_STABLE_PARCELABLE,
147 "NdkOnlyStableParcelable",
148 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
149 {}},
150 {AidlAnnotation::Type::BACKING,
151 "Backing",
152 CONTEXT_TYPE_ENUM,
153 {{"type", kStringType, /* required= */ true}}},
154 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
155 "JavaPassthrough",
156 CONTEXT_ALL,
157 {{"annotation", kStringType, /* required= */ true}},
158 /* repeatable= */ true},
159 {AidlAnnotation::Type::JAVA_DERIVE,
160 "JavaDerive",
161 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION | CONTEXT_TYPE_ENUM,
162 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
163 {AidlAnnotation::Type::JAVA_DEFAULT, "JavaDefault", CONTEXT_TYPE_INTERFACE, {}},
164 {AidlAnnotation::Type::JAVA_DELEGATOR, "JavaDelegator", CONTEXT_TYPE_INTERFACE, {}},
165 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
166 "JavaOnlyImmutable",
167 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
168 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
169 {}},
170 {AidlAnnotation::Type::JAVA_SUPPRESS_LINT,
171 "JavaSuppressLint",
172 CONTEXT_ALL,
173 {{"value", kStringArrayType, /* required= */ true}}},
174 {AidlAnnotation::Type::FIXED_SIZE,
175 "FixedSize",
176 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
177 {}},
178 {AidlAnnotation::Type::DESCRIPTOR,
179 "Descriptor",
180 CONTEXT_TYPE_INTERFACE,
181 {{"value", kStringType, /* required= */ true}}},
182 {AidlAnnotation::Type::RUST_DERIVE,
183 "RustDerive",
184 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
185 {{"Copy", kBooleanType},
186 {"Clone", kBooleanType},
187 {"PartialOrd", kBooleanType},
188 {"Ord", kBooleanType},
189 {"PartialEq", kBooleanType},
190 {"Eq", kBooleanType},
191 {"Hash", kBooleanType}}},
192 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
193 "SuppressWarnings",
194 CONTEXT_TYPE | CONTEXT_MEMBER,
195 {{"value", kStringArrayType, /* required= */ true}}},
196 {AidlAnnotation::Type::PERMISSION_ENFORCE,
197 "EnforcePermission",
198 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
199 {{"value", kStringType}, {"anyOf", kStringArrayType}, {"allOf", kStringArrayType}}},
200 {AidlAnnotation::Type::PERMISSION_MANUAL,
201 "PermissionManuallyEnforced",
202 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
203 {}},
204 {AidlAnnotation::Type::PERMISSION_NONE,
205 "RequiresNoPermission",
206 CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
207 {}},
208 {AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING,
209 "PropagateAllowBlocking",
210 CONTEXT_METHOD,
211 {}},
212 };
213 return kSchemas;
214 }
215
TypeToString(Type type)216 std::string AidlAnnotation::TypeToString(Type type) {
217 for (const Schema& schema : AllSchemas()) {
218 if (type == schema.type) return schema.name;
219 }
220 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
221 __builtin_unreachable();
222 }
223
Parse(const AidlLocation & location,const string & name,std::map<std::string,std::shared_ptr<AidlConstantValue>> parameter_list,const Comments & comments)224 std::unique_ptr<AidlAnnotation> AidlAnnotation::Parse(
225 const AidlLocation& location, const string& name,
226 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
227 const Comments& comments) {
228 const Schema* schema = nullptr;
229 for (const Schema& a_schema : AllSchemas()) {
230 if (a_schema.name == name) {
231 schema = &a_schema;
232 }
233 }
234
235 if (schema == nullptr) {
236 std::ostringstream stream;
237 stream << "'" << name << "' is not a recognized annotation. ";
238 stream << "It must be one of:";
239 for (const Schema& s : AllSchemas()) {
240 stream << " " << s.name;
241 }
242 stream << ".";
243 AIDL_ERROR(location) << stream.str();
244 return {};
245 }
246
247 return std::unique_ptr<AidlAnnotation>(
248 new AidlAnnotation(location, *schema, std::move(parameter_list), comments));
249 }
250
AidlAnnotation(const AidlLocation & location,const Schema & schema,std::map<std::string,std::shared_ptr<AidlConstantValue>> parameters,const Comments & comments)251 AidlAnnotation::AidlAnnotation(const AidlLocation& location, const Schema& schema,
252 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
253 const Comments& comments)
254 : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
255
256 struct ConstReferenceFinder : AidlVisitor {
257 const AidlConstantReference* found = nullptr;
VisitConstReferenceFinder258 void Visit(const AidlConstantReference& ref) override {
259 if (!found) found = &ref;
260 }
FindConstReferenceFinder261 static const AidlConstantReference* Find(const AidlConstantValue& c) {
262 ConstReferenceFinder finder;
263 VisitTopDown(finder, c);
264 return finder.found;
265 }
266 };
267
268 // Checks if annotation complies with the schema
269 // - every parameter is known and has well-typed value.
270 // - every required parameter is present.
CheckValid() const271 bool AidlAnnotation::CheckValid() const {
272 for (const auto& name_and_param : parameters_) {
273 const std::string& param_name = name_and_param.first;
274 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
275
276 const ParamType* param_type = schema_.ParamType(param_name);
277 if (!param_type) {
278 std::ostringstream stream;
279 stream << "Parameter " << param_name << " not supported ";
280 stream << "for annotation " << GetName() << ". ";
281 stream << "It must be one of:";
282 for (const auto& param : schema_.parameters) {
283 stream << " " << param.name;
284 }
285 AIDL_ERROR(this) << stream.str();
286 return false;
287 }
288
289 const auto& found = ConstReferenceFinder::Find(*param);
290 if (found) {
291 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
292 << found->GetFieldName() << ".";
293 return false;
294 }
295
296 if (!param->CheckValid()) {
297 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
298 << GetName() << ".";
299 return false;
300 }
301
302 const std::string param_value =
303 param->ValueString(param_type->type, AidlConstantValueDecorator);
304 // Assume error on empty string.
305 if (param_value == "") {
306 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
307 << GetName() << ".";
308 return false;
309 }
310 }
311 bool success = true;
312 for (const auto& param : schema_.parameters) {
313 if (param.required && parameters_.count(param.name) == 0) {
314 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
315 success = false;
316 }
317 }
318 if (!success) {
319 return false;
320 }
321 // For @Enforce annotations, validates the expression.
322 if (schema_.type == AidlAnnotation::Type::PERMISSION_ENFORCE) {
323 auto expr = EnforceExpression();
324 if (!expr.ok()) {
325 AIDL_ERROR(this) << "Unable to parse @EnforcePermission annotation: " << expr.error();
326 return false;
327 }
328 }
329 return true;
330 }
331
EnforceExpression() const332 Result<unique_ptr<android::aidl::perm::Expression>> AidlAnnotation::EnforceExpression() const {
333 auto single = ParamValue<std::string>("value");
334 auto anyOf = ParamValue<std::vector<std::string>>("anyOf");
335 auto allOf = ParamValue<std::vector<std::string>>("allOf");
336 if (single.has_value()) {
337 return std::make_unique<android::aidl::perm::Expression>(single.value());
338 } else if (anyOf.has_value()) {
339 auto v = android::aidl::perm::AnyOf{anyOf.value()};
340 return std::make_unique<android::aidl::perm::Expression>(v);
341 } else if (allOf.has_value()) {
342 auto v = android::aidl::perm::AllOf{allOf.value()};
343 return std::make_unique<android::aidl::perm::Expression>(v);
344 }
345 return Error() << "No parameter for @EnforcePermission";
346 }
347
348 // Checks if the annotation is applicable to the current context.
349 // For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
350 // nodes.
CheckContext(TargetContext context) const351 bool AidlAnnotation::CheckContext(TargetContext context) const {
352 if (schema_.target_context & static_cast<uint32_t>(context)) {
353 return true;
354 }
355 const static map<TargetContext, string> context_name_map{
356 {CONTEXT_TYPE_INTERFACE, "interface"},
357 {CONTEXT_TYPE_ENUM, "enum"},
358 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "parcelable definition"},
359 {CONTEXT_TYPE_UNION, "union"},
360 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable declaration"},
361 {CONTEXT_CONST, "constant"},
362 {CONTEXT_FIELD, "field"},
363 {CONTEXT_METHOD, "method"},
364 {CONTEXT_TYPE_SPECIFIER, "type"},
365 };
366 vector<string> available;
367 for (const auto& [context, name] : context_name_map) {
368 if (schema_.target_context & context) {
369 available.push_back(name);
370 }
371 }
372 AIDL_ERROR(this) << "@" << GetName()
373 << " is not available. It can only annotate: " << Join(available, ", ") << ".";
374 return false;
375 }
376
AnnotationParams(const ConstantValueDecorator & decorator) const377 std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
378 const ConstantValueDecorator& decorator) const {
379 std::map<std::string, std::string> raw_params;
380 for (const auto& name_and_param : parameters_) {
381 const std::string& param_name = name_and_param.first;
382 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
383 const ParamType* param_type = schema_.ParamType(param_name);
384 AIDL_FATAL_IF(!param_type, this);
385 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
386 }
387 return raw_params;
388 }
389
ToString() const390 std::string AidlAnnotation::ToString() const {
391 if (parameters_.empty()) {
392 return "@" + GetName();
393 } else {
394 vector<string> param_strings;
395 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
396 param_strings.emplace_back(name + "=" + value);
397 }
398 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
399 }
400 }
401
TraverseChildren(std::function<void (const AidlNode &)> traverse) const402 void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
403 for (const auto& [name, value] : parameters_) {
404 (void)name;
405 traverse(*value);
406 }
407 }
408
GetAnnotation(const vector<std::unique_ptr<AidlAnnotation>> & annotations,AidlAnnotation::Type type)409 static const AidlAnnotation* GetAnnotation(
410 const vector<std::unique_ptr<AidlAnnotation>>& annotations, AidlAnnotation::Type type) {
411 for (const auto& a : annotations) {
412 if (a->GetType() == type) {
413 AIDL_FATAL_IF(a->Repeatable(), a)
414 << "Trying to get a single annotation when it is repeatable.";
415 return a.get();
416 }
417 }
418 return nullptr;
419 }
420
GetScopedAnnotation(const AidlDefinedType & defined_type,AidlAnnotation::Type type)421 static const AidlAnnotation* GetScopedAnnotation(const AidlDefinedType& defined_type,
422 AidlAnnotation::Type type) {
423 const AidlAnnotation* annotation = GetAnnotation(defined_type.GetAnnotations(), type);
424 if (annotation) {
425 return annotation;
426 }
427 const AidlDefinedType* enclosing_type = defined_type.GetParentType();
428 if (enclosing_type) {
429 return GetScopedAnnotation(*enclosing_type, type);
430 }
431 return nullptr;
432 }
433
AidlAnnotatable(const AidlLocation & location,const Comments & comments)434 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
435 : AidlCommentable(location, comments) {}
436
IsNullable() const437 bool AidlAnnotatable::IsNullable() const {
438 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
439 }
440
IsHeapNullable() const441 bool AidlAnnotatable::IsHeapNullable() const {
442 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
443 if (annot) {
444 return annot->ParamValue<bool>("heap").value_or(false);
445 }
446 return false;
447 }
448
IsUtf8InCpp() const449 bool AidlAnnotatable::IsUtf8InCpp() const {
450 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
451 }
452
IsSensitiveData() const453 bool AidlAnnotatable::IsSensitiveData() const {
454 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
455 }
456
IsVintfStability() const457 bool AidlAnnotatable::IsVintfStability() const {
458 auto defined_type = AidlCast<AidlDefinedType>(*this);
459 AIDL_FATAL_IF(!defined_type, *this) << "@VintfStability is not attached to a type";
460 return GetScopedAnnotation(*defined_type, AidlAnnotation::Type::VINTF_STABILITY);
461 }
462
IsJavaOnlyImmutable() const463 bool AidlAnnotatable::IsJavaOnlyImmutable() const {
464 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
465 }
466
IsFixedSize() const467 bool AidlAnnotatable::IsFixedSize() const {
468 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
469 }
470
UnsupportedAppUsage() const471 const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
472 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
473 }
474
RustDerive() const475 std::vector<std::string> AidlAnnotatable::RustDerive() const {
476 std::vector<std::string> ret;
477 if (const auto* ann = GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE)) {
478 for (const auto& name_and_param : ann->AnnotationParams(AidlConstantValueDecorator)) {
479 if (name_and_param.second == "true") {
480 ret.push_back(name_and_param.first);
481 }
482 }
483 }
484 return ret;
485 }
486
BackingType() const487 const AidlAnnotation* AidlAnnotatable::BackingType() const {
488 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
489 }
490
SuppressWarnings() const491 std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
492 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
493 if (annot) {
494 auto names = annot->ParamValue<std::vector<std::string>>("value");
495 AIDL_FATAL_IF(!names.has_value(), this);
496 return std::move(names.value());
497 }
498 return {};
499 }
500
501 // Parses the @Enforce annotation expression.
EnforceExpression() const502 std::unique_ptr<android::aidl::perm::Expression> AidlAnnotatable::EnforceExpression() const {
503 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_ENFORCE);
504 if (annot) {
505 auto perm_expr = annot->EnforceExpression();
506 if (!perm_expr.ok()) {
507 // This should have been caught during validation.
508 AIDL_FATAL(this) << "Unable to parse @EnforcePermission annotation: " << perm_expr.error();
509 }
510 return std::move(perm_expr.value());
511 }
512 return {};
513 }
514
IsPermissionManual() const515 bool AidlAnnotatable::IsPermissionManual() const {
516 return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_MANUAL);
517 }
518
IsPermissionNone() const519 bool AidlAnnotatable::IsPermissionNone() const {
520 return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_NONE);
521 }
522
IsPermissionAnnotated() const523 bool AidlAnnotatable::IsPermissionAnnotated() const {
524 return IsPermissionNone() || IsPermissionManual() || EnforceExpression();
525 }
526
IsPropagateAllowBlocking() const527 bool AidlAnnotatable::IsPropagateAllowBlocking() const {
528 return GetAnnotation(annotations_, AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING);
529 }
530
IsStableApiParcelable(Options::Language lang) const531 bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
532 if (lang == Options::Language::JAVA)
533 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
534 if (lang == Options::Language::NDK)
535 return GetAnnotation(annotations_, AidlAnnotation::Type::NDK_STABLE_PARCELABLE);
536 return false;
537 }
538
JavaDerive(const std::string & method) const539 bool AidlAnnotatable::JavaDerive(const std::string& method) const {
540 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
541 if (annotation != nullptr) {
542 return annotation->ParamValue<bool>(method).value_or(false);
543 }
544 return false;
545 }
546
IsJavaDefault() const547 bool AidlAnnotatable::IsJavaDefault() const {
548 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEFAULT);
549 }
550
IsJavaDelegator() const551 bool AidlAnnotatable::IsJavaDelegator() const {
552 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DELEGATOR);
553 }
554
GetDescriptor() const555 std::string AidlAnnotatable::GetDescriptor() const {
556 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
557 if (annotation != nullptr) {
558 return annotation->ParamValue<std::string>("value").value();
559 }
560 return "";
561 }
562
CheckValid(const AidlTypenames &) const563 bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
564 for (const auto& annotation : GetAnnotations()) {
565 if (!annotation->CheckValid()) {
566 return false;
567 }
568 }
569
570 std::map<AidlAnnotation::Type, AidlLocation> declared;
571 for (const auto& annotation : GetAnnotations()) {
572 const auto& [iter, inserted] =
573 declared.emplace(annotation->GetType(), annotation->GetLocation());
574 if (!inserted && !annotation->Repeatable()) {
575 AIDL_ERROR(this) << "'" << annotation->GetName()
576 << "' is repeated, but not allowed. Previous location: " << iter->second;
577 return false;
578 }
579 }
580
581 return true;
582 }
583
ToString() const584 string AidlAnnotatable::ToString() const {
585 vector<string> ret;
586 for (const auto& a : annotations_) {
587 ret.emplace_back(a->ToString());
588 }
589 std::sort(ret.begin(), ret.end());
590 return Join(ret, " ");
591 }
592
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,std::optional<ArrayType> array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const Comments & comments)593 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
594 std::optional<ArrayType> array,
595 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
596 const Comments& comments)
597 : AidlAnnotatable(location, comments),
598 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
599 unresolved_name_(unresolved_name),
600 array_(std::move(array)),
601 split_name_(Split(unresolved_name, ".")) {}
602
ViewAsArrayBase(std::function<void (const AidlTypeSpecifier &)> func) const603 void AidlTypeSpecifier::ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const {
604 AIDL_FATAL_IF(!array_.has_value(), this);
605 // Declaring array of generic type cannot happen, it is grammar error.
606 AIDL_FATAL_IF(IsGeneric(), this);
607
608 bool is_mutated = mutated_;
609 mutated_ = true;
610 // mutate the array type to its base by removing a single dimension
611 // e.g.) T[] => T, T[N][M] => T[M] (note that, M is removed)
612 if (IsFixedSizeArray() && std::get<FixedSizeArray>(*array_).dimensions.size() > 1) {
613 auto& dimensions = std::get<FixedSizeArray>(*array_).dimensions;
614 auto dim = std::move(dimensions.front());
615 dimensions.erase(dimensions.begin());
616 func(*this);
617 dimensions.insert(dimensions.begin(), std::move(dim));
618 } else {
619 ArrayType array_type = std::move(array_.value());
620 array_ = std::nullopt;
621 func(*this);
622 array_ = std::move(array_type);
623 }
624 mutated_ = is_mutated;
625 }
626
MakeArray(ArrayType array_type)627 bool AidlTypeSpecifier::MakeArray(ArrayType array_type) {
628 // T becomes T[] or T[N]
629 if (!IsArray()) {
630 array_ = std::move(array_type);
631 return true;
632 }
633 // T[N] becomes T[N][M]
634 if (auto fixed_size_array = std::get_if<FixedSizeArray>(&array_type);
635 fixed_size_array != nullptr && IsFixedSizeArray()) {
636 // concat dimensions
637 for (auto& dim : fixed_size_array->dimensions) {
638 std::get<FixedSizeArray>(*array_).dimensions.push_back(std::move(dim));
639 }
640 return true;
641 }
642 return false;
643 }
644
GetDimensionInts() const645 std::vector<int32_t> FixedSizeArray::GetDimensionInts() const {
646 std::vector<int32_t> ints;
647 for (const auto& dim : dimensions) {
648 ints.push_back(dim->EvaluatedValue<int32_t>());
649 }
650 return ints;
651 }
652
GetFixedSizeArrayDimensions() const653 std::vector<int32_t> AidlTypeSpecifier::GetFixedSizeArrayDimensions() const {
654 AIDL_FATAL_IF(!IsFixedSizeArray(), "not a fixed-size array");
655 return std::get<FixedSizeArray>(GetArray()).GetDimensionInts();
656 }
657
Signature() const658 string AidlTypeSpecifier::Signature() const {
659 string ret = GetName();
660 if (IsGeneric()) {
661 vector<string> arg_names;
662 for (const auto& ta : GetTypeParameters()) {
663 arg_names.emplace_back(ta->Signature());
664 }
665 ret += "<" + Join(arg_names, ",") + ">";
666 }
667 if (IsArray()) {
668 if (IsFixedSizeArray()) {
669 for (const auto& dim : GetFixedSizeArrayDimensions()) {
670 ret += "[" + std::to_string(dim) + "]";
671 }
672 } else {
673 ret += "[]";
674 }
675 }
676 return ret;
677 }
678
ToString() const679 string AidlTypeSpecifier::ToString() const {
680 string ret = Signature();
681 string annotations = AidlAnnotatable::ToString();
682 if (annotations != "") {
683 ret = annotations + " " + ret;
684 }
685 return ret;
686 }
687
688 // When `scope` is specified, name is resolved first based on it.
689 // `scope` can be null for built-in types and fully-qualified types.
Resolve(const AidlTypenames & typenames,const AidlScope * scope)690 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames, const AidlScope* scope) {
691 AIDL_FATAL_IF(IsResolved(), this);
692 std::string name = unresolved_name_;
693 if (scope) {
694 name = scope->ResolveName(name);
695 }
696 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(name);
697 if (result.is_resolved) {
698 fully_qualified_name_ = result.canonical_name;
699 split_name_ = Split(fully_qualified_name_, ".");
700 defined_type_ = result.defined_type;
701 }
702 return result.is_resolved;
703 }
704
GetDefinedType() const705 const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
706 return defined_type_;
707 }
708
CheckValid(const AidlTypenames & typenames) const709 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
710 if (!AidlAnnotatable::CheckValid(typenames)) {
711 return false;
712 }
713 if (IsGeneric()) {
714 const auto& types = GetTypeParameters();
715 for (const auto& arg : types) {
716 if (!arg->CheckValid(typenames)) {
717 return false;
718 }
719 }
720
721 const string& type_name = GetName();
722 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
723 if (type_name == "List" || type_name == "Map") {
724 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
725 return !type_ptr->IsArray() &&
726 (typenames.GetEnumDeclaration(*type_ptr) ||
727 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
728 })) {
729 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
730 return false;
731 }
732 }
733 const auto defined_type = typenames.TryGetDefinedType(type_name);
734 const auto parameterizable =
735 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
736 const bool is_user_defined_generic_type =
737 parameterizable != nullptr && parameterizable->IsGeneric();
738 const size_t num_params = GetTypeParameters().size();
739 if (type_name == "List") {
740 if (num_params > 1) {
741 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
742 << "'";
743 return false;
744 }
745 static const char* kListUsage =
746 "List<T> supports interface/parcelable/union, String, IBinder, and ParcelFileDescriptor.";
747 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
748 if (contained_type.IsArray()) {
749 AIDL_ERROR(this) << "List of arrays is not supported. " << kListUsage;
750 return false;
751 }
752 const string& contained_type_name = contained_type.GetName();
753 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
754 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
755 contained_type_name != "ParcelFileDescriptor") {
756 AIDL_ERROR(this) << "List<" << contained_type_name << "> is not supported. "
757 << kListUsage;
758 return false;
759 }
760 }
761 } else if (type_name == "Map") {
762 if (num_params != 0 && num_params != 2) {
763 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
764 << "'" << Signature() << "'";
765 return false;
766 }
767 if (num_params == 2) {
768 const string& key_type = GetTypeParameters()[0]->Signature();
769 if (key_type != "String") {
770 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
771 << "'" << key_type << "'";
772 return false;
773 }
774 }
775 } else if (is_user_defined_generic_type) {
776 const size_t allowed = parameterizable->GetTypeParameters().size();
777 if (num_params != allowed) {
778 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
779 << num_params;
780 return false;
781 }
782 } else {
783 AIDL_ERROR(this) << type_name << " is not a generic type.";
784 return false;
785 }
786 }
787
788 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
789 GetTypeParameters().size() == 1 &&
790 GetTypeParameters()[0]->GetName() == "String";
791 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
792 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
793 return false;
794 }
795
796 if (GetName() == "void") {
797 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
798 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
799 return false;
800 }
801 }
802
803 if (IsArray()) {
804 if (GetName() == "ParcelableHolder" || GetName() == "List" || GetName() == "Map" ||
805 GetName() == "CharSequence") {
806 AIDL_ERROR(this) << "Arrays of " << GetName() << " are not supported.";
807 return false;
808 }
809 }
810
811 if (IsNullable()) {
812 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
813 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
814 return false;
815 }
816 const auto defined_type = typenames.TryGetDefinedType(GetName());
817 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
818 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
819 return false;
820 }
821 if (GetName() == "ParcelableHolder") {
822 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
823 return false;
824 }
825 if (IsHeapNullable()) {
826 if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
827 AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
828 return false;
829 }
830 }
831 }
832
833 if (IsFixedSizeArray()) {
834 for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
835 if (!dim->Evaluate()) {
836 return false;
837 }
838 if (dim->GetType() > AidlConstantValue::Type::INT32) {
839 AIDL_ERROR(this) << "Array size must be a positive number: " << dim->Literal();
840 return false;
841 }
842 auto value = dim->EvaluatedValue<int32_t>();
843 if (value < 0) {
844 AIDL_ERROR(this) << "Array size must be a positive number: " << value;
845 return false;
846 }
847 }
848 }
849 return true;
850 }
851
TraverseChildren(std::function<void (const AidlNode &)> traverse) const852 void AidlTypeSpecifier::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
853 AidlAnnotatable::TraverseChildren(traverse);
854 if (IsGeneric()) {
855 for (const auto& tp : GetTypeParameters()) {
856 traverse(*tp);
857 }
858 }
859 if (IsFixedSizeArray()) {
860 for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
861 traverse(*dim);
862 }
863 }
864 }
865
AidlConstantValueDecorator(const AidlTypeSpecifier & type,const std::variant<std::string,std::vector<std::string>> & raw_value)866 std::string AidlConstantValueDecorator(
867 const AidlTypeSpecifier& type,
868 const std::variant<std::string, std::vector<std::string>>& raw_value) {
869 if (type.IsArray()) {
870 const auto& values = std::get<std::vector<std::string>>(raw_value);
871 return "{" + Join(values, ", ") + "}";
872 }
873 const std::string& value = std::get<std::string>(raw_value);
874 if (auto defined_type = type.GetDefinedType(); defined_type) {
875 auto enum_type = defined_type->AsEnumDeclaration();
876 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
877 return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
878 }
879 return value;
880 }
881
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)882 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
883 AidlTypeSpecifier* type, const std::string& name)
884 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
885 default_user_specified_ = false;
886 }
887
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)888 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
889 AidlTypeSpecifier* type, const std::string& name,
890 AidlConstantValue* default_value)
891 : AidlMember(location, type->GetComments()),
892 type_(type),
893 name_(name),
894 default_user_specified_(true),
895 default_value_(default_value) {}
896
HasUsefulDefaultValue() const897 bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
898 if (GetDefaultValue()) {
899 return true;
900 }
901 // null is accepted as a valid default value in all backends
902 if (GetType().IsNullable()) {
903 return true;
904 }
905 return false;
906 }
907
CheckValid(const AidlTypenames & typenames) const908 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
909 bool valid = true;
910 valid &= type_->CheckValid(typenames);
911
912 if (type_->GetName() == "void") {
913 AIDL_ERROR(this) << "Declaration " << name_
914 << " is void, but declarations cannot be of void type.";
915 valid = false;
916 }
917
918 if (default_value_ == nullptr) return valid;
919 valid &= default_value_->CheckValid();
920
921 if (!valid) return false;
922
923 return !ValueString(AidlConstantValueDecorator).empty();
924 }
925
GetCapitalizedName() const926 string AidlVariableDeclaration::GetCapitalizedName() const {
927 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
928 string str = name_;
929 str[0] = static_cast<char>(toupper(str[0]));
930 return str;
931 }
932
ToString() const933 string AidlVariableDeclaration::ToString() const {
934 string ret = type_->ToString() + " " + name_;
935 if (default_value_ != nullptr && default_user_specified_) {
936 ret += " = " + ValueString(AidlConstantValueDecorator);
937 }
938 return ret;
939 }
940
Signature() const941 string AidlVariableDeclaration::Signature() const {
942 return type_->Signature() + " " + name_;
943 }
944
ValueString(const ConstantValueDecorator & decorator) const945 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
946 if (default_value_ != nullptr) {
947 return default_value_->ValueString(GetType(), decorator);
948 } else {
949 return "";
950 }
951 }
952
TraverseChildren(std::function<void (const AidlNode &)> traverse) const953 void AidlVariableDeclaration::TraverseChildren(
954 std::function<void(const AidlNode&)> traverse) const {
955 traverse(GetType());
956 if (auto default_value = GetDefaultValue(); default_value) {
957 traverse(*default_value);
958 }
959 }
960
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)961 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
962 AidlTypeSpecifier* type, const std::string& name)
963 : AidlVariableDeclaration(location, type, name),
964 direction_(direction),
965 direction_specified_(true) {}
966
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)967 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
968 const std::string& name)
969 : AidlVariableDeclaration(location, type, name),
970 direction_(AidlArgument::IN_DIR),
971 direction_specified_(false) {}
972
to_string(AidlArgument::Direction direction)973 static std::string to_string(AidlArgument::Direction direction) {
974 switch (direction) {
975 case AidlArgument::IN_DIR:
976 return "in";
977 case AidlArgument::OUT_DIR:
978 return "out";
979 case AidlArgument::INOUT_DIR:
980 return "inout";
981 }
982 }
983
GetDirectionSpecifier() const984 string AidlArgument::GetDirectionSpecifier() const {
985 string ret;
986 if (direction_specified_) {
987 ret = to_string(direction_);
988 }
989 return ret;
990 }
991
ToString() const992 string AidlArgument::ToString() const {
993 if (direction_specified_) {
994 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
995 } else {
996 return AidlVariableDeclaration::ToString();
997 }
998 }
999
FormatDirections(const std::set<AidlArgument::Direction> & directions)1000 static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
1001 std::vector<std::string> out;
1002 for (const auto& d : directions) {
1003 out.push_back(to_string(d));
1004 }
1005
1006 if (out.size() <= 1) { // [] => "" or [A] => "A"
1007 return Join(out, "");
1008 } else if (out.size() == 2) { // [A,B] => "A or B"
1009 return Join(out, " or ");
1010 } else { // [A,B,C] => "A, B, or C"
1011 out.back() = "or " + out.back();
1012 return Join(out, ", ");
1013 }
1014 }
1015
CheckValid(const AidlTypenames & typenames) const1016 bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
1017 if (!GetType().CheckValid(typenames)) {
1018 return false;
1019 }
1020
1021 const auto& aspect = typenames.GetArgumentAspect(GetType());
1022
1023 if (aspect.possible_directions.size() == 0) {
1024 AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
1025 return false;
1026 }
1027
1028 // when direction is not specified, "in" is assumed and should be the only possible direction
1029 if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
1030 AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
1031 << " can be an " << FormatDirections(aspect.possible_directions)
1032 << " parameter.";
1033 return false;
1034 }
1035
1036 if (aspect.possible_directions.count(GetDirection()) == 0) {
1037 AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
1038 << " parameter because " << aspect.name << " can only be an "
1039 << FormatDirections(aspect.possible_directions) << " parameter.";
1040 return false;
1041 }
1042
1043 return true;
1044 }
1045
IsHidden() const1046 bool AidlCommentable::IsHidden() const {
1047 return android::aidl::HasHideInComments(GetComments());
1048 }
1049
IsDeprecated() const1050 bool AidlCommentable::IsDeprecated() const {
1051 return android::aidl::FindDeprecated(GetComments()).has_value();
1052 }
1053
AidlMember(const AidlLocation & location,const Comments & comments)1054 AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
1055 : AidlAnnotatable(location, comments) {}
1056
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)1057 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
1058 AidlTypeSpecifier* type, const std::string& name,
1059 AidlConstantValue* value)
1060 : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}
1061
CheckValid(const AidlTypenames & typenames) const1062 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
1063 bool valid = true;
1064 valid &= type_->CheckValid(typenames);
1065 valid &= value_->CheckValid();
1066 valid = valid && !ValueString(AidlConstantValueDecorator).empty();
1067 if (!valid) return false;
1068
1069 const static set<string> kSupportedConstTypes = {"String", "byte", "int",
1070 "long", "float", "double"};
1071 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
1072 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
1073 return false;
1074 }
1075
1076 return true;
1077 }
1078
ToString() const1079 string AidlConstantDeclaration::ToString() const {
1080 return "const " + type_->ToString() + " " + name_ + " = " +
1081 ValueString(AidlConstantValueDecorator);
1082 }
1083
Signature() const1084 string AidlConstantDeclaration::Signature() const {
1085 return type_->Signature() + " " + name_;
1086 }
1087
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const Comments & comments)1088 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
1089 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
1090 const Comments& comments)
1091 : AidlMethod(location, oneway, type, name, args, comments, 0) {
1092 has_id_ = false;
1093 }
1094
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const Comments & comments,int id)1095 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
1096 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
1097 const Comments& comments, int id)
1098 : AidlMember(location, comments),
1099 oneway_(oneway),
1100 type_(type),
1101 name_(name),
1102 arguments_(std::move(*args)),
1103 id_(id) {
1104 has_id_ = true;
1105 delete args;
1106 for (const unique_ptr<AidlArgument>& a : arguments_) {
1107 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
1108 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
1109 }
1110 }
1111
Signature() const1112 string AidlMethod::Signature() const {
1113 vector<string> arg_signatures;
1114 for (const auto& arg : GetArguments()) {
1115 arg_signatures.emplace_back(arg->GetType().Signature());
1116 }
1117 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
1118 }
1119
ToString() const1120 string AidlMethod::ToString() const {
1121 vector<string> arg_strings;
1122 for (const auto& arg : GetArguments()) {
1123 arg_strings.emplace_back(arg->ToString());
1124 }
1125 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
1126 Join(arg_strings, ", ") + ")";
1127 if (HasId()) {
1128 ret += " = " + std::to_string(GetId());
1129 }
1130 return ret;
1131 }
1132
CheckValid(const AidlTypenames & typenames) const1133 bool AidlMethod::CheckValid(const AidlTypenames& typenames) const {
1134 if (!GetType().CheckValid(typenames)) {
1135 return false;
1136 }
1137
1138 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1139 if (GetType().GetName() == "ParcelableHolder") {
1140 AIDL_ERROR(this) << "ParcelableHolder cannot be a return type";
1141 return false;
1142 }
1143 if (IsOneway() && GetType().GetName() != "void") {
1144 AIDL_ERROR(this) << "oneway method '" << GetName() << "' cannot return a value";
1145 return false;
1146 }
1147
1148 set<string> argument_names;
1149 for (const auto& arg : GetArguments()) {
1150 auto it = argument_names.find(arg->GetName());
1151 if (it != argument_names.end()) {
1152 AIDL_ERROR(this) << "method '" << GetName() << "' has duplicate argument name '"
1153 << arg->GetName() << "'";
1154 return false;
1155 }
1156 argument_names.insert(arg->GetName());
1157
1158 if (!arg->CheckValid(typenames)) {
1159 return false;
1160 }
1161
1162 if (IsOneway() && arg->IsOut()) {
1163 AIDL_ERROR(this) << "oneway method '" << this->GetName() << "' cannot have out parameters";
1164 return false;
1165 }
1166
1167 // check that the name doesn't match a keyword
1168 if (IsJavaKeyword(arg->GetName().c_str())) {
1169 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1170 return false;
1171 }
1172
1173 // Reserve a namespace for internal use
1174 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1175 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1176 return false;
1177 }
1178
1179 if (arg->GetType().GetName() == "void") {
1180 AIDL_ERROR(arg->GetType()) << "'void' is an invalid type for the parameter '"
1181 << arg->GetName() << "'";
1182 return false;
1183 }
1184 }
1185 return true;
1186 }
1187
AidlDefinedType(const AidlLocation & location,const std::string & name,const Comments & comments,const std::string & package,std::vector<std::unique_ptr<AidlMember>> * members)1188 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
1189 const Comments& comments, const std::string& package,
1190 std::vector<std::unique_ptr<AidlMember>>* members)
1191 : AidlMember(location, comments), AidlScope(this), name_(name), package_(package) {
1192 // adjust name/package when name is fully qualified (for preprocessed files)
1193 if (package_.empty() && name_.find('.') != std::string::npos) {
1194 // Note that this logic is absolutely wrong. Given a parcelable
1195 // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
1196 // the class is just Bar. However, this was the way it was done in the past.
1197 //
1198 // See b/17415692
1199 auto pos = name.rfind('.');
1200 // name is the last part.
1201 name_ = name.substr(pos + 1);
1202 // package is the initial parts (except the last).
1203 package_ = name.substr(0, pos);
1204 }
1205 if (members) {
1206 for (auto& m : *members) {
1207 if (auto constant = AidlCast<AidlConstantDeclaration>(*m); constant) {
1208 constants_.emplace_back(constant);
1209 } else if (auto variable = AidlCast<AidlVariableDeclaration>(*m); variable) {
1210 variables_.emplace_back(variable);
1211 } else if (auto method = AidlCast<AidlMethod>(*m); method) {
1212 methods_.emplace_back(method);
1213 } else if (auto type = AidlCast<AidlDefinedType>(*m); type) {
1214 type->SetEnclosingScope(this);
1215 types_.emplace_back(type);
1216 } else {
1217 AIDL_FATAL(*m) << "Unknown member type.";
1218 }
1219 members_.push_back(m.release());
1220 }
1221 delete members;
1222 }
1223 }
1224
CheckValid(const AidlTypenames & typenames) const1225 bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
1226 if (!AidlAnnotatable::CheckValid(typenames)) {
1227 return false;
1228 }
1229 if (!CheckValidWithMembers(typenames)) {
1230 return false;
1231 }
1232 return true;
1233 }
1234
GetCanonicalName() const1235 std::string AidlDefinedType::GetCanonicalName() const {
1236 if (auto parent = GetParentType(); parent) {
1237 return parent->GetCanonicalName() + "." + GetName();
1238 }
1239 if (package_.empty()) {
1240 return GetName();
1241 }
1242 return GetPackage() + "." + GetName();
1243 }
1244
CheckValidWithMembers(const AidlTypenames & typenames) const1245 bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
1246 bool success = true;
1247
1248 for (const auto& t : GetNestedTypes()) {
1249 success = success && t->CheckValid(typenames);
1250 }
1251
1252 if (auto parameterizable = AsParameterizable();
1253 parameterizable && parameterizable->IsGeneric() && !GetNestedTypes().empty()) {
1254 AIDL_ERROR(this) << "Generic types can't have nested types.";
1255 return false;
1256 }
1257
1258 std::set<std::string> nested_type_names;
1259 for (const auto& t : GetNestedTypes()) {
1260 bool duplicated = !nested_type_names.emplace(t->GetName()).second;
1261 if (duplicated) {
1262 AIDL_ERROR(t) << "Redefinition of '" << t->GetName() << "'.";
1263 success = false;
1264 }
1265 // nested type can't have a parent name
1266 if (t->GetName() == GetName()) {
1267 AIDL_ERROR(t) << "Nested type '" << GetName() << "' has the same name as its parent.";
1268 success = false;
1269 }
1270 // Having unstructured parcelables as nested types doesn't make sense because they are defined
1271 // somewhere else in native languages (e.g. C++, Java...).
1272 if (AidlCast<AidlParcelable>(*t)) {
1273 AIDL_ERROR(t) << "'" << t->GetName()
1274 << "' is nested. Unstructured parcelables should be at the root scope.";
1275 return false;
1276 }
1277 }
1278
1279 if (!TopologicalVisit(GetNestedTypes(), [](auto&) {})) {
1280 AIDL_ERROR(this) << GetName()
1281 << " has nested types with cyclic references. C++ and NDK backends don't "
1282 "support cyclic references.";
1283 return false;
1284 }
1285
1286 for (const auto& v : GetFields()) {
1287 const bool field_valid = v->CheckValid(typenames);
1288 success = success && field_valid;
1289 }
1290
1291 // field names should be unique
1292 std::set<std::string> fieldnames;
1293 for (const auto& v : GetFields()) {
1294 bool duplicated = !fieldnames.emplace(v->GetName()).second;
1295 if (duplicated) {
1296 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
1297 success = false;
1298 }
1299 }
1300
1301 // immutable parcelables should have immutable fields.
1302 if (IsJavaOnlyImmutable()) {
1303 for (const auto& v : GetFields()) {
1304 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
1305 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
1306 << "non-immutable field named '" << v->GetName() << "'.";
1307 success = false;
1308 }
1309 }
1310 }
1311
1312 // Rust derive fields must be transitive
1313 const std::vector<std::string> rust_derives = RustDerive();
1314 for (const auto& v : GetFields()) {
1315 const AidlDefinedType* field = typenames.TryGetDefinedType(v->GetType().GetName());
1316 if (!field) continue;
1317
1318 // could get this from CONTEXT_*, but we don't currently save this info when we validated
1319 // contexts
1320 if (!field->AsStructuredParcelable() && !field->AsUnionDeclaration()) continue;
1321
1322 auto subs = field->RustDerive();
1323 for (const std::string& derive : rust_derives) {
1324 if (std::find(subs.begin(), subs.end(), derive) == subs.end()) {
1325 AIDL_ERROR(v) << "Field " << v->GetName() << " of type with @RustDerive " << derive
1326 << " also needs to derive this";
1327 success = false;
1328 }
1329 }
1330 }
1331
1332 set<string> constant_names;
1333 for (const auto& constant : GetConstantDeclarations()) {
1334 if (constant_names.count(constant->GetName()) > 0) {
1335 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
1336 success = false;
1337 }
1338 constant_names.insert(constant->GetName());
1339 success = success && constant->CheckValid(typenames);
1340 }
1341
1342 return success;
1343 }
1344
CheckValidForGetterNames() const1345 bool AidlDefinedType::CheckValidForGetterNames() const {
1346 bool success = true;
1347 std::set<std::string> getters;
1348 for (const auto& v : GetFields()) {
1349 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
1350 if (duplicated) {
1351 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
1352 << "' after capitalizing the first letter";
1353 success = false;
1354 }
1355 }
1356 return success;
1357 }
1358
GetParentType() const1359 const AidlDefinedType* AidlDefinedType::GetParentType() const {
1360 AIDL_FATAL_IF(GetEnclosingScope() == nullptr, this) << "Scope is not set.";
1361 return AidlCast<AidlDefinedType>(GetEnclosingScope()->GetNode());
1362 }
1363
GetRootType() const1364 const AidlDefinedType* AidlDefinedType::GetRootType() const {
1365 const AidlDefinedType* root = this;
1366 for (auto parent = root->GetParentType(); parent; parent = parent->GetParentType()) {
1367 root = parent;
1368 }
1369 return root;
1370 }
1371
1372 // Resolve `name` in the current scope. If not found, delegate to the parent
ResolveName(const std::string & name) const1373 std::string AidlDefinedType::ResolveName(const std::string& name) const {
1374 // For example, in the following, t1's type Baz means x.Foo.Bar.Baz
1375 // while t2's type is y.Baz.
1376 // package x;
1377 // import y.Baz;
1378 // parcelable Foo {
1379 // parcelable Bar {
1380 // enum Baz { ... }
1381 // Baz t1; // -> should be x.Foo.Bar.Baz
1382 // }
1383 // Baz t2; // -> should be y.Baz
1384 // Bar.Baz t3; // -> should be x.Foo.Bar.Baz
1385 // }
1386 AIDL_FATAL_IF(!GetEnclosingScope(), this)
1387 << "Type should have an enclosing scope.(e.g. AidlDocument)";
1388 if (AidlTypenames::IsBuiltinTypename(name)) {
1389 return name;
1390 }
1391
1392 const auto first_dot = name.find_first_of('.');
1393 // For "Outer.Inner", we look up "Outer" in the import list.
1394 const std::string class_name =
1395 (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
1396 // Keep ".Inner", to make a fully-qualified name
1397 const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
1398
1399 // check if it is a nested type
1400 for (const auto& type : GetNestedTypes()) {
1401 if (type->GetName() == class_name) {
1402 return type->GetCanonicalName() + nested_type;
1403 }
1404 }
1405
1406 return GetEnclosingScope()->ResolveName(name);
1407 }
1408
1409 template <>
AidlCast(const AidlNode & node)1410 const AidlDefinedType* AidlCast<AidlDefinedType>(const AidlNode& node) {
1411 struct Visitor : AidlVisitor {
1412 const AidlDefinedType* defined_type = nullptr;
1413 void Visit(const AidlInterface& t) override { defined_type = &t; }
1414 void Visit(const AidlEnumDeclaration& t) override { defined_type = &t; }
1415 void Visit(const AidlStructuredParcelable& t) override { defined_type = &t; }
1416 void Visit(const AidlUnionDecl& t) override { defined_type = &t; }
1417 void Visit(const AidlParcelable& t) override { defined_type = &t; }
1418 } v;
1419 node.DispatchVisit(v);
1420 return v.defined_type;
1421 }
1422
GetDocument() const1423 const AidlDocument& AidlDefinedType::GetDocument() const {
1424 const AidlDefinedType* root = GetRootType();
1425 auto scope = root->GetEnclosingScope();
1426 AIDL_FATAL_IF(!scope, this) << "no scope defined.";
1427 auto doc = AidlCast<AidlDocument>(scope->GetNode());
1428 AIDL_FATAL_IF(!doc, this) << "root scope is not a document.";
1429 return *doc;
1430 }
1431
AidlParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,const AidlUnstructuredHeaders & headers,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)1432 AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
1433 const std::string& package, const Comments& comments,
1434 const AidlUnstructuredHeaders& headers,
1435 std::vector<std::string>* type_params,
1436 std::vector<std::unique_ptr<AidlMember>>* members)
1437 : AidlDefinedType(location, name, comments, package, members),
1438 AidlParameterizable<std::string>(type_params),
1439 headers_(headers) {
1440 // Strip off quotation marks if we actually have headers.
1441 if (headers_.cpp.length() >= 2) {
1442 headers_.cpp = headers_.cpp.substr(1, headers_.cpp.length() - 2);
1443 }
1444 if (headers_.ndk.length() >= 2) {
1445 headers_.ndk = headers_.ndk.substr(1, headers_.ndk.length() - 2);
1446 }
1447 }
1448
1449 template <typename T>
CheckValid() const1450 bool AidlParameterizable<T>::CheckValid() const {
1451 return true;
1452 };
1453
1454 template <>
CheckValid() const1455 bool AidlParameterizable<std::string>::CheckValid() const {
1456 if (!IsGeneric()) {
1457 return true;
1458 }
1459 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
1460 if (set.size() != GetTypeParameters().size()) {
1461 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
1462 return false;
1463 }
1464 return true;
1465 }
1466
CheckValid(const AidlTypenames & typenames) const1467 bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1468 if (!AidlDefinedType::CheckValid(typenames)) {
1469 return false;
1470 }
1471 if (!AidlParameterizable<std::string>::CheckValid()) {
1472 return false;
1473 }
1474
1475 bool success = true;
1476 if (IsFixedSize()) {
1477 for (const auto& v : GetFields()) {
1478 if (!typenames.CanBeFixedSize(v->GetType())) {
1479 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1480 << "non-fixed size field named " << v->GetName() << ".";
1481 success = false;
1482 }
1483 }
1484 }
1485
1486 return success;
1487 }
1488
AidlStructuredParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)1489 AidlStructuredParcelable::AidlStructuredParcelable(
1490 const AidlLocation& location, const std::string& name, const std::string& package,
1491 const Comments& comments, std::vector<std::string>* type_params,
1492 std::vector<std::unique_ptr<AidlMember>>* members)
1493 : AidlParcelable(location, name, package, comments, {} /*headers*/, type_params, members) {}
1494
CheckValid(const AidlTypenames & typenames) const1495 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1496 if (!AidlParcelable::CheckValid(typenames)) {
1497 return false;
1498 }
1499
1500 bool success = true;
1501
1502 if (IsJavaOnlyImmutable()) {
1503 // Immutable parcelables provide getters
1504 if (!CheckValidForGetterNames()) {
1505 success = false;
1506 }
1507 }
1508
1509 return success;
1510 }
1511
1512 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const1513 bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
1514 if (this->GetName() == "FileDescriptor" &&
1515 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1516 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
1517 return false;
1518 }
1519
1520 if (lang != Options::Language::JAVA) {
1521 if (this->GetName() == "List" && !this->IsGeneric()) {
1522 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1523 return false;
1524 }
1525 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1526 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1527 return false;
1528 }
1529 }
1530
1531 return true;
1532 }
1533
1534 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const1535 bool AidlDefinedType::LanguageSpecificCheckValid(Options::Language lang) const {
1536 struct Visitor : AidlVisitor {
1537 Visitor(Options::Language lang) : lang(lang) {}
1538 void Visit(const AidlTypeSpecifier& type) override {
1539 success = success && type.LanguageSpecificCheckValid(lang);
1540 }
1541 Options::Language lang;
1542 bool success = true;
1543 } v(lang);
1544 VisitTopDown(v, *this);
1545 return v.success;
1546 }
1547
AidlEnumerator(const AidlLocation & location,const std::string & name,AidlConstantValue * value,const Comments & comments)1548 AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
1549 AidlConstantValue* value, const Comments& comments)
1550 : AidlCommentable(location, comments),
1551 name_(name),
1552 value_(value),
1553 value_user_specified_(value != nullptr) {}
1554
CheckValid(const AidlTypeSpecifier & enum_backing_type) const1555 bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1556 if (GetValue() == nullptr) {
1557 return false;
1558 }
1559 if (!GetValue()->CheckValid()) {
1560 return false;
1561 }
1562 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
1563 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1564 return false;
1565 }
1566 return true;
1567 }
1568
ValueString(const AidlTypeSpecifier & backing_type,const ConstantValueDecorator & decorator) const1569 string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1570 const ConstantValueDecorator& decorator) const {
1571 return GetValue()->ValueString(backing_type, decorator);
1572 }
1573
AidlEnumDeclaration(const AidlLocation & location,const std::string & name,std::vector<std::unique_ptr<AidlEnumerator>> * enumerators,const std::string & package,const Comments & comments)1574 AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1575 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
1576 const std::string& package, const Comments& comments)
1577 : AidlDefinedType(location, name, comments, package, nullptr),
1578 enumerators_(std::move(*enumerators)) {
1579 // Fill missing enumerator values with <prev + 1>
1580 // This can't be done in Autofill() because type/ref resolution depends on this.
1581 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1582 // resolved if A has no value set.
1583 const AidlEnumerator* previous = nullptr;
1584 for (const auto& enumerator : enumerators_) {
1585 if (enumerator->GetValue() == nullptr) {
1586 auto loc = enumerator->GetLocation();
1587 if (previous == nullptr) {
1588 enumerator->SetValue(
1589 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
1590 } else {
1591 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
1592 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
1593 loc, std::move(prev_value), "+",
1594 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
1595 }
1596 }
1597 previous = enumerator.get();
1598 }
1599 }
1600
Autofill(const AidlTypenames & typenames)1601 bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1602 if (auto annot = BackingType(); annot != nullptr) {
1603 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1604 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
1605 // need to call CheckValid().
1606 if (!annot->CheckValid()) {
1607 return false;
1608 }
1609 auto type = annot->ParamValue<std::string>("type").value();
1610 backing_type_ = typenames.MakeResolvedType(annot->GetLocation(), type, false);
1611 } else {
1612 // Default to byte type for enums.
1613 backing_type_ = typenames.MakeResolvedType(GetLocation(), "byte", false);
1614 }
1615
1616 // we only support/test a few backing types, so make sure this is a supported
1617 // one (otherwise boolean might work, which isn't supported/tested in all
1618 // backends)
1619 static std::set<string> kBackingTypes = {"byte", "int", "long"};
1620 if (kBackingTypes.find(backing_type_->GetName()) == kBackingTypes.end()) {
1621 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName()
1622 << ". Backing type must be one of: " << Join(kBackingTypes, ", ");
1623 return false;
1624 }
1625 return true;
1626 }
1627
CheckValid(const AidlTypenames & typenames) const1628 bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1629 if (!AidlDefinedType::CheckValid(typenames)) {
1630 return false;
1631 }
1632 if (!GetMembers().empty()) {
1633 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1634 return false;
1635 }
1636 if (backing_type_ == nullptr) {
1637 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1638 return false;
1639 }
1640 bool success = true;
1641 for (const auto& enumerator : enumerators_) {
1642 success = success && enumerator->CheckValid(GetBackingType());
1643 }
1644
1645 return success;
1646 }
1647
AidlUnionDecl(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)1648 AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1649 const std::string& package, const Comments& comments,
1650 std::vector<std::string>* type_params,
1651 std::vector<std::unique_ptr<AidlMember>>* members)
1652 : AidlParcelable(location, name, package, comments, {} /*headers*/, type_params, members) {}
1653
CheckValid(const AidlTypenames & typenames) const1654 bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
1655 // visit parents
1656 if (!AidlParcelable::CheckValid(typenames)) {
1657 return false;
1658 }
1659
1660 // unions provide getters always
1661 if (!CheckValidForGetterNames()) {
1662 return false;
1663 }
1664
1665 // now, visit self!
1666 bool success = true;
1667
1668 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1669 for (const auto& v : GetFields()) {
1670 if (v->GetType().GetName() == "ParcelableHolder") {
1671 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1672 success = false;
1673 }
1674 }
1675
1676 if (GetFields().empty()) {
1677 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1678 return false;
1679 }
1680
1681 // first member should have useful default value (implicit or explicit)
1682 const auto& first = GetFields()[0];
1683 if (!first->HasUsefulDefaultValue()) {
1684 // Most types can be initialized without a default value. For example,
1685 // interface types are inherently nullable. But, enum types should have
1686 // an explicit default value.
1687 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1688 AIDL_ERROR(first)
1689 << "The union's first member should have a useful default value. Enum types can be "
1690 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1691 return false;
1692 }
1693 // In Java, array types are initialized as null without a default value. To be sure that default
1694 // initialized unions are accepted by other backends we require arrays also have a default
1695 // value.
1696 if (first->GetType().IsArray()) {
1697 AIDL_ERROR(first)
1698 << "The union's first member should have a useful default value. Arrays can be "
1699 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1700 return false;
1701 }
1702 }
1703
1704 return success;
1705 }
1706
AidlInterface(const AidlLocation & location,const std::string & name,const Comments & comments,bool oneway,const std::string & package,std::vector<std::unique_ptr<AidlMember>> * members)1707 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
1708 const Comments& comments, bool oneway, const std::string& package,
1709 std::vector<std::unique_ptr<AidlMember>>* members)
1710 : AidlDefinedType(location, name, comments, package, members) {
1711 for (auto& m : GetMethods()) {
1712 m.get()->ApplyInterfaceOneway(oneway);
1713 }
1714 }
1715
CheckValid(const AidlTypenames & typenames) const1716 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1717 if (!AidlDefinedType::CheckValid(typenames)) {
1718 return false;
1719 }
1720 // Has to be a pointer due to deleting copy constructor. No idea why.
1721 map<string, const AidlMethod*> method_names;
1722 for (const auto& m : GetMethods()) {
1723 if (!m->CheckValid(typenames)) {
1724 return false;
1725 }
1726
1727 auto it = method_names.find(m->GetName());
1728 // prevent duplicate methods
1729 if (it == method_names.end()) {
1730 method_names[m->GetName()] = m.get();
1731 } else {
1732 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1733 AIDL_ERROR(it->second) << "previously defined here.";
1734 return false;
1735 }
1736
1737 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
1738 "getTransactionName(int)"};
1739
1740 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1741 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
1742 return false;
1743 }
1744
1745 if (!CheckValidPermissionAnnotations(*m.get())) {
1746 return false;
1747 }
1748 }
1749
1750 return true;
1751 }
1752
CheckValidPermissionAnnotations(const AidlMethod & m) const1753 bool AidlInterface::CheckValidPermissionAnnotations(const AidlMethod& m) const {
1754 if (IsPermissionAnnotated() && m.GetType().IsPermissionAnnotated()) {
1755 AIDL_ERROR(m) << "The interface " << GetName()
1756 << " uses a permission annotation but the method " << m.GetName()
1757 << " is also annotated.\n"
1758 << "Consider distributing the annotation to each method.";
1759 return false;
1760 }
1761 return true;
1762 }
1763
UsesPermissions() const1764 bool AidlInterface::UsesPermissions() const {
1765 if (EnforceExpression()) {
1766 return true;
1767 }
1768 for (auto& m : GetMethods()) {
1769 if (m->GetType().EnforceExpression()) {
1770 return true;
1771 }
1772 }
1773 return false;
1774 }
1775
GetDescriptor() const1776 std::string AidlInterface::GetDescriptor() const {
1777 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1778 if (annotatedDescriptor != "") {
1779 return annotatedDescriptor;
1780 }
1781 return GetCanonicalName();
1782 }
1783
AidlDocument(const AidlLocation & location,const Comments & comments,std::vector<string> imports,std::vector<std::unique_ptr<AidlDefinedType>> defined_types,bool is_preprocessed)1784 AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
1785 std::vector<string> imports,
1786 std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
1787 bool is_preprocessed)
1788 : AidlCommentable(location, comments),
1789 AidlScope(this),
1790 imports_(std::move(imports)),
1791 defined_types_(std::move(defined_types)),
1792 is_preprocessed_(is_preprocessed) {
1793 for (const auto& t : defined_types_) {
1794 t->SetEnclosingScope(this);
1795 }
1796 }
1797
1798 // Resolves type name in the current document.
1799 // - built-in types
1800 // - imported types
1801 // - top-level type
ResolveName(const std::string & name) const1802 std::string AidlDocument::ResolveName(const std::string& name) const {
1803 if (AidlTypenames::IsBuiltinTypename(name)) {
1804 return name;
1805 }
1806
1807 const auto first_dot = name.find_first_of('.');
1808 // For "Outer.Inner", we look up "Outer" in the import list.
1809 const std::string class_name =
1810 (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
1811 // Keep ".Inner", to make a fully-qualified name
1812 const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
1813
1814 for (const auto& import : Imports()) {
1815 if (SimpleName(import) == class_name) {
1816 return import + nested_type;
1817 }
1818 }
1819
1820 // check if it is a top-level type.
1821 for (const auto& type : DefinedTypes()) {
1822 if (type->GetName() == class_name) {
1823 return type->GetCanonicalName() + nested_type;
1824 }
1825 }
1826
1827 // name itself might be fully-qualified name.
1828 return name;
1829 }
1830