blob: 31fe1901ebfa45862f69ed3f33a3899d7f12ac19 [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"
Neel Mehta0ee353f2019-05-30 17:40:29 -070025#include "Method.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070026#include "Scope.h"
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070027#include "TypeDef.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070028
Andreas Hubereb1081f2016-07-28 13:13:24 -070029#include <android-base/logging.h>
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070030#include <hidl-util/FQName.h>
31#include <hidl-util/Formatter.h>
32#include <hidl-util/StringHelper.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070033#include <stdlib.h>
Neel Mehta0ee353f2019-05-30 17:40:29 -070034
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070035#include <algorithm>
36#include <iostream>
Neel Mehta0ee353f2019-05-30 17:40:29 -070037#include <map>
38#include <string>
Andreas Huberc9410c72016-07-28 12:18:40 -070039
Andreas Huberc9410c72016-07-28 12:18:40 -070040namespace android {
41
Steven Moreland04dea8d2018-02-06 13:11:24 -080042AST::AST(const Coordinator* coordinator, const Hash* fileHash)
Andreas Huber5345ec22016-07-29 13:33:27 -070043 : mCoordinator(coordinator),
Steven Moreland04dea8d2018-02-06 13:11:24 -080044 mFileHash(fileHash),
Neel Mehtaf6293d32019-06-12 17:16:38 -070045 mRootScope("(root scope)", FQName(),
46 Location::startOf(coordinator->makeRelative(fileHash->getPath())),
Steven Moreland04dea8d2018-02-06 13:11:24 -080047 nullptr /* parent */) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070048
Neel Mehta693169b2019-05-29 18:45:25 -070049Scope* AST::getMutableRootScope() {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070050 return &mRootScope;
Andreas Huberc9410c72016-07-28 12:18:40 -070051}
52
Neel Mehta693169b2019-05-29 18:45:25 -070053const Scope& AST::getRootScope() const {
54 return mRootScope;
55}
56
Yifan Hongbe627b32016-10-28 18:38:56 -070057// used by the parser.
58void AST::addSyntaxError() {
59 mSyntaxErrors++;
60}
61
62size_t AST::syntaxErrors() const {
63 return mSyntaxErrors;
64}
65
Steven Moreland04dea8d2018-02-06 13:11:24 -080066const std::string& AST::getFilename() const {
67 return mFileHash->getPath();
68}
69const Hash* AST::getFileHash() const {
70 return mFileHash;
Andreas Huber0d0f9a22016-08-17 10:26:11 -070071}
72
Neel Mehtaf6293d32019-06-12 17:16:38 -070073const Coordinator& AST::getCoordinator() const {
74 return *mCoordinator;
75}
76
Andreas Huber84f89de2016-07-28 15:39:51 -070077bool AST::setPackage(const char *package) {
Steven Morelande1b157e2018-03-06 14:18:32 -080078 if (!mPackage.setTo(package)) {
79 return false;
80 }
Andreas Huber84f89de2016-07-28 15:39:51 -070081
Andreas Huberda51b8e2016-07-28 16:00:57 -070082 if (mPackage.package().empty()
83 || mPackage.version().empty()
84 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070085 return false;
86 }
87
Andreas Huber84f89de2016-07-28 15:39:51 -070088 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070089}
90
Andreas Hubera2723d22016-07-29 15:36:07 -070091FQName AST::package() const {
92 return mPackage;
93}
94
Steven Moreland19f11b52017-05-12 18:22:21 -070095bool AST::isInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070096 return mRootScope.getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070097}
98
Steven Morelandb47a2622018-07-11 09:04:25 -070099bool AST::definesInterfaces() const {
100 return mRootScope.definesInterfaces();
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700101}
102
Timur Iskhakov33431e62017-08-21 17:31:23 -0700103status_t AST::postParse() {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700104 status_t err;
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700105
Yifan Hong0e192c42018-10-23 15:32:19 -0700106 // lookupTypes is the first pass for references to be resolved.
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700107 err = lookupTypes();
108 if (err != OK) return err;
Yifan Hong0e192c42018-10-23 15:32:19 -0700109
110 // Indicate that all types are now in "postParse" stage.
111 err = setParseStage(Type::ParseStage::PARSE, Type::ParseStage::POST_PARSE);
112 if (err != OK) return err;
113
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700114 // validateDefinedTypesUniqueNames is the first call
115 // after lookup, as other errors could appear because
116 // user meant different type than we assumed.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700117 err = validateDefinedTypesUniqueNames();
118 if (err != OK) return err;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700119 // topologicalReorder is before resolveInheritance, as we
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700120 // need to have no cycle while getting parent class.
Timur Iskhakov458ca362017-09-12 23:16:03 -0700121 err = topologicalReorder();
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700122 if (err != OK) return err;
123 err = resolveInheritance();
124 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700125 err = lookupConstantExpressions();
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700126 if (err != OK) return err;
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700127 // checkAcyclicConstantExpressions is after resolveInheritance,
128 // as resolveInheritance autofills enum values.
129 err = checkAcyclicConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700130 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700131 err = validateConstantExpressions();
132 if (err != OK) return err;
133 err = evaluateConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700134 if (err != OK) return err;
135 err = validate();
136 if (err != OK) return err;
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700137 err = checkForwardReferenceRestrictions();
138 if (err != OK) return err;
Andreas Huber308d8a22017-11-06 14:46:52 -0800139 err = gatherReferencedTypes();
140 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -0700141
Timur Iskhakov35930c42017-08-28 18:49:54 -0700142 // Make future packages not to call passes
143 // for processed types and expressions
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700144 constantExpressionRecursivePass(
145 [](ConstantExpression* ce) {
146 ce->setPostParseCompleted();
147 return OK;
148 },
149 true /* processBeforeDependencies */);
Yifan Hong0e192c42018-10-23 15:32:19 -0700150
151 err = setParseStage(Type::ParseStage::POST_PARSE, Type::ParseStage::COMPLETED);
152 if (err != OK) return err;
Timur Iskhakov35930c42017-08-28 18:49:54 -0700153
Timur Iskhakov33431e62017-08-21 17:31:23 -0700154 return OK;
155}
156
Timur Iskhakov891a8662017-08-25 21:53:48 -0700157status_t AST::constantExpressionRecursivePass(
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700158 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700159 std::unordered_set<const Type*> visitedTypes;
160 std::unordered_set<const ConstantExpression*> visitedCE;
Yifan Hong0e192c42018-10-23 15:32:19 -0700161 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
162 [&](Type* type) -> status_t {
163 for (auto* ce : type->getConstantExpressions()) {
164 status_t err = ce->recursivePass(
165 func, &visitedCE, processBeforeDependencies);
166 if (err != OK) return err;
167 }
168 return OK;
169 },
170 &visitedTypes);
171}
172
Steven Moreland12f0ab12018-11-02 17:27:37 -0700173status_t AST::constantExpressionRecursivePass(
174 const std::function<status_t(const ConstantExpression*)>& func,
175 bool processBeforeDependencies) const {
176 std::unordered_set<const Type*> visitedTypes;
177 std::unordered_set<const ConstantExpression*> visitedCE;
178 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
179 [&](const Type* type) -> status_t {
180 for (auto* ce : type->getConstantExpressions()) {
181 status_t err = ce->recursivePass(
182 func, &visitedCE, processBeforeDependencies);
183 if (err != OK) return err;
184 }
185 return OK;
186 },
187 &visitedTypes);
188}
189
Yifan Hong0e192c42018-10-23 15:32:19 -0700190status_t AST::setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage) {
191 std::unordered_set<const Type*> visited;
192 return mRootScope.recursivePass(oldStage,
193 [oldStage, newStage](Type* type) {
194 CHECK(type->getParseStage() == oldStage);
195 type->setParseStage(newStage);
196 return OK;
197 },
198 &visited);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700199}
200
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700201status_t AST::lookupTypes() {
202 std::unordered_set<const Type*> visited;
203 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700204 Type::ParseStage::PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700205 [&](Type* type) -> status_t {
206 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
207
208 for (auto* nextRef : type->getReferences()) {
Andreas Huber308d8a22017-11-06 14:46:52 -0800209 if (nextRef->isResolved()) {
210 continue;
211 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700212
213 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
214 if (nextType == nullptr) {
215 std::cerr << "ERROR: Failed to lookup type '"
216 << nextRef->getLookupFqName().string() << "' at "
Steven Morelandfebfc0c2019-12-12 16:32:48 -0800217 << nextRef->location()
218 << " (is it imported and spelled correctly?)\n";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700219 return UNKNOWN_ERROR;
220 }
221 nextRef->set(nextType);
222 }
223
224 return OK;
225 },
226 &visited);
227}
228
Andreas Huber308d8a22017-11-06 14:46:52 -0800229status_t AST::gatherReferencedTypes() {
230 std::unordered_set<const Type*> visited;
231 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700232 Type::ParseStage::POST_PARSE,
Andreas Huber308d8a22017-11-06 14:46:52 -0800233 [&](Type* type) -> status_t {
234 for (auto* nextRef : type->getReferences()) {
235 const Type *targetType = nextRef->get();
236 if (targetType->isNamedType()) {
237 mReferencedTypeNames.insert(
238 static_cast<const NamedType *>(targetType)->fqName());
239 }
240 }
241
242 return OK;
243 },
244 &visited);
245}
246
Steven Moreland12f0ab12018-11-02 17:27:37 -0700247status_t AST::lookupConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700248 std::unordered_set<const Type*> visitedTypes;
249 std::unordered_set<const ConstantExpression*> visitedCE;
250
251 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700252 Type::ParseStage::POST_PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700253 [&](Type* type) -> status_t {
254 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
255
256 for (auto* ce : type->getConstantExpressions()) {
257 status_t err = ce->recursivePass(
258 [&](ConstantExpression* ce) {
259 for (auto* nextRef : ce->getReferences()) {
260 if (nextRef->isResolved()) continue;
261
262 LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope);
263 if (iden == nullptr) return UNKNOWN_ERROR;
264 nextRef->set(iden);
265 }
Steven Moreland12f0ab12018-11-02 17:27:37 -0700266 for (auto* nextRef : ce->getTypeReferences()) {
267 if (nextRef->isResolved()) continue;
268
269 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
270 if (nextType == nullptr) {
271 std::cerr << "ERROR: Failed to lookup type '"
272 << nextRef->getLookupFqName().string() << "' at "
273 << nextRef->location() << "\n";
274 return UNKNOWN_ERROR;
275 }
276 nextRef->set(nextType);
277 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700278 return OK;
279 },
280 &visitedCE, true /* processBeforeDependencies */);
281 if (err != OK) return err;
282 }
283
284 return OK;
285 },
286 &visitedTypes);
287}
288
Timur Iskhakov565b0132017-09-06 18:07:11 -0700289status_t AST::validateDefinedTypesUniqueNames() const {
290 std::unordered_set<const Type*> visited;
291 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700292 Type::ParseStage::POST_PARSE,
Timur Iskhakov565b0132017-09-06 18:07:11 -0700293 [&](const Type* type) -> status_t {
294 // We only want to validate type definition names in this place.
295 if (type->isScope()) {
296 return static_cast<const Scope*>(type)->validateUniqueNames();
297 }
298 return OK;
299 },
300 &visited);
301}
302
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700303status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700304 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700305 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::resolveInheritance,
306 &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700307}
308
Steven Moreland12f0ab12018-11-02 17:27:37 -0700309status_t AST::validateConstantExpressions() const {
310 return constantExpressionRecursivePass(
311 [](const ConstantExpression* ce) { return ce->validate(); },
312 true /* processBeforeDependencies */);
313}
314
315status_t AST::evaluateConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700316 return constantExpressionRecursivePass(
317 [](ConstantExpression* ce) {
318 ce->evaluate();
319 return OK;
320 },
321 false /* processBeforeDependencies */);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700322}
323
324status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700325 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700326 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700327}
328
Timur Iskhakov458ca362017-09-12 23:16:03 -0700329status_t AST::topologicalReorder() {
330 std::unordered_map<const Type*, size_t> reversedOrder;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700331 std::unordered_set<const Type*> stack;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700332 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
333 if (err != OK) return err;
334
335 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700336 mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
337 [&](Type* type) {
338 if (type->isScope()) {
339 static_cast<Scope*>(type)->topologicalReorder(reversedOrder);
340 }
341 return OK;
342 },
343 &visited);
Timur Iskhakov458ca362017-09-12 23:16:03 -0700344 return OK;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700345}
346
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700347status_t AST::checkAcyclicConstantExpressions() const {
348 std::unordered_set<const Type*> visitedTypes;
349 std::unordered_set<const ConstantExpression*> visitedCE;
350 std::unordered_set<const ConstantExpression*> stack;
Yifan Hong0e192c42018-10-23 15:32:19 -0700351 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
352 [&](const Type* type) -> status_t {
353 for (auto* ce : type->getConstantExpressions()) {
354 status_t err =
355 ce->checkAcyclic(&visitedCE, &stack).status;
356 CHECK(err != OK || stack.empty());
357 if (err != OK) return err;
358 }
359 return OK;
360 },
361 &visitedTypes);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700362}
363
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700364status_t AST::checkForwardReferenceRestrictions() const {
365 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700366 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
367 [](const Type* type) -> status_t {
368 for (const Reference<Type>* ref : type->getReferences()) {
369 status_t err =
370 type->checkForwardReferenceRestrictions(*ref);
371 if (err != OK) return err;
372 }
373 return OK;
374 },
375 &visited);
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700376}
377
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700378bool AST::importFQName(const FQName& fqName) {
Andreas Huber5345ec22016-07-29 13:33:27 -0700379 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700380 // import a package
Andreas Huber4ba5c972017-11-29 11:06:25 -0800381
Andreas Huberd2943e12016-08-05 11:59:31 -0700382 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700383
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700384 status_t err = mCoordinator->appendPackageInterfacesToVector(fqName, &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
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700390 for (const auto& subFQName : packageInterfaces) {
Yifan Hongf619fc72017-04-07 15:40:06 -0700391 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700392 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700393 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700394 return false;
395 }
Steven Morelandb7c47472019-11-20 10:52:40 -0800396 addToImportedNamesGranular(subFQName);
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
Yifan Hong1977ea32016-10-05 12:49:08 -0700405 // cases like android.hardware.foo@1.0::IFoo.Internal
406 // android.hardware.foo@1.0::Abc.Internal
407
408 // assume it is an interface, and try to import it.
409 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700410 // Do not enforce restrictions on imports.
Steven Moreland71f09132018-02-20 12:24:30 -0800411 AST* importAST;
412 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
413 Coordinator::Enforce::NONE);
414 if (err != OK) return false;
415 // importAST nullptr == file doesn't exist
Yifan Hong1977ea32016-10-05 12:49:08 -0700416
417 if (importAST != nullptr) {
418 // cases like android.hardware.foo@1.0::IFoo.Internal
419 // and android.hardware.foo@1.0::IFoo
420 if (fqName == interfaceName) {
421 // import a single file.
422 // all previous single type imports are ignored.
423 // cases like android.hardware.foo@1.0::IFoo
424 // and android.hardware.foo@1.0::types
425 mImportedTypes.erase(importAST);
Steven Morelandb7c47472019-11-20 10:52:40 -0800426 addToImportedNamesGranular(fqName);
Yifan Hong1977ea32016-10-05 12:49:08 -0700427 return true;
428 }
429
430 // import a single type from this file
431 // cases like android.hardware.foo@1.0::IFoo.Internal
432 FQName matchingName;
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700433 Type* match = importAST->findDefinedType(fqName, &matchingName);
Yifan Hong1977ea32016-10-05 12:49:08 -0700434 if (match == nullptr) {
435 return false;
436 }
437 // will automatically create a set if it does not exist
438 mImportedTypes[importAST].insert(match);
Steven Morelandb7c47472019-11-20 10:52:40 -0800439 addToImportedNamesGranular(fqName);
Yifan Hong1977ea32016-10-05 12:49:08 -0700440 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;
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700452 Type* match = importAST->findDefinedType(fqName, &matchingName);
Yifan Hong1977ea32016-10-05 12:49:08 -0700453 if (match == nullptr) {
454 return false;
455 }
456 // will automatically create a set if not exist
457 mImportedTypes[importAST].insert(match);
Steven Morelandb7c47472019-11-20 10:52:40 -0800458 addToImportedNamesGranular(fqName);
Yifan Hong1977ea32016-10-05 12:49:08 -0700459 return true;
460 }
461
462 // can't find an appropriate AST for fqName.
463 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700464}
465
Neel Mehta8b0f06a2019-07-11 18:13:21 -0700466bool AST::addImplicitImport(const FQName& fqName) {
467 CHECK(fqName.isFullyQualified());
468
469 if (importFQName(fqName)) {
470 mImplicitImports.push_back(fqName);
471 return true;
472 }
473
474 return false;
475}
476
477bool AST::addImport(const char* import, const Location& location) {
478 FQName fqName;
479 if (!FQName::parse(import, &fqName)) {
480 std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
481 return false;
482 }
483
484 fqName.applyDefaults(mPackage.package(), mPackage.version());
485
486 if (importFQName(fqName)) {
487 mImportStatements.push_back({fqName, location});
488 return true;
489 }
490
491 return false;
492}
493
Andreas Huber39fa7182016-08-19 14:27:33 -0700494void AST::addImportedAST(AST *ast) {
495 mImportedASTs.insert(ast);
496}
497
Timur Iskhakov565b0132017-09-06 18:07:11 -0700498FQName AST::makeFullName(const char* localName, Scope* scope) const {
499 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700500 for (; scope != &mRootScope; scope = scope->parent()) {
Neel Mehta9200af02019-07-19 13:24:57 -0700501 pathComponents.push_back(scope->definedName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700502 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700503
504 std::reverse(pathComponents.begin(), pathComponents.end());
505 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700506
Timur Iskhakov565b0132017-09-06 18:07:11 -0700507 return FQName(mPackage.package(), mPackage.version(), path);
508}
Andreas Huber39fa7182016-08-19 14:27:33 -0700509
Timur Iskhakov565b0132017-09-06 18:07:11 -0700510void AST::addScopedType(NamedType* type, Scope* scope) {
511 scope->addType(type);
512 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700513}
514
Steven Moreland8f8e8622019-11-04 12:38:38 -0800515LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref,
516 const Scope* scope) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700517 const FQName& fqName = ref.getLookupFqName();
518
519 if (fqName.isIdentifier()) {
520 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
521 if (iden == nullptr) {
522 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
523 << ref.location() << "\n";
524 return nullptr;
525 }
526 return iden;
527 } else {
528 std::string errorMsg;
529 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
530 if (enumValue == nullptr) {
531 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
532 return nullptr;
533 }
534 return enumValue;
535 }
536}
537
Steven Moreland8f8e8622019-11-04 12:38:38 -0800538EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, const Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700539 FQName enumTypeName = fqName.typeName();
540 std::string enumValueName = fqName.valueName();
541
Yifan Hongf24fa852016-09-23 11:03:15 -0700542 CHECK(!enumValueName.empty());
543
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700544 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700545 if(type == nullptr) {
546 *errorMsg = "Cannot find type " + enumTypeName.string();
547 return nullptr;
548 }
Steven Morelandd965ce92017-11-27 16:05:34 -0800549 type = type->resolve();
Yifan Hongf24fa852016-09-23 11:03:15 -0700550 if(!type->isEnum()) {
551 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
552 return nullptr;
553 }
554
555 EnumType *enumType = static_cast<EnumType *>(type);
556 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
557 if(v == nullptr) {
558 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
559 return nullptr;
560 }
Andreas Huber4ba5c972017-11-29 11:06:25 -0800561
562 mReferencedTypeNames.insert(enumType->fqName());
563
Yifan Hongf24fa852016-09-23 11:03:15 -0700564 return v;
565}
566
Steven Moreland8f8e8622019-11-04 12:38:38 -0800567Type* AST::lookupType(const FQName& fqName, const Scope* scope) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700568 if (fqName.name().empty()) {
569 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700570 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700571 }
572
Yifan Hong87ff8232017-01-09 12:07:05 -0800573 Type *returnedType = nullptr;
574
Andreas Huber84f89de2016-07-28 15:39:51 -0700575 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800576 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700577 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800578 if (returnedType != nullptr) {
579 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700580 }
581 }
582
Steven Moreland87e69dc2017-09-12 18:14:28 -0700583 status_t status = lookupAutofilledType(fqName, &returnedType);
584 if (status != OK) {
585 return nullptr;
586 }
587 if (returnedType != nullptr) {
588 return returnedType;
Yifan Hong87ff8232017-01-09 12:07:05 -0800589 }
590
591 return lookupTypeFromImports(fqName);
592}
593
594// Rule 0: try resolve locally
Steven Moreland8f8e8622019-11-04 12:38:38 -0800595Type* AST::lookupTypeLocally(const FQName& fqName, const Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800596 CHECK(fqName.package().empty() && fqName.version().empty()
597 && !fqName.name().empty() && fqName.valueName().empty());
598
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700599 for (; scope != nullptr; scope = scope->parent()) {
600 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800601 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800602 return type;
603 }
604 }
605
606 return nullptr;
607}
608
609// Rule 1: auto-fill with current package
610status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
Steven Moreland87e69dc2017-09-12 18:14:28 -0700611 CHECK(!fqName.name().empty() && fqName.valueName().empty());
Yifan Hong87ff8232017-01-09 12:07:05 -0800612
613 FQName autofilled = fqName;
614 autofilled.applyDefaults(mPackage.package(), mPackage.version());
615 FQName matchingName;
616 // Given this fully-qualified name, the type may be defined in this AST, or other files
617 // in import.
618 Type *local = findDefinedType(autofilled, &matchingName);
619 CHECK(local == nullptr || autofilled == matchingName);
Steven Moreland87e69dc2017-09-12 18:14:28 -0700620 Type* fromImport = lookupTypeFromImports(autofilled);
Yifan Hong87ff8232017-01-09 12:07:05 -0800621
622 if (local != nullptr && fromImport != nullptr && local != fromImport) {
623 // Something bad happen; two types have the same FQName.
624 std::cerr << "ERROR: Unable to resolve type name '"
625 << fqName.string()
626 << "' (i.e. '"
627 << autofilled.string()
628 << "'), multiple definitions found.\n";
629
630 return UNKNOWN_ERROR;
631 }
632 if (local != nullptr) {
633 *returnedType = local;
634 return OK;
635 }
636 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
637 *returnedType = fromImport;
638 return OK;
639}
640
641// Rule 2: look at imports
642Type *AST::lookupTypeFromImports(const FQName &fqName) {
643
Andreas Huber39fa7182016-08-19 14:27:33 -0700644 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700645 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700646 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700647
Andreas Huber39fa7182016-08-19 14:27:33 -0700648 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700649 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
650 // ignore single type imports
651 continue;
652 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700653 FQName matchingName;
654 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700655
Andreas Huber39fa7182016-08-19 14:27:33 -0700656 if (match != nullptr) {
657 if (resolvedType != nullptr) {
658 std::cerr << "ERROR: Unable to resolve type name '"
659 << fqName.string()
660 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700661
Andreas Huber39fa7182016-08-19 14:27:33 -0700662 std::cerr << " " << resolvedName.string() << "\n";
663 std::cerr << " " << matchingName.string() << "\n";
664
Yifan Hong1977ea32016-10-05 12:49:08 -0700665 return nullptr;
666 }
667
668 resolvedType = match;
669 returnedType = resolvedType;
670 resolvedName = matchingName;
671
672 // Keep going even after finding a match.
673 }
674 }
675
676 for (const auto &pair : mImportedTypes) {
677 AST *importedAST = pair.first;
678 std::set<Type *> importedTypes = pair.second;
679
680 FQName matchingName;
681 Type *match = importedAST->findDefinedType(fqName, &matchingName);
682 if (match != nullptr &&
683 importedTypes.find(match) != importedTypes.end()) {
684 if (resolvedType != nullptr) {
685 std::cerr << "ERROR: Unable to resolve type name '"
686 << fqName.string()
687 << "', multiple matches found:\n";
688
689 std::cerr << " " << resolvedName.string() << "\n";
690 std::cerr << " " << matchingName.string() << "\n";
691
692 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700693 }
694
695 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700696 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700697 resolvedName = matchingName;
698
699 // Keep going even after finding a match.
700 }
701 }
702
703 if (resolvedType) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700704 returnedType = resolvedType;
705
706 // If the resolved type is not an interface, we need to determine
707 // whether it is defined in types.hal, or in some other interface. In
708 // the latter case, we need to emit a dependency for the interface in
709 // which the type is defined.
710 //
711 // Consider the following:
712 // android.hardware.tests.foo@1.0::Record
713 // android.hardware.tests.foo@1.0::IFoo.Folder
714 // android.hardware.tests.foo@1.0::Folder
715 //
716 // If Record is an interface, then we keep track of it for the purpose
717 // of emitting dependencies in the target language (for example #include
718 // in C++). If Record is a UDT, then we assume it is defined in
719 // types.hal in android.hardware.tests.foo@1.0.
720 //
721 // In the case of IFoo.Folder, the same applies. If IFoo is an
722 // interface, we need to track this for the purpose of emitting
723 // dependencies. If not, then it must have been defined in types.hal.
724 //
725 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800726 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700727 // above applies.
728
729 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800730 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700731 for (const auto &importedAST : mImportedASTs) {
732 FQName matchingName;
733 Type *match = importedAST->findDefinedType(ifc, &matchingName);
734 if (match != nullptr && match->isInterface()) {
735 resolvedType = match;
736 }
737 }
738 }
739
Andreas Huber39fa7182016-08-19 14:27:33 -0700740 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700741 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800742 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700743
Andreas Huber0e00de42016-08-03 09:56:02 -0700744 mImportedNames.insert(typesName);
745 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700746 // Do _not_ use fqName, i.e. the name we used to look up the type,
747 // but instead use the name of the interface we found.
748 // This is necessary because if fqName pointed to a typedef which
749 // in turn referenced the found interface we'd mistakenly use the
750 // name of the typedef instead of the proper name of the interface.
751
Andreas Huber4ba5c972017-11-29 11:06:25 -0800752 const FQName &typeName =
753 static_cast<Interface *>(resolvedType)->fqName();
754
755 mImportedNames.insert(typeName);
Andreas Huber0e00de42016-08-03 09:56:02 -0700756 }
Andreas Huber737080b2016-08-02 15:38:04 -0700757 }
758
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700759 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700760}
761
Andreas Huber4ba5c972017-11-29 11:06:25 -0800762void AST::addToImportedNamesGranular(const FQName &fqName) {
763 if (fqName.package() == package().package()
764 && fqName.version() == package().version()) {
765 // Our own names are _defined_ here, not imported.
766 return;
767 }
768
769 mImportedNamesGranular.insert(fqName);
770}
771
Andreas Huber39fa7182016-08-19 14:27:33 -0700772Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700773 for (const auto &pair : mDefinedTypesByFullName) {
774 const FQName &key = pair.first;
775 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700776
Andreas Huber39fa7182016-08-19 14:27:33 -0700777 if (key.endsWith(fqName)) {
778 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700779 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700780 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700781 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700782
783 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700784}
785
Neel Mehta55c065e2019-05-31 13:30:12 -0700786const std::vector<ImportStatement>& AST::getImportStatements() const {
787 return mImportStatements;
788}
789
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700790void AST::getImportedPackages(std::set<FQName> *importSet) const {
Steven Moreland06a81cf2018-01-17 11:13:46 -0800791 for (const auto& fqName : mImportedNamesGranular) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800792 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700793
794 if (packageName == mPackage) {
795 // We only care about external imports, not our own package.
796 continue;
797 }
798
799 importSet->insert(packageName);
800 }
801}
802
Yifan Hong40a373d2016-11-30 15:16:47 -0800803void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
804 getImportedPackages(importSet);
Steven Moreland06a81cf2018-01-17 11:13:46 -0800805
Yifan Hong40a373d2016-11-30 15:16:47 -0800806 std::set<FQName> newSet;
807 for (const auto &ast : mImportedASTs) {
808 if (importSet->find(ast->package()) != importSet->end()) {
809 ast->getImportedPackagesHierarchy(&newSet);
810 }
811 }
812 importSet->insert(newSet.begin(), newSet.end());
813}
814
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800815void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
816 for (const auto& name : mImportedNames) {
817 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700818 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800819 ast->getAllImportedNames(allImportNames);
820 }
821}
822
Andreas Huber4ba5c972017-11-29 11:06:25 -0800823void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
824 for (const auto& fqName : mImportedNamesGranular) {
825 if (fqName.name() == "types") {
826 // A package will export everything _defined_ but will not
827 // re-export anything it itself imported.
828 AST* ast = mCoordinator->parse(
829 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
830
Steven Morelandb7c47472019-11-20 10:52:40 -0800831 // imported names must have already been validated
832 CHECK(ast != nullptr) << fqName.string();
833
Andreas Huber4ba5c972017-11-29 11:06:25 -0800834 ast->addDefinedTypes(allImportNames);
835 } else {
836 allImportNames->insert(fqName);
837 }
838 }
839}
840
Andreas Huber0fa9e392016-08-31 09:05:44 -0700841bool AST::isJavaCompatible() const {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700842 return mRootScope.isJavaCompatible();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700843}
844
Andreas Huber019d21d2016-10-03 12:59:47 -0700845void AST::appendToExportedTypesVector(
846 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700847 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700848}
849
Yifan Hongc8934042016-11-17 17:10:52 -0800850bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700851 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800852 return iface != nullptr && iface->isIBase();
853}
854
Yifan Hong78b38d12017-02-13 18:14:46 +0000855const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700856 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000857}
858
Steven Moreland19f11b52017-05-12 18:22:21 -0700859std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700860 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700861
862 return iface ? iface->getBaseName() : "types";
863}
864
Andreas Huber308d8a22017-11-06 14:46:52 -0800865void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
866 std::for_each(
867 mDefinedTypesByFullName.begin(),
868 mDefinedTypesByFullName.end(),
869 [definedTypes](const auto &elem) {
870 if (!elem.second->isTypeDef()) {
871 definedTypes->insert(elem.first);
872 }
873 });
874}
875
876void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
877 std::for_each(
878 mReferencedTypeNames.begin(),
879 mReferencedTypeNames.end(),
880 [referencedTypes](const auto &fqName) {
881 referencedTypes->insert(fqName);
882 });
883}
884
Neel Mehta0ee353f2019-05-30 17:40:29 -0700885bool AST::addMethod(Method* method, Interface* iface) {
886 if (iface->isIBase()) {
887 if (!mAllReservedMethods.emplace(method->name(), method).second) {
888 std::cerr << "ERROR: hidl-gen encountered duplicated reserved method " << method->name()
889 << std::endl;
890 return false;
891 }
892
893 // methods will be added to iface in addAllReservedMethodsToInterface
894 return true;
895 }
896
897 iface->addUserDefinedMethod(method);
898
899 return true;
900}
901
902bool AST::addAllReservedMethodsToInterface(Interface* iface) {
903 std::map<std::string, Method*> allReservedMethods(mAllReservedMethods);
904 // Looking for the IBase AST which is imported for all interfaces that are not IBase
905 for (const AST* importedAST : mImportedASTs) {
906 allReservedMethods.insert(importedAST->mAllReservedMethods.begin(),
907 importedAST->mAllReservedMethods.end());
908 }
909
910 return iface->addAllReservedMethods(allReservedMethods);
911}
912
Steven Moreland4d89ee22019-03-08 13:25:32 -0800913void AST::setHeader(const DocComment* header) {
914 mHeader = header;
915}
916
917const DocComment* AST::getHeader() const {
918 return mHeader;
919}
920
921void AST::addUnhandledComment(const DocComment* docComment) {
922 if (docComment != nullptr) mUnhandledComments.push_back(docComment);
923}
924
925const std::vector<const DocComment*> AST::getUnhandledComments() const {
926 return mUnhandledComments;
927}
928
Andreas Huberc9410c72016-07-28 12:18:40 -0700929} // namespace android;