blob: 2dfd7fa0914d9e39807c353613a44c860c1a75ca [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
18
Andreas Huber5345ec22016-07-29 13:33:27 -070019#include "Coordinator.h"
Yifan Hongf24fa852016-09-23 11:03:15 -070020#include "EnumType.h"
Andreas Hubereb1081f2016-07-28 13:13:24 -070021#include "HandleType.h"
Andreas Huberbfd76212016-08-09 11:12:16 -070022#include "Interface.h"
Yifan Honga4b53d02016-10-31 17:29:10 -070023#include "Location.h"
Hridya Valsarajua32bde82016-12-27 11:47:46 -080024#include "FmqType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070025#include "Scope.h"
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070026#include "TypeDef.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070027
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070028#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080029#include <hidl-util/FQName.h>
Andreas Hubereb1081f2016-07-28 13:13:24 -070030#include <android-base/logging.h>
Andreas Huber39fa7182016-08-19 14:27:33 -070031#include <iostream>
Andreas Huberc9410c72016-07-28 12:18:40 -070032#include <stdlib.h>
33
Andreas Huberc9410c72016-07-28 12:18:40 -070034namespace android {
35
Steven Moreland28b9b532017-05-12 17:02:58 -070036AST::AST(const Coordinator *coordinator, const std::string &path)
Andreas Huber5345ec22016-07-29 13:33:27 -070037 : mCoordinator(coordinator),
Andreas Huber0d0f9a22016-08-17 10:26:11 -070038 mPath(path),
Andreas Huber5345ec22016-07-29 13:33:27 -070039 mScanner(NULL),
Yifan Honga4b53d02016-10-31 17:29:10 -070040 mRootScope(new Scope("" /* localName */, Location::startOf(path))) {
Andreas Huberc9410c72016-07-28 12:18:40 -070041 enterScope(mRootScope);
42}
43
44AST::~AST() {
Andreas Huberc9410c72016-07-28 12:18:40 -070045 delete mRootScope;
Yifan Hong1977ea32016-10-05 12:49:08 -070046 mRootScope = nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -070047
Andreas Hubereb1081f2016-07-28 13:13:24 -070048 CHECK(mScanner == NULL);
Andreas Huberc9410c72016-07-28 12:18:40 -070049}
50
Yifan Hongbe627b32016-10-28 18:38:56 -070051// used by the parser.
52void AST::addSyntaxError() {
53 mSyntaxErrors++;
54}
55
56size_t AST::syntaxErrors() const {
57 return mSyntaxErrors;
58}
59
Andreas Huberc9410c72016-07-28 12:18:40 -070060void *AST::scanner() {
61 return mScanner;
62}
63
64void AST::setScanner(void *scanner) {
65 mScanner = scanner;
66}
67
Andreas Huber0d0f9a22016-08-17 10:26:11 -070068const std::string &AST::getFilename() const {
69 return mPath;
70}
71
Andreas Huber84f89de2016-07-28 15:39:51 -070072bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070073 mPackage.setTo(package);
74 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070075
Andreas Huberda51b8e2016-07-28 16:00:57 -070076 if (mPackage.package().empty()
77 || mPackage.version().empty()
78 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070079 return false;
80 }
81
Andreas Huber84f89de2016-07-28 15:39:51 -070082 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070083}
84
Andreas Hubera2723d22016-07-29 15:36:07 -070085FQName AST::package() const {
86 return mPackage;
87}
88
Steven Moreland19f11b52017-05-12 18:22:21 -070089bool AST::isInterface() const {
90 return mRootScope->getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070091}
92
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070093bool AST::containsInterfaces() const {
94 return mRootScope->containsInterfaces();
95}
96
Andreas Huber5345ec22016-07-29 13:33:27 -070097bool AST::addImport(const char *import) {
98 FQName fqName(import);
99 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -0700100
Andreas Huber5345ec22016-07-29 13:33:27 -0700101 fqName.applyDefaults(mPackage.package(), mPackage.version());
102
Andreas Huber68f24592016-07-29 14:53:48 -0700103 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -0700104
105 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700106 // import a package
Andreas Huberd2943e12016-08-05 11:59:31 -0700107 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700108
Andreas Huberd2943e12016-08-05 11:59:31 -0700109 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700110 mCoordinator->appendPackageInterfacesToVector(fqName,
111 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700112
113 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700114 return false;
115 }
116
Andreas Huberd2943e12016-08-05 11:59:31 -0700117 for (const auto &subFQName : packageInterfaces) {
Yifan Hongf619fc72017-04-07 15:40:06 -0700118 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700119 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700120 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700121 return false;
122 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700123 // all previous single type imports are ignored.
124 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700125 }
126
127 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700128 }
129
Yifan Hong1977ea32016-10-05 12:49:08 -0700130 AST *importAST;
Andreas Huber5345ec22016-07-29 13:33:27 -0700131
Yifan Hong1977ea32016-10-05 12:49:08 -0700132 // cases like android.hardware.foo@1.0::IFoo.Internal
133 // android.hardware.foo@1.0::Abc.Internal
134
135 // assume it is an interface, and try to import it.
136 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700137 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700138 importAST = mCoordinator->parse(interfaceName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700139
140 if (importAST != nullptr) {
141 // cases like android.hardware.foo@1.0::IFoo.Internal
142 // and android.hardware.foo@1.0::IFoo
143 if (fqName == interfaceName) {
144 // import a single file.
145 // all previous single type imports are ignored.
146 // cases like android.hardware.foo@1.0::IFoo
147 // and android.hardware.foo@1.0::types
148 mImportedTypes.erase(importAST);
149 return true;
150 }
151
152 // import a single type from this file
153 // cases like android.hardware.foo@1.0::IFoo.Internal
154 FQName matchingName;
155 Type *match = importAST->findDefinedType(fqName, &matchingName);
156 if (match == nullptr) {
157 return false;
158 }
159 // will automatically create a set if it does not exist
160 mImportedTypes[importAST].insert(match);
161 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700162 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700163
Yifan Hong1977ea32016-10-05 12:49:08 -0700164 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
165 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700166
167 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700168 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700169
170 if (importAST != nullptr) {
171 // Attempt to find Abc.Internal in types.
172 FQName matchingName;
173 Type *match = importAST->findDefinedType(fqName, &matchingName);
174 if (match == nullptr) {
175 return false;
176 }
177 // will automatically create a set if not exist
178 mImportedTypes[importAST].insert(match);
179 return true;
180 }
181
182 // can't find an appropriate AST for fqName.
183 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700184}
185
Andreas Huber39fa7182016-08-19 14:27:33 -0700186void AST::addImportedAST(AST *ast) {
187 mImportedASTs.insert(ast);
188}
189
Andreas Huberc9410c72016-07-28 12:18:40 -0700190void AST::enterScope(Scope *container) {
191 mScopePath.push_back(container);
192}
193
194void AST::leaveScope() {
Steven Morelandd537ab02016-09-12 10:32:01 -0700195 mScopePath.pop_back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700196}
197
198Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700199 CHECK(!mScopePath.empty());
Steven Morelandd537ab02016-09-12 10:32:01 -0700200 return mScopePath.back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700201}
202
Yifan Honga4b53d02016-10-31 17:29:10 -0700203bool AST::addTypeDef(const char *localName, Type *type, const Location &location,
204 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700205 // The reason we wrap the given type in a TypeDef is simply to suppress
206 // emitting any type definitions later on, since this is just an alias
207 // to a type defined elsewhere.
208 return addScopedTypeInternal(
Yifan Honga4b53d02016-10-31 17:29:10 -0700209 new TypeDef(localName, location, type), errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700210}
211
Andreas Huber9ed827c2016-08-22 12:31:13 -0700212bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700213 return addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700214 type, errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700215}
216
217bool AST::addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700218 NamedType *type,
219 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700220
Steven Morelandd537ab02016-09-12 10:32:01 -0700221 bool success = scope()->addType(type, errorMsg);
Andreas Huber5a545442016-08-03 10:44:56 -0700222 if (!success) {
223 return false;
224 }
225
Andreas Huber31629bc2016-08-03 09:06:40 -0700226 std::string path;
227 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700228 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700229 path.append(".");
230 }
Steven Morelandd537ab02016-09-12 10:32:01 -0700231 path.append(type->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700232
Andreas Huber31629bc2016-08-03 09:06:40 -0700233 FQName fqName(mPackage.package(), mPackage.version(), path);
Andreas Huber39fa7182016-08-19 14:27:33 -0700234
Steven Morelandd537ab02016-09-12 10:32:01 -0700235 type->setFullName(fqName);
Andreas Huber39fa7182016-08-19 14:27:33 -0700236
Steven Morelandd537ab02016-09-12 10:32:01 -0700237 mDefinedTypesByFullName[fqName] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700238
Andreas Huber5a545442016-08-03 10:44:56 -0700239 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700240}
241
Yifan Hongf24fa852016-09-23 11:03:15 -0700242EnumValue *AST::lookupEnumValue(const FQName &fqName, std::string *errorMsg) {
243
244 FQName enumTypeName = fqName.typeName();
245 std::string enumValueName = fqName.valueName();
246
247 CHECK(enumTypeName.isValid());
248 CHECK(!enumValueName.empty());
249
250 Type *type = lookupType(enumTypeName);
251 if(type == nullptr) {
252 *errorMsg = "Cannot find type " + enumTypeName.string();
253 return nullptr;
254 }
255 if(!type->isEnum()) {
256 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
257 return nullptr;
258 }
259
260 EnumType *enumType = static_cast<EnumType *>(type);
261 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
262 if(v == nullptr) {
263 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
264 return nullptr;
265 }
266 return v;
267}
268
Yifan Hongae16eed2016-09-23 13:25:25 -0700269Type *AST::lookupType(const FQName &fqName) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700270 CHECK(fqName.isValid());
271
Andreas Huberda51b8e2016-07-28 16:00:57 -0700272 if (fqName.name().empty()) {
273 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700274 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700275 }
276
Yifan Hong87ff8232017-01-09 12:07:05 -0800277 Type *returnedType = nullptr;
278
Andreas Huber84f89de2016-07-28 15:39:51 -0700279 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800280 // resolve locally first if possible.
281 returnedType = lookupTypeLocally(fqName);
282 if (returnedType != nullptr) {
283 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700284 }
285 }
286
Yifan Hong87ff8232017-01-09 12:07:05 -0800287 if (!fqName.isFullyQualified()) {
288 status_t status = lookupAutofilledType(fqName, &returnedType);
289 if (status != OK) {
290 return nullptr;
291 }
292 if (returnedType != nullptr) {
293 return returnedType;
294 }
295 }
296
297 return lookupTypeFromImports(fqName);
298}
299
300// Rule 0: try resolve locally
301Type *AST::lookupTypeLocally(const FQName &fqName) {
302 CHECK(fqName.package().empty() && fqName.version().empty()
303 && !fqName.name().empty() && fqName.valueName().empty());
304
305 for (size_t i = mScopePath.size(); i-- > 0;) {
306 Type *type = mScopePath[i]->lookupType(fqName);
307
308 if (type != nullptr) {
309 // Resolve typeDefs to the target type.
310 while (type->isTypeDef()) {
311 type = static_cast<TypeDef *>(type)->referencedType();
312 }
313
314 return type;
315 }
316 }
317
318 return nullptr;
319}
320
321// Rule 1: auto-fill with current package
322status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
323 CHECK(!fqName.isFullyQualified() && !fqName.name().empty() && fqName.valueName().empty());
324
325 FQName autofilled = fqName;
326 autofilled.applyDefaults(mPackage.package(), mPackage.version());
327 FQName matchingName;
328 // Given this fully-qualified name, the type may be defined in this AST, or other files
329 // in import.
330 Type *local = findDefinedType(autofilled, &matchingName);
331 CHECK(local == nullptr || autofilled == matchingName);
332 Type *fromImport = lookupType(autofilled);
333
334 if (local != nullptr && fromImport != nullptr && local != fromImport) {
335 // Something bad happen; two types have the same FQName.
336 std::cerr << "ERROR: Unable to resolve type name '"
337 << fqName.string()
338 << "' (i.e. '"
339 << autofilled.string()
340 << "'), multiple definitions found.\n";
341
342 return UNKNOWN_ERROR;
343 }
344 if (local != nullptr) {
345 *returnedType = local;
346 return OK;
347 }
348 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
349 *returnedType = fromImport;
350 return OK;
351}
352
353// Rule 2: look at imports
354Type *AST::lookupTypeFromImports(const FQName &fqName) {
355
Andreas Huber39fa7182016-08-19 14:27:33 -0700356 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700357 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700358 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700359
Andreas Huber39fa7182016-08-19 14:27:33 -0700360 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700361 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
362 // ignore single type imports
363 continue;
364 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700365 FQName matchingName;
366 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700367
Andreas Huber39fa7182016-08-19 14:27:33 -0700368 if (match != nullptr) {
369 if (resolvedType != nullptr) {
370 std::cerr << "ERROR: Unable to resolve type name '"
371 << fqName.string()
372 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700373
Andreas Huber39fa7182016-08-19 14:27:33 -0700374 std::cerr << " " << resolvedName.string() << "\n";
375 std::cerr << " " << matchingName.string() << "\n";
376
Yifan Hong1977ea32016-10-05 12:49:08 -0700377 return nullptr;
378 }
379
380 resolvedType = match;
381 returnedType = resolvedType;
382 resolvedName = matchingName;
383
384 // Keep going even after finding a match.
385 }
386 }
387
388 for (const auto &pair : mImportedTypes) {
389 AST *importedAST = pair.first;
390 std::set<Type *> importedTypes = pair.second;
391
392 FQName matchingName;
393 Type *match = importedAST->findDefinedType(fqName, &matchingName);
394 if (match != nullptr &&
395 importedTypes.find(match) != importedTypes.end()) {
396 if (resolvedType != nullptr) {
397 std::cerr << "ERROR: Unable to resolve type name '"
398 << fqName.string()
399 << "', multiple matches found:\n";
400
401 std::cerr << " " << resolvedName.string() << "\n";
402 std::cerr << " " << matchingName.string() << "\n";
403
404 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700405 }
406
407 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700408 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700409 resolvedName = matchingName;
410
411 // Keep going even after finding a match.
412 }
413 }
414
415 if (resolvedType) {
416#if 0
417 LOG(INFO) << "found '"
418 << resolvedName.string()
419 << "' after looking for '"
420 << fqName.string()
421 << "'.";
422#endif
423
424 // Resolve typeDefs to the target type.
425 while (resolvedType->isTypeDef()) {
426 resolvedType =
427 static_cast<TypeDef *>(resolvedType)->referencedType();
428 }
429
Iliyan Malchev800273d2016-09-02 15:25:07 -0700430 returnedType = resolvedType;
431
432 // If the resolved type is not an interface, we need to determine
433 // whether it is defined in types.hal, or in some other interface. In
434 // the latter case, we need to emit a dependency for the interface in
435 // which the type is defined.
436 //
437 // Consider the following:
438 // android.hardware.tests.foo@1.0::Record
439 // android.hardware.tests.foo@1.0::IFoo.Folder
440 // android.hardware.tests.foo@1.0::Folder
441 //
442 // If Record is an interface, then we keep track of it for the purpose
443 // of emitting dependencies in the target language (for example #include
444 // in C++). If Record is a UDT, then we assume it is defined in
445 // types.hal in android.hardware.tests.foo@1.0.
446 //
447 // In the case of IFoo.Folder, the same applies. If IFoo is an
448 // interface, we need to track this for the purpose of emitting
449 // dependencies. If not, then it must have been defined in types.hal.
450 //
451 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800452 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700453 // above applies.
454
455 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800456 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700457 for (const auto &importedAST : mImportedASTs) {
458 FQName matchingName;
459 Type *match = importedAST->findDefinedType(ifc, &matchingName);
460 if (match != nullptr && match->isInterface()) {
461 resolvedType = match;
462 }
463 }
464 }
465
Andreas Huber39fa7182016-08-19 14:27:33 -0700466 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700467 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800468 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700469
Andreas Huber0e00de42016-08-03 09:56:02 -0700470 mImportedNames.insert(typesName);
471 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700472 // Do _not_ use fqName, i.e. the name we used to look up the type,
473 // but instead use the name of the interface we found.
474 // This is necessary because if fqName pointed to a typedef which
475 // in turn referenced the found interface we'd mistakenly use the
476 // name of the typedef instead of the proper name of the interface.
477
478 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700479 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700480 }
Andreas Huber737080b2016-08-02 15:38:04 -0700481 }
482
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700483 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700484}
485
Andreas Huber39fa7182016-08-19 14:27:33 -0700486Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700487 for (const auto &pair : mDefinedTypesByFullName) {
488 const FQName &key = pair.first;
489 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700490
Andreas Huber39fa7182016-08-19 14:27:33 -0700491 if (key.endsWith(fqName)) {
492 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700493 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700494 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700495 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700496
497 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700498}
499
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700500void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700501 for (const auto &fqName : mImportedNames) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800502 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700503
504 if (packageName == mPackage) {
505 // We only care about external imports, not our own package.
506 continue;
507 }
508
509 importSet->insert(packageName);
510 }
511}
512
Yifan Hong40a373d2016-11-30 15:16:47 -0800513void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
514 getImportedPackages(importSet);
515 std::set<FQName> newSet;
516 for (const auto &ast : mImportedASTs) {
517 if (importSet->find(ast->package()) != importSet->end()) {
518 ast->getImportedPackagesHierarchy(&newSet);
519 }
520 }
521 importSet->insert(newSet.begin(), newSet.end());
522}
523
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800524void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
525 for (const auto& name : mImportedNames) {
526 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700527 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800528 ast->getAllImportedNames(allImportNames);
529 }
530}
531
Andreas Huber0fa9e392016-08-31 09:05:44 -0700532bool AST::isJavaCompatible() const {
Steven Moreland19f11b52017-05-12 18:22:21 -0700533 if (!AST::isInterface()) {
Steven Morelandd537ab02016-09-12 10:32:01 -0700534 for (const auto *type : mRootScope->getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700535 if (!type->isJavaCompatible()) {
536 return false;
537 }
538 }
539
540 return true;
541 }
542
543 const Interface *iface = mRootScope->getInterface();
544 return iface->isJavaCompatible();
545}
546
Andreas Huber019d21d2016-10-03 12:59:47 -0700547void AST::appendToExportedTypesVector(
548 std::vector<const Type *> *exportedTypes) const {
549 mRootScope->appendToExportedTypesVector(exportedTypes);
550}
551
Yifan Hongc8934042016-11-17 17:10:52 -0800552bool AST::isIBase() const {
553 Interface *iface = mRootScope->getInterface();
554 return iface != nullptr && iface->isIBase();
555}
556
Yifan Hong78b38d12017-02-13 18:14:46 +0000557const Interface *AST::getInterface() const {
558 return mRootScope->getInterface();
559}
560
Steven Moreland19f11b52017-05-12 18:22:21 -0700561std::string AST::getBaseName() const {
562 const Interface *iface = mRootScope->getInterface();
563
564 return iface ? iface->getBaseName() : "types";
565}
566
Andreas Huberc9410c72016-07-28 12:18:40 -0700567} // namespace android;