blob: a22872d5efab4a5c2e4b45ce709574d00a0ef8a2 [file] [log] [blame]
Jiyong Park1deecc32018-07-17 01:14:41 +09001/*
2 * Copyright (C) 2018, 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_typenames.h"
18#include "aidl_language.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090019#include "logging.h"
Jiyong Park1deecc32018-07-17 01:14:41 +090020
21#include <android-base/strings.h>
22
23#include <map>
24#include <memory>
25#include <set>
26#include <string>
27#include <utility>
28#include <vector>
29
Jiyong Park1deecc32018-07-17 01:14:41 +090030using android::base::Split;
Jiyong Park1deecc32018-07-17 01:14:41 +090031
32using std::make_pair;
33using std::map;
34using std::pair;
35using std::set;
36using std::string;
37using std::unique_ptr;
38using std::vector;
39
40namespace android {
41namespace aidl {
42
Jiyong Parkac896042018-07-23 21:23:05 +090043// The built-in AIDL types..
Jeongik Cha649e8a72020-03-27 17:47:40 +090044static const set<string> kBuiltinTypes = {"void",
45 "boolean",
46 "byte",
47 "char",
48 "int",
49 "long",
50 "float",
51 "double",
52 "String",
53 "List",
54 "Map",
55 "IBinder",
56 "FileDescriptor",
57 "CharSequence",
58 "ParcelFileDescriptor",
59 "ParcelableHolder"};
Jiyong Parkac896042018-07-23 21:23:05 +090060
Jeongik Chadb0f59e2018-11-01 18:11:21 +090061static const set<string> kPrimitiveTypes = {"void", "boolean", "byte", "char",
62 "int", "long", "float", "double"};
63
Jiyong Parkac896042018-07-23 21:23:05 +090064// Note: these types may look wrong because they look like Java
65// types, but they have long been supported from the time when Java
66// was the only target language of this compiler. They are added here for
67// backwards compatibility, but we internally treat them as List and Map,
68// respectively.
69static const map<string, string> kJavaLikeTypeToAidlType = {
Jiyong Parke05195e2018-10-08 18:24:23 +090070 {"java.util.List", "List"},
71 {"java.util.Map", "Map"},
72 {"android.os.ParcelFileDescriptor", "ParcelFileDescriptor"},
Jiyong Parkac896042018-07-23 21:23:05 +090073};
74
Jiyong Parkb034bf02018-07-30 17:44:33 +090075// Package name and type name can't be one of these as they are keywords
76// in Java and C++. Using these names will eventually cause compilation error,
77// so checking this here is not a must have, but early detection of errors
78// is always better.
Steven Moreland79f0ed12020-04-27 19:43:11 -070079static const set<string> kCppOrJavaReservedWord = {
Jiyong Parkb034bf02018-07-30 17:44:33 +090080 "break", "case", "catch", "char", "class", "continue", "default",
81 "do", "double", "else", "enum", "false", "float", "for",
82 "goto", "if", "int", "long", "new", "private", "protected",
83 "public", "return", "short", "static", "switch", "this", "throw",
84 "true", "try", "void", "volatile", "while"};
85
Steven Moreland79f0ed12020-04-27 19:43:11 -070086static bool HasValidNameComponents(const AidlDefinedType& defined) {
87 bool success = true;
88 vector<string> pieces = Split(defined.GetCanonicalName(), ".");
89 for (const string& piece : pieces) {
90 if (kCppOrJavaReservedWord.find(piece) != kCppOrJavaReservedWord.end()) {
91 AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
92 << "' is a Java or C++ identifier.";
93 success = false;
94 }
95 // not checking kJavaLikeTypeToAidl, since that wouldn't make sense here
96 if (kBuiltinTypes.find(piece) != kBuiltinTypes.end()) {
97 AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
98 << "' is a built-in AIDL type.";
99 success = false;
Jiyong Parkb034bf02018-07-30 17:44:33 +0900100 }
101 }
Steven Moreland79f0ed12020-04-27 19:43:11 -0700102 return success;
Jiyong Parkb034bf02018-07-30 17:44:33 +0900103}
104
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900105bool AidlTypenames::IsIgnorableImport(const string& import) const {
106 static set<string> ignore_import = {"android.os.IInterface", "android.os.IBinder",
107 "android.os.Parcelable", "android.os.Parcel",
108 "android.content.Context", "java.lang.String"};
Jiyong Park8f6ec462020-01-19 20:52:47 +0900109 // these known built-in types don't need to be imported
110 const bool in_ignore_import = ignore_import.find(import) != ignore_import.end();
111 // an already defined type doesn't need to be imported again unless it is from
112 // the preprocessed file
113 auto ret = TryGetDefinedTypeImpl(import);
114 const bool defined_type_not_from_preprocessed = ret.type != nullptr && !ret.from_preprocessed;
115 return in_ignore_import || defined_type_not_from_preprocessed;
Jeongik Cha047c5ee2019-08-07 23:16:49 +0900116}
117
Jiyong Park8e79b7f2020-07-20 20:52:38 +0900118bool AidlTypenames::AddDocument(std::unique_ptr<AidlDocument> doc) {
119 for (const auto& type : doc->DefinedTypes()) {
120 if (defined_types_.find(type->GetCanonicalName()) != defined_types_.end()) {
121 return false;
122 }
123 if (!HasValidNameComponents(*type)) {
124 return false;
125 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900126 }
Jiyong Park8e79b7f2020-07-20 20:52:38 +0900127 documents_.push_back(std::move(doc));
128 for (const auto& type : documents_.back()->DefinedTypes()) {
129 defined_types_.emplace(type->GetCanonicalName(), type.get());
Jiyong Parkb034bf02018-07-30 17:44:33 +0900130 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900131 return true;
132}
133
Jiyong Park8e79b7f2020-07-20 20:52:38 +0900134const AidlDocument& AidlTypenames::MainDocument() const {
135 CHECK(documents_.size() != 0) << "Main document doesn't exist";
136 return *(documents_[0]);
137}
138
Jiyong Park1deecc32018-07-17 01:14:41 +0900139bool AidlTypenames::AddPreprocessedType(unique_ptr<AidlDefinedType> type) {
140 const string name = type->GetCanonicalName();
141 if (preprocessed_types_.find(name) != preprocessed_types_.end()) {
142 return false;
143 }
Steven Moreland79f0ed12020-04-27 19:43:11 -0700144 if (!HasValidNameComponents(*type)) {
Jiyong Parkb034bf02018-07-30 17:44:33 +0900145 return false;
146 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900147 preprocessed_types_.insert(make_pair(name, std::move(type)));
148 return true;
149}
150
151bool AidlTypenames::IsBuiltinTypename(const string& type_name) {
Jiyong Parkac896042018-07-23 21:23:05 +0900152 return kBuiltinTypes.find(type_name) != kBuiltinTypes.end() ||
153 kJavaLikeTypeToAidlType.find(type_name) != kJavaLikeTypeToAidlType.end();
Jiyong Park1deecc32018-07-17 01:14:41 +0900154}
155
Jeongik Chadb0f59e2018-11-01 18:11:21 +0900156bool AidlTypenames::IsPrimitiveTypename(const string& type_name) {
157 return kPrimitiveTypes.find(type_name) != kPrimitiveTypes.end();
158}
159
Jiyong Parkac896042018-07-23 21:23:05 +0900160const AidlDefinedType* AidlTypenames::TryGetDefinedType(const string& type_name) const {
Jiyong Park8f6ec462020-01-19 20:52:47 +0900161 return TryGetDefinedTypeImpl(type_name).type;
162}
163
164AidlTypenames::DefinedImplResult AidlTypenames::TryGetDefinedTypeImpl(
165 const string& type_name) const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900166 // Do the exact match first.
Jiyong Parkac896042018-07-23 21:23:05 +0900167 auto found_def = defined_types_.find(type_name);
168 if (found_def != defined_types_.end()) {
Jiyong Park8e79b7f2020-07-20 20:52:38 +0900169 return DefinedImplResult(found_def->second, false);
Jiyong Park1deecc32018-07-17 01:14:41 +0900170 }
171
Jiyong Parkac896042018-07-23 21:23:05 +0900172 auto found_prep = preprocessed_types_.find(type_name);
173 if (found_prep != preprocessed_types_.end()) {
Jiyong Park8f6ec462020-01-19 20:52:47 +0900174 return DefinedImplResult(found_prep->second.get(), true);
Jiyong Park1deecc32018-07-17 01:14:41 +0900175 }
176
177 // Then match with the class name. Defined types has higher priority than
178 // types from the preprocessed file.
179 for (auto it = defined_types_.begin(); it != defined_types_.end(); it++) {
180 if (it->second->GetName() == type_name) {
Jiyong Park8e79b7f2020-07-20 20:52:38 +0900181 return DefinedImplResult(it->second, false);
Jiyong Park1deecc32018-07-17 01:14:41 +0900182 }
183 }
184
185 for (auto it = preprocessed_types_.begin(); it != preprocessed_types_.end(); it++) {
186 if (it->second->GetName() == type_name) {
Jiyong Park8f6ec462020-01-19 20:52:47 +0900187 return DefinedImplResult(it->second.get(), true);
Jiyong Park1deecc32018-07-17 01:14:41 +0900188 }
189 }
190
Jiyong Park8f6ec462020-01-19 20:52:47 +0900191 return DefinedImplResult(nullptr, false);
Jiyong Park1deecc32018-07-17 01:14:41 +0900192}
193
Jiyong Park0cf03b12020-07-22 19:36:34 +0900194std::vector<AidlDefinedType*> AidlTypenames::AllDefinedTypes() const {
195 std::vector<AidlDefinedType*> res;
196 for (const auto& d : AllDocuments()) {
197 for (const auto& t : d->DefinedTypes()) {
198 res.push_back(t.get());
199 }
200 }
201 return res;
202}
203
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700204AidlTypenames::ResolvedTypename AidlTypenames::ResolveTypename(const string& type_name) const {
Jiyong Park1deecc32018-07-17 01:14:41 +0900205 if (IsBuiltinTypename(type_name)) {
Jiyong Parkac896042018-07-23 21:23:05 +0900206 auto found = kJavaLikeTypeToAidlType.find(type_name);
207 if (found != kJavaLikeTypeToAidlType.end()) {
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700208 return {found->second, true};
Jiyong Parkac896042018-07-23 21:23:05 +0900209 }
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700210 return {type_name, true};
Jiyong Park1deecc32018-07-17 01:14:41 +0900211 }
212 const AidlDefinedType* defined_type = TryGetDefinedType(type_name);
213 if (defined_type != nullptr) {
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700214 return {defined_type->GetCanonicalName(), true};
Jiyong Park1deecc32018-07-17 01:14:41 +0900215 } else {
Steven Morelandcb1bcd72020-04-29 16:30:35 -0700216 return {type_name, false};
Jiyong Park1deecc32018-07-17 01:14:41 +0900217 }
218}
219
Jeongik Cha36f76c32020-07-28 00:25:52 +0900220// Only immutable Parcelable, primitive type, and String, and List, Map, array of the types can be
221// immutable.
Jeongik Chad0a10272020-08-06 16:33:36 +0900222bool AidlTypenames::CanBeJavaOnlyImmutable(const AidlTypeSpecifier& type) const {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900223 const string& name = type.GetName();
224 if (type.IsGeneric()) {
225 if (type.GetName() == "List" || type.GetName() == "Map") {
226 const auto& types = type.GetTypeParameters();
227 return std::all_of(types.begin(), types.end(),
Jeongik Chad0a10272020-08-06 16:33:36 +0900228 [this](const auto& t) { return CanBeJavaOnlyImmutable(*t); });
Jeongik Cha36f76c32020-07-28 00:25:52 +0900229 }
230 AIDL_ERROR(type) << "For a generic type, an immutable parcelable can contain only List or Map.";
231 return false;
232 }
233 if (IsPrimitiveTypename(name) || name == "String") {
234 return true;
235 }
236 const AidlDefinedType* t = TryGetDefinedType(type.GetName());
237 if (t == nullptr) {
238 AIDL_ERROR(type) << "An immutable parcelable can contain only immutable Parcelable, primitive "
239 "type, and String.";
240 return false;
241 }
Jeongik Chad0a10272020-08-06 16:33:36 +0900242 return t->IsJavaOnlyImmutable();
Jeongik Cha36f76c32020-07-28 00:25:52 +0900243}
244
Devin Moorec7e47a32020-08-07 10:55:25 -0700245// Only FixedSize Parcelable, primitive types, and enum types can be FixedSize.
246bool AidlTypenames::CanBeFixedSize(const AidlTypeSpecifier& type) const {
247 const string& name = type.GetName();
248 if (type.IsGeneric() || type.IsArray()) {
249 return false;
250 }
251 if (IsPrimitiveTypename(name)) {
252 return true;
253 }
254 const AidlDefinedType* t = TryGetDefinedType(type.GetName());
255 AIDL_FATAL_IF(t == nullptr, type)
256 << "Failed to look up type. Cannot determine if it can be fixed size.";
257
258 if (t->AsEnumDeclaration()) {
259 return true;
260 }
261 return t->IsFixedSize();
262}
263
Devin Moore693e6732020-08-28 11:07:38 -0700264bool AidlTypenames::IsList(const AidlTypeSpecifier& type) {
Devin Mooref12cc112020-08-26 16:25:00 -0700265 return type.GetName() == "List";
266}
267
Jeongik Cha36f76c32020-07-28 00:25:52 +0900268// Only T[], List, Map, ParcelFileDescriptor and mutable Parcelable can be an out parameter.
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900269bool AidlTypenames::CanBeOutParameter(const AidlTypeSpecifier& type) const {
270 const string& name = type.GetName();
Daniel Normanee8674f2019-09-20 16:07:00 -0700271 if (IsBuiltinTypename(name) || GetEnumDeclaration(type)) {
Jiyong Parke05195e2018-10-08 18:24:23 +0900272 return type.IsArray() || type.GetName() == "List" || type.GetName() == "Map" ||
273 type.GetName() == "ParcelFileDescriptor";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900274 }
275 const AidlDefinedType* t = TryGetDefinedType(type.GetName());
276 CHECK(t != nullptr) << "Unrecognized type: '" << type.GetName() << "'";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900277 // An 'out' field is passed as an argument, so it doesn't make sense if it is immutable.
Jeongik Chad0a10272020-08-06 16:33:36 +0900278 return t->AsParcelable() != nullptr && !t->IsJavaOnlyImmutable();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900279}
280
Daniel Norman85aed542019-08-21 12:01:14 -0700281const AidlEnumDeclaration* AidlTypenames::GetEnumDeclaration(const AidlTypeSpecifier& type) const {
282 if (auto defined_type = TryGetDefinedType(type.GetName()); defined_type != nullptr) {
283 if (auto enum_decl = defined_type->AsEnumDeclaration(); enum_decl != nullptr) {
284 return enum_decl;
285 }
286 }
287 return nullptr;
288}
289
290const AidlInterface* AidlTypenames::GetInterface(const AidlTypeSpecifier& type) const {
291 if (auto defined_type = TryGetDefinedType(type.GetName()); defined_type != nullptr) {
292 if (auto intf = defined_type->AsInterface(); intf != nullptr) {
293 return intf;
294 }
295 }
296 return nullptr;
297}
298
Steven Moreland6cee3482018-07-18 14:39:58 -0700299void AidlTypenames::IterateTypes(const std::function<void(const AidlDefinedType&)>& body) const {
300 for (const auto& kv : defined_types_) {
301 body(*kv.second);
302 }
303 for (const auto& kv : preprocessed_types_) {
304 body(*kv.second);
305 }
306}
307
Jiyong Park1deecc32018-07-17 01:14:41 +0900308} // namespace aidl
309} // namespace android