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