blob: 95b84b48df286bb214cc77abc486cd8c40db2f6a [file] [log] [blame]
Will McVickerefd970d2019-09-25 15:28:30 -07001/*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinskiffa16862014-01-23 18:17:42 -080017#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +090018#include "aidl_typenames.h"
Jiyong Parke5c45292020-05-26 19:06:24 +090019#include "parser.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070020
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080022#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -070023#include <string.h>
Jiyong Park68bc77a2018-07-19 19:00:45 +090024#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +090025#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090026#include <set>
27#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070028#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090029#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070030
Steven Moreland1c4ba202018-08-09 10:49:54 -070031#include <android-base/parsedouble.h>
Roshan Pius9d7810a2016-07-28 08:57:50 -070032#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080033#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070034
Steven Moreland21780812020-09-11 01:29:45 +000035#include "aidl_language_y.h"
Jooyung Hand4fe00e2021-01-11 16:21:53 +090036#include "comments.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070037#include "logging.h"
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +020038#include "permission/parser.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080039
Will McVickerd7d18df2019-09-12 13:40:50 -070040#include "aidl.h"
41
Casey Dahlin07b9dde2015-09-10 19:13:49 -070042#ifdef _WIN32
43int isatty(int fd)
44{
45 return (fd == 0);
46}
47#endif
48
Christopher Wiley4a2884b2015-10-07 11:27:45 -070049using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070050using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080051using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070052using std::cerr;
Jiyong Park1deecc32018-07-17 01:14:41 +090053using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090054using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070055using std::string;
56using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090057using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080058
Jeongik Cha047c5ee2019-08-07 23:16:49 +090059namespace {
Jeongik Cha997281d2020-01-16 15:23:59 +090060bool IsJavaKeyword(const char* str) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +090061 static const std::vector<std::string> kJavaKeywords{
62 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
63 "char", "class", "const", "continue", "default", "do", "double",
64 "else", "enum", "extends", "final", "finally", "float", "for",
65 "goto", "if", "implements", "import", "instanceof", "int", "interface",
66 "long", "native", "new", "package", "private", "protected", "public",
67 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
68 "this", "throw", "throws", "transient", "try", "void", "volatile",
69 "while", "true", "false", "null",
70 };
71 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
72}
73} // namespace
74
Jooyung Han8451a202021-01-16 03:07:06 +090075AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +090076 : location_(location), comments_(comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -070077
Mathew Inwoodadb74672019-11-29 14:01:53 +000078std::string AidlNode::PrintLine() const {
Andrei Onea8714b022019-02-01 18:55:54 +000079 std::stringstream ss;
80 ss << location_.file_ << ":" << location_.begin_.line;
81 return ss.str();
82}
83
Mathew Inwoodadb74672019-11-29 14:01:53 +000084std::string AidlNode::PrintLocation() const {
85 std::stringstream ss;
86 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
87 << location_.end_.line << ":" << location_.end_.column;
88 return ss.str();
89}
90
Jooyung Han8451a202021-01-16 03:07:06 +090091static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
92 Comments{}};
93static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
94 Comments{}};
95static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
96static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
97static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
98 Comments{}};
Jooyung Han5c2fcae2020-12-26 00:04:39 +090099
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700100const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
101 static const std::vector<Schema> kSchemas{
Jooyung Han01720ed2021-08-13 07:46:07 +0900102 {AidlAnnotation::Type::NULLABLE,
103 "nullable",
104 CONTEXT_TYPE_SPECIFIER,
105 {{"heap", kBooleanType}}},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900106 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
107 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
108 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700109 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
110 "UnsupportedAppUsage",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900111 CONTEXT_TYPE | CONTEXT_MEMBER,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900112 {{"expectedSignature", kStringType},
113 {"implicitMember", kStringType},
114 {"maxTargetSdk", kIntType},
115 {"publicAlternatives", kStringType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900116 {"trackingBug", kLongType}}},
117 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
118 "JavaOnlyStableParcelable",
119 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
120 {}},
121 {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
122 {AidlAnnotation::Type::BACKING,
123 "Backing",
124 CONTEXT_TYPE_ENUM,
125 {{"type", kStringType, /* required= */ true}}},
Jooyung Han5721a232020-12-24 04:34:55 +0900126 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
127 "JavaPassthrough",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900128 CONTEXT_ALL,
129 {{"annotation", kStringType, /* required= */ true}},
130 /* repeatable= */ true},
Jiyong Park9aa3d042020-12-04 23:30:02 +0900131 {AidlAnnotation::Type::JAVA_DERIVE,
Jooyung Han5721a232020-12-24 04:34:55 +0900132 "JavaDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900133 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
134 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
135 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
136 "JavaOnlyImmutable",
137 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
138 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
139 {}},
140 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
141 {AidlAnnotation::Type::DESCRIPTOR,
142 "Descriptor",
143 CONTEXT_TYPE_INTERFACE,
144 {{"value", kStringType, /* required= */ true}}},
Andrei Homescue61feb52020-08-18 15:44:24 -0700145 {AidlAnnotation::Type::RUST_DERIVE,
146 "RustDerive",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900147 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
Jooyung Han5c2fcae2020-12-26 00:04:39 +0900148 {{"Copy", kBooleanType},
149 {"Clone", kBooleanType},
150 {"PartialOrd", kBooleanType},
151 {"Ord", kBooleanType},
152 {"PartialEq", kBooleanType},
153 {"Eq", kBooleanType},
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900154 {"Hash", kBooleanType}}},
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900155 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
156 "SuppressWarnings",
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900157 CONTEXT_TYPE | CONTEXT_MEMBER,
158 {{"value", kStringArrayType, /* required= */ true}}},
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +0200159 {AidlAnnotation::Type::ENFORCE, "Enforce", CONTEXT_METHOD, {{"condition", kStringType}}},
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900160 };
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700161 return kSchemas;
162}
Jiyong Park68bc77a2018-07-19 19:00:45 +0900163
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700164std::string AidlAnnotation::TypeToString(Type type) {
165 for (const Schema& schema : AllSchemas()) {
166 if (type == schema.type) return schema.name;
167 }
168 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
169 __builtin_unreachable();
170}
Andrei Onea9445fc62019-06-27 18:11:59 +0100171
Jooyung Han442cacf2021-09-13 17:44:56 +0900172std::unique_ptr<AidlAnnotation> AidlAnnotation::Parse(
Andrei Onea9445fc62019-06-27 18:11:59 +0100173 const AidlLocation& location, const string& name,
Jooyung Han442cacf2021-09-13 17:44:56 +0900174 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
Jooyung Han8451a202021-01-16 03:07:06 +0900175 const Comments& comments) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700176 const Schema* schema = nullptr;
177 for (const Schema& a_schema : AllSchemas()) {
178 if (a_schema.name == name) {
179 schema = &a_schema;
180 }
181 }
182
183 if (schema == nullptr) {
Jiyong Park68bc77a2018-07-19 19:00:45 +0900184 std::ostringstream stream;
Steven Moreland46e9da82018-07-27 15:45:29 -0700185 stream << "'" << name << "' is not a recognized annotation. ";
Jiyong Park68bc77a2018-07-19 19:00:45 +0900186 stream << "It must be one of:";
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700187 for (const Schema& s : AllSchemas()) {
188 stream << " " << s.name;
Jiyong Park68bc77a2018-07-19 19:00:45 +0900189 }
190 stream << ".";
Steven Moreland46e9da82018-07-27 15:45:29 -0700191 AIDL_ERROR(location) << stream.str();
Jooyung Han442cacf2021-09-13 17:44:56 +0900192 return {};
Andrei Onea9445fc62019-06-27 18:11:59 +0100193 }
194
Jooyung Han442cacf2021-09-13 17:44:56 +0900195 return std::unique_ptr<AidlAnnotation>(
196 new AidlAnnotation(location, *schema, std::move(parameter_list), comments));
Jiyong Park68bc77a2018-07-19 19:00:45 +0900197}
198
Jooyung Han442cacf2021-09-13 17:44:56 +0900199AidlAnnotation::AidlAnnotation(const AidlLocation& location, const Schema& schema,
200 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
201 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900202 : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
Andrei Onea9445fc62019-06-27 18:11:59 +0100203
Jooyung Hanc5688f72021-01-05 15:41:48 +0900204struct ConstReferenceFinder : AidlVisitor {
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900205 const AidlConstantReference* found;
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900206 void Visit(const AidlConstantReference& ref) override {
Jooyung Han690f5842020-12-04 13:02:04 +0900207 if (!found) found = &ref;
208 }
Jooyung Hanc5688f72021-01-05 15:41:48 +0900209 static const AidlConstantReference* Find(const AidlConstantValue& c) {
210 ConstReferenceFinder finder;
211 VisitTopDown(finder, c);
212 return finder.found;
213 }
Jooyung Han690f5842020-12-04 13:02:04 +0900214};
215
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900216// Checks if annotation complies with the schema
217// - every parameter is known and has well-typed value.
218// - every required parameter is present.
Andrei Onea9445fc62019-06-27 18:11:59 +0100219bool AidlAnnotation::CheckValid() const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100220 for (const auto& name_and_param : parameters_) {
221 const std::string& param_name = name_and_param.first;
222 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han690f5842020-12-04 13:02:04 +0900223
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900224 const ParamType* param_type = schema_.ParamType(param_name);
225 if (!param_type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100226 std::ostringstream stream;
227 stream << "Parameter " << param_name << " not supported ";
Devin Mooredecaf292020-04-30 09:16:40 -0700228 stream << "for annotation " << GetName() << ". ";
Andrei Onea9445fc62019-06-27 18:11:59 +0100229 stream << "It must be one of:";
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900230 for (const auto& param : schema_.parameters) {
231 stream << " " << param.name;
Andrei Onea9445fc62019-06-27 18:11:59 +0100232 }
233 AIDL_ERROR(this) << stream.str();
234 return false;
235 }
Jooyung Han690f5842020-12-04 13:02:04 +0900236
Jooyung Hanc5688f72021-01-05 15:41:48 +0900237 const auto& found = ConstReferenceFinder::Find(*param);
238 if (found) {
239 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
240 << found->GetFieldName() << ".";
Jooyung Han690f5842020-12-04 13:02:04 +0900241 return false;
242 }
243
244 if (!param->CheckValid()) {
245 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
246 << GetName() << ".";
247 return false;
248 }
249
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900250 const std::string param_value =
251 param->ValueString(param_type->type, AidlConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100252 // Assume error on empty string.
253 if (param_value == "") {
254 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
255 << GetName() << ".";
256 return false;
257 }
258 }
Jooyung Han5721a232020-12-24 04:34:55 +0900259 bool success = true;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900260 for (const auto& param : schema_.parameters) {
261 if (param.required && parameters_.count(param.name) == 0) {
262 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
Jooyung Han5721a232020-12-24 04:34:55 +0900263 success = false;
264 }
265 }
266 return success;
Andrei Onea9445fc62019-06-27 18:11:59 +0100267}
268
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900269// Checks if the annotation is applicable to the current context.
270// For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
271// nodes.
272bool AidlAnnotation::CheckContext(TargetContext context) const {
273 if (schema_.target_context & static_cast<uint32_t>(context)) {
274 return true;
275 }
276 const static map<TargetContext, string> context_name_map{
277 {CONTEXT_TYPE_INTERFACE, "interface"},
278 {CONTEXT_TYPE_ENUM, "enum"},
279 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
280 {CONTEXT_TYPE_UNION, "union"},
281 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
282 {CONTEXT_CONST, "constant"},
283 {CONTEXT_FIELD, "field"},
284 {CONTEXT_METHOD, "method"},
285 {CONTEXT_TYPE_SPECIFIER, "type"},
286 };
287 vector<string> available;
288 for (const auto& [context, name] : context_name_map) {
289 if (schema_.target_context & context) {
290 available.push_back(name);
291 }
292 }
293 AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
294 << Join(available, ", ") << "}.";
295 return false;
296}
297
Andrei Onea9445fc62019-06-27 18:11:59 +0100298std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
299 const ConstantValueDecorator& decorator) const {
300 std::map<std::string, std::string> raw_params;
Andrei Onea9445fc62019-06-27 18:11:59 +0100301 for (const auto& name_and_param : parameters_) {
302 const std::string& param_name = name_and_param.first;
303 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
Jooyung Han2d6b5c42021-01-09 01:01:06 +0900304 const ParamType* param_type = schema_.ParamType(param_name);
305 AIDL_FATAL_IF(!param_type, this);
306 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
Andrei Onea9445fc62019-06-27 18:11:59 +0100307 }
308 return raw_params;
309}
Steven Moreland46e9da82018-07-27 15:45:29 -0700310
Jooyung Han965e31d2020-11-27 12:30:16 +0900311std::string AidlAnnotation::ToString() const {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700312 if (parameters_.empty()) {
313 return "@" + GetName();
314 } else {
315 vector<string> param_strings;
Jooyung Han965e31d2020-11-27 12:30:16 +0900316 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700317 param_strings.emplace_back(name + "=" + value);
318 }
319 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
320 }
321}
322
Jooyung Hanc5688f72021-01-05 15:41:48 +0900323void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
324 for (const auto& [name, value] : parameters_) {
325 (void)name;
326 traverse(*value);
327 }
328}
329
Andrei Onea9445fc62019-06-27 18:11:59 +0100330static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700331 AidlAnnotation::Type type) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100332 for (const auto& a : annotations) {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700333 if (a.GetType() == type) {
Jooyung Hand902a972020-10-23 17:32:44 +0900334 AIDL_FATAL_IF(a.Repeatable(), a)
335 << "Trying to get a single annotation when it is repeatable.";
Andrei Onea9445fc62019-06-27 18:11:59 +0100336 return &a;
337 }
338 }
339 return nullptr;
340}
341
Jooyung Han8451a202021-01-16 03:07:06 +0900342AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900343 : AidlCommentable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700344
Jiyong Park68bc77a2018-07-19 19:00:45 +0900345bool AidlAnnotatable::IsNullable() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700346 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900347}
348
Jooyung Han01720ed2021-08-13 07:46:07 +0900349bool AidlAnnotatable::IsHeapNullable() const {
350 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
351 if (annot) {
352 return annot->ParamValue<bool>("heap").value_or(false);
353 }
354 return false;
355}
356
Jiyong Park68bc77a2018-07-19 19:00:45 +0900357bool AidlAnnotatable::IsUtf8InCpp() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700358 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
Jiyong Park68bc77a2018-07-19 19:00:45 +0900359}
360
Steven Morelanda7764e52020-10-27 17:29:29 +0000361bool AidlAnnotatable::IsSensitiveData() const {
362 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
363}
364
Steven Morelanda57d0a62019-07-30 09:41:14 -0700365bool AidlAnnotatable::IsVintfStability() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700366 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
Steven Morelanda57d0a62019-07-30 09:41:14 -0700367}
368
Jeongik Chad0a10272020-08-06 16:33:36 +0900369bool AidlAnnotatable::IsJavaOnlyImmutable() const {
370 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900371}
372
Devin Moorec7e47a32020-08-07 10:55:25 -0700373bool AidlAnnotatable::IsFixedSize() const {
374 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
375}
376
Andrei Onea9445fc62019-06-27 18:11:59 +0100377const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700378 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
Jiyong Parka6605ab2018-11-11 14:30:21 +0900379}
380
Andrei Homescue61feb52020-08-18 15:44:24 -0700381const AidlAnnotation* AidlAnnotatable::RustDerive() const {
382 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
383}
384
Jooyung Han672557b2020-12-24 05:18:00 +0900385const AidlAnnotation* AidlAnnotatable::BackingType() const {
386 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
Daniel Norman85aed542019-08-21 12:01:14 -0700387}
388
Jooyung Hanf8dbbcc2020-12-26 03:05:55 +0900389std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
390 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
391 if (annot) {
392 auto names = annot->ParamValue<std::vector<std::string>>("value");
393 AIDL_FATAL_IF(!names.has_value(), this);
394 return std::move(names.value());
395 }
396 return {};
397}
398
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +0200399// Parses the @Enforce annotation expression.
400std::unique_ptr<perm::Expression> AidlAnnotatable::EnforceExpression(
401 const AidlNode& context) const {
402 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::ENFORCE);
403 if (annot) {
404 auto perm_expr = annot->ParamValue<std::string>("condition");
405 if (perm_expr.has_value()) {
406 auto expr = perm::Parser::Parse(perm_expr.value());
407 if (expr.ok()) {
408 return std::move(expr.value());
409 }
410 AIDL_FATAL(context) << "Unable to parse @Enforce annotation: " << expr.error();
411 }
412 AIDL_FATAL(context) << "@Enforce annotation without condition";
413 }
414 return {};
415}
416
Jeongik Cha88f95a82020-01-15 13:02:16 +0900417bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700418 return lang == Options::Language::JAVA &&
419 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
Jeongik Cha82317dd2019-02-27 20:26:11 +0900420}
421
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800422bool AidlAnnotatable::IsHide() const {
Steven Moreland0cea4aa2020-04-20 21:06:02 -0700423 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800424}
425
Jooyung Han829ec7c2020-12-02 12:07:36 +0900426bool AidlAnnotatable::JavaDerive(const std::string& method) const {
427 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
428 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900429 return annotation->ParamValue<bool>(method).value_or(false);
Jooyung Han829ec7c2020-12-02 12:07:36 +0900430 }
431 return false;
Jiyong Park43113fb2020-07-20 16:26:19 +0900432}
433
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900434std::string AidlAnnotatable::GetDescriptor() const {
435 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
436 if (annotation != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900437 return annotation->ParamValue<std::string>("value").value();
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900438 }
439 return "";
440}
441
Devin Moore24f68572020-02-26 13:20:59 -0800442bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
Andrei Onea9445fc62019-06-27 18:11:59 +0100443 for (const auto& annotation : GetAnnotations()) {
Jooyung Hand902a972020-10-23 17:32:44 +0900444 if (!annotation.CheckValid()) {
445 return false;
446 }
447 }
448
449 std::map<AidlAnnotation::Type, AidlLocation> declared;
450 for (const auto& annotation : GetAnnotations()) {
451 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
452 if (!inserted && !annotation.Repeatable()) {
453 AIDL_ERROR(this) << "'" << annotation.GetName()
454 << "' is repeated, but not allowed. Previous location: " << iter->second;
455 return false;
456 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100457 }
Steven Morelanda57d0a62019-07-30 09:41:14 -0700458
Andrei Onea9445fc62019-06-27 18:11:59 +0100459 return true;
460}
461
Jiyong Park68bc77a2018-07-19 19:00:45 +0900462string AidlAnnotatable::ToString() const {
463 vector<string> ret;
464 for (const auto& a : annotations_) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900465 ret.emplace_back(a.ToString());
Jiyong Park68bc77a2018-07-19 19:00:45 +0900466 }
467 std::sort(ret.begin(), ret.end());
468 return Join(ret, " ");
469}
470
Steven Moreland46e9da82018-07-27 15:45:29 -0700471AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
472 bool is_array,
Jiyong Park1deecc32018-07-17 01:14:41 +0900473 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
Jooyung Han8451a202021-01-16 03:07:06 +0900474 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900475 : AidlAnnotatable(location, comments),
Jeongik Chadf76dc72019-11-28 00:08:47 +0900476 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
Steven Moreland46e9da82018-07-27 15:45:29 -0700477 unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700478 is_array_(is_array),
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900479 split_name_(Split(unresolved_name, ".")) {}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700480
Jooyung Hand2fa0232020-10-19 02:51:41 +0900481const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
Steven Moreland3f658cf2018-08-20 13:40:54 -0700482 AIDL_FATAL_IF(!is_array_, this);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900483 // Declaring array of generic type cannot happen, it is grammar error.
484 AIDL_FATAL_IF(IsGeneric(), this);
Steven Moreland3f658cf2018-08-20 13:40:54 -0700485
Jooyung Hand2fa0232020-10-19 02:51:41 +0900486 if (!array_base_) {
487 array_base_.reset(new AidlTypeSpecifier(*this));
488 array_base_->is_array_ = false;
489 }
490 return *array_base_;
Steven Moreland3f658cf2018-08-20 13:40:54 -0700491}
492
Jooyung Han965e31d2020-11-27 12:30:16 +0900493string AidlTypeSpecifier::Signature() const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900494 string ret = GetName();
495 if (IsGeneric()) {
496 vector<string> arg_names;
497 for (const auto& ta : GetTypeParameters()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900498 arg_names.emplace_back(ta->Signature());
Jiyong Parkccf00f82018-07-17 01:39:23 +0900499 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900500 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900501 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900502 if (IsArray()) {
503 ret += "[]";
504 }
505 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900506}
507
Jooyung Han965e31d2020-11-27 12:30:16 +0900508string AidlTypeSpecifier::ToString() const {
509 string ret = Signature();
Jiyong Park02da7422018-07-16 16:00:26 +0900510 string annotations = AidlAnnotatable::ToString();
511 if (annotations != "") {
512 ret = annotations + " " + ret;
513 }
514 return ret;
515}
516
Jooyung Han13f1fa52021-06-11 18:06:12 +0900517// When `scope` is specified, name is resolved first based on it.
518// `scope` can be null for built-in types and fully-qualified types.
519bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames, const AidlScope* scope) {
Steven Moreland21780812020-09-11 01:29:45 +0000520 AIDL_FATAL_IF(IsResolved(), this);
Jooyung Han13f1fa52021-06-11 18:06:12 +0900521 std::string name = unresolved_name_;
522 if (scope) {
523 name = scope->ResolveName(name);
524 }
525 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(name);
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700526 if (result.is_resolved) {
527 fully_qualified_name_ = result.canonical_name;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900528 split_name_ = Split(fully_qualified_name_, ".");
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900529 defined_type_ = result.defined_type;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900530 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700531 return result.is_resolved;
Casey Dahlin70078e62015-09-30 17:01:30 -0700532}
533
Jooyung Hane9bb9de2020-11-01 22:16:57 +0900534const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
535 return defined_type_;
536}
537
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900538bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800539 if (!AidlAnnotatable::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +0100540 return false;
541 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900542 if (IsGeneric()) {
Jooyung Hand09a21d2021-02-15 18:56:55 +0900543 const auto& types = GetTypeParameters();
544 for (const auto& arg : types) {
545 if (!arg->CheckValid(typenames)) {
546 return false;
547 }
548 }
Jeongik Chae74c86d2019-12-12 16:54:03 +0900549
Jooyung Hand09a21d2021-02-15 18:56:55 +0900550 const string& type_name = GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900551 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
552 if (type_name == "List" || type_name == "Map") {
Jooyung Hane87cdd02020-12-11 16:47:35 +0900553 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
Jooyung Han1f35ef32021-02-15 19:08:05 +0900554 return !type_ptr->IsArray() &&
555 (typenames.GetEnumDeclaration(*type_ptr) ||
556 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
Jeongik Chae74c86d2019-12-12 16:54:03 +0900557 })) {
Devin Moore7b8d5c92020-03-17 14:14:08 -0700558 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
Jeongik Chae74c86d2019-12-12 16:54:03 +0900559 return false;
560 }
561 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800562 const auto defined_type = typenames.TryGetDefinedType(type_name);
Jeongik Chadf76dc72019-11-28 00:08:47 +0900563 const auto parameterizable =
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800564 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
565 const bool is_user_defined_generic_type =
Jeongik Chadf76dc72019-11-28 00:08:47 +0900566 parameterizable != nullptr && parameterizable->IsGeneric();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800567 const size_t num_params = GetTypeParameters().size();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900568 if (type_name == "List") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800569 if (num_params > 1) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900570 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
Steven Morelandebc3c5d2020-09-30 23:40:33 +0000571 << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900572 return false;
573 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900574 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
Jooyung Hancea89002021-02-15 17:04:04 +0900575 if (contained_type.IsArray()) {
576 AIDL_ERROR(this)
577 << "List of arrays is not supported. List<T> supports parcelable/union, String, "
578 "IBinder, and ParcelFileDescriptor.";
579 return false;
580 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900581 const string& contained_type_name = contained_type.GetName();
582 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
583 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
584 contained_type_name != "ParcelFileDescriptor") {
585 AIDL_ERROR(this) << "List<" << contained_type_name
586 << "> is not supported. List<T> supports parcelable/union, String, "
587 "IBinder, and ParcelFileDescriptor.";
588 return false;
589 }
590 } else { // Defined types
591 if (typenames.GetInterface(contained_type)) {
592 AIDL_ERROR(this) << "List<" << contained_type_name
593 << "> is not supported. List<T> supports parcelable/union, String, "
594 "IBinder, and ParcelFileDescriptor.";
595 return false;
596 }
597 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900598 } else if (type_name == "Map") {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800599 if (num_params != 0 && num_params != 2) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900600 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
Jooyung Han965e31d2020-11-27 12:30:16 +0900601 << "'" << Signature() << "'";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900602 return false;
603 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800604 if (num_params == 2) {
Jooyung Hanaab242a2021-02-15 19:01:15 +0900605 const string& key_type = GetTypeParameters()[0]->Signature();
Jeongik Chae48d9942020-01-02 17:39:00 +0900606 if (key_type != "String") {
607 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
608 << "'" << key_type << "'";
609 return false;
610 }
611 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800612 } else if (is_user_defined_generic_type) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900613 const size_t allowed = parameterizable->GetTypeParameters().size();
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800614 if (num_params != allowed) {
Jeongik Chadf76dc72019-11-28 00:08:47 +0900615 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800616 << num_params;
Jeongik Chadf76dc72019-11-28 00:08:47 +0900617 return false;
618 }
619 } else {
620 AIDL_ERROR(this) << type_name << " is not a generic type.";
621 return false;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900622 }
623 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900624
Steven Moreland11cb9452020-01-21 16:56:58 -0800625 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
626 GetTypeParameters().size() == 1 &&
627 GetTypeParameters()[0]->GetName() == "String";
628 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
629 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
630 return false;
631 }
632
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900633 if (GetName() == "void") {
634 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
635 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
636 return false;
637 }
638 }
639
640 if (IsArray()) {
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800641 const auto defined_type = typenames.TryGetDefinedType(GetName());
642 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900643 AIDL_ERROR(this) << "Binder type cannot be an array";
644 return false;
645 }
Steven Moreland8042d2d2020-09-30 23:31:32 +0000646 if (GetName() == "ParcelableHolder") {
647 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
648 return false;
649 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900650 }
651
652 if (IsNullable()) {
653 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
654 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
655 return false;
656 }
Steven Moreland0d9c26e2020-01-22 08:52:08 -0800657 const auto defined_type = typenames.TryGetDefinedType(GetName());
658 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700659 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
660 return false;
661 }
Jeongik Chaf6ec8982020-10-15 00:10:30 +0900662 if (GetName() == "ParcelableHolder") {
663 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
664 return false;
665 }
Jooyung Han01720ed2021-08-13 07:46:07 +0900666 if (IsHeapNullable()) {
667 if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
668 AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
669 return false;
670 }
671 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900672 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900673 return true;
674}
675
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900676std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
Steven Moreland860b1942018-08-16 14:59:28 -0700677 const std::string& raw_value) {
Jooyung Hanfdaae1d2020-12-14 13:16:15 +0900678 if (type.IsArray()) {
679 return raw_value;
680 }
681
682 if (auto defined_type = type.GetDefinedType(); defined_type) {
683 auto enum_type = defined_type->AsEnumDeclaration();
684 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
685 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
686 }
Steven Moreland860b1942018-08-16 14:59:28 -0700687 return raw_value;
688}
689
Steven Moreland46e9da82018-07-27 15:45:29 -0700690AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
691 AidlTypeSpecifier* type, const std::string& name)
Steven Moreland541788d2020-05-21 22:05:52 +0000692 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
693 default_user_specified_ = false;
694}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700695
Steven Moreland46e9da82018-07-27 15:45:29 -0700696AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
697 AidlTypeSpecifier* type, const std::string& name,
698 AidlConstantValue* default_value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900699 : AidlMember(location, type->GetComments()),
Steven Moreland541788d2020-05-21 22:05:52 +0000700 type_(type),
701 name_(name),
702 default_user_specified_(true),
703 default_value_(default_value) {}
Steven Moreland9ea10e32018-07-19 15:26:09 -0700704
Jooyung Han53fb4242020-12-17 16:03:49 +0900705bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
706 if (GetDefaultValue()) {
707 return true;
708 }
709 // null is accepted as a valid default value in all backends
710 if (GetType().IsNullable()) {
711 return true;
712 }
713 return false;
714}
715
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900716bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700717 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900718 valid &= type_->CheckValid(typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900719
Steven Moreland54be7bd2019-12-05 11:17:53 -0800720 if (type_->GetName() == "void") {
721 AIDL_ERROR(this) << "Declaration " << name_
722 << " is void, but declarations cannot be of void type.";
723 valid = false;
724 }
725
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900726 if (default_value_ == nullptr) return valid;
Steven Moreland25294322018-08-07 18:13:55 -0700727 valid &= default_value_->CheckValid();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700728
Steven Moreland25294322018-08-07 18:13:55 -0700729 if (!valid) return false;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700730
Steven Moreland860b1942018-08-16 14:59:28 -0700731 return !ValueString(AidlConstantValueDecorator).empty();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700732}
Steven Moreland5557f1c2018-07-02 13:50:23 -0700733
Jooyung Hanacae85d2020-10-28 16:39:09 +0900734string AidlVariableDeclaration::GetCapitalizedName() const {
735 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
736 string str = name_;
737 str[0] = static_cast<char>(toupper(str[0]));
738 return str;
739}
740
Steven Moreland5557f1c2018-07-02 13:50:23 -0700741string AidlVariableDeclaration::ToString() const {
Jooyung Han965e31d2020-11-27 12:30:16 +0900742 string ret = type_->ToString() + " " + name_;
Steven Moreland541788d2020-05-21 22:05:52 +0000743 if (default_value_ != nullptr && default_user_specified_) {
Steven Moreland860b1942018-08-16 14:59:28 -0700744 ret += " = " + ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700745 }
746 return ret;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700747}
748
Jiyong Park02da7422018-07-16 16:00:26 +0900749string AidlVariableDeclaration::Signature() const {
750 return type_->Signature() + " " + name_;
751}
752
Steven Moreland860b1942018-08-16 14:59:28 -0700753std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
Jiyong Parka468e2a2018-08-29 21:25:18 +0900754 if (default_value_ != nullptr) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700755 return default_value_->ValueString(GetType(), decorator);
Jiyong Parka468e2a2018-08-29 21:25:18 +0900756 } else {
757 return "";
758 }
Steven Moreland25294322018-08-07 18:13:55 -0700759}
760
Jooyung Hanc5688f72021-01-05 15:41:48 +0900761void AidlVariableDeclaration::TraverseChildren(
762 std::function<void(const AidlNode&)> traverse) const {
763 traverse(GetType());
764 if (IsDefaultUserSpecified()) {
765 traverse(*GetDefaultValue());
766 }
767}
768
Steven Moreland46e9da82018-07-27 15:45:29 -0700769AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
770 AidlTypeSpecifier* type, const std::string& name)
771 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700772 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700773 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700774
Steven Moreland46e9da82018-07-27 15:45:29 -0700775AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
776 const std::string& name)
777 : AidlVariableDeclaration(location, type, name),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700778 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700779 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700780
Jooyung Han020d8d12021-02-26 17:23:02 +0900781static std::string to_string(AidlArgument::Direction direction) {
782 switch (direction) {
783 case AidlArgument::IN_DIR:
784 return "in";
785 case AidlArgument::OUT_DIR:
786 return "out";
787 case AidlArgument::INOUT_DIR:
788 return "inout";
789 }
790}
791
Jiyong Park02da7422018-07-16 16:00:26 +0900792string AidlArgument::GetDirectionSpecifier() const {
Casey Dahlinc378c992015-09-29 16:50:40 -0700793 string ret;
Casey Dahlinc378c992015-09-29 16:50:40 -0700794 if (direction_specified_) {
Jooyung Han020d8d12021-02-26 17:23:02 +0900795 ret = to_string(direction_);
Casey Dahlinc378c992015-09-29 16:50:40 -0700796 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700797 return ret;
798}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700799
Jiyong Park02da7422018-07-16 16:00:26 +0900800string AidlArgument::ToString() const {
Devin Mooreeccdb902020-03-24 16:22:40 -0700801 if (direction_specified_) {
802 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
803 } else {
804 return AidlVariableDeclaration::ToString();
805 }
Jiyong Park02da7422018-07-16 16:00:26 +0900806}
807
Jooyung Han020d8d12021-02-26 17:23:02 +0900808static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
809 std::vector<std::string> out;
810 for (const auto& d : directions) {
811 out.push_back(to_string(d));
812 }
813
814 if (out.size() <= 1) { // [] => "" or [A] => "A"
815 return Join(out, "");
816 } else if (out.size() == 2) { // [A,B] => "A or B"
817 return Join(out, " or ");
818 } else { // [A,B,C] => "A, B, or C"
819 out.back() = "or " + out.back();
820 return Join(out, ", ");
821 }
822}
823
824bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
825 if (!GetType().CheckValid(typenames)) {
826 return false;
827 }
828
829 const auto& aspect = typenames.GetArgumentAspect(GetType());
830
831 if (aspect.possible_directions.size() == 0) {
832 AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
833 return false;
834 }
835
836 // when direction is not specified, "in" is assumed and should be the only possible direction
837 if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
838 AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
839 << " can be an " << FormatDirections(aspect.possible_directions)
840 << " parameter.";
841 return false;
842 }
843
844 if (aspect.possible_directions.count(GetDirection()) == 0) {
845 AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
846 << " parameter because " << aspect.name << " can only be an "
847 << FormatDirections(aspect.possible_directions) << " parameter.";
848 return false;
849 }
850
851 return true;
852}
853
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900854bool AidlCommentable::IsHidden() const {
Jooyung Han24effbf2021-01-16 10:24:03 +0900855 return android::aidl::HasHideInComments(GetComments());
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900856}
857
858bool AidlCommentable::IsDeprecated() const {
Jooyung Hand4fe00e2021-01-11 16:21:53 +0900859 return android::aidl::FindDeprecated(GetComments()).has_value();
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900860}
861
Jooyung Han8451a202021-01-16 03:07:06 +0900862AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +0900863 : AidlCommentable(location, comments) {}
Steven Moreland46e9da82018-07-27 15:45:29 -0700864
Steven Moreland46e9da82018-07-27 15:45:29 -0700865AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
866 AidlTypeSpecifier* type, const std::string& name,
867 AidlConstantValue* value)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900868 : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}
Steven Moreland693640b2018-07-19 13:46:27 -0700869
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900870bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
Steven Moreland25294322018-08-07 18:13:55 -0700871 bool valid = true;
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900872 valid &= type_->CheckValid(typenames);
Steven Moreland25294322018-08-07 18:13:55 -0700873 valid &= value_->CheckValid();
874 if (!valid) return false;
Steven Moreland693640b2018-07-19 13:46:27 -0700875
Steven Morelande689da22020-11-10 02:06:30 +0000876 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
Jooyung Han965e31d2020-11-27 12:30:16 +0900877 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
878 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
Steven Moreland693640b2018-07-19 13:46:27 -0700879 return false;
880 }
881
Will McVickerd7d18df2019-09-12 13:40:50 -0700882 return true;
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700883}
884
Jiyong Parka428d212018-08-29 22:26:30 +0900885string AidlConstantDeclaration::ToString() const {
Jooyung Hanb3ca6302020-11-27 14:13:27 +0900886 return "const " + type_->ToString() + " " + name_ + " = " +
887 ValueString(AidlConstantValueDecorator);
Jiyong Parka428d212018-08-29 22:26:30 +0900888}
889
890string AidlConstantDeclaration::Signature() const {
891 return type_->Signature() + " " + name_;
892}
893
Steven Moreland46e9da82018-07-27 15:45:29 -0700894AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
895 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900896 const Comments& comments)
Jiyong Parkb034bf02018-07-30 17:44:33 +0900897 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
898 has_id_ = false;
899}
900
901AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
902 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
Jooyung Han8451a202021-01-16 03:07:06 +0900903 const Comments& comments, int id, bool is_user_defined)
Jooyung Han8aeef8c2021-01-11 12:16:19 +0900904 : AidlMember(location, comments),
Steven Moreland46e9da82018-07-27 15:45:29 -0700905 oneway_(oneway),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700906 type_(type),
907 name_(name),
Casey Dahlinf4a93112015-10-05 16:58:09 -0700908 arguments_(std::move(*args)),
Jiyong Parkb034bf02018-07-30 17:44:33 +0900909 id_(id),
910 is_user_defined_(is_user_defined) {
Casey Dahlinf4a93112015-10-05 16:58:09 -0700911 has_id_ = true;
912 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700913 for (const unique_ptr<AidlArgument>& a : arguments_) {
914 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
915 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
916 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700917}
918
Jiyong Park02da7422018-07-16 16:00:26 +0900919string AidlMethod::Signature() const {
920 vector<string> arg_signatures;
921 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900922 arg_signatures.emplace_back(arg->GetType().Signature());
Jiyong Park02da7422018-07-16 16:00:26 +0900923 }
Jiyong Park309668e2018-07-28 16:55:44 +0900924 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
925}
926
927string AidlMethod::ToString() const {
928 vector<string> arg_strings;
929 for (const auto& arg : GetArguments()) {
Jooyung Han965e31d2020-11-27 12:30:16 +0900930 arg_strings.emplace_back(arg->ToString());
Jiyong Park309668e2018-07-28 16:55:44 +0900931 }
Jooyung Han965e31d2020-11-27 12:30:16 +0900932 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
Steven Moreland4ee68632018-12-14 15:52:46 -0800933 Join(arg_strings, ", ") + ")";
Jiyong Parked65bf42018-08-28 15:43:27 +0900934 if (HasId()) {
935 ret += " = " + std::to_string(GetId());
936 }
937 return ret;
Jiyong Park02da7422018-07-16 16:00:26 +0900938}
939
Steven Moreland46e9da82018-07-27 15:45:29 -0700940AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +0900941 const Comments& comments, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +0900942 std::vector<std::unique_ptr<AidlMember>>* members)
Jooyung Han35784982021-06-29 06:26:12 +0900943 : AidlAnnotatable(location, comments), AidlScope(this), name_(name), package_(package) {
Jooyung Han93f48f02021-06-05 00:11:16 +0900944 // adjust name/package when name is fully qualified (for preprocessed files)
945 if (package_.empty() && name_.find('.') != std::string::npos) {
946 // Note that this logic is absolutely wrong. Given a parcelable
947 // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
948 // the class is just Bar. However, this was the way it was done in the past.
949 //
950 // See b/17415692
951 auto pos = name.rfind('.');
952 // name is the last part.
953 name_ = name.substr(pos + 1);
954 // package is the initial parts (except the last).
955 package_ = name.substr(0, pos);
956 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900957 if (members) {
958 for (auto& m : *members) {
959 if (auto constant = m->AsConstantDeclaration(); constant) {
960 constants_.emplace_back(constant);
961 } else if (auto variable = m->AsVariableDeclaration(); variable) {
962 variables_.emplace_back(variable);
963 } else if (auto method = m->AsMethod(); method) {
964 methods_.emplace_back(method);
965 } else {
966 AIDL_FATAL(*m);
967 }
968 members_.push_back(m.release());
969 }
970 delete members;
971 }
972}
Steven Moreland787b0432018-07-03 09:00:58 -0700973
Jooyung Han808a2a02020-12-28 16:46:54 +0900974bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
Devin Moore24f68572020-02-26 13:20:59 -0800975 if (!AidlAnnotatable::CheckValid(typenames)) {
976 return false;
977 }
Jooyung Han829ec7c2020-12-02 12:07:36 +0900978 if (!CheckValidWithMembers(typenames)) {
979 return false;
980 }
Devin Moore24f68572020-02-26 13:20:59 -0800981 return true;
982}
983
Steven Moreland787b0432018-07-03 09:00:58 -0700984std::string AidlDefinedType::GetCanonicalName() const {
985 if (package_.empty()) {
986 return GetName();
987 }
988 return GetPackage() + "." + GetName();
989}
990
Jooyung Han829ec7c2020-12-02 12:07:36 +0900991bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
992 bool success = true;
993
994 for (const auto& v : GetFields()) {
995 const bool field_valid = v->CheckValid(typenames);
996 success = success && field_valid;
997 }
998
999 // field names should be unique
1000 std::set<std::string> fieldnames;
1001 for (const auto& v : GetFields()) {
1002 bool duplicated = !fieldnames.emplace(v->GetName()).second;
1003 if (duplicated) {
1004 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
1005 success = false;
1006 }
1007 }
1008
1009 // immutable parcelables should have immutable fields.
1010 if (IsJavaOnlyImmutable()) {
1011 for (const auto& v : GetFields()) {
1012 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
1013 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
1014 << "non-immutable field named '" << v->GetName() << "'.";
1015 success = false;
1016 }
1017 }
1018 }
1019
1020 set<string> constant_names;
1021 for (const auto& constant : GetConstantDeclarations()) {
1022 if (constant_names.count(constant->GetName()) > 0) {
1023 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
1024 success = false;
1025 }
1026 constant_names.insert(constant->GetName());
1027 success = success && constant->CheckValid(typenames);
1028 }
1029
1030 return success;
1031}
1032
1033bool AidlDefinedType::CheckValidForGetterNames() const {
1034 bool success = true;
1035 std::set<std::string> getters;
1036 for (const auto& v : GetFields()) {
1037 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
1038 if (duplicated) {
1039 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
1040 << "' after capitalizing the first letter";
1041 success = false;
1042 }
1043 }
1044 return success;
1045}
1046
Jooyung Han13f1fa52021-06-11 18:06:12 +09001047std::string AidlDefinedType::ResolveName(const std::string& name) const {
1048 // TODO(b/182508839): resolve with nested types when we support nested types
1049 //
1050 // For example, in the following (the syntax is TBD), t1's Type is x.Foo.Bar.Type
1051 // while t2's Type is y.Type.
1052 //
1053 // package x;
1054 // import y.Type;
1055 // parcelable Foo {
1056 // parcelable Bar {
1057 // enum Type { Type1, Type2 }
1058 // Type t1;
1059 // }
1060 // Type t2;
1061 // }
1062 AIDL_FATAL_IF(!GetEnclosingScope(), this)
1063 << "Type should have an enclosing scope.(e.g. AidlDocument)";
1064 return GetEnclosingScope()->ResolveName(name);
1065}
1066
Jooyung Han35784982021-06-29 06:26:12 +09001067template <typename T>
1068const T* AidlCast(const AidlNode& node) {
1069 struct CastVisitor : AidlVisitor {
1070 const T* cast = nullptr;
1071 void Visit(const T& t) override { cast = &t; }
1072 } visitor;
1073 node.DispatchVisit(visitor);
1074 return visitor.cast;
1075}
1076
1077const AidlDocument& AidlDefinedType::GetDocument() const {
1078 // TODO(b/182508839): resolve with nested types when we support nested types
1079 auto scope = GetEnclosingScope();
1080 AIDL_FATAL_IF(!scope, this) << "no scope defined.";
1081 auto doc = AidlCast<AidlDocument>(scope->GetNode());
1082 AIDL_FATAL_IF(!doc, this) << "scope is not a document.";
1083 return *doc;
1084}
1085
Jiyong Park18132182020-06-08 20:24:40 +09001086AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001087 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001088 const std::string& cpp_header, std::vector<std::string>* type_params,
1089 std::vector<std::unique_ptr<AidlMember>>* members)
1090 : AidlDefinedType(location, name, comments, package, members),
Jeongik Chadf76dc72019-11-28 00:08:47 +09001091 AidlParameterizable<std::string>(type_params),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -08001092 cpp_header_(cpp_header) {
1093 // Strip off quotation marks if we actually have a cpp header.
1094 if (cpp_header_.length() >= 2) {
1095 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
1096 }
Casey Dahlin59401da2015-10-09 18:16:45 -07001097}
Jeongik Chadf76dc72019-11-28 00:08:47 +09001098template <typename T>
1099AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
1100 // Copying is not supported if it has type parameters.
1101 // It doesn't make a problem because only ArrayBase() makes a copy,
1102 // and it can be called only if a type is not generic.
Steven Moreland21780812020-09-11 01:29:45 +00001103 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
Jeongik Chadf76dc72019-11-28 00:08:47 +09001104}
1105
1106template <typename T>
1107bool AidlParameterizable<T>::CheckValid() const {
1108 return true;
1109};
1110
1111template <>
1112bool AidlParameterizable<std::string>::CheckValid() const {
1113 if (!IsGeneric()) {
1114 return true;
1115 }
1116 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
1117 if (set.size() != GetTypeParameters().size()) {
1118 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
1119 return false;
1120 }
1121 return true;
1122}
Casey Dahlin59401da2015-10-09 18:16:45 -07001123
Jooyung Han808a2a02020-12-28 16:46:54 +09001124bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1125 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001126 return false;
1127 }
Jeongik Chadf76dc72019-11-28 00:08:47 +09001128 if (!AidlParameterizable<std::string>::CheckValid()) {
1129 return false;
1130 }
Jeongik Cha82317dd2019-02-27 20:26:11 +09001131
1132 return true;
1133}
1134
Steven Moreland5557f1c2018-07-02 13:50:23 -07001135AidlStructuredParcelable::AidlStructuredParcelable(
Jiyong Park18132182020-06-08 20:24:40 +09001136 const AidlLocation& location, const std::string& name, const std::string& package,
Jooyung Han8451a202021-01-16 03:07:06 +09001137 const Comments& comments, std::vector<std::string>* type_params,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001138 std::vector<std::unique_ptr<AidlMember>>* members)
1139 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Steven Moreland5557f1c2018-07-02 13:50:23 -07001140
Jooyung Han808a2a02020-12-28 16:46:54 +09001141bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1142 if (!AidlParcelable::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001143 return false;
1144 }
Jeongik Cha13066da2020-08-06 15:43:19 +09001145
Jooyung Han59af9cc2020-10-25 21:44:14 +09001146 bool success = true;
Jeongik Cha36f76c32020-07-28 00:25:52 +09001147
Jooyung Hand4057c42020-10-23 13:28:22 +09001148 if (IsFixedSize()) {
1149 for (const auto& v : GetFields()) {
1150 if (!typenames.CanBeFixedSize(v->GetType())) {
1151 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1152 << "non-fixed size field named " << v->GetName() << ".";
1153 success = false;
1154 }
1155 }
1156 }
1157
1158 if (IsJavaOnlyImmutable()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001159 // Immutable parcelables provide getters
Jooyung Han829ec7c2020-12-02 12:07:36 +09001160 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001161 success = false;
Jooyung Hand4057c42020-10-23 13:28:22 +09001162 }
1163 }
1164
Daniel Norman85aed542019-08-21 12:01:14 -07001165 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001166}
1167
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001168// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001169bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1170 Options::Language lang) const {
Jooyung Hand09a21d2021-02-15 18:56:55 +09001171 if (IsGeneric()) {
1172 const auto& types = GetTypeParameters();
1173 for (const auto& arg : types) {
1174 if (!arg->LanguageSpecificCheckValid(typenames, lang)) {
1175 return false;
1176 }
1177 }
1178 }
1179
Andrei Homescub62afd92020-05-11 19:24:59 -07001180 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1181 GetName() == "IBinder") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001182 AIDL_ERROR(this) << "The " << to_string(lang) << " backend does not support array of IBinder";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001183 return false;
1184 }
Jeongik Cha8f02a532020-10-14 00:16:28 +09001185 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1186 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1187 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
Jeongik Cha225519b2020-08-29 01:55:32 +09001188 return false;
1189 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001190 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1191 IsNullable()) {
Steven Moreland0185d9b2020-05-15 23:21:22 +00001192 if (GetName() == "ParcelFileDescriptor") {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001193 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001194 << " backend does not support nullable array of ParcelFileDescriptor";
Steven Moreland0185d9b2020-05-15 23:21:22 +00001195 return false;
1196 }
1197
Steven Morelandd59e3172020-05-11 16:42:09 -07001198 const auto defined_type = typenames.TryGetDefinedType(GetName());
1199 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001200 AIDL_ERROR(this) << "The " << to_string(lang)
Andrei Homescub62afd92020-05-11 19:24:59 -07001201 << " backend does not support nullable array of parcelable";
Steven Morelandd59e3172020-05-11 16:42:09 -07001202 return false;
1203 }
1204 }
Andrei Homescub62afd92020-05-11 19:24:59 -07001205 if (this->GetName() == "FileDescriptor" &&
1206 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
Jooyung Han9435e9a2021-01-06 10:16:31 +09001207 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
Steven Morelandc8a4ca82020-01-21 17:50:08 -08001208 return false;
1209 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001210 if (this->IsGeneric()) {
1211 if (this->GetName() == "List") {
Jooyung Han55f96ad2020-12-13 10:08:33 +09001212 if (lang == Options::Language::NDK) {
1213 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1214 const string& contained_type_name = contained_type.GetName();
Jooyung Hane87cdd02020-12-11 16:47:35 +09001215 if (typenames.GetInterface(contained_type)) {
1216 AIDL_ERROR(this) << "List<" << contained_type_name
1217 << "> is not supported. List in NDK doesn't support interface.";
1218 return false;
1219 }
1220 if (contained_type_name == "IBinder") {
1221 AIDL_ERROR(this) << "List<" << contained_type_name
1222 << "> is not supported. List in NDK doesn't support IBinder.";
1223 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001224 }
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001225 }
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001226 }
1227 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001228
1229 if (this->IsArray()) {
1230 if (this->GetName() == "List" || this->GetName() == "Map" ||
1231 this->GetName() == "CharSequence") {
1232 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
Jeongik Chabb55b5e2020-01-07 23:11:26 +09001233 return false;
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001234 }
1235 }
Devin Moore6a01ca12020-08-28 10:24:19 -07001236
1237 if (lang != Options::Language::JAVA) {
1238 if (this->GetName() == "List" && !this->IsGeneric()) {
1239 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1240 return false;
1241 }
1242 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1243 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1244 return false;
Jeongik Cha08ca2182019-11-21 14:01:13 +09001245 }
1246 }
1247
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001248 return true;
1249}
1250
1251// TODO: we should treat every backend all the same in future.
Jooyung Han2cb8ecd2021-07-28 18:41:30 +09001252bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
Steven Morelandd59e3172020-05-11 16:42:09 -07001253 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001254 for (const auto& v : this->GetFields()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001255 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001256 return false;
1257 }
1258 }
1259 return true;
1260}
1261
Daniel Norman85aed542019-08-21 12:01:14 -07001262AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001263 AidlConstantValue* value, const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +09001264 : AidlCommentable(location, comments),
Jooyung Han29813842020-12-08 01:28:03 +09001265 name_(name),
1266 value_(value),
Jooyung Han29813842020-12-08 01:28:03 +09001267 value_user_specified_(value != nullptr) {}
Daniel Norman85aed542019-08-21 12:01:14 -07001268
1269bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1270 if (GetValue() == nullptr) {
1271 return false;
1272 }
1273 if (!GetValue()->CheckValid()) {
1274 return false;
1275 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001276 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
Daniel Norman85aed542019-08-21 12:01:14 -07001277 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1278 return false;
1279 }
1280 return true;
1281}
1282
1283string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1284 const ConstantValueDecorator& decorator) const {
Will McVickerd7d18df2019-09-12 13:40:50 -07001285 return GetValue()->ValueString(backing_type, decorator);
Daniel Norman85aed542019-08-21 12:01:14 -07001286}
1287
1288AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1289 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
Jooyung Han8451a202021-01-16 03:07:06 +09001290 const std::string& package, const Comments& comments)
Jooyung Han829ec7c2020-12-02 12:07:36 +09001291 : AidlDefinedType(location, name, comments, package, nullptr),
Jooyung Han29813842020-12-08 01:28:03 +09001292 enumerators_(std::move(*enumerators)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001293 // Fill missing enumerator values with <prev + 1>
1294 // This can't be done in Autofill() because type/ref resolution depends on this.
1295 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1296 // resolved if A has no value set.
Daniel Normanb28684e2019-10-17 15:31:39 -07001297 const AidlEnumerator* previous = nullptr;
1298 for (const auto& enumerator : enumerators_) {
1299 if (enumerator->GetValue() == nullptr) {
Jooyung Han29813842020-12-08 01:28:03 +09001300 auto loc = enumerator->GetLocation();
Daniel Normanb28684e2019-10-17 15:31:39 -07001301 if (previous == nullptr) {
Devin Mooredf93ebb2020-03-25 14:03:35 -07001302 enumerator->SetValue(
Jooyung Han29813842020-12-08 01:28:03 +09001303 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
Daniel Normanb28684e2019-10-17 15:31:39 -07001304 } else {
Jooyung Hand0c8af02021-01-06 18:08:01 +09001305 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
Daniel Normanb28684e2019-10-17 15:31:39 -07001306 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
Jooyung Han29813842020-12-08 01:28:03 +09001307 loc, std::move(prev_value), "+",
1308 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
Daniel Normanb28684e2019-10-17 15:31:39 -07001309 }
1310 }
1311 previous = enumerator.get();
1312 }
1313}
1314
Jooyung Han672557b2020-12-24 05:18:00 +09001315bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1316 if (auto annot = BackingType(); annot != nullptr) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001317 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1318 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
Jooyung Han672557b2020-12-24 05:18:00 +09001319 // need to call CheckValid().
1320 if (!annot->CheckValid()) {
1321 return false;
1322 }
Jooyung Hanb3c77ed2020-12-26 02:02:45 +09001323 auto type = annot->ParamValue<std::string>("type").value();
1324 backing_type_ =
Jooyung Han8451a202021-01-16 03:07:06 +09001325 std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, Comments{});
Jooyung Han672557b2020-12-24 05:18:00 +09001326 } else {
1327 // Default to byte type for enums.
1328 backing_type_ =
Jooyung Han8451a202021-01-16 03:07:06 +09001329 std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, Comments{});
Jooyung Han672557b2020-12-24 05:18:00 +09001330 }
1331 // Autofill() is called after type resolution, we resolve the backing type manually.
Jooyung Han13f1fa52021-06-11 18:06:12 +09001332 if (!backing_type_->Resolve(typenames, nullptr)) {
Jooyung Han672557b2020-12-24 05:18:00 +09001333 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
1334 }
1335 return true;
1336}
1337
Jooyung Han808a2a02020-12-28 16:46:54 +09001338bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1339 if (!AidlDefinedType::CheckValid(typenames)) {
Devin Moore24f68572020-02-26 13:20:59 -08001340 return false;
1341 }
Jooyung Han829ec7c2020-12-02 12:07:36 +09001342 if (!GetMembers().empty()) {
1343 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1344 return false;
1345 }
Daniel Norman85aed542019-08-21 12:01:14 -07001346 if (backing_type_ == nullptr) {
1347 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1348 return false;
1349 }
1350 bool success = true;
1351 for (const auto& enumerator : enumerators_) {
1352 success = success && enumerator->CheckValid(GetBackingType());
1353 }
Jooyung Han3b990182020-12-22 17:44:31 +09001354
Jooyung Han808a2a02020-12-28 16:46:54 +09001355 return success;
Daniel Norman85aed542019-08-21 12:01:14 -07001356}
1357
Jooyung Han2946afc2020-10-05 20:29:16 +09001358AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001359 const std::string& package, const Comments& comments,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001360 std::vector<std::string>* type_params,
1361 std::vector<std::unique_ptr<AidlMember>>* members)
1362 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
Jooyung Han2946afc2020-10-05 20:29:16 +09001363
Jooyung Han808a2a02020-12-28 16:46:54 +09001364bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001365 // visit parents
Jooyung Han808a2a02020-12-28 16:46:54 +09001366 if (!AidlParcelable::CheckValid(typenames)) {
Jooyung Hanfe89f122020-10-14 03:49:18 +09001367 return false;
1368 }
Jooyung Han59af9cc2020-10-25 21:44:14 +09001369
1370 // unions provide getters always
Jooyung Han829ec7c2020-12-02 12:07:36 +09001371 if (!CheckValidForGetterNames()) {
Jooyung Han59af9cc2020-10-25 21:44:14 +09001372 return false;
Jooyung Hanfe89f122020-10-14 03:49:18 +09001373 }
1374
1375 // now, visit self!
1376 bool success = true;
1377
1378 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1379 for (const auto& v : GetFields()) {
1380 if (v->GetType().GetName() == "ParcelableHolder") {
1381 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1382 success = false;
1383 }
1384 }
1385
Jooyung Hanfe89f122020-10-14 03:49:18 +09001386 if (GetFields().empty()) {
1387 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1388 return false;
1389 }
1390
Jooyung Han53fb4242020-12-17 16:03:49 +09001391 // first member should have useful default value (implicit or explicit)
1392 const auto& first = GetFields()[0];
1393 if (!first->HasUsefulDefaultValue()) {
1394 // Most types can be initialized without a default value. For example,
1395 // interface types are inherently nullable. But, enum types should have
1396 // an explicit default value.
1397 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1398 AIDL_ERROR(first)
1399 << "The union's first member should have a useful default value. Enum types can be "
1400 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1401 return false;
1402 }
1403 // In Java, array types are initialized as null without a default value. To be sure that default
1404 // initialized unions are accepted by other backends we require arrays also have a default
1405 // value.
1406 if (first->GetType().IsArray()) {
1407 AIDL_ERROR(first)
1408 << "The union's first member should have a useful default value. Arrays can be "
1409 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1410 return false;
1411 }
1412 }
1413
Jooyung Hanfe89f122020-10-14 03:49:18 +09001414 return success;
1415}
1416
1417// TODO: we should treat every backend all the same in future.
Steven Morelandd59e3172020-05-11 16:42:09 -07001418bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1419 Options::Language lang) const {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001420 for (const auto& m : this->GetMethods()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001421 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001422 return false;
1423 }
1424 for (const auto& arg : m->GetArguments()) {
Steven Morelandd59e3172020-05-11 16:42:09 -07001425 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001426 return false;
1427 }
1428 }
1429 }
1430 return true;
1431}
1432
Steven Moreland46e9da82018-07-27 15:45:29 -07001433AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
Jooyung Han8451a202021-01-16 03:07:06 +09001434 const Comments& comments, bool oneway, const std::string& package,
Jooyung Han829ec7c2020-12-02 12:07:36 +09001435 std::vector<std::unique_ptr<AidlMember>>* members)
1436 : AidlDefinedType(location, name, comments, package, members) {
1437 for (auto& m : GetMethods()) {
1438 m.get()->ApplyInterfaceOneway(oneway);
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001439 }
Casey Dahlinfb7da2e2015-10-08 17:26:09 -07001440}
1441
Jooyung Han808a2a02020-12-28 16:46:54 +09001442bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1443 if (!AidlDefinedType::CheckValid(typenames)) {
Andrei Onea9445fc62019-06-27 18:11:59 +01001444 return false;
1445 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001446 // Has to be a pointer due to deleting copy constructor. No idea why.
1447 map<string, const AidlMethod*> method_names;
1448 for (const auto& m : GetMethods()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001449 if (!m->GetType().CheckValid(typenames)) {
1450 return false;
1451 }
1452
Jeongik Cha649e8a72020-03-27 17:47:40 +09001453 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1454 if (m->GetType().GetName() == "ParcelableHolder") {
1455 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1456 return false;
1457 }
Steven Morelandacd53472018-12-14 10:17:26 -08001458 if (m->IsOneway() && m->GetType().GetName() != "void") {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001459 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1460 return false;
1461 }
1462
1463 set<string> argument_names;
1464 for (const auto& arg : m->GetArguments()) {
1465 auto it = argument_names.find(arg->GetName());
1466 if (it != argument_names.end()) {
1467 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1468 << arg->GetName() << "'";
1469 return false;
1470 }
1471 argument_names.insert(arg->GetName());
1472
Jooyung Han020d8d12021-02-26 17:23:02 +09001473 if (!arg->CheckValid(typenames)) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001474 return false;
1475 }
1476
Steven Morelandacd53472018-12-14 10:17:26 -08001477 if (m->IsOneway() && arg->IsOut()) {
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001478 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1479 return false;
1480 }
Jooyung Han15fd6c62020-10-23 13:54:46 +09001481
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001482 // check that the name doesn't match a keyword
Jeongik Cha997281d2020-01-16 15:23:59 +09001483 if (IsJavaKeyword(arg->GetName().c_str())) {
Jeongik Cha047c5ee2019-08-07 23:16:49 +09001484 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1485 return false;
1486 }
1487
1488 // Reserve a namespace for internal use
1489 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1490 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1491 return false;
1492 }
Jooyung Hanfa181932021-06-12 07:56:53 +09001493
1494 if (arg->GetType().GetName() == "void") {
1495 AIDL_ERROR(arg->GetType())
1496 << "'void' is an invalid type for the parameter '" << arg->GetName() << "'";
1497 return false;
1498 }
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001499 }
1500
1501 auto it = method_names.find(m->GetName());
1502 // prevent duplicate methods
1503 if (it == method_names.end()) {
1504 method_names[m->GetName()] = m.get();
1505 } else {
1506 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1507 AIDL_ERROR(it->second) << "previously defined here.";
1508 return false;
1509 }
1510
Paul Trautrimb77048c2020-01-21 16:39:32 +09001511 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001512 "getTransactionName(int)"};
1513
1514 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001515 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001516 return false;
1517 }
1518 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001519
1520 bool success = true;
1521 set<string> constant_names;
Jooyung Han3f347ca2020-12-01 12:41:50 +09001522 for (const auto& constant : GetConstantDeclarations()) {
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001523 if (constant_names.count(constant->GetName()) > 0) {
Devin Moore097a3ab2020-03-11 16:08:44 -07001524 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001525 success = false;
1526 }
1527 constant_names.insert(constant->GetName());
1528 success = success && constant->CheckValid(typenames);
1529 }
Steven Moreland4d12f9a2018-10-31 14:30:55 -07001530 return success;
Jeongik Chadb0f59e2018-11-01 18:11:21 +09001531}
1532
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001533std::string AidlInterface::GetDescriptor() const {
1534 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1535 if (annotatedDescriptor != "") {
1536 return annotatedDescriptor;
1537 }
1538 return GetCanonicalName();
1539}
1540
Jooyung Han132cf802021-01-15 02:17:32 +09001541AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class,
Jooyung Han8451a202021-01-16 03:07:06 +09001542 const Comments& comments)
Jooyung Han5c7e77c2021-01-20 16:00:29 +09001543 : AidlNode(location, comments), needed_class_(needed_class) {}
Jooyung Han29813842020-12-08 01:28:03 +09001544
Jooyung Han13f1fa52021-06-11 18:06:12 +09001545AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
1546 std::vector<std::unique_ptr<AidlImport>> imports,
Jooyung Han35784982021-06-29 06:26:12 +09001547 std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
1548 bool is_preprocessed)
Jooyung Han13f1fa52021-06-11 18:06:12 +09001549 : AidlCommentable(location, comments),
Jooyung Han35784982021-06-29 06:26:12 +09001550 AidlScope(this),
Jooyung Han13f1fa52021-06-11 18:06:12 +09001551 imports_(std::move(imports)),
Jooyung Han35784982021-06-29 06:26:12 +09001552 defined_types_(std::move(defined_types)),
1553 is_preprocessed_(is_preprocessed) {
Jooyung Han13f1fa52021-06-11 18:06:12 +09001554 for (const auto& t : defined_types_) {
1555 t->SetEnclosingScope(this);
1556 }
1557}
1558
1559// Resolves type name in the current document.
1560// - built-in types
1561// - imported types
1562// - top-level type
1563std::string AidlDocument::ResolveName(const std::string& name) const {
1564 if (AidlTypenames::IsBuiltinTypename(name)) {
1565 return name;
1566 }
1567
1568 const auto first_dot = name.find_first_of('.');
1569 // For "Outer.Inner", we look up "Outer" in the import list.
Jooyung Han29813842020-12-08 01:28:03 +09001570 const std::string class_name =
Jooyung Han13f1fa52021-06-11 18:06:12 +09001571 (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
1572 // Keep ".Inner", to make a fully-qualified name
1573 const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
1574
Jooyung Han29813842020-12-08 01:28:03 +09001575 for (const auto& import : Imports()) {
Jooyung Han13f1fa52021-06-11 18:06:12 +09001576 if (import->SimpleName() == class_name) {
1577 return import->GetNeededClass() + nested_type;
Jooyung Han29813842020-12-08 01:28:03 +09001578 }
1579 }
Jooyung Han13f1fa52021-06-11 18:06:12 +09001580
1581 // check if it is a top-level type.
1582 for (const auto& type : DefinedTypes()) {
1583 if (type->GetName() == class_name) {
1584 return type->GetCanonicalName() + nested_type;
1585 }
Jooyung Han29813842020-12-08 01:28:03 +09001586 }
Jooyung Han13f1fa52021-06-11 18:06:12 +09001587
1588 // name itself might be fully-qualified name.
1589 return name;
Steven Moreland26318532020-12-23 20:08:36 +00001590}