blob: 834dc5a5d0eabfb316c71d4f97ddc898d82cabbd [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
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070044Scope* AST::getRootScope() {
45 return &mRootScope;
Andreas Huberc9410c72016-07-28 12:18:40 -070046}
47
Yifan Hongbe627b32016-10-28 18:38:56 -070048// used by the parser.
49void AST::addSyntaxError() {
50 mSyntaxErrors++;
51}
52
53size_t AST::syntaxErrors() const {
54 return mSyntaxErrors;
55}
56
Steven Moreland04dea8d2018-02-06 13:11:24 -080057const std::string& AST::getFilename() const {
58 return mFileHash->getPath();
59}
60const Hash* AST::getFileHash() const {
61 return mFileHash;
Andreas Huber0d0f9a22016-08-17 10:26:11 -070062}
63
Andreas Huber84f89de2016-07-28 15:39:51 -070064bool AST::setPackage(const char *package) {
Steven Morelande1b157e2018-03-06 14:18:32 -080065 if (!mPackage.setTo(package)) {
66 return false;
67 }
Andreas Huber84f89de2016-07-28 15:39:51 -070068
Andreas Huberda51b8e2016-07-28 16:00:57 -070069 if (mPackage.package().empty()
70 || mPackage.version().empty()
71 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070072 return false;
73 }
74
Andreas Huber84f89de2016-07-28 15:39:51 -070075 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070076}
77
Andreas Hubera2723d22016-07-29 15:36:07 -070078FQName AST::package() const {
79 return mPackage;
80}
81
Steven Moreland19f11b52017-05-12 18:22:21 -070082bool AST::isInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070083 return mRootScope.getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070084}
85
Steven Morelandb47a2622018-07-11 09:04:25 -070086bool AST::definesInterfaces() const {
87 return mRootScope.definesInterfaces();
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070088}
89
Timur Iskhakov33431e62017-08-21 17:31:23 -070090status_t AST::postParse() {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -070091 status_t err;
Timur Iskhakov82c048e2017-09-09 01:20:53 -070092
Yifan Hong0e192c42018-10-23 15:32:19 -070093 // lookupTypes is the first pass for references to be resolved.
Timur Iskhakov82c048e2017-09-09 01:20:53 -070094 err = lookupTypes();
95 if (err != OK) return err;
Yifan Hong0e192c42018-10-23 15:32:19 -070096
97 // Indicate that all types are now in "postParse" stage.
98 err = setParseStage(Type::ParseStage::PARSE, Type::ParseStage::POST_PARSE);
99 if (err != OK) return err;
100
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700101 // validateDefinedTypesUniqueNames is the first call
102 // after lookup, as other errors could appear because
103 // user meant different type than we assumed.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700104 err = validateDefinedTypesUniqueNames();
105 if (err != OK) return err;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700106 // topologicalReorder is before resolveInheritance, as we
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700107 // need to have no cycle while getting parent class.
Timur Iskhakov458ca362017-09-12 23:16:03 -0700108 err = topologicalReorder();
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700109 if (err != OK) return err;
110 err = resolveInheritance();
111 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700112 err = lookupConstantExpressions();
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700113 if (err != OK) return err;
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700114 // checkAcyclicConstantExpressions is after resolveInheritance,
115 // as resolveInheritance autofills enum values.
116 err = checkAcyclicConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700117 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700118 err = validateConstantExpressions();
119 if (err != OK) return err;
120 err = evaluateConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700121 if (err != OK) return err;
122 err = validate();
123 if (err != OK) return err;
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700124 err = checkForwardReferenceRestrictions();
125 if (err != OK) return err;
Andreas Huber308d8a22017-11-06 14:46:52 -0800126 err = gatherReferencedTypes();
127 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -0700128
Timur Iskhakov35930c42017-08-28 18:49:54 -0700129 // Make future packages not to call passes
130 // for processed types and expressions
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700131 constantExpressionRecursivePass(
132 [](ConstantExpression* ce) {
133 ce->setPostParseCompleted();
134 return OK;
135 },
136 true /* processBeforeDependencies */);
Yifan Hong0e192c42018-10-23 15:32:19 -0700137
138 err = setParseStage(Type::ParseStage::POST_PARSE, Type::ParseStage::COMPLETED);
139 if (err != OK) return err;
Timur Iskhakov35930c42017-08-28 18:49:54 -0700140
Timur Iskhakov33431e62017-08-21 17:31:23 -0700141 return OK;
142}
143
Timur Iskhakov891a8662017-08-25 21:53:48 -0700144status_t AST::constantExpressionRecursivePass(
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700145 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700146 std::unordered_set<const Type*> visitedTypes;
147 std::unordered_set<const ConstantExpression*> visitedCE;
Yifan Hong0e192c42018-10-23 15:32:19 -0700148 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
149 [&](Type* type) -> status_t {
150 for (auto* ce : type->getConstantExpressions()) {
151 status_t err = ce->recursivePass(
152 func, &visitedCE, processBeforeDependencies);
153 if (err != OK) return err;
154 }
155 return OK;
156 },
157 &visitedTypes);
158}
159
Steven Moreland12f0ab12018-11-02 17:27:37 -0700160status_t AST::constantExpressionRecursivePass(
161 const std::function<status_t(const ConstantExpression*)>& func,
162 bool processBeforeDependencies) const {
163 std::unordered_set<const Type*> visitedTypes;
164 std::unordered_set<const ConstantExpression*> visitedCE;
165 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
166 [&](const Type* type) -> status_t {
167 for (auto* ce : type->getConstantExpressions()) {
168 status_t err = ce->recursivePass(
169 func, &visitedCE, processBeforeDependencies);
170 if (err != OK) return err;
171 }
172 return OK;
173 },
174 &visitedTypes);
175}
176
Yifan Hong0e192c42018-10-23 15:32:19 -0700177status_t AST::setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage) {
178 std::unordered_set<const Type*> visited;
179 return mRootScope.recursivePass(oldStage,
180 [oldStage, newStage](Type* type) {
181 CHECK(type->getParseStage() == oldStage);
182 type->setParseStage(newStage);
183 return OK;
184 },
185 &visited);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700186}
187
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700188status_t AST::lookupTypes() {
189 std::unordered_set<const Type*> visited;
190 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700191 Type::ParseStage::PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700192 [&](Type* type) -> status_t {
193 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
194
195 for (auto* nextRef : type->getReferences()) {
Andreas Huber308d8a22017-11-06 14:46:52 -0800196 if (nextRef->isResolved()) {
197 continue;
198 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700199
200 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
201 if (nextType == nullptr) {
202 std::cerr << "ERROR: Failed to lookup type '"
203 << nextRef->getLookupFqName().string() << "' at "
204 << nextRef->location() << "\n";
205 return UNKNOWN_ERROR;
206 }
207 nextRef->set(nextType);
208 }
209
210 return OK;
211 },
212 &visited);
213}
214
Andreas Huber308d8a22017-11-06 14:46:52 -0800215status_t AST::gatherReferencedTypes() {
216 std::unordered_set<const Type*> visited;
217 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700218 Type::ParseStage::POST_PARSE,
Andreas Huber308d8a22017-11-06 14:46:52 -0800219 [&](Type* type) -> status_t {
220 for (auto* nextRef : type->getReferences()) {
221 const Type *targetType = nextRef->get();
222 if (targetType->isNamedType()) {
223 mReferencedTypeNames.insert(
224 static_cast<const NamedType *>(targetType)->fqName());
225 }
226 }
227
228 return OK;
229 },
230 &visited);
231}
232
Steven Moreland12f0ab12018-11-02 17:27:37 -0700233status_t AST::lookupConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700234 std::unordered_set<const Type*> visitedTypes;
235 std::unordered_set<const ConstantExpression*> visitedCE;
236
237 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700238 Type::ParseStage::POST_PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700239 [&](Type* type) -> status_t {
240 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
241
242 for (auto* ce : type->getConstantExpressions()) {
243 status_t err = ce->recursivePass(
244 [&](ConstantExpression* ce) {
245 for (auto* nextRef : ce->getReferences()) {
246 if (nextRef->isResolved()) continue;
247
248 LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope);
249 if (iden == nullptr) return UNKNOWN_ERROR;
250 nextRef->set(iden);
251 }
Steven Moreland12f0ab12018-11-02 17:27:37 -0700252 for (auto* nextRef : ce->getTypeReferences()) {
253 if (nextRef->isResolved()) continue;
254
255 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
256 if (nextType == nullptr) {
257 std::cerr << "ERROR: Failed to lookup type '"
258 << nextRef->getLookupFqName().string() << "' at "
259 << nextRef->location() << "\n";
260 return UNKNOWN_ERROR;
261 }
262 nextRef->set(nextType);
263 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700264 return OK;
265 },
266 &visitedCE, true /* processBeforeDependencies */);
267 if (err != OK) return err;
268 }
269
270 return OK;
271 },
272 &visitedTypes);
273}
274
Timur Iskhakov565b0132017-09-06 18:07:11 -0700275status_t AST::validateDefinedTypesUniqueNames() const {
276 std::unordered_set<const Type*> visited;
277 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700278 Type::ParseStage::POST_PARSE,
Timur Iskhakov565b0132017-09-06 18:07:11 -0700279 [&](const Type* type) -> status_t {
280 // We only want to validate type definition names in this place.
281 if (type->isScope()) {
282 return static_cast<const Scope*>(type)->validateUniqueNames();
283 }
284 return OK;
285 },
286 &visited);
287}
288
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700289status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700290 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700291 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::resolveInheritance,
292 &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700293}
294
Steven Moreland12f0ab12018-11-02 17:27:37 -0700295status_t AST::validateConstantExpressions() const {
296 return constantExpressionRecursivePass(
297 [](const ConstantExpression* ce) { return ce->validate(); },
298 true /* processBeforeDependencies */);
299}
300
301status_t AST::evaluateConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700302 return constantExpressionRecursivePass(
303 [](ConstantExpression* ce) {
304 ce->evaluate();
305 return OK;
306 },
307 false /* processBeforeDependencies */);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700308}
309
310status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700311 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700312 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700313}
314
Timur Iskhakov458ca362017-09-12 23:16:03 -0700315status_t AST::topologicalReorder() {
316 std::unordered_map<const Type*, size_t> reversedOrder;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700317 std::unordered_set<const Type*> stack;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700318 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
319 if (err != OK) return err;
320
321 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700322 mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
323 [&](Type* type) {
324 if (type->isScope()) {
325 static_cast<Scope*>(type)->topologicalReorder(reversedOrder);
326 }
327 return OK;
328 },
329 &visited);
Timur Iskhakov458ca362017-09-12 23:16:03 -0700330 return OK;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700331}
332
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700333status_t AST::checkAcyclicConstantExpressions() const {
334 std::unordered_set<const Type*> visitedTypes;
335 std::unordered_set<const ConstantExpression*> visitedCE;
336 std::unordered_set<const ConstantExpression*> stack;
Yifan Hong0e192c42018-10-23 15:32:19 -0700337 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
338 [&](const Type* type) -> status_t {
339 for (auto* ce : type->getConstantExpressions()) {
340 status_t err =
341 ce->checkAcyclic(&visitedCE, &stack).status;
342 CHECK(err != OK || stack.empty());
343 if (err != OK) return err;
344 }
345 return OK;
346 },
347 &visitedTypes);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700348}
349
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700350status_t AST::checkForwardReferenceRestrictions() const {
351 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700352 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
353 [](const Type* type) -> status_t {
354 for (const Reference<Type>* ref : type->getReferences()) {
355 status_t err =
356 type->checkForwardReferenceRestrictions(*ref);
357 if (err != OK) return err;
358 }
359 return OK;
360 },
361 &visited);
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700362}
363
Andreas Huber5345ec22016-07-29 13:33:27 -0700364bool AST::addImport(const char *import) {
Steven Morelande1b157e2018-03-06 14:18:32 -0800365 FQName fqName;
366 if (!FQName::parse(import, &fqName)) {
Steven Moreland01857a32018-01-03 10:15:01 -0800367 std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
368 return false;
369 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700370
Andreas Huber5345ec22016-07-29 13:33:27 -0700371 fqName.applyDefaults(mPackage.package(), mPackage.version());
372
Andreas Huber5345ec22016-07-29 13:33:27 -0700373 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700374 // import a package
Andreas Huber4ba5c972017-11-29 11:06:25 -0800375
Andreas Huberd2943e12016-08-05 11:59:31 -0700376 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700377
Andreas Huberd2943e12016-08-05 11:59:31 -0700378 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700379 mCoordinator->appendPackageInterfacesToVector(fqName,
380 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700381
382 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700383 return false;
384 }
385
Andreas Huberd2943e12016-08-05 11:59:31 -0700386 for (const auto &subFQName : packageInterfaces) {
Andreas Huber4ba5c972017-11-29 11:06:25 -0800387 addToImportedNamesGranular(subFQName);
388
Yifan Hongf619fc72017-04-07 15:40:06 -0700389 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700390 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700391 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700392 return false;
393 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700394 // all previous single type imports are ignored.
395 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700396 }
397
398 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700399 }
400
Andreas Huber4ba5c972017-11-29 11:06:25 -0800401 addToImportedNamesGranular(fqName);
402
Yifan Hong1977ea32016-10-05 12:49:08 -0700403 // cases like android.hardware.foo@1.0::IFoo.Internal
404 // android.hardware.foo@1.0::Abc.Internal
405
406 // assume it is an interface, and try to import it.
407 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700408 // Do not enforce restrictions on imports.
Steven Moreland71f09132018-02-20 12:24:30 -0800409 AST* importAST;
410 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
411 Coordinator::Enforce::NONE);
412 if (err != OK) return false;
413 // importAST nullptr == file doesn't exist
Yifan Hong1977ea32016-10-05 12:49:08 -0700414
415 if (importAST != nullptr) {
416 // cases like android.hardware.foo@1.0::IFoo.Internal
417 // and android.hardware.foo@1.0::IFoo
418 if (fqName == interfaceName) {
419 // import a single file.
420 // all previous single type imports are ignored.
421 // cases like android.hardware.foo@1.0::IFoo
422 // and android.hardware.foo@1.0::types
423 mImportedTypes.erase(importAST);
424 return true;
425 }
426
427 // import a single type from this file
428 // cases like android.hardware.foo@1.0::IFoo.Internal
429 FQName matchingName;
430 Type *match = importAST->findDefinedType(fqName, &matchingName);
431 if (match == nullptr) {
432 return false;
433 }
434 // will automatically create a set if it does not exist
435 mImportedTypes[importAST].insert(match);
436 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700437 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700438
Yifan Hong1977ea32016-10-05 12:49:08 -0700439 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
440 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700441
442 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700443 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700444
445 if (importAST != nullptr) {
446 // Attempt to find Abc.Internal in types.
447 FQName matchingName;
448 Type *match = importAST->findDefinedType(fqName, &matchingName);
449 if (match == nullptr) {
450 return false;
451 }
452 // will automatically create a set if not exist
453 mImportedTypes[importAST].insert(match);
454 return true;
455 }
456
457 // can't find an appropriate AST for fqName.
458 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700459}
460
Andreas Huber39fa7182016-08-19 14:27:33 -0700461void AST::addImportedAST(AST *ast) {
462 mImportedASTs.insert(ast);
463}
464
Timur Iskhakov565b0132017-09-06 18:07:11 -0700465FQName AST::makeFullName(const char* localName, Scope* scope) const {
466 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700467 for (; scope != &mRootScope; scope = scope->parent()) {
468 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700469 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700470
471 std::reverse(pathComponents.begin(), pathComponents.end());
472 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700473
Timur Iskhakov565b0132017-09-06 18:07:11 -0700474 return FQName(mPackage.package(), mPackage.version(), path);
475}
Andreas Huber39fa7182016-08-19 14:27:33 -0700476
Timur Iskhakov565b0132017-09-06 18:07:11 -0700477void AST::addScopedType(NamedType* type, Scope* scope) {
478 scope->addType(type);
479 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700480}
481
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700482LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) {
483 const FQName& fqName = ref.getLookupFqName();
484
485 if (fqName.isIdentifier()) {
486 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
487 if (iden == nullptr) {
488 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
489 << ref.location() << "\n";
490 return nullptr;
491 }
492 return iden;
493 } else {
494 std::string errorMsg;
495 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
496 if (enumValue == nullptr) {
497 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
498 return nullptr;
499 }
500 return enumValue;
501 }
502}
503
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700504EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700505 FQName enumTypeName = fqName.typeName();
506 std::string enumValueName = fqName.valueName();
507
Yifan Hongf24fa852016-09-23 11:03:15 -0700508 CHECK(!enumValueName.empty());
509
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700510 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700511 if(type == nullptr) {
512 *errorMsg = "Cannot find type " + enumTypeName.string();
513 return nullptr;
514 }
Steven Morelandd965ce92017-11-27 16:05:34 -0800515 type = type->resolve();
Yifan Hongf24fa852016-09-23 11:03:15 -0700516 if(!type->isEnum()) {
517 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
518 return nullptr;
519 }
520
521 EnumType *enumType = static_cast<EnumType *>(type);
522 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
523 if(v == nullptr) {
524 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
525 return nullptr;
526 }
Andreas Huber4ba5c972017-11-29 11:06:25 -0800527
528 mReferencedTypeNames.insert(enumType->fqName());
529
Yifan Hongf24fa852016-09-23 11:03:15 -0700530 return v;
531}
532
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700533Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700534 if (fqName.name().empty()) {
535 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700536 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700537 }
538
Yifan Hong87ff8232017-01-09 12:07:05 -0800539 Type *returnedType = nullptr;
540
Andreas Huber84f89de2016-07-28 15:39:51 -0700541 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800542 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700543 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800544 if (returnedType != nullptr) {
545 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700546 }
547 }
548
Steven Moreland87e69dc2017-09-12 18:14:28 -0700549 status_t status = lookupAutofilledType(fqName, &returnedType);
550 if (status != OK) {
551 return nullptr;
552 }
553 if (returnedType != nullptr) {
554 return returnedType;
Yifan Hong87ff8232017-01-09 12:07:05 -0800555 }
556
557 return lookupTypeFromImports(fqName);
558}
559
560// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700561Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800562 CHECK(fqName.package().empty() && fqName.version().empty()
563 && !fqName.name().empty() && fqName.valueName().empty());
564
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700565 for (; scope != nullptr; scope = scope->parent()) {
566 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800567 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800568 return type;
569 }
570 }
571
572 return nullptr;
573}
574
575// Rule 1: auto-fill with current package
576status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
Steven Moreland87e69dc2017-09-12 18:14:28 -0700577 CHECK(!fqName.name().empty() && fqName.valueName().empty());
Yifan Hong87ff8232017-01-09 12:07:05 -0800578
579 FQName autofilled = fqName;
580 autofilled.applyDefaults(mPackage.package(), mPackage.version());
581 FQName matchingName;
582 // Given this fully-qualified name, the type may be defined in this AST, or other files
583 // in import.
584 Type *local = findDefinedType(autofilled, &matchingName);
585 CHECK(local == nullptr || autofilled == matchingName);
Steven Moreland87e69dc2017-09-12 18:14:28 -0700586 Type* fromImport = lookupTypeFromImports(autofilled);
Yifan Hong87ff8232017-01-09 12:07:05 -0800587
588 if (local != nullptr && fromImport != nullptr && local != fromImport) {
589 // Something bad happen; two types have the same FQName.
590 std::cerr << "ERROR: Unable to resolve type name '"
591 << fqName.string()
592 << "' (i.e. '"
593 << autofilled.string()
594 << "'), multiple definitions found.\n";
595
596 return UNKNOWN_ERROR;
597 }
598 if (local != nullptr) {
599 *returnedType = local;
600 return OK;
601 }
602 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
603 *returnedType = fromImport;
604 return OK;
605}
606
607// Rule 2: look at imports
608Type *AST::lookupTypeFromImports(const FQName &fqName) {
609
Andreas Huber39fa7182016-08-19 14:27:33 -0700610 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700611 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700612 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700613
Andreas Huber39fa7182016-08-19 14:27:33 -0700614 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700615 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
616 // ignore single type imports
617 continue;
618 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700619 FQName matchingName;
620 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700621
Andreas Huber39fa7182016-08-19 14:27:33 -0700622 if (match != nullptr) {
623 if (resolvedType != nullptr) {
624 std::cerr << "ERROR: Unable to resolve type name '"
625 << fqName.string()
626 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700627
Andreas Huber39fa7182016-08-19 14:27:33 -0700628 std::cerr << " " << resolvedName.string() << "\n";
629 std::cerr << " " << matchingName.string() << "\n";
630
Yifan Hong1977ea32016-10-05 12:49:08 -0700631 return nullptr;
632 }
633
634 resolvedType = match;
635 returnedType = resolvedType;
636 resolvedName = matchingName;
637
638 // Keep going even after finding a match.
639 }
640 }
641
642 for (const auto &pair : mImportedTypes) {
643 AST *importedAST = pair.first;
644 std::set<Type *> importedTypes = pair.second;
645
646 FQName matchingName;
647 Type *match = importedAST->findDefinedType(fqName, &matchingName);
648 if (match != nullptr &&
649 importedTypes.find(match) != importedTypes.end()) {
650 if (resolvedType != nullptr) {
651 std::cerr << "ERROR: Unable to resolve type name '"
652 << fqName.string()
653 << "', multiple matches found:\n";
654
655 std::cerr << " " << resolvedName.string() << "\n";
656 std::cerr << " " << matchingName.string() << "\n";
657
658 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700659 }
660
661 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700662 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700663 resolvedName = matchingName;
664
665 // Keep going even after finding a match.
666 }
667 }
668
669 if (resolvedType) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700670 returnedType = resolvedType;
671
672 // If the resolved type is not an interface, we need to determine
673 // whether it is defined in types.hal, or in some other interface. In
674 // the latter case, we need to emit a dependency for the interface in
675 // which the type is defined.
676 //
677 // Consider the following:
678 // android.hardware.tests.foo@1.0::Record
679 // android.hardware.tests.foo@1.0::IFoo.Folder
680 // android.hardware.tests.foo@1.0::Folder
681 //
682 // If Record is an interface, then we keep track of it for the purpose
683 // of emitting dependencies in the target language (for example #include
684 // in C++). If Record is a UDT, then we assume it is defined in
685 // types.hal in android.hardware.tests.foo@1.0.
686 //
687 // In the case of IFoo.Folder, the same applies. If IFoo is an
688 // interface, we need to track this for the purpose of emitting
689 // dependencies. If not, then it must have been defined in types.hal.
690 //
691 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800692 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700693 // above applies.
694
695 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800696 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700697 for (const auto &importedAST : mImportedASTs) {
698 FQName matchingName;
699 Type *match = importedAST->findDefinedType(ifc, &matchingName);
700 if (match != nullptr && match->isInterface()) {
701 resolvedType = match;
702 }
703 }
704 }
705
Andreas Huber39fa7182016-08-19 14:27:33 -0700706 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700707 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800708 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700709
Andreas Huber0e00de42016-08-03 09:56:02 -0700710 mImportedNames.insert(typesName);
711 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700712 // Do _not_ use fqName, i.e. the name we used to look up the type,
713 // but instead use the name of the interface we found.
714 // This is necessary because if fqName pointed to a typedef which
715 // in turn referenced the found interface we'd mistakenly use the
716 // name of the typedef instead of the proper name of the interface.
717
Andreas Huber4ba5c972017-11-29 11:06:25 -0800718 const FQName &typeName =
719 static_cast<Interface *>(resolvedType)->fqName();
720
721 mImportedNames.insert(typeName);
Andreas Huber0e00de42016-08-03 09:56:02 -0700722 }
Andreas Huber737080b2016-08-02 15:38:04 -0700723 }
724
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700725 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700726}
727
Andreas Huber4ba5c972017-11-29 11:06:25 -0800728void AST::addToImportedNamesGranular(const FQName &fqName) {
729 if (fqName.package() == package().package()
730 && fqName.version() == package().version()) {
731 // Our own names are _defined_ here, not imported.
732 return;
733 }
734
735 mImportedNamesGranular.insert(fqName);
736}
737
Andreas Huber39fa7182016-08-19 14:27:33 -0700738Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700739 for (const auto &pair : mDefinedTypesByFullName) {
740 const FQName &key = pair.first;
741 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700742
Andreas Huber39fa7182016-08-19 14:27:33 -0700743 if (key.endsWith(fqName)) {
744 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700745 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700746 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700747 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700748
749 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700750}
751
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700752void AST::getImportedPackages(std::set<FQName> *importSet) const {
Steven Moreland06a81cf2018-01-17 11:13:46 -0800753 for (const auto& fqName : mImportedNamesGranular) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800754 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700755
756 if (packageName == mPackage) {
757 // We only care about external imports, not our own package.
758 continue;
759 }
760
761 importSet->insert(packageName);
762 }
763}
764
Yifan Hong40a373d2016-11-30 15:16:47 -0800765void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
766 getImportedPackages(importSet);
Steven Moreland06a81cf2018-01-17 11:13:46 -0800767
Yifan Hong40a373d2016-11-30 15:16:47 -0800768 std::set<FQName> newSet;
769 for (const auto &ast : mImportedASTs) {
770 if (importSet->find(ast->package()) != importSet->end()) {
771 ast->getImportedPackagesHierarchy(&newSet);
772 }
773 }
774 importSet->insert(newSet.begin(), newSet.end());
775}
776
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800777void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
778 for (const auto& name : mImportedNames) {
779 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700780 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800781 ast->getAllImportedNames(allImportNames);
782 }
783}
784
Andreas Huber4ba5c972017-11-29 11:06:25 -0800785void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
786 for (const auto& fqName : mImportedNamesGranular) {
787 if (fqName.name() == "types") {
788 // A package will export everything _defined_ but will not
789 // re-export anything it itself imported.
790 AST* ast = mCoordinator->parse(
791 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
792
793 ast->addDefinedTypes(allImportNames);
794 } else {
795 allImportNames->insert(fqName);
796 }
797 }
798}
799
Andreas Huber0fa9e392016-08-31 09:05:44 -0700800bool AST::isJavaCompatible() const {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700801 return mRootScope.isJavaCompatible();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700802}
803
Andreas Huber019d21d2016-10-03 12:59:47 -0700804void AST::appendToExportedTypesVector(
805 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700806 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700807}
808
Yifan Hongc8934042016-11-17 17:10:52 -0800809bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700810 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800811 return iface != nullptr && iface->isIBase();
812}
813
Yifan Hong78b38d12017-02-13 18:14:46 +0000814const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700815 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000816}
817
Steven Moreland19f11b52017-05-12 18:22:21 -0700818std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700819 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700820
821 return iface ? iface->getBaseName() : "types";
822}
823
Andreas Huber308d8a22017-11-06 14:46:52 -0800824void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
825 std::for_each(
826 mDefinedTypesByFullName.begin(),
827 mDefinedTypesByFullName.end(),
828 [definedTypes](const auto &elem) {
829 if (!elem.second->isTypeDef()) {
830 definedTypes->insert(elem.first);
831 }
832 });
833}
834
835void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
836 std::for_each(
837 mReferencedTypeNames.begin(),
838 mReferencedTypeNames.end(),
839 [referencedTypes](const auto &fqName) {
840 referencedTypes->insert(fqName);
841 });
842}
843
Andreas Huberc9410c72016-07-28 12:18:40 -0700844} // namespace android;