blob: 479302121ff6122a843148bfae385c3a115d7de4 [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
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036AST::AST(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
Andreas Huber5345ec22016-07-29 13:33:27 -070050 // Ownership of "coordinator" was NOT transferred.
Andreas Huberc9410c72016-07-28 12:18:40 -070051}
52
Yifan Hongbe627b32016-10-28 18:38:56 -070053// used by the parser.
54void AST::addSyntaxError() {
55 mSyntaxErrors++;
56}
57
58size_t AST::syntaxErrors() const {
59 return mSyntaxErrors;
60}
61
Andreas Huberc9410c72016-07-28 12:18:40 -070062void *AST::scanner() {
63 return mScanner;
64}
65
66void AST::setScanner(void *scanner) {
67 mScanner = scanner;
68}
69
Andreas Huber0d0f9a22016-08-17 10:26:11 -070070const std::string &AST::getFilename() const {
71 return mPath;
72}
73
Andreas Huber84f89de2016-07-28 15:39:51 -070074bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070075 mPackage.setTo(package);
76 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070077
Andreas Huberda51b8e2016-07-28 16:00:57 -070078 if (mPackage.package().empty()
79 || mPackage.version().empty()
80 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070081 return false;
82 }
83
Andreas Huber84f89de2016-07-28 15:39:51 -070084 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070085}
86
Andreas Hubera2723d22016-07-29 15:36:07 -070087FQName AST::package() const {
88 return mPackage;
89}
90
91bool AST::isInterface(std::string *ifaceName) const {
92 return mRootScope->containsSingleInterface(ifaceName);
93}
94
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070095bool AST::containsInterfaces() const {
96 return mRootScope->containsInterfaces();
97}
98
Andreas Huber5345ec22016-07-29 13:33:27 -070099bool AST::addImport(const char *import) {
100 FQName fqName(import);
101 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -0700102
Andreas Huber5345ec22016-07-29 13:33:27 -0700103 fqName.applyDefaults(mPackage.package(), mPackage.version());
104
Andreas Huber68f24592016-07-29 14:53:48 -0700105 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -0700106
107 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700108 // import a package
Andreas Huberd2943e12016-08-05 11:59:31 -0700109 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700110
Andreas Huberd2943e12016-08-05 11:59:31 -0700111 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700112 mCoordinator->appendPackageInterfacesToVector(fqName,
113 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700114
115 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700116 return false;
117 }
118
Andreas Huberd2943e12016-08-05 11:59:31 -0700119 for (const auto &subFQName : packageInterfaces) {
Yifan Hongf619fc72017-04-07 15:40:06 -0700120 // Do not enforce restrictions on imports.
121 AST *ast = mCoordinator->parse(subFQName, &mImportedASTs, false /* enforce */);
Yifan Hong1977ea32016-10-05 12:49:08 -0700122 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700123 return false;
124 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700125 // all previous single type imports are ignored.
126 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700127 }
128
129 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700130 }
131
Yifan Hong1977ea32016-10-05 12:49:08 -0700132 AST *importAST;
Andreas Huber5345ec22016-07-29 13:33:27 -0700133
Yifan Hong1977ea32016-10-05 12:49:08 -0700134 // cases like android.hardware.foo@1.0::IFoo.Internal
135 // android.hardware.foo@1.0::Abc.Internal
136
137 // assume it is an interface, and try to import it.
138 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700139 // Do not enforce restrictions on imports.
140 importAST = mCoordinator->parse(interfaceName, &mImportedASTs, false /* enforce */);
Yifan Hong1977ea32016-10-05 12:49:08 -0700141
142 if (importAST != nullptr) {
143 // cases like android.hardware.foo@1.0::IFoo.Internal
144 // and android.hardware.foo@1.0::IFoo
145 if (fqName == interfaceName) {
146 // import a single file.
147 // all previous single type imports are ignored.
148 // cases like android.hardware.foo@1.0::IFoo
149 // and android.hardware.foo@1.0::types
150 mImportedTypes.erase(importAST);
151 return true;
152 }
153
154 // import a single type from this file
155 // cases like android.hardware.foo@1.0::IFoo.Internal
156 FQName matchingName;
157 Type *match = importAST->findDefinedType(fqName, &matchingName);
158 if (match == nullptr) {
159 return false;
160 }
161 // will automatically create a set if it does not exist
162 mImportedTypes[importAST].insert(match);
163 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700164 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700165
Yifan Hong1977ea32016-10-05 12:49:08 -0700166 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
167 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700168
169 // Do not enforce restrictions on imports.
170 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, false /* enforce */);
Yifan Hong1977ea32016-10-05 12:49:08 -0700171
172 if (importAST != nullptr) {
173 // Attempt to find Abc.Internal in types.
174 FQName matchingName;
175 Type *match = importAST->findDefinedType(fqName, &matchingName);
176 if (match == nullptr) {
177 return false;
178 }
179 // will automatically create a set if not exist
180 mImportedTypes[importAST].insert(match);
181 return true;
182 }
183
184 // can't find an appropriate AST for fqName.
185 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700186}
187
Andreas Huber39fa7182016-08-19 14:27:33 -0700188void AST::addImportedAST(AST *ast) {
189 mImportedASTs.insert(ast);
190}
191
Andreas Huberc9410c72016-07-28 12:18:40 -0700192void AST::enterScope(Scope *container) {
193 mScopePath.push_back(container);
194}
195
196void AST::leaveScope() {
Steven Morelandd537ab02016-09-12 10:32:01 -0700197 mScopePath.pop_back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700198}
199
200Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700201 CHECK(!mScopePath.empty());
Steven Morelandd537ab02016-09-12 10:32:01 -0700202 return mScopePath.back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700203}
204
Yifan Honga4b53d02016-10-31 17:29:10 -0700205bool AST::addTypeDef(const char *localName, Type *type, const Location &location,
206 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700207 // The reason we wrap the given type in a TypeDef is simply to suppress
208 // emitting any type definitions later on, since this is just an alias
209 // to a type defined elsewhere.
210 return addScopedTypeInternal(
Yifan Honga4b53d02016-10-31 17:29:10 -0700211 new TypeDef(localName, location, type), errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700212}
213
Andreas Huber9ed827c2016-08-22 12:31:13 -0700214bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700215 return addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700216 type, errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700217}
218
219bool AST::addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700220 NamedType *type,
221 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700222
Steven Morelandd537ab02016-09-12 10:32:01 -0700223 bool success = scope()->addType(type, errorMsg);
Andreas Huber5a545442016-08-03 10:44:56 -0700224 if (!success) {
225 return false;
226 }
227
Andreas Huber31629bc2016-08-03 09:06:40 -0700228 std::string path;
229 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700230 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700231 path.append(".");
232 }
Steven Morelandd537ab02016-09-12 10:32:01 -0700233 path.append(type->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700234
Andreas Huber31629bc2016-08-03 09:06:40 -0700235 FQName fqName(mPackage.package(), mPackage.version(), path);
Andreas Huber39fa7182016-08-19 14:27:33 -0700236
Steven Morelandd537ab02016-09-12 10:32:01 -0700237 type->setFullName(fqName);
Andreas Huber39fa7182016-08-19 14:27:33 -0700238
Steven Morelandd537ab02016-09-12 10:32:01 -0700239 mDefinedTypesByFullName[fqName] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700240
Andreas Huber5a545442016-08-03 10:44:56 -0700241 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700242}
243
Yifan Hongf24fa852016-09-23 11:03:15 -0700244EnumValue *AST::lookupEnumValue(const FQName &fqName, std::string *errorMsg) {
245
246 FQName enumTypeName = fqName.typeName();
247 std::string enumValueName = fqName.valueName();
248
249 CHECK(enumTypeName.isValid());
250 CHECK(!enumValueName.empty());
251
252 Type *type = lookupType(enumTypeName);
253 if(type == nullptr) {
254 *errorMsg = "Cannot find type " + enumTypeName.string();
255 return nullptr;
256 }
257 if(!type->isEnum()) {
258 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
259 return nullptr;
260 }
261
262 EnumType *enumType = static_cast<EnumType *>(type);
263 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
264 if(v == nullptr) {
265 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
266 return nullptr;
267 }
268 return v;
269}
270
Yifan Hongae16eed2016-09-23 13:25:25 -0700271Type *AST::lookupType(const FQName &fqName) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700272 CHECK(fqName.isValid());
273
Andreas Huberda51b8e2016-07-28 16:00:57 -0700274 if (fqName.name().empty()) {
275 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700276 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700277 }
278
Yifan Hong87ff8232017-01-09 12:07:05 -0800279 Type *returnedType = nullptr;
280
Andreas Huber84f89de2016-07-28 15:39:51 -0700281 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800282 // resolve locally first if possible.
283 returnedType = lookupTypeLocally(fqName);
284 if (returnedType != nullptr) {
285 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700286 }
287 }
288
Yifan Hong87ff8232017-01-09 12:07:05 -0800289 if (!fqName.isFullyQualified()) {
290 status_t status = lookupAutofilledType(fqName, &returnedType);
291 if (status != OK) {
292 return nullptr;
293 }
294 if (returnedType != nullptr) {
295 return returnedType;
296 }
297 }
298
299 return lookupTypeFromImports(fqName);
300}
301
302// Rule 0: try resolve locally
303Type *AST::lookupTypeLocally(const FQName &fqName) {
304 CHECK(fqName.package().empty() && fqName.version().empty()
305 && !fqName.name().empty() && fqName.valueName().empty());
306
307 for (size_t i = mScopePath.size(); i-- > 0;) {
308 Type *type = mScopePath[i]->lookupType(fqName);
309
310 if (type != nullptr) {
311 // Resolve typeDefs to the target type.
312 while (type->isTypeDef()) {
313 type = static_cast<TypeDef *>(type)->referencedType();
314 }
315
316 return type;
317 }
318 }
319
320 return nullptr;
321}
322
323// Rule 1: auto-fill with current package
324status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
325 CHECK(!fqName.isFullyQualified() && !fqName.name().empty() && fqName.valueName().empty());
326
327 FQName autofilled = fqName;
328 autofilled.applyDefaults(mPackage.package(), mPackage.version());
329 FQName matchingName;
330 // Given this fully-qualified name, the type may be defined in this AST, or other files
331 // in import.
332 Type *local = findDefinedType(autofilled, &matchingName);
333 CHECK(local == nullptr || autofilled == matchingName);
334 Type *fromImport = lookupType(autofilled);
335
336 if (local != nullptr && fromImport != nullptr && local != fromImport) {
337 // Something bad happen; two types have the same FQName.
338 std::cerr << "ERROR: Unable to resolve type name '"
339 << fqName.string()
340 << "' (i.e. '"
341 << autofilled.string()
342 << "'), multiple definitions found.\n";
343
344 return UNKNOWN_ERROR;
345 }
346 if (local != nullptr) {
347 *returnedType = local;
348 return OK;
349 }
350 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
351 *returnedType = fromImport;
352 return OK;
353}
354
355// Rule 2: look at imports
356Type *AST::lookupTypeFromImports(const FQName &fqName) {
357
Andreas Huber39fa7182016-08-19 14:27:33 -0700358 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700359 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700360 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700361
Andreas Huber39fa7182016-08-19 14:27:33 -0700362 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700363 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
364 // ignore single type imports
365 continue;
366 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700367 FQName matchingName;
368 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700369
Andreas Huber39fa7182016-08-19 14:27:33 -0700370 if (match != nullptr) {
371 if (resolvedType != nullptr) {
372 std::cerr << "ERROR: Unable to resolve type name '"
373 << fqName.string()
374 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700375
Andreas Huber39fa7182016-08-19 14:27:33 -0700376 std::cerr << " " << resolvedName.string() << "\n";
377 std::cerr << " " << matchingName.string() << "\n";
378
Yifan Hong1977ea32016-10-05 12:49:08 -0700379 return nullptr;
380 }
381
382 resolvedType = match;
383 returnedType = resolvedType;
384 resolvedName = matchingName;
385
386 // Keep going even after finding a match.
387 }
388 }
389
390 for (const auto &pair : mImportedTypes) {
391 AST *importedAST = pair.first;
392 std::set<Type *> importedTypes = pair.second;
393
394 FQName matchingName;
395 Type *match = importedAST->findDefinedType(fqName, &matchingName);
396 if (match != nullptr &&
397 importedTypes.find(match) != importedTypes.end()) {
398 if (resolvedType != nullptr) {
399 std::cerr << "ERROR: Unable to resolve type name '"
400 << fqName.string()
401 << "', multiple matches found:\n";
402
403 std::cerr << " " << resolvedName.string() << "\n";
404 std::cerr << " " << matchingName.string() << "\n";
405
406 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700407 }
408
409 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700410 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700411 resolvedName = matchingName;
412
413 // Keep going even after finding a match.
414 }
415 }
416
417 if (resolvedType) {
418#if 0
419 LOG(INFO) << "found '"
420 << resolvedName.string()
421 << "' after looking for '"
422 << fqName.string()
423 << "'.";
424#endif
425
426 // Resolve typeDefs to the target type.
427 while (resolvedType->isTypeDef()) {
428 resolvedType =
429 static_cast<TypeDef *>(resolvedType)->referencedType();
430 }
431
Iliyan Malchev800273d2016-09-02 15:25:07 -0700432 returnedType = resolvedType;
433
434 // If the resolved type is not an interface, we need to determine
435 // whether it is defined in types.hal, or in some other interface. In
436 // the latter case, we need to emit a dependency for the interface in
437 // which the type is defined.
438 //
439 // Consider the following:
440 // android.hardware.tests.foo@1.0::Record
441 // android.hardware.tests.foo@1.0::IFoo.Folder
442 // android.hardware.tests.foo@1.0::Folder
443 //
444 // If Record is an interface, then we keep track of it for the purpose
445 // of emitting dependencies in the target language (for example #include
446 // in C++). If Record is a UDT, then we assume it is defined in
447 // types.hal in android.hardware.tests.foo@1.0.
448 //
449 // In the case of IFoo.Folder, the same applies. If IFoo is an
450 // interface, we need to track this for the purpose of emitting
451 // dependencies. If not, then it must have been defined in types.hal.
452 //
453 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800454 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700455 // above applies.
456
457 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800458 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700459 for (const auto &importedAST : mImportedASTs) {
460 FQName matchingName;
461 Type *match = importedAST->findDefinedType(ifc, &matchingName);
462 if (match != nullptr && match->isInterface()) {
463 resolvedType = match;
464 }
465 }
466 }
467
Andreas Huber39fa7182016-08-19 14:27:33 -0700468 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700469 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800470 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700471
Andreas Huber0e00de42016-08-03 09:56:02 -0700472 mImportedNames.insert(typesName);
473 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700474 // Do _not_ use fqName, i.e. the name we used to look up the type,
475 // but instead use the name of the interface we found.
476 // This is necessary because if fqName pointed to a typedef which
477 // in turn referenced the found interface we'd mistakenly use the
478 // name of the typedef instead of the proper name of the interface.
479
480 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700481 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700482 }
Andreas Huber737080b2016-08-02 15:38:04 -0700483 }
484
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700485 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700486}
487
Andreas Huber39fa7182016-08-19 14:27:33 -0700488Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700489 for (const auto &pair : mDefinedTypesByFullName) {
490 const FQName &key = pair.first;
491 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700492
Andreas Huber39fa7182016-08-19 14:27:33 -0700493 if (key.endsWith(fqName)) {
494 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700495 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700496 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700497 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700498
499 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700500}
501
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700502void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700503 for (const auto &fqName : mImportedNames) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800504 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700505
506 if (packageName == mPackage) {
507 // We only care about external imports, not our own package.
508 continue;
509 }
510
511 importSet->insert(packageName);
512 }
513}
514
Yifan Hong40a373d2016-11-30 15:16:47 -0800515void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
516 getImportedPackages(importSet);
517 std::set<FQName> newSet;
518 for (const auto &ast : mImportedASTs) {
519 if (importSet->find(ast->package()) != importSet->end()) {
520 ast->getImportedPackagesHierarchy(&newSet);
521 }
522 }
523 importSet->insert(newSet.begin(), newSet.end());
524}
525
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800526void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
527 for (const auto& name : mImportedNames) {
528 allImportNames->insert(name);
Yifan Hongf619fc72017-04-07 15:40:06 -0700529 AST *ast = mCoordinator->parse(name, nullptr /* imported */, false /* enforce */);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800530 ast->getAllImportedNames(allImportNames);
531 }
532}
533
Andreas Huber0fa9e392016-08-31 09:05:44 -0700534bool AST::isJavaCompatible() const {
535 std::string ifaceName;
536 if (!AST::isInterface(&ifaceName)) {
Steven Morelandd537ab02016-09-12 10:32:01 -0700537 for (const auto *type : mRootScope->getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700538 if (!type->isJavaCompatible()) {
539 return false;
540 }
541 }
542
543 return true;
544 }
545
546 const Interface *iface = mRootScope->getInterface();
547 return iface->isJavaCompatible();
548}
549
Andreas Huber019d21d2016-10-03 12:59:47 -0700550void AST::appendToExportedTypesVector(
551 std::vector<const Type *> *exportedTypes) const {
552 mRootScope->appendToExportedTypesVector(exportedTypes);
553}
554
Yifan Hongc8934042016-11-17 17:10:52 -0800555bool AST::isIBase() const {
556 Interface *iface = mRootScope->getInterface();
557 return iface != nullptr && iface->isIBase();
558}
559
Yifan Hong78b38d12017-02-13 18:14:46 +0000560const Interface *AST::getInterface() const {
561 return mRootScope->getInterface();
562}
563
Andreas Huberc9410c72016-07-28 12:18:40 -0700564} // namespace android;