blob: ed58a371f18bb0f96ccdc9010f2d5a2e5759622d [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),
Timur Iskhakov565b0132017-09-06 18:07:11 -070041 mRootScope("(root scope)", FQName(), 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() {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -070086 status_t err;
Timur Iskhakov565b0132017-09-06 18:07:11 -070087 // validateDefinedTypesUniqueNames is the first call,
88 // as other errors could appear because user meant
89 // different type than we assumed.
90 err = validateDefinedTypesUniqueNames();
91 if (err != OK) return err;
Timur Iskhakov77dd65c2017-08-31 22:46:56 -070092 // checkAcyclicTypes is before resolveInheritance, as we
93 // need to have no cycle while getting parent class.
94 err = checkAcyclicTypes();
95 if (err != OK) return err;
96 err = resolveInheritance();
97 if (err != OK) return err;
98 // checkAcyclicConstantExpressions is after resolveInheritance,
99 // as resolveInheritance autofills enum values.
100 err = checkAcyclicConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700101 if (err != OK) return err;
102 err = evaluate();
103 if (err != OK) return err;
104 err = validate();
105 if (err != OK) return err;
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700106 err = checkForwardReferenceRestrictions();
107 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -0700108
Timur Iskhakov35930c42017-08-28 18:49:54 -0700109 // Make future packages not to call passes
110 // for processed types and expressions
111 constantExpressionRecursivePass([](ConstantExpression* ce) {
112 ce->setPostParseCompleted();
113 return OK;
114 });
115 std::unordered_set<const Type*> visited;
116 mRootScope.recursivePass(
117 [](Type* type) {
118 type->setPostParseCompleted();
119 return OK;
120 },
121 &visited);
122
Timur Iskhakov33431e62017-08-21 17:31:23 -0700123 return OK;
124}
125
Timur Iskhakov891a8662017-08-25 21:53:48 -0700126status_t AST::constantExpressionRecursivePass(
127 const std::function<status_t(ConstantExpression*)>& func) {
128 std::unordered_set<const Type*> visitedTypes;
129 std::unordered_set<const ConstantExpression*> visitedCE;
130 return mRootScope.recursivePass(
131 [&](Type* type) -> status_t {
132 for (auto* ce : type->getConstantExpressions()) {
133 status_t err = ce->recursivePass(func, &visitedCE);
134 if (err != OK) return err;
135 }
136 return OK;
137 },
138 &visitedTypes);
139}
140
Timur Iskhakov565b0132017-09-06 18:07:11 -0700141status_t AST::validateDefinedTypesUniqueNames() const {
142 std::unordered_set<const Type*> visited;
143 return mRootScope.recursivePass(
144 [&](const Type* type) -> status_t {
145 // We only want to validate type definition names in this place.
146 if (type->isScope()) {
147 return static_cast<const Scope*>(type)->validateUniqueNames();
148 }
149 return OK;
150 },
151 &visited);
152}
153
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700154status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700155 std::unordered_set<const Type*> visited;
156 return mRootScope.recursivePass(&Type::resolveInheritance, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700157}
158
159status_t AST::evaluate() {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700160 return constantExpressionRecursivePass([](ConstantExpression* ce) {
161 ce->evaluate();
162 return OK;
163 });
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700164}
165
166status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700167 std::unordered_set<const Type*> visited;
168 return mRootScope.recursivePass(&Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700169}
170
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700171status_t AST::checkAcyclicTypes() const {
Timur Iskhakov40731af2017-08-24 14:18:35 -0700172 std::unordered_set<const Type*> visited;
173 std::unordered_set<const Type*> stack;
174 return mRootScope.checkAcyclic(&visited, &stack).status;
175}
176
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700177status_t AST::checkAcyclicConstantExpressions() const {
178 std::unordered_set<const Type*> visitedTypes;
179 std::unordered_set<const ConstantExpression*> visitedCE;
180 std::unordered_set<const ConstantExpression*> stack;
181 return mRootScope.recursivePass(
182 [&](const Type* type) -> status_t {
183 for (auto* ce : type->getConstantExpressions()) {
184 status_t err = ce->checkAcyclic(&visitedCE, &stack).status;
185 CHECK(err != OK || stack.empty());
186 if (err != OK) return err;
187 }
188 return OK;
189 },
190 &visitedTypes);
191}
192
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700193status_t AST::checkForwardReferenceRestrictions() const {
194 std::unordered_set<const Type*> visited;
195 return mRootScope.recursivePass(
196 [](const Type* type) -> status_t {
197 for (const Reference<Type>* ref : type->getReferences()) {
198 status_t err = type->checkForwardReferenceRestrictions(*ref);
199 if (err != OK) return err;
200 }
201 return OK;
202 },
203 &visited);
204}
205
Andreas Huber5345ec22016-07-29 13:33:27 -0700206bool AST::addImport(const char *import) {
207 FQName fqName(import);
208 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -0700209
Andreas Huber5345ec22016-07-29 13:33:27 -0700210 fqName.applyDefaults(mPackage.package(), mPackage.version());
211
Andreas Huber68f24592016-07-29 14:53:48 -0700212 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -0700213
214 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700215 // import a package
Andreas Huberd2943e12016-08-05 11:59:31 -0700216 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700217
Andreas Huberd2943e12016-08-05 11:59:31 -0700218 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700219 mCoordinator->appendPackageInterfacesToVector(fqName,
220 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700221
222 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700223 return false;
224 }
225
Andreas Huberd2943e12016-08-05 11:59:31 -0700226 for (const auto &subFQName : packageInterfaces) {
Yifan Hongf619fc72017-04-07 15:40:06 -0700227 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700228 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700229 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700230 return false;
231 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700232 // all previous single type imports are ignored.
233 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700234 }
235
236 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700237 }
238
Yifan Hong1977ea32016-10-05 12:49:08 -0700239 AST *importAST;
Andreas Huber5345ec22016-07-29 13:33:27 -0700240
Yifan Hong1977ea32016-10-05 12:49:08 -0700241 // cases like android.hardware.foo@1.0::IFoo.Internal
242 // android.hardware.foo@1.0::Abc.Internal
243
244 // assume it is an interface, and try to import it.
245 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700246 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700247 importAST = mCoordinator->parse(interfaceName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700248
249 if (importAST != nullptr) {
250 // cases like android.hardware.foo@1.0::IFoo.Internal
251 // and android.hardware.foo@1.0::IFoo
252 if (fqName == interfaceName) {
253 // import a single file.
254 // all previous single type imports are ignored.
255 // cases like android.hardware.foo@1.0::IFoo
256 // and android.hardware.foo@1.0::types
257 mImportedTypes.erase(importAST);
258 return true;
259 }
260
261 // import a single type from this file
262 // cases like android.hardware.foo@1.0::IFoo.Internal
263 FQName matchingName;
264 Type *match = importAST->findDefinedType(fqName, &matchingName);
265 if (match == nullptr) {
266 return false;
267 }
268 // will automatically create a set if it does not exist
269 mImportedTypes[importAST].insert(match);
270 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700271 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700272
Yifan Hong1977ea32016-10-05 12:49:08 -0700273 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
274 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700275
276 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700277 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700278
279 if (importAST != nullptr) {
280 // Attempt to find Abc.Internal in types.
281 FQName matchingName;
282 Type *match = importAST->findDefinedType(fqName, &matchingName);
283 if (match == nullptr) {
284 return false;
285 }
286 // will automatically create a set if not exist
287 mImportedTypes[importAST].insert(match);
288 return true;
289 }
290
291 // can't find an appropriate AST for fqName.
292 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700293}
294
Andreas Huber39fa7182016-08-19 14:27:33 -0700295void AST::addImportedAST(AST *ast) {
296 mImportedASTs.insert(ast);
297}
298
Timur Iskhakov565b0132017-09-06 18:07:11 -0700299FQName AST::makeFullName(const char* localName, Scope* scope) const {
300 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700301 for (; scope != &mRootScope; scope = scope->parent()) {
302 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700303 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700304
305 std::reverse(pathComponents.begin(), pathComponents.end());
306 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700307
Timur Iskhakov565b0132017-09-06 18:07:11 -0700308 return FQName(mPackage.package(), mPackage.version(), path);
309}
Andreas Huber39fa7182016-08-19 14:27:33 -0700310
Timur Iskhakov565b0132017-09-06 18:07:11 -0700311void AST::addScopedType(NamedType* type, Scope* scope) {
312 scope->addType(type);
313 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700314}
315
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700316EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700317 FQName enumTypeName = fqName.typeName();
318 std::string enumValueName = fqName.valueName();
319
320 CHECK(enumTypeName.isValid());
321 CHECK(!enumValueName.empty());
322
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700323 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700324 if(type == nullptr) {
325 *errorMsg = "Cannot find type " + enumTypeName.string();
326 return nullptr;
327 }
328 if(!type->isEnum()) {
329 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
330 return nullptr;
331 }
332
333 EnumType *enumType = static_cast<EnumType *>(type);
334 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
335 if(v == nullptr) {
336 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
337 return nullptr;
338 }
339 return v;
340}
341
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700342Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700343 CHECK(fqName.isValid());
344
Andreas Huberda51b8e2016-07-28 16:00:57 -0700345 if (fqName.name().empty()) {
346 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700347 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700348 }
349
Yifan Hong87ff8232017-01-09 12:07:05 -0800350 Type *returnedType = nullptr;
351
Andreas Huber84f89de2016-07-28 15:39:51 -0700352 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800353 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700354 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800355 if (returnedType != nullptr) {
356 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700357 }
358 }
359
Yifan Hong87ff8232017-01-09 12:07:05 -0800360 if (!fqName.isFullyQualified()) {
361 status_t status = lookupAutofilledType(fqName, &returnedType);
362 if (status != OK) {
363 return nullptr;
364 }
365 if (returnedType != nullptr) {
366 return returnedType;
367 }
368 }
369
370 return lookupTypeFromImports(fqName);
371}
372
373// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700374Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800375 CHECK(fqName.package().empty() && fqName.version().empty()
376 && !fqName.name().empty() && fqName.valueName().empty());
377
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700378 for (; scope != nullptr; scope = scope->parent()) {
379 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800380 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800381 return type;
382 }
383 }
384
385 return nullptr;
386}
387
388// Rule 1: auto-fill with current package
389status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
390 CHECK(!fqName.isFullyQualified() && !fqName.name().empty() && fqName.valueName().empty());
391
392 FQName autofilled = fqName;
393 autofilled.applyDefaults(mPackage.package(), mPackage.version());
394 FQName matchingName;
395 // Given this fully-qualified name, the type may be defined in this AST, or other files
396 // in import.
397 Type *local = findDefinedType(autofilled, &matchingName);
398 CHECK(local == nullptr || autofilled == matchingName);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700399 Type* fromImport = lookupType(autofilled, nullptr /* scope */);
Yifan Hong87ff8232017-01-09 12:07:05 -0800400
401 if (local != nullptr && fromImport != nullptr && local != fromImport) {
402 // Something bad happen; two types have the same FQName.
403 std::cerr << "ERROR: Unable to resolve type name '"
404 << fqName.string()
405 << "' (i.e. '"
406 << autofilled.string()
407 << "'), multiple definitions found.\n";
408
409 return UNKNOWN_ERROR;
410 }
411 if (local != nullptr) {
412 *returnedType = local;
413 return OK;
414 }
415 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
416 *returnedType = fromImport;
417 return OK;
418}
419
420// Rule 2: look at imports
421Type *AST::lookupTypeFromImports(const FQName &fqName) {
422
Andreas Huber39fa7182016-08-19 14:27:33 -0700423 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700424 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700425 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700426
Andreas Huber39fa7182016-08-19 14:27:33 -0700427 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700428 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
429 // ignore single type imports
430 continue;
431 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700432 FQName matchingName;
433 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700434
Andreas Huber39fa7182016-08-19 14:27:33 -0700435 if (match != nullptr) {
436 if (resolvedType != nullptr) {
437 std::cerr << "ERROR: Unable to resolve type name '"
438 << fqName.string()
439 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700440
Andreas Huber39fa7182016-08-19 14:27:33 -0700441 std::cerr << " " << resolvedName.string() << "\n";
442 std::cerr << " " << matchingName.string() << "\n";
443
Yifan Hong1977ea32016-10-05 12:49:08 -0700444 return nullptr;
445 }
446
447 resolvedType = match;
448 returnedType = resolvedType;
449 resolvedName = matchingName;
450
451 // Keep going even after finding a match.
452 }
453 }
454
455 for (const auto &pair : mImportedTypes) {
456 AST *importedAST = pair.first;
457 std::set<Type *> importedTypes = pair.second;
458
459 FQName matchingName;
460 Type *match = importedAST->findDefinedType(fqName, &matchingName);
461 if (match != nullptr &&
462 importedTypes.find(match) != importedTypes.end()) {
463 if (resolvedType != nullptr) {
464 std::cerr << "ERROR: Unable to resolve type name '"
465 << fqName.string()
466 << "', multiple matches found:\n";
467
468 std::cerr << " " << resolvedName.string() << "\n";
469 std::cerr << " " << matchingName.string() << "\n";
470
471 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700472 }
473
474 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700475 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700476 resolvedName = matchingName;
477
478 // Keep going even after finding a match.
479 }
480 }
481
482 if (resolvedType) {
483#if 0
484 LOG(INFO) << "found '"
485 << resolvedName.string()
486 << "' after looking for '"
487 << fqName.string()
488 << "'.";
489#endif
490
Iliyan Malchev800273d2016-09-02 15:25:07 -0700491 returnedType = resolvedType;
492
493 // If the resolved type is not an interface, we need to determine
494 // whether it is defined in types.hal, or in some other interface. In
495 // the latter case, we need to emit a dependency for the interface in
496 // which the type is defined.
497 //
498 // Consider the following:
499 // android.hardware.tests.foo@1.0::Record
500 // android.hardware.tests.foo@1.0::IFoo.Folder
501 // android.hardware.tests.foo@1.0::Folder
502 //
503 // If Record is an interface, then we keep track of it for the purpose
504 // of emitting dependencies in the target language (for example #include
505 // in C++). If Record is a UDT, then we assume it is defined in
506 // types.hal in android.hardware.tests.foo@1.0.
507 //
508 // In the case of IFoo.Folder, the same applies. If IFoo is an
509 // interface, we need to track this for the purpose of emitting
510 // dependencies. If not, then it must have been defined in types.hal.
511 //
512 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800513 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700514 // above applies.
515
516 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800517 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700518 for (const auto &importedAST : mImportedASTs) {
519 FQName matchingName;
520 Type *match = importedAST->findDefinedType(ifc, &matchingName);
521 if (match != nullptr && match->isInterface()) {
522 resolvedType = match;
523 }
524 }
525 }
526
Andreas Huber39fa7182016-08-19 14:27:33 -0700527 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700528 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800529 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700530
Andreas Huber0e00de42016-08-03 09:56:02 -0700531 mImportedNames.insert(typesName);
532 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700533 // Do _not_ use fqName, i.e. the name we used to look up the type,
534 // but instead use the name of the interface we found.
535 // This is necessary because if fqName pointed to a typedef which
536 // in turn referenced the found interface we'd mistakenly use the
537 // name of the typedef instead of the proper name of the interface.
538
539 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700540 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700541 }
Andreas Huber737080b2016-08-02 15:38:04 -0700542 }
543
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700544 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700545}
546
Andreas Huber39fa7182016-08-19 14:27:33 -0700547Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700548 for (const auto &pair : mDefinedTypesByFullName) {
549 const FQName &key = pair.first;
550 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700551
Andreas Huber39fa7182016-08-19 14:27:33 -0700552 if (key.endsWith(fqName)) {
553 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700554 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700555 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700556 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700557
558 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700559}
560
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700561void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700562 for (const auto &fqName : mImportedNames) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800563 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700564
565 if (packageName == mPackage) {
566 // We only care about external imports, not our own package.
567 continue;
568 }
569
570 importSet->insert(packageName);
571 }
572}
573
Yifan Hong40a373d2016-11-30 15:16:47 -0800574void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
575 getImportedPackages(importSet);
576 std::set<FQName> newSet;
577 for (const auto &ast : mImportedASTs) {
578 if (importSet->find(ast->package()) != importSet->end()) {
579 ast->getImportedPackagesHierarchy(&newSet);
580 }
581 }
582 importSet->insert(newSet.begin(), newSet.end());
583}
584
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800585void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
586 for (const auto& name : mImportedNames) {
587 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700588 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800589 ast->getAllImportedNames(allImportNames);
590 }
591}
592
Andreas Huber0fa9e392016-08-31 09:05:44 -0700593bool AST::isJavaCompatible() const {
Steven Moreland19f11b52017-05-12 18:22:21 -0700594 if (!AST::isInterface()) {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700595 for (const auto* type : mRootScope.getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700596 if (!type->isJavaCompatible()) {
597 return false;
598 }
599 }
600
601 return true;
602 }
603
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700604 const Interface* iface = mRootScope.getInterface();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700605 return iface->isJavaCompatible();
606}
607
Andreas Huber019d21d2016-10-03 12:59:47 -0700608void AST::appendToExportedTypesVector(
609 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700610 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700611}
612
Yifan Hongc8934042016-11-17 17:10:52 -0800613bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700614 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800615 return iface != nullptr && iface->isIBase();
616}
617
Yifan Hong78b38d12017-02-13 18:14:46 +0000618const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700619 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000620}
621
Steven Moreland19f11b52017-05-12 18:22:21 -0700622std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700623 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700624
625 return iface ? iface->getBaseName() : "types";
626}
627
Andreas Huberc9410c72016-07-28 12:18:40 -0700628} // namespace android;