blob: b2f16c6b2a0a32efef5ea43da3621b03f97fb47f [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"
Timur Iskhakov33431e62017-08-21 17:31:23 -070021#include "FmqType.h"
Andreas Hubereb1081f2016-07-28 13:13:24 -070022#include "HandleType.h"
Andreas Huberbfd76212016-08-09 11:12:16 -070023#include "Interface.h"
Yifan Honga4b53d02016-10-31 17:29:10 -070024#include "Location.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
Andreas Hubereb1081f2016-07-28 13:13:24 -070028#include <android-base/logging.h>
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070029#include <hidl-util/FQName.h>
30#include <hidl-util/Formatter.h>
31#include <hidl-util/StringHelper.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070032#include <stdlib.h>
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070033#include <algorithm>
34#include <iostream>
Andreas Huberc9410c72016-07-28 12:18:40 -070035
Andreas Huberc9410c72016-07-28 12:18:40 -070036namespace android {
37
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070038AST::AST(const Coordinator* coordinator, const std::string& path)
Andreas Huber5345ec22016-07-29 13:33:27 -070039 : mCoordinator(coordinator),
Andreas Huber0d0f9a22016-08-17 10:26:11 -070040 mPath(path),
Steven Moreland0ecc7b82017-07-19 12:59:23 -070041 mRootScope("(root scope)", Location::startOf(path), nullptr /* parent */) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070042
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070043Scope* AST::getRootScope() {
44 return &mRootScope;
Andreas Huberc9410c72016-07-28 12:18:40 -070045}
46
Yifan Hongbe627b32016-10-28 18:38:56 -070047// used by the parser.
48void AST::addSyntaxError() {
49 mSyntaxErrors++;
50}
51
52size_t AST::syntaxErrors() const {
53 return mSyntaxErrors;
54}
55
Andreas Huber0d0f9a22016-08-17 10:26:11 -070056const std::string &AST::getFilename() const {
57 return mPath;
58}
59
Andreas Huber84f89de2016-07-28 15:39:51 -070060bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070061 mPackage.setTo(package);
62 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070063
Andreas Huberda51b8e2016-07-28 16:00:57 -070064 if (mPackage.package().empty()
65 || mPackage.version().empty()
66 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070067 return false;
68 }
69
Andreas Huber84f89de2016-07-28 15:39:51 -070070 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070071}
72
Andreas Hubera2723d22016-07-29 15:36:07 -070073FQName AST::package() const {
74 return mPackage;
75}
76
Steven Moreland19f11b52017-05-12 18:22:21 -070077bool AST::isInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070078 return mRootScope.getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070079}
80
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070081bool AST::containsInterfaces() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070082 return mRootScope.containsInterfaces();
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070083}
84
Timur Iskhakov33431e62017-08-21 17:31:23 -070085status_t AST::postParse() {
86 status_t err = resolveInheritance();
87 if (err != OK) return err;
88 err = evaluate();
89 if (err != OK) return err;
90 err = validate();
91 if (err != OK) return err;
Timur Iskhakov40731af2017-08-24 14:18:35 -070092 err = checkAcyclic();
93 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -070094
Timur Iskhakov35930c42017-08-28 18:49:54 -070095 // Make future packages not to call passes
96 // for processed types and expressions
97 constantExpressionRecursivePass([](ConstantExpression* ce) {
98 ce->setPostParseCompleted();
99 return OK;
100 });
101 std::unordered_set<const Type*> visited;
102 mRootScope.recursivePass(
103 [](Type* type) {
104 type->setPostParseCompleted();
105 return OK;
106 },
107 &visited);
108
Timur Iskhakov33431e62017-08-21 17:31:23 -0700109 return OK;
110}
111
Timur Iskhakov891a8662017-08-25 21:53:48 -0700112status_t AST::constantExpressionRecursivePass(
113 const std::function<status_t(ConstantExpression*)>& func) {
114 std::unordered_set<const Type*> visitedTypes;
115 std::unordered_set<const ConstantExpression*> visitedCE;
116 return mRootScope.recursivePass(
117 [&](Type* type) -> status_t {
118 for (auto* ce : type->getConstantExpressions()) {
119 status_t err = ce->recursivePass(func, &visitedCE);
120 if (err != OK) return err;
121 }
122 return OK;
123 },
124 &visitedTypes);
125}
126
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700127status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700128 std::unordered_set<const Type*> visited;
129 return mRootScope.recursivePass(&Type::resolveInheritance, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700130}
131
132status_t AST::evaluate() {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700133 return constantExpressionRecursivePass([](ConstantExpression* ce) {
134 ce->evaluate();
135 return OK;
136 });
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700137}
138
139status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700140 std::unordered_set<const Type*> visited;
141 return mRootScope.recursivePass(&Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700142}
143
Timur Iskhakov40731af2017-08-24 14:18:35 -0700144status_t AST::checkAcyclic() const {
145 std::unordered_set<const Type*> visited;
146 std::unordered_set<const Type*> stack;
147 return mRootScope.checkAcyclic(&visited, &stack).status;
148}
149
Andreas Huber5345ec22016-07-29 13:33:27 -0700150bool AST::addImport(const char *import) {
151 FQName fqName(import);
152 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -0700153
Andreas Huber5345ec22016-07-29 13:33:27 -0700154 fqName.applyDefaults(mPackage.package(), mPackage.version());
155
Andreas Huber68f24592016-07-29 14:53:48 -0700156 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -0700157
158 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700159 // import a package
Andreas Huberd2943e12016-08-05 11:59:31 -0700160 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700161
Andreas Huberd2943e12016-08-05 11:59:31 -0700162 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700163 mCoordinator->appendPackageInterfacesToVector(fqName,
164 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700165
166 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700167 return false;
168 }
169
Andreas Huberd2943e12016-08-05 11:59:31 -0700170 for (const auto &subFQName : packageInterfaces) {
Yifan Hongf619fc72017-04-07 15:40:06 -0700171 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700172 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700173 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700174 return false;
175 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700176 // all previous single type imports are ignored.
177 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700178 }
179
180 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700181 }
182
Yifan Hong1977ea32016-10-05 12:49:08 -0700183 AST *importAST;
Andreas Huber5345ec22016-07-29 13:33:27 -0700184
Yifan Hong1977ea32016-10-05 12:49:08 -0700185 // cases like android.hardware.foo@1.0::IFoo.Internal
186 // android.hardware.foo@1.0::Abc.Internal
187
188 // assume it is an interface, and try to import it.
189 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700190 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700191 importAST = mCoordinator->parse(interfaceName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700192
193 if (importAST != nullptr) {
194 // cases like android.hardware.foo@1.0::IFoo.Internal
195 // and android.hardware.foo@1.0::IFoo
196 if (fqName == interfaceName) {
197 // import a single file.
198 // all previous single type imports are ignored.
199 // cases like android.hardware.foo@1.0::IFoo
200 // and android.hardware.foo@1.0::types
201 mImportedTypes.erase(importAST);
202 return true;
203 }
204
205 // import a single type from this file
206 // cases like android.hardware.foo@1.0::IFoo.Internal
207 FQName matchingName;
208 Type *match = importAST->findDefinedType(fqName, &matchingName);
209 if (match == nullptr) {
210 return false;
211 }
212 // will automatically create a set if it does not exist
213 mImportedTypes[importAST].insert(match);
214 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700215 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700216
Yifan Hong1977ea32016-10-05 12:49:08 -0700217 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
218 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700219
220 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700221 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700222
223 if (importAST != nullptr) {
224 // Attempt to find Abc.Internal in types.
225 FQName matchingName;
226 Type *match = importAST->findDefinedType(fqName, &matchingName);
227 if (match == nullptr) {
228 return false;
229 }
230 // will automatically create a set if not exist
231 mImportedTypes[importAST].insert(match);
232 return true;
233 }
234
235 // can't find an appropriate AST for fqName.
236 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700237}
238
Andreas Huber39fa7182016-08-19 14:27:33 -0700239void AST::addImportedAST(AST *ast) {
240 mImportedASTs.insert(ast);
241}
242
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700243bool AST::addScopedType(NamedType* type, std::string* errorMsg, Scope* scope) {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700244 bool success = scope->addType(type, errorMsg);
Andreas Huber5a545442016-08-03 10:44:56 -0700245 if (!success) {
246 return false;
247 }
248
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700249 std::vector<std::string> pathComponents{{type->localName()}};
250 for (; scope != &mRootScope; scope = scope->parent()) {
251 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700252 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700253
254 std::reverse(pathComponents.begin(), pathComponents.end());
255 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700256
Andreas Huber31629bc2016-08-03 09:06:40 -0700257 FQName fqName(mPackage.package(), mPackage.version(), path);
Steven Morelandd537ab02016-09-12 10:32:01 -0700258 type->setFullName(fqName);
Andreas Huber39fa7182016-08-19 14:27:33 -0700259
Steven Morelandd537ab02016-09-12 10:32:01 -0700260 mDefinedTypesByFullName[fqName] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700261
Andreas Huber5a545442016-08-03 10:44:56 -0700262 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700263}
264
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700265EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700266 FQName enumTypeName = fqName.typeName();
267 std::string enumValueName = fqName.valueName();
268
269 CHECK(enumTypeName.isValid());
270 CHECK(!enumValueName.empty());
271
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700272 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700273 if(type == nullptr) {
274 *errorMsg = "Cannot find type " + enumTypeName.string();
275 return nullptr;
276 }
277 if(!type->isEnum()) {
278 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
279 return nullptr;
280 }
281
282 EnumType *enumType = static_cast<EnumType *>(type);
283 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
284 if(v == nullptr) {
285 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
286 return nullptr;
287 }
288 return v;
289}
290
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700291Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700292 CHECK(fqName.isValid());
293
Andreas Huberda51b8e2016-07-28 16:00:57 -0700294 if (fqName.name().empty()) {
295 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700296 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700297 }
298
Yifan Hong87ff8232017-01-09 12:07:05 -0800299 Type *returnedType = nullptr;
300
Andreas Huber84f89de2016-07-28 15:39:51 -0700301 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800302 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700303 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800304 if (returnedType != nullptr) {
305 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700306 }
307 }
308
Yifan Hong87ff8232017-01-09 12:07:05 -0800309 if (!fqName.isFullyQualified()) {
310 status_t status = lookupAutofilledType(fqName, &returnedType);
311 if (status != OK) {
312 return nullptr;
313 }
314 if (returnedType != nullptr) {
315 return returnedType;
316 }
317 }
318
319 return lookupTypeFromImports(fqName);
320}
321
322// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700323Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800324 CHECK(fqName.package().empty() && fqName.version().empty()
325 && !fqName.name().empty() && fqName.valueName().empty());
326
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700327 for (; scope != nullptr; scope = scope->parent()) {
328 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800329
330 if (type != nullptr) {
331 // Resolve typeDefs to the target type.
332 while (type->isTypeDef()) {
333 type = static_cast<TypeDef *>(type)->referencedType();
334 }
335
336 return type;
337 }
338 }
339
340 return nullptr;
341}
342
343// Rule 1: auto-fill with current package
344status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
345 CHECK(!fqName.isFullyQualified() && !fqName.name().empty() && fqName.valueName().empty());
346
347 FQName autofilled = fqName;
348 autofilled.applyDefaults(mPackage.package(), mPackage.version());
349 FQName matchingName;
350 // Given this fully-qualified name, the type may be defined in this AST, or other files
351 // in import.
352 Type *local = findDefinedType(autofilled, &matchingName);
353 CHECK(local == nullptr || autofilled == matchingName);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700354 Type* fromImport = lookupType(autofilled, nullptr /* scope */);
Yifan Hong87ff8232017-01-09 12:07:05 -0800355
356 if (local != nullptr && fromImport != nullptr && local != fromImport) {
357 // Something bad happen; two types have the same FQName.
358 std::cerr << "ERROR: Unable to resolve type name '"
359 << fqName.string()
360 << "' (i.e. '"
361 << autofilled.string()
362 << "'), multiple definitions found.\n";
363
364 return UNKNOWN_ERROR;
365 }
366 if (local != nullptr) {
367 *returnedType = local;
368 return OK;
369 }
370 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
371 *returnedType = fromImport;
372 return OK;
373}
374
375// Rule 2: look at imports
376Type *AST::lookupTypeFromImports(const FQName &fqName) {
377
Andreas Huber39fa7182016-08-19 14:27:33 -0700378 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700379 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700380 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700381
Andreas Huber39fa7182016-08-19 14:27:33 -0700382 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700383 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
384 // ignore single type imports
385 continue;
386 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700387 FQName matchingName;
388 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700389
Andreas Huber39fa7182016-08-19 14:27:33 -0700390 if (match != nullptr) {
391 if (resolvedType != nullptr) {
392 std::cerr << "ERROR: Unable to resolve type name '"
393 << fqName.string()
394 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700395
Andreas Huber39fa7182016-08-19 14:27:33 -0700396 std::cerr << " " << resolvedName.string() << "\n";
397 std::cerr << " " << matchingName.string() << "\n";
398
Yifan Hong1977ea32016-10-05 12:49:08 -0700399 return nullptr;
400 }
401
402 resolvedType = match;
403 returnedType = resolvedType;
404 resolvedName = matchingName;
405
406 // Keep going even after finding a match.
407 }
408 }
409
410 for (const auto &pair : mImportedTypes) {
411 AST *importedAST = pair.first;
412 std::set<Type *> importedTypes = pair.second;
413
414 FQName matchingName;
415 Type *match = importedAST->findDefinedType(fqName, &matchingName);
416 if (match != nullptr &&
417 importedTypes.find(match) != importedTypes.end()) {
418 if (resolvedType != nullptr) {
419 std::cerr << "ERROR: Unable to resolve type name '"
420 << fqName.string()
421 << "', multiple matches found:\n";
422
423 std::cerr << " " << resolvedName.string() << "\n";
424 std::cerr << " " << matchingName.string() << "\n";
425
426 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700427 }
428
429 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700430 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700431 resolvedName = matchingName;
432
433 // Keep going even after finding a match.
434 }
435 }
436
437 if (resolvedType) {
438#if 0
439 LOG(INFO) << "found '"
440 << resolvedName.string()
441 << "' after looking for '"
442 << fqName.string()
443 << "'.";
444#endif
445
446 // Resolve typeDefs to the target type.
447 while (resolvedType->isTypeDef()) {
448 resolvedType =
449 static_cast<TypeDef *>(resolvedType)->referencedType();
450 }
451
Iliyan Malchev800273d2016-09-02 15:25:07 -0700452 returnedType = resolvedType;
453
454 // If the resolved type is not an interface, we need to determine
455 // whether it is defined in types.hal, or in some other interface. In
456 // the latter case, we need to emit a dependency for the interface in
457 // which the type is defined.
458 //
459 // Consider the following:
460 // android.hardware.tests.foo@1.0::Record
461 // android.hardware.tests.foo@1.0::IFoo.Folder
462 // android.hardware.tests.foo@1.0::Folder
463 //
464 // If Record is an interface, then we keep track of it for the purpose
465 // of emitting dependencies in the target language (for example #include
466 // in C++). If Record is a UDT, then we assume it is defined in
467 // types.hal in android.hardware.tests.foo@1.0.
468 //
469 // In the case of IFoo.Folder, the same applies. If IFoo is an
470 // interface, we need to track this for the purpose of emitting
471 // dependencies. If not, then it must have been defined in types.hal.
472 //
473 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800474 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700475 // above applies.
476
477 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800478 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700479 for (const auto &importedAST : mImportedASTs) {
480 FQName matchingName;
481 Type *match = importedAST->findDefinedType(ifc, &matchingName);
482 if (match != nullptr && match->isInterface()) {
483 resolvedType = match;
484 }
485 }
486 }
487
Andreas Huber39fa7182016-08-19 14:27:33 -0700488 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700489 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800490 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700491
Andreas Huber0e00de42016-08-03 09:56:02 -0700492 mImportedNames.insert(typesName);
493 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700494 // Do _not_ use fqName, i.e. the name we used to look up the type,
495 // but instead use the name of the interface we found.
496 // This is necessary because if fqName pointed to a typedef which
497 // in turn referenced the found interface we'd mistakenly use the
498 // name of the typedef instead of the proper name of the interface.
499
500 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700501 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700502 }
Andreas Huber737080b2016-08-02 15:38:04 -0700503 }
504
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700505 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700506}
507
Andreas Huber39fa7182016-08-19 14:27:33 -0700508Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700509 for (const auto &pair : mDefinedTypesByFullName) {
510 const FQName &key = pair.first;
511 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700512
Andreas Huber39fa7182016-08-19 14:27:33 -0700513 if (key.endsWith(fqName)) {
514 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700515 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700516 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700517 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700518
519 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700520}
521
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700522void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700523 for (const auto &fqName : mImportedNames) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800524 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700525
526 if (packageName == mPackage) {
527 // We only care about external imports, not our own package.
528 continue;
529 }
530
531 importSet->insert(packageName);
532 }
533}
534
Yifan Hong40a373d2016-11-30 15:16:47 -0800535void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
536 getImportedPackages(importSet);
537 std::set<FQName> newSet;
538 for (const auto &ast : mImportedASTs) {
539 if (importSet->find(ast->package()) != importSet->end()) {
540 ast->getImportedPackagesHierarchy(&newSet);
541 }
542 }
543 importSet->insert(newSet.begin(), newSet.end());
544}
545
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800546void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
547 for (const auto& name : mImportedNames) {
548 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700549 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800550 ast->getAllImportedNames(allImportNames);
551 }
552}
553
Andreas Huber0fa9e392016-08-31 09:05:44 -0700554bool AST::isJavaCompatible() const {
Steven Moreland19f11b52017-05-12 18:22:21 -0700555 if (!AST::isInterface()) {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700556 for (const auto* type : mRootScope.getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700557 if (!type->isJavaCompatible()) {
558 return false;
559 }
560 }
561
562 return true;
563 }
564
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700565 const Interface* iface = mRootScope.getInterface();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700566 return iface->isJavaCompatible();
567}
568
Andreas Huber019d21d2016-10-03 12:59:47 -0700569void AST::appendToExportedTypesVector(
570 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700571 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700572}
573
Yifan Hongc8934042016-11-17 17:10:52 -0800574bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700575 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800576 return iface != nullptr && iface->isIBase();
577}
578
Yifan Hong78b38d12017-02-13 18:14:46 +0000579const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700580 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000581}
582
Steven Moreland19f11b52017-05-12 18:22:21 -0700583std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700584 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700585
586 return iface ? iface->getBaseName() : "types";
587}
588
Andreas Huberc9410c72016-07-28 12:18:40 -0700589} // namespace android;