blob: b05c458de54d4ca210d67f95bf1429bede01d170 [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
Steven Moreland04dea8d2018-02-06 13:11:24 -080038AST::AST(const Coordinator* coordinator, const Hash* fileHash)
Andreas Huber5345ec22016-07-29 13:33:27 -070039 : mCoordinator(coordinator),
Steven Moreland04dea8d2018-02-06 13:11:24 -080040 mFileHash(fileHash),
41 mRootScope("(root scope)", FQName(), Location::startOf(fileHash->getPath()),
42 nullptr /* parent */) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070043
Neel Mehta693169b2019-05-29 18:45:25 -070044Scope* AST::getMutableRootScope() {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070045 return &mRootScope;
Andreas Huberc9410c72016-07-28 12:18:40 -070046}
47
Neel Mehta693169b2019-05-29 18:45:25 -070048const Scope& AST::getRootScope() const {
49 return mRootScope;
50}
51
Yifan Hongbe627b32016-10-28 18:38:56 -070052// used by the parser.
53void AST::addSyntaxError() {
54 mSyntaxErrors++;
55}
56
57size_t AST::syntaxErrors() const {
58 return mSyntaxErrors;
59}
60
Steven Moreland04dea8d2018-02-06 13:11:24 -080061const std::string& AST::getFilename() const {
62 return mFileHash->getPath();
63}
64const Hash* AST::getFileHash() const {
65 return mFileHash;
Andreas Huber0d0f9a22016-08-17 10:26:11 -070066}
67
Andreas Huber84f89de2016-07-28 15:39:51 -070068bool AST::setPackage(const char *package) {
Steven Morelande1b157e2018-03-06 14:18:32 -080069 if (!mPackage.setTo(package)) {
70 return false;
71 }
Andreas Huber84f89de2016-07-28 15:39:51 -070072
Andreas Huberda51b8e2016-07-28 16:00:57 -070073 if (mPackage.package().empty()
74 || mPackage.version().empty()
75 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070076 return false;
77 }
78
Andreas Huber84f89de2016-07-28 15:39:51 -070079 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070080}
81
Andreas Hubera2723d22016-07-29 15:36:07 -070082FQName AST::package() const {
83 return mPackage;
84}
85
Steven Moreland19f11b52017-05-12 18:22:21 -070086bool AST::isInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070087 return mRootScope.getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070088}
89
Steven Morelandb47a2622018-07-11 09:04:25 -070090bool AST::definesInterfaces() const {
91 return mRootScope.definesInterfaces();
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070092}
93
Timur Iskhakov33431e62017-08-21 17:31:23 -070094status_t AST::postParse() {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -070095 status_t err;
Timur Iskhakov82c048e2017-09-09 01:20:53 -070096
Yifan Hong0e192c42018-10-23 15:32:19 -070097 // lookupTypes is the first pass for references to be resolved.
Timur Iskhakov82c048e2017-09-09 01:20:53 -070098 err = lookupTypes();
99 if (err != OK) return err;
Yifan Hong0e192c42018-10-23 15:32:19 -0700100
101 // Indicate that all types are now in "postParse" stage.
102 err = setParseStage(Type::ParseStage::PARSE, Type::ParseStage::POST_PARSE);
103 if (err != OK) return err;
104
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700105 // validateDefinedTypesUniqueNames is the first call
106 // after lookup, as other errors could appear because
107 // user meant different type than we assumed.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700108 err = validateDefinedTypesUniqueNames();
109 if (err != OK) return err;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700110 // topologicalReorder is before resolveInheritance, as we
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700111 // need to have no cycle while getting parent class.
Timur Iskhakov458ca362017-09-12 23:16:03 -0700112 err = topologicalReorder();
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700113 if (err != OK) return err;
114 err = resolveInheritance();
115 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700116 err = lookupConstantExpressions();
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700117 if (err != OK) return err;
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700118 // checkAcyclicConstantExpressions is after resolveInheritance,
119 // as resolveInheritance autofills enum values.
120 err = checkAcyclicConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700121 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700122 err = validateConstantExpressions();
123 if (err != OK) return err;
124 err = evaluateConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700125 if (err != OK) return err;
126 err = validate();
127 if (err != OK) return err;
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700128 err = checkForwardReferenceRestrictions();
129 if (err != OK) return err;
Andreas Huber308d8a22017-11-06 14:46:52 -0800130 err = gatherReferencedTypes();
131 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -0700132
Timur Iskhakov35930c42017-08-28 18:49:54 -0700133 // Make future packages not to call passes
134 // for processed types and expressions
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700135 constantExpressionRecursivePass(
136 [](ConstantExpression* ce) {
137 ce->setPostParseCompleted();
138 return OK;
139 },
140 true /* processBeforeDependencies */);
Yifan Hong0e192c42018-10-23 15:32:19 -0700141
142 err = setParseStage(Type::ParseStage::POST_PARSE, Type::ParseStage::COMPLETED);
143 if (err != OK) return err;
Timur Iskhakov35930c42017-08-28 18:49:54 -0700144
Timur Iskhakov33431e62017-08-21 17:31:23 -0700145 return OK;
146}
147
Timur Iskhakov891a8662017-08-25 21:53:48 -0700148status_t AST::constantExpressionRecursivePass(
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700149 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700150 std::unordered_set<const Type*> visitedTypes;
151 std::unordered_set<const ConstantExpression*> visitedCE;
Yifan Hong0e192c42018-10-23 15:32:19 -0700152 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
153 [&](Type* type) -> status_t {
154 for (auto* ce : type->getConstantExpressions()) {
155 status_t err = ce->recursivePass(
156 func, &visitedCE, processBeforeDependencies);
157 if (err != OK) return err;
158 }
159 return OK;
160 },
161 &visitedTypes);
162}
163
Steven Moreland12f0ab12018-11-02 17:27:37 -0700164status_t AST::constantExpressionRecursivePass(
165 const std::function<status_t(const ConstantExpression*)>& func,
166 bool processBeforeDependencies) const {
167 std::unordered_set<const Type*> visitedTypes;
168 std::unordered_set<const ConstantExpression*> visitedCE;
169 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
170 [&](const Type* type) -> status_t {
171 for (auto* ce : type->getConstantExpressions()) {
172 status_t err = ce->recursivePass(
173 func, &visitedCE, processBeforeDependencies);
174 if (err != OK) return err;
175 }
176 return OK;
177 },
178 &visitedTypes);
179}
180
Yifan Hong0e192c42018-10-23 15:32:19 -0700181status_t AST::setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage) {
182 std::unordered_set<const Type*> visited;
183 return mRootScope.recursivePass(oldStage,
184 [oldStage, newStage](Type* type) {
185 CHECK(type->getParseStage() == oldStage);
186 type->setParseStage(newStage);
187 return OK;
188 },
189 &visited);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700190}
191
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700192status_t AST::lookupTypes() {
193 std::unordered_set<const Type*> visited;
194 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700195 Type::ParseStage::PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700196 [&](Type* type) -> status_t {
197 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
198
199 for (auto* nextRef : type->getReferences()) {
Andreas Huber308d8a22017-11-06 14:46:52 -0800200 if (nextRef->isResolved()) {
201 continue;
202 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700203
204 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
205 if (nextType == nullptr) {
206 std::cerr << "ERROR: Failed to lookup type '"
207 << nextRef->getLookupFqName().string() << "' at "
208 << nextRef->location() << "\n";
209 return UNKNOWN_ERROR;
210 }
211 nextRef->set(nextType);
212 }
213
214 return OK;
215 },
216 &visited);
217}
218
Andreas Huber308d8a22017-11-06 14:46:52 -0800219status_t AST::gatherReferencedTypes() {
220 std::unordered_set<const Type*> visited;
221 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700222 Type::ParseStage::POST_PARSE,
Andreas Huber308d8a22017-11-06 14:46:52 -0800223 [&](Type* type) -> status_t {
224 for (auto* nextRef : type->getReferences()) {
225 const Type *targetType = nextRef->get();
226 if (targetType->isNamedType()) {
227 mReferencedTypeNames.insert(
228 static_cast<const NamedType *>(targetType)->fqName());
229 }
230 }
231
232 return OK;
233 },
234 &visited);
235}
236
Steven Moreland12f0ab12018-11-02 17:27:37 -0700237status_t AST::lookupConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700238 std::unordered_set<const Type*> visitedTypes;
239 std::unordered_set<const ConstantExpression*> visitedCE;
240
241 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700242 Type::ParseStage::POST_PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700243 [&](Type* type) -> status_t {
244 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
245
246 for (auto* ce : type->getConstantExpressions()) {
247 status_t err = ce->recursivePass(
248 [&](ConstantExpression* ce) {
249 for (auto* nextRef : ce->getReferences()) {
250 if (nextRef->isResolved()) continue;
251
252 LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope);
253 if (iden == nullptr) return UNKNOWN_ERROR;
254 nextRef->set(iden);
255 }
Steven Moreland12f0ab12018-11-02 17:27:37 -0700256 for (auto* nextRef : ce->getTypeReferences()) {
257 if (nextRef->isResolved()) continue;
258
259 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
260 if (nextType == nullptr) {
261 std::cerr << "ERROR: Failed to lookup type '"
262 << nextRef->getLookupFqName().string() << "' at "
263 << nextRef->location() << "\n";
264 return UNKNOWN_ERROR;
265 }
266 nextRef->set(nextType);
267 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700268 return OK;
269 },
270 &visitedCE, true /* processBeforeDependencies */);
271 if (err != OK) return err;
272 }
273
274 return OK;
275 },
276 &visitedTypes);
277}
278
Timur Iskhakov565b0132017-09-06 18:07:11 -0700279status_t AST::validateDefinedTypesUniqueNames() const {
280 std::unordered_set<const Type*> visited;
281 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700282 Type::ParseStage::POST_PARSE,
Timur Iskhakov565b0132017-09-06 18:07:11 -0700283 [&](const Type* type) -> status_t {
284 // We only want to validate type definition names in this place.
285 if (type->isScope()) {
286 return static_cast<const Scope*>(type)->validateUniqueNames();
287 }
288 return OK;
289 },
290 &visited);
291}
292
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700293status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700294 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700295 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::resolveInheritance,
296 &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700297}
298
Steven Moreland12f0ab12018-11-02 17:27:37 -0700299status_t AST::validateConstantExpressions() const {
300 return constantExpressionRecursivePass(
301 [](const ConstantExpression* ce) { return ce->validate(); },
302 true /* processBeforeDependencies */);
303}
304
305status_t AST::evaluateConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700306 return constantExpressionRecursivePass(
307 [](ConstantExpression* ce) {
308 ce->evaluate();
309 return OK;
310 },
311 false /* processBeforeDependencies */);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700312}
313
314status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700315 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700316 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700317}
318
Timur Iskhakov458ca362017-09-12 23:16:03 -0700319status_t AST::topologicalReorder() {
320 std::unordered_map<const Type*, size_t> reversedOrder;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700321 std::unordered_set<const Type*> stack;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700322 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
323 if (err != OK) return err;
324
325 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700326 mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
327 [&](Type* type) {
328 if (type->isScope()) {
329 static_cast<Scope*>(type)->topologicalReorder(reversedOrder);
330 }
331 return OK;
332 },
333 &visited);
Timur Iskhakov458ca362017-09-12 23:16:03 -0700334 return OK;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700335}
336
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700337status_t AST::checkAcyclicConstantExpressions() const {
338 std::unordered_set<const Type*> visitedTypes;
339 std::unordered_set<const ConstantExpression*> visitedCE;
340 std::unordered_set<const ConstantExpression*> stack;
Yifan Hong0e192c42018-10-23 15:32:19 -0700341 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
342 [&](const Type* type) -> status_t {
343 for (auto* ce : type->getConstantExpressions()) {
344 status_t err =
345 ce->checkAcyclic(&visitedCE, &stack).status;
346 CHECK(err != OK || stack.empty());
347 if (err != OK) return err;
348 }
349 return OK;
350 },
351 &visitedTypes);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700352}
353
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700354status_t AST::checkForwardReferenceRestrictions() const {
355 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700356 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
357 [](const Type* type) -> status_t {
358 for (const Reference<Type>* ref : type->getReferences()) {
359 status_t err =
360 type->checkForwardReferenceRestrictions(*ref);
361 if (err != OK) return err;
362 }
363 return OK;
364 },
365 &visited);
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700366}
367
Andreas Huber5345ec22016-07-29 13:33:27 -0700368bool AST::addImport(const char *import) {
Steven Morelande1b157e2018-03-06 14:18:32 -0800369 FQName fqName;
370 if (!FQName::parse(import, &fqName)) {
Steven Moreland01857a32018-01-03 10:15:01 -0800371 std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
372 return false;
373 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700374
Andreas Huber5345ec22016-07-29 13:33:27 -0700375 fqName.applyDefaults(mPackage.package(), mPackage.version());
376
Andreas Huber5345ec22016-07-29 13:33:27 -0700377 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700378 // import a package
Andreas Huber4ba5c972017-11-29 11:06:25 -0800379
Andreas Huberd2943e12016-08-05 11:59:31 -0700380 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700381
Andreas Huberd2943e12016-08-05 11:59:31 -0700382 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700383 mCoordinator->appendPackageInterfacesToVector(fqName,
384 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700385
386 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700387 return false;
388 }
389
Andreas Huberd2943e12016-08-05 11:59:31 -0700390 for (const auto &subFQName : packageInterfaces) {
Andreas Huber4ba5c972017-11-29 11:06:25 -0800391 addToImportedNamesGranular(subFQName);
392
Yifan Hongf619fc72017-04-07 15:40:06 -0700393 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700394 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700395 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700396 return false;
397 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700398 // all previous single type imports are ignored.
399 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700400 }
401
402 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700403 }
404
Andreas Huber4ba5c972017-11-29 11:06:25 -0800405 addToImportedNamesGranular(fqName);
406
Yifan Hong1977ea32016-10-05 12:49:08 -0700407 // cases like android.hardware.foo@1.0::IFoo.Internal
408 // android.hardware.foo@1.0::Abc.Internal
409
410 // assume it is an interface, and try to import it.
411 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700412 // Do not enforce restrictions on imports.
Steven Moreland71f09132018-02-20 12:24:30 -0800413 AST* importAST;
414 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
415 Coordinator::Enforce::NONE);
416 if (err != OK) return false;
417 // importAST nullptr == file doesn't exist
Yifan Hong1977ea32016-10-05 12:49:08 -0700418
419 if (importAST != nullptr) {
420 // cases like android.hardware.foo@1.0::IFoo.Internal
421 // and android.hardware.foo@1.0::IFoo
422 if (fqName == interfaceName) {
423 // import a single file.
424 // all previous single type imports are ignored.
425 // cases like android.hardware.foo@1.0::IFoo
426 // and android.hardware.foo@1.0::types
427 mImportedTypes.erase(importAST);
428 return true;
429 }
430
431 // import a single type from this file
432 // cases like android.hardware.foo@1.0::IFoo.Internal
433 FQName matchingName;
434 Type *match = importAST->findDefinedType(fqName, &matchingName);
435 if (match == nullptr) {
436 return false;
437 }
438 // will automatically create a set if it does not exist
439 mImportedTypes[importAST].insert(match);
440 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700441 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700442
Yifan Hong1977ea32016-10-05 12:49:08 -0700443 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
444 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700445
446 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700447 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700448
449 if (importAST != nullptr) {
450 // Attempt to find Abc.Internal in types.
451 FQName matchingName;
452 Type *match = importAST->findDefinedType(fqName, &matchingName);
453 if (match == nullptr) {
454 return false;
455 }
456 // will automatically create a set if not exist
457 mImportedTypes[importAST].insert(match);
458 return true;
459 }
460
461 // can't find an appropriate AST for fqName.
462 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700463}
464
Andreas Huber39fa7182016-08-19 14:27:33 -0700465void AST::addImportedAST(AST *ast) {
466 mImportedASTs.insert(ast);
467}
468
Timur Iskhakov565b0132017-09-06 18:07:11 -0700469FQName AST::makeFullName(const char* localName, Scope* scope) const {
470 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700471 for (; scope != &mRootScope; scope = scope->parent()) {
472 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700473 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700474
475 std::reverse(pathComponents.begin(), pathComponents.end());
476 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700477
Timur Iskhakov565b0132017-09-06 18:07:11 -0700478 return FQName(mPackage.package(), mPackage.version(), path);
479}
Andreas Huber39fa7182016-08-19 14:27:33 -0700480
Timur Iskhakov565b0132017-09-06 18:07:11 -0700481void AST::addScopedType(NamedType* type, Scope* scope) {
482 scope->addType(type);
483 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700484}
485
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700486LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) {
487 const FQName& fqName = ref.getLookupFqName();
488
489 if (fqName.isIdentifier()) {
490 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
491 if (iden == nullptr) {
492 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
493 << ref.location() << "\n";
494 return nullptr;
495 }
496 return iden;
497 } else {
498 std::string errorMsg;
499 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
500 if (enumValue == nullptr) {
501 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
502 return nullptr;
503 }
504 return enumValue;
505 }
506}
507
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700508EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700509 FQName enumTypeName = fqName.typeName();
510 std::string enumValueName = fqName.valueName();
511
Yifan Hongf24fa852016-09-23 11:03:15 -0700512 CHECK(!enumValueName.empty());
513
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700514 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700515 if(type == nullptr) {
516 *errorMsg = "Cannot find type " + enumTypeName.string();
517 return nullptr;
518 }
Steven Morelandd965ce92017-11-27 16:05:34 -0800519 type = type->resolve();
Yifan Hongf24fa852016-09-23 11:03:15 -0700520 if(!type->isEnum()) {
521 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
522 return nullptr;
523 }
524
525 EnumType *enumType = static_cast<EnumType *>(type);
526 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
527 if(v == nullptr) {
528 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
529 return nullptr;
530 }
Andreas Huber4ba5c972017-11-29 11:06:25 -0800531
532 mReferencedTypeNames.insert(enumType->fqName());
533
Yifan Hongf24fa852016-09-23 11:03:15 -0700534 return v;
535}
536
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700537Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700538 if (fqName.name().empty()) {
539 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700540 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700541 }
542
Yifan Hong87ff8232017-01-09 12:07:05 -0800543 Type *returnedType = nullptr;
544
Andreas Huber84f89de2016-07-28 15:39:51 -0700545 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800546 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700547 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800548 if (returnedType != nullptr) {
549 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700550 }
551 }
552
Steven Moreland87e69dc2017-09-12 18:14:28 -0700553 status_t status = lookupAutofilledType(fqName, &returnedType);
554 if (status != OK) {
555 return nullptr;
556 }
557 if (returnedType != nullptr) {
558 return returnedType;
Yifan Hong87ff8232017-01-09 12:07:05 -0800559 }
560
561 return lookupTypeFromImports(fqName);
562}
563
564// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700565Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800566 CHECK(fqName.package().empty() && fqName.version().empty()
567 && !fqName.name().empty() && fqName.valueName().empty());
568
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700569 for (; scope != nullptr; scope = scope->parent()) {
570 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800571 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800572 return type;
573 }
574 }
575
576 return nullptr;
577}
578
579// Rule 1: auto-fill with current package
580status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
Steven Moreland87e69dc2017-09-12 18:14:28 -0700581 CHECK(!fqName.name().empty() && fqName.valueName().empty());
Yifan Hong87ff8232017-01-09 12:07:05 -0800582
583 FQName autofilled = fqName;
584 autofilled.applyDefaults(mPackage.package(), mPackage.version());
585 FQName matchingName;
586 // Given this fully-qualified name, the type may be defined in this AST, or other files
587 // in import.
588 Type *local = findDefinedType(autofilled, &matchingName);
589 CHECK(local == nullptr || autofilled == matchingName);
Steven Moreland87e69dc2017-09-12 18:14:28 -0700590 Type* fromImport = lookupTypeFromImports(autofilled);
Yifan Hong87ff8232017-01-09 12:07:05 -0800591
592 if (local != nullptr && fromImport != nullptr && local != fromImport) {
593 // Something bad happen; two types have the same FQName.
594 std::cerr << "ERROR: Unable to resolve type name '"
595 << fqName.string()
596 << "' (i.e. '"
597 << autofilled.string()
598 << "'), multiple definitions found.\n";
599
600 return UNKNOWN_ERROR;
601 }
602 if (local != nullptr) {
603 *returnedType = local;
604 return OK;
605 }
606 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
607 *returnedType = fromImport;
608 return OK;
609}
610
611// Rule 2: look at imports
612Type *AST::lookupTypeFromImports(const FQName &fqName) {
613
Andreas Huber39fa7182016-08-19 14:27:33 -0700614 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700615 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700616 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700617
Andreas Huber39fa7182016-08-19 14:27:33 -0700618 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700619 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
620 // ignore single type imports
621 continue;
622 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700623 FQName matchingName;
624 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700625
Andreas Huber39fa7182016-08-19 14:27:33 -0700626 if (match != nullptr) {
627 if (resolvedType != nullptr) {
628 std::cerr << "ERROR: Unable to resolve type name '"
629 << fqName.string()
630 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700631
Andreas Huber39fa7182016-08-19 14:27:33 -0700632 std::cerr << " " << resolvedName.string() << "\n";
633 std::cerr << " " << matchingName.string() << "\n";
634
Yifan Hong1977ea32016-10-05 12:49:08 -0700635 return nullptr;
636 }
637
638 resolvedType = match;
639 returnedType = resolvedType;
640 resolvedName = matchingName;
641
642 // Keep going even after finding a match.
643 }
644 }
645
646 for (const auto &pair : mImportedTypes) {
647 AST *importedAST = pair.first;
648 std::set<Type *> importedTypes = pair.second;
649
650 FQName matchingName;
651 Type *match = importedAST->findDefinedType(fqName, &matchingName);
652 if (match != nullptr &&
653 importedTypes.find(match) != importedTypes.end()) {
654 if (resolvedType != nullptr) {
655 std::cerr << "ERROR: Unable to resolve type name '"
656 << fqName.string()
657 << "', multiple matches found:\n";
658
659 std::cerr << " " << resolvedName.string() << "\n";
660 std::cerr << " " << matchingName.string() << "\n";
661
662 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700663 }
664
665 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700666 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700667 resolvedName = matchingName;
668
669 // Keep going even after finding a match.
670 }
671 }
672
673 if (resolvedType) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700674 returnedType = resolvedType;
675
676 // If the resolved type is not an interface, we need to determine
677 // whether it is defined in types.hal, or in some other interface. In
678 // the latter case, we need to emit a dependency for the interface in
679 // which the type is defined.
680 //
681 // Consider the following:
682 // android.hardware.tests.foo@1.0::Record
683 // android.hardware.tests.foo@1.0::IFoo.Folder
684 // android.hardware.tests.foo@1.0::Folder
685 //
686 // If Record is an interface, then we keep track of it for the purpose
687 // of emitting dependencies in the target language (for example #include
688 // in C++). If Record is a UDT, then we assume it is defined in
689 // types.hal in android.hardware.tests.foo@1.0.
690 //
691 // In the case of IFoo.Folder, the same applies. If IFoo is an
692 // interface, we need to track this for the purpose of emitting
693 // dependencies. If not, then it must have been defined in types.hal.
694 //
695 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800696 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700697 // above applies.
698
699 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800700 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700701 for (const auto &importedAST : mImportedASTs) {
702 FQName matchingName;
703 Type *match = importedAST->findDefinedType(ifc, &matchingName);
704 if (match != nullptr && match->isInterface()) {
705 resolvedType = match;
706 }
707 }
708 }
709
Andreas Huber39fa7182016-08-19 14:27:33 -0700710 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700711 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800712 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700713
Andreas Huber0e00de42016-08-03 09:56:02 -0700714 mImportedNames.insert(typesName);
715 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700716 // Do _not_ use fqName, i.e. the name we used to look up the type,
717 // but instead use the name of the interface we found.
718 // This is necessary because if fqName pointed to a typedef which
719 // in turn referenced the found interface we'd mistakenly use the
720 // name of the typedef instead of the proper name of the interface.
721
Andreas Huber4ba5c972017-11-29 11:06:25 -0800722 const FQName &typeName =
723 static_cast<Interface *>(resolvedType)->fqName();
724
725 mImportedNames.insert(typeName);
Andreas Huber0e00de42016-08-03 09:56:02 -0700726 }
Andreas Huber737080b2016-08-02 15:38:04 -0700727 }
728
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700729 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700730}
731
Andreas Huber4ba5c972017-11-29 11:06:25 -0800732void AST::addToImportedNamesGranular(const FQName &fqName) {
733 if (fqName.package() == package().package()
734 && fqName.version() == package().version()) {
735 // Our own names are _defined_ here, not imported.
736 return;
737 }
738
739 mImportedNamesGranular.insert(fqName);
740}
741
Andreas Huber39fa7182016-08-19 14:27:33 -0700742Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700743 for (const auto &pair : mDefinedTypesByFullName) {
744 const FQName &key = pair.first;
745 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700746
Andreas Huber39fa7182016-08-19 14:27:33 -0700747 if (key.endsWith(fqName)) {
748 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700749 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700750 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700751 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700752
753 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700754}
755
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700756void AST::getImportedPackages(std::set<FQName> *importSet) const {
Steven Moreland06a81cf2018-01-17 11:13:46 -0800757 for (const auto& fqName : mImportedNamesGranular) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800758 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700759
760 if (packageName == mPackage) {
761 // We only care about external imports, not our own package.
762 continue;
763 }
764
765 importSet->insert(packageName);
766 }
767}
768
Yifan Hong40a373d2016-11-30 15:16:47 -0800769void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
770 getImportedPackages(importSet);
Steven Moreland06a81cf2018-01-17 11:13:46 -0800771
Yifan Hong40a373d2016-11-30 15:16:47 -0800772 std::set<FQName> newSet;
773 for (const auto &ast : mImportedASTs) {
774 if (importSet->find(ast->package()) != importSet->end()) {
775 ast->getImportedPackagesHierarchy(&newSet);
776 }
777 }
778 importSet->insert(newSet.begin(), newSet.end());
779}
780
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800781void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
782 for (const auto& name : mImportedNames) {
783 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700784 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800785 ast->getAllImportedNames(allImportNames);
786 }
787}
788
Andreas Huber4ba5c972017-11-29 11:06:25 -0800789void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
790 for (const auto& fqName : mImportedNamesGranular) {
791 if (fqName.name() == "types") {
792 // A package will export everything _defined_ but will not
793 // re-export anything it itself imported.
794 AST* ast = mCoordinator->parse(
795 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
796
797 ast->addDefinedTypes(allImportNames);
798 } else {
799 allImportNames->insert(fqName);
800 }
801 }
802}
803
Andreas Huber0fa9e392016-08-31 09:05:44 -0700804bool AST::isJavaCompatible() const {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700805 return mRootScope.isJavaCompatible();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700806}
807
Andreas Huber019d21d2016-10-03 12:59:47 -0700808void AST::appendToExportedTypesVector(
809 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700810 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700811}
812
Yifan Hongc8934042016-11-17 17:10:52 -0800813bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700814 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800815 return iface != nullptr && iface->isIBase();
816}
817
Yifan Hong78b38d12017-02-13 18:14:46 +0000818const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700819 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000820}
821
Steven Moreland19f11b52017-05-12 18:22:21 -0700822std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700823 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700824
825 return iface ? iface->getBaseName() : "types";
826}
827
Andreas Huber308d8a22017-11-06 14:46:52 -0800828void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
829 std::for_each(
830 mDefinedTypesByFullName.begin(),
831 mDefinedTypesByFullName.end(),
832 [definedTypes](const auto &elem) {
833 if (!elem.second->isTypeDef()) {
834 definedTypes->insert(elem.first);
835 }
836 });
837}
838
839void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
840 std::for_each(
841 mReferencedTypeNames.begin(),
842 mReferencedTypeNames.end(),
843 [referencedTypes](const auto &fqName) {
844 referencedTypes->insert(fqName);
845 });
846}
847
Andreas Huberc9410c72016-07-28 12:18:40 -0700848} // namespace android;