blob: 07f50beeab6bf345a0a5cba9bb3aa41b5a01c7c5 [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),
45 mRootScope("(root scope)", FQName(), Location::startOf(fileHash->getPath()),
46 nullptr /* parent */) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070047
Neel Mehta693169b2019-05-29 18:45:25 -070048Scope* AST::getMutableRootScope() {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070049 return &mRootScope;
Andreas Huberc9410c72016-07-28 12:18:40 -070050}
51
Neel Mehta693169b2019-05-29 18:45:25 -070052const Scope& AST::getRootScope() const {
53 return mRootScope;
54}
55
Yifan Hongbe627b32016-10-28 18:38:56 -070056// used by the parser.
57void AST::addSyntaxError() {
58 mSyntaxErrors++;
59}
60
61size_t AST::syntaxErrors() const {
62 return mSyntaxErrors;
63}
64
Steven Moreland04dea8d2018-02-06 13:11:24 -080065const std::string& AST::getFilename() const {
66 return mFileHash->getPath();
67}
68const Hash* AST::getFileHash() const {
69 return mFileHash;
Andreas Huber0d0f9a22016-08-17 10:26:11 -070070}
71
Andreas Huber84f89de2016-07-28 15:39:51 -070072bool AST::setPackage(const char *package) {
Steven Morelande1b157e2018-03-06 14:18:32 -080073 if (!mPackage.setTo(package)) {
74 return false;
75 }
Andreas Huber84f89de2016-07-28 15:39:51 -070076
Andreas Huberda51b8e2016-07-28 16:00:57 -070077 if (mPackage.package().empty()
78 || mPackage.version().empty()
79 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070080 return false;
81 }
82
Andreas Huber84f89de2016-07-28 15:39:51 -070083 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070084}
85
Andreas Hubera2723d22016-07-29 15:36:07 -070086FQName AST::package() const {
87 return mPackage;
88}
89
Steven Moreland19f11b52017-05-12 18:22:21 -070090bool AST::isInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070091 return mRootScope.getInterface() != nullptr;
Andreas Hubera2723d22016-07-29 15:36:07 -070092}
93
Steven Morelandb47a2622018-07-11 09:04:25 -070094bool AST::definesInterfaces() const {
95 return mRootScope.definesInterfaces();
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070096}
97
Timur Iskhakov33431e62017-08-21 17:31:23 -070098status_t AST::postParse() {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -070099 status_t err;
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700100
Yifan Hong0e192c42018-10-23 15:32:19 -0700101 // lookupTypes is the first pass for references to be resolved.
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700102 err = lookupTypes();
103 if (err != OK) return err;
Yifan Hong0e192c42018-10-23 15:32:19 -0700104
105 // Indicate that all types are now in "postParse" stage.
106 err = setParseStage(Type::ParseStage::PARSE, Type::ParseStage::POST_PARSE);
107 if (err != OK) return err;
108
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700109 // validateDefinedTypesUniqueNames is the first call
110 // after lookup, as other errors could appear because
111 // user meant different type than we assumed.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700112 err = validateDefinedTypesUniqueNames();
113 if (err != OK) return err;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700114 // topologicalReorder is before resolveInheritance, as we
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700115 // need to have no cycle while getting parent class.
Timur Iskhakov458ca362017-09-12 23:16:03 -0700116 err = topologicalReorder();
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700117 if (err != OK) return err;
118 err = resolveInheritance();
119 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700120 err = lookupConstantExpressions();
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700121 if (err != OK) return err;
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700122 // checkAcyclicConstantExpressions is after resolveInheritance,
123 // as resolveInheritance autofills enum values.
124 err = checkAcyclicConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700125 if (err != OK) return err;
Steven Moreland12f0ab12018-11-02 17:27:37 -0700126 err = validateConstantExpressions();
127 if (err != OK) return err;
128 err = evaluateConstantExpressions();
Timur Iskhakov33431e62017-08-21 17:31:23 -0700129 if (err != OK) return err;
130 err = validate();
131 if (err != OK) return err;
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700132 err = checkForwardReferenceRestrictions();
133 if (err != OK) return err;
Andreas Huber308d8a22017-11-06 14:46:52 -0800134 err = gatherReferencedTypes();
135 if (err != OK) return err;
Timur Iskhakov33431e62017-08-21 17:31:23 -0700136
Timur Iskhakov35930c42017-08-28 18:49:54 -0700137 // Make future packages not to call passes
138 // for processed types and expressions
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700139 constantExpressionRecursivePass(
140 [](ConstantExpression* ce) {
141 ce->setPostParseCompleted();
142 return OK;
143 },
144 true /* processBeforeDependencies */);
Yifan Hong0e192c42018-10-23 15:32:19 -0700145
146 err = setParseStage(Type::ParseStage::POST_PARSE, Type::ParseStage::COMPLETED);
147 if (err != OK) return err;
Timur Iskhakov35930c42017-08-28 18:49:54 -0700148
Timur Iskhakov33431e62017-08-21 17:31:23 -0700149 return OK;
150}
151
Timur Iskhakov891a8662017-08-25 21:53:48 -0700152status_t AST::constantExpressionRecursivePass(
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700153 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700154 std::unordered_set<const Type*> visitedTypes;
155 std::unordered_set<const ConstantExpression*> visitedCE;
Yifan Hong0e192c42018-10-23 15:32:19 -0700156 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
157 [&](Type* type) -> status_t {
158 for (auto* ce : type->getConstantExpressions()) {
159 status_t err = ce->recursivePass(
160 func, &visitedCE, processBeforeDependencies);
161 if (err != OK) return err;
162 }
163 return OK;
164 },
165 &visitedTypes);
166}
167
Steven Moreland12f0ab12018-11-02 17:27:37 -0700168status_t AST::constantExpressionRecursivePass(
169 const std::function<status_t(const ConstantExpression*)>& func,
170 bool processBeforeDependencies) const {
171 std::unordered_set<const Type*> visitedTypes;
172 std::unordered_set<const ConstantExpression*> visitedCE;
173 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
174 [&](const Type* type) -> status_t {
175 for (auto* ce : type->getConstantExpressions()) {
176 status_t err = ce->recursivePass(
177 func, &visitedCE, processBeforeDependencies);
178 if (err != OK) return err;
179 }
180 return OK;
181 },
182 &visitedTypes);
183}
184
Yifan Hong0e192c42018-10-23 15:32:19 -0700185status_t AST::setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage) {
186 std::unordered_set<const Type*> visited;
187 return mRootScope.recursivePass(oldStage,
188 [oldStage, newStage](Type* type) {
189 CHECK(type->getParseStage() == oldStage);
190 type->setParseStage(newStage);
191 return OK;
192 },
193 &visited);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700194}
195
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700196status_t AST::lookupTypes() {
197 std::unordered_set<const Type*> visited;
198 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700199 Type::ParseStage::PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700200 [&](Type* type) -> status_t {
201 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
202
203 for (auto* nextRef : type->getReferences()) {
Andreas Huber308d8a22017-11-06 14:46:52 -0800204 if (nextRef->isResolved()) {
205 continue;
206 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700207
208 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
209 if (nextType == nullptr) {
210 std::cerr << "ERROR: Failed to lookup type '"
211 << nextRef->getLookupFqName().string() << "' at "
212 << nextRef->location() << "\n";
213 return UNKNOWN_ERROR;
214 }
215 nextRef->set(nextType);
216 }
217
218 return OK;
219 },
220 &visited);
221}
222
Andreas Huber308d8a22017-11-06 14:46:52 -0800223status_t AST::gatherReferencedTypes() {
224 std::unordered_set<const Type*> visited;
225 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700226 Type::ParseStage::POST_PARSE,
Andreas Huber308d8a22017-11-06 14:46:52 -0800227 [&](Type* type) -> status_t {
228 for (auto* nextRef : type->getReferences()) {
229 const Type *targetType = nextRef->get();
230 if (targetType->isNamedType()) {
231 mReferencedTypeNames.insert(
232 static_cast<const NamedType *>(targetType)->fqName());
233 }
234 }
235
236 return OK;
237 },
238 &visited);
239}
240
Steven Moreland12f0ab12018-11-02 17:27:37 -0700241status_t AST::lookupConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700242 std::unordered_set<const Type*> visitedTypes;
243 std::unordered_set<const ConstantExpression*> visitedCE;
244
245 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700246 Type::ParseStage::POST_PARSE,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700247 [&](Type* type) -> status_t {
248 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
249
250 for (auto* ce : type->getConstantExpressions()) {
251 status_t err = ce->recursivePass(
252 [&](ConstantExpression* ce) {
253 for (auto* nextRef : ce->getReferences()) {
254 if (nextRef->isResolved()) continue;
255
256 LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope);
257 if (iden == nullptr) return UNKNOWN_ERROR;
258 nextRef->set(iden);
259 }
Steven Moreland12f0ab12018-11-02 17:27:37 -0700260 for (auto* nextRef : ce->getTypeReferences()) {
261 if (nextRef->isResolved()) continue;
262
263 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
264 if (nextType == nullptr) {
265 std::cerr << "ERROR: Failed to lookup type '"
266 << nextRef->getLookupFqName().string() << "' at "
267 << nextRef->location() << "\n";
268 return UNKNOWN_ERROR;
269 }
270 nextRef->set(nextType);
271 }
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700272 return OK;
273 },
274 &visitedCE, true /* processBeforeDependencies */);
275 if (err != OK) return err;
276 }
277
278 return OK;
279 },
280 &visitedTypes);
281}
282
Timur Iskhakov565b0132017-09-06 18:07:11 -0700283status_t AST::validateDefinedTypesUniqueNames() const {
284 std::unordered_set<const Type*> visited;
285 return mRootScope.recursivePass(
Yifan Hong0e192c42018-10-23 15:32:19 -0700286 Type::ParseStage::POST_PARSE,
Timur Iskhakov565b0132017-09-06 18:07:11 -0700287 [&](const Type* type) -> status_t {
288 // We only want to validate type definition names in this place.
289 if (type->isScope()) {
290 return static_cast<const Scope*>(type)->validateUniqueNames();
291 }
292 return OK;
293 },
294 &visited);
295}
296
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700297status_t AST::resolveInheritance() {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700298 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700299 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::resolveInheritance,
300 &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700301}
302
Steven Moreland12f0ab12018-11-02 17:27:37 -0700303status_t AST::validateConstantExpressions() const {
304 return constantExpressionRecursivePass(
305 [](const ConstantExpression* ce) { return ce->validate(); },
306 true /* processBeforeDependencies */);
307}
308
309status_t AST::evaluateConstantExpressions() {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700310 return constantExpressionRecursivePass(
311 [](ConstantExpression* ce) {
312 ce->evaluate();
313 return OK;
314 },
315 false /* processBeforeDependencies */);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700316}
317
318status_t AST::validate() const {
Timur Iskhakov33431e62017-08-21 17:31:23 -0700319 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700320 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::validate, &visited);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700321}
322
Timur Iskhakov458ca362017-09-12 23:16:03 -0700323status_t AST::topologicalReorder() {
324 std::unordered_map<const Type*, size_t> reversedOrder;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700325 std::unordered_set<const Type*> stack;
Timur Iskhakov458ca362017-09-12 23:16:03 -0700326 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
327 if (err != OK) return err;
328
329 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700330 mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
331 [&](Type* type) {
332 if (type->isScope()) {
333 static_cast<Scope*>(type)->topologicalReorder(reversedOrder);
334 }
335 return OK;
336 },
337 &visited);
Timur Iskhakov458ca362017-09-12 23:16:03 -0700338 return OK;
Timur Iskhakov40731af2017-08-24 14:18:35 -0700339}
340
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700341status_t AST::checkAcyclicConstantExpressions() const {
342 std::unordered_set<const Type*> visitedTypes;
343 std::unordered_set<const ConstantExpression*> visitedCE;
344 std::unordered_set<const ConstantExpression*> stack;
Yifan Hong0e192c42018-10-23 15:32:19 -0700345 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
346 [&](const Type* type) -> status_t {
347 for (auto* ce : type->getConstantExpressions()) {
348 status_t err =
349 ce->checkAcyclic(&visitedCE, &stack).status;
350 CHECK(err != OK || stack.empty());
351 if (err != OK) return err;
352 }
353 return OK;
354 },
355 &visitedTypes);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700356}
357
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700358status_t AST::checkForwardReferenceRestrictions() const {
359 std::unordered_set<const Type*> visited;
Yifan Hong0e192c42018-10-23 15:32:19 -0700360 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE,
361 [](const Type* type) -> status_t {
362 for (const Reference<Type>* ref : type->getReferences()) {
363 status_t err =
364 type->checkForwardReferenceRestrictions(*ref);
365 if (err != OK) return err;
366 }
367 return OK;
368 },
369 &visited);
Timur Iskhakov041fdfe2017-09-06 15:56:01 -0700370}
371
Andreas Huber5345ec22016-07-29 13:33:27 -0700372bool AST::addImport(const char *import) {
Steven Morelande1b157e2018-03-06 14:18:32 -0800373 FQName fqName;
374 if (!FQName::parse(import, &fqName)) {
Steven Moreland01857a32018-01-03 10:15:01 -0800375 std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
376 return false;
377 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700378
Andreas Huber5345ec22016-07-29 13:33:27 -0700379 fqName.applyDefaults(mPackage.package(), mPackage.version());
380
Andreas Huber5345ec22016-07-29 13:33:27 -0700381 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700382 // import a package
Andreas Huber4ba5c972017-11-29 11:06:25 -0800383
Andreas Huberd2943e12016-08-05 11:59:31 -0700384 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700385
Andreas Huberd2943e12016-08-05 11:59:31 -0700386 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700387 mCoordinator->appendPackageInterfacesToVector(fqName,
388 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700389
390 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700391 return false;
392 }
393
Andreas Huberd2943e12016-08-05 11:59:31 -0700394 for (const auto &subFQName : packageInterfaces) {
Andreas Huber4ba5c972017-11-29 11:06:25 -0800395 addToImportedNamesGranular(subFQName);
396
Yifan Hongf619fc72017-04-07 15:40:06 -0700397 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700398 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700399 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700400 return false;
401 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700402 // all previous single type imports are ignored.
403 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700404 }
405
406 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700407 }
408
Andreas Huber4ba5c972017-11-29 11:06:25 -0800409 addToImportedNamesGranular(fqName);
410
Yifan Hong1977ea32016-10-05 12:49:08 -0700411 // cases like android.hardware.foo@1.0::IFoo.Internal
412 // android.hardware.foo@1.0::Abc.Internal
413
414 // assume it is an interface, and try to import it.
415 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700416 // Do not enforce restrictions on imports.
Steven Moreland71f09132018-02-20 12:24:30 -0800417 AST* importAST;
418 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
419 Coordinator::Enforce::NONE);
420 if (err != OK) return false;
421 // importAST nullptr == file doesn't exist
Yifan Hong1977ea32016-10-05 12:49:08 -0700422
423 if (importAST != nullptr) {
424 // cases like android.hardware.foo@1.0::IFoo.Internal
425 // and android.hardware.foo@1.0::IFoo
426 if (fqName == interfaceName) {
427 // import a single file.
428 // all previous single type imports are ignored.
429 // cases like android.hardware.foo@1.0::IFoo
430 // and android.hardware.foo@1.0::types
431 mImportedTypes.erase(importAST);
432 return true;
433 }
434
435 // import a single type from this file
436 // cases like android.hardware.foo@1.0::IFoo.Internal
437 FQName matchingName;
438 Type *match = importAST->findDefinedType(fqName, &matchingName);
439 if (match == nullptr) {
440 return false;
441 }
442 // will automatically create a set if it does not exist
443 mImportedTypes[importAST].insert(match);
444 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700445 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700446
Yifan Hong1977ea32016-10-05 12:49:08 -0700447 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
448 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700449
450 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700451 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700452
453 if (importAST != nullptr) {
454 // Attempt to find Abc.Internal in types.
455 FQName matchingName;
456 Type *match = importAST->findDefinedType(fqName, &matchingName);
457 if (match == nullptr) {
458 return false;
459 }
460 // will automatically create a set if not exist
461 mImportedTypes[importAST].insert(match);
462 return true;
463 }
464
465 // can't find an appropriate AST for fqName.
466 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700467}
468
Andreas Huber39fa7182016-08-19 14:27:33 -0700469void AST::addImportedAST(AST *ast) {
470 mImportedASTs.insert(ast);
471}
472
Timur Iskhakov565b0132017-09-06 18:07:11 -0700473FQName AST::makeFullName(const char* localName, Scope* scope) const {
474 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700475 for (; scope != &mRootScope; scope = scope->parent()) {
476 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700477 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700478
479 std::reverse(pathComponents.begin(), pathComponents.end());
480 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700481
Timur Iskhakov565b0132017-09-06 18:07:11 -0700482 return FQName(mPackage.package(), mPackage.version(), path);
483}
Andreas Huber39fa7182016-08-19 14:27:33 -0700484
Timur Iskhakov565b0132017-09-06 18:07:11 -0700485void AST::addScopedType(NamedType* type, Scope* scope) {
486 scope->addType(type);
487 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700488}
489
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700490LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) {
491 const FQName& fqName = ref.getLookupFqName();
492
493 if (fqName.isIdentifier()) {
494 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
495 if (iden == nullptr) {
496 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
497 << ref.location() << "\n";
498 return nullptr;
499 }
500 return iden;
501 } else {
502 std::string errorMsg;
503 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
504 if (enumValue == nullptr) {
505 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
506 return nullptr;
507 }
508 return enumValue;
509 }
510}
511
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700512EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700513 FQName enumTypeName = fqName.typeName();
514 std::string enumValueName = fqName.valueName();
515
Yifan Hongf24fa852016-09-23 11:03:15 -0700516 CHECK(!enumValueName.empty());
517
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700518 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700519 if(type == nullptr) {
520 *errorMsg = "Cannot find type " + enumTypeName.string();
521 return nullptr;
522 }
Steven Morelandd965ce92017-11-27 16:05:34 -0800523 type = type->resolve();
Yifan Hongf24fa852016-09-23 11:03:15 -0700524 if(!type->isEnum()) {
525 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
526 return nullptr;
527 }
528
529 EnumType *enumType = static_cast<EnumType *>(type);
530 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
531 if(v == nullptr) {
532 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
533 return nullptr;
534 }
Andreas Huber4ba5c972017-11-29 11:06:25 -0800535
536 mReferencedTypeNames.insert(enumType->fqName());
537
Yifan Hongf24fa852016-09-23 11:03:15 -0700538 return v;
539}
540
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700541Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700542 if (fqName.name().empty()) {
543 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700544 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700545 }
546
Yifan Hong87ff8232017-01-09 12:07:05 -0800547 Type *returnedType = nullptr;
548
Andreas Huber84f89de2016-07-28 15:39:51 -0700549 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800550 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700551 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800552 if (returnedType != nullptr) {
553 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700554 }
555 }
556
Steven Moreland87e69dc2017-09-12 18:14:28 -0700557 status_t status = lookupAutofilledType(fqName, &returnedType);
558 if (status != OK) {
559 return nullptr;
560 }
561 if (returnedType != nullptr) {
562 return returnedType;
Yifan Hong87ff8232017-01-09 12:07:05 -0800563 }
564
565 return lookupTypeFromImports(fqName);
566}
567
568// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700569Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800570 CHECK(fqName.package().empty() && fqName.version().empty()
571 && !fqName.name().empty() && fqName.valueName().empty());
572
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700573 for (; scope != nullptr; scope = scope->parent()) {
574 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800575 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800576 return type;
577 }
578 }
579
580 return nullptr;
581}
582
583// Rule 1: auto-fill with current package
584status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
Steven Moreland87e69dc2017-09-12 18:14:28 -0700585 CHECK(!fqName.name().empty() && fqName.valueName().empty());
Yifan Hong87ff8232017-01-09 12:07:05 -0800586
587 FQName autofilled = fqName;
588 autofilled.applyDefaults(mPackage.package(), mPackage.version());
589 FQName matchingName;
590 // Given this fully-qualified name, the type may be defined in this AST, or other files
591 // in import.
592 Type *local = findDefinedType(autofilled, &matchingName);
593 CHECK(local == nullptr || autofilled == matchingName);
Steven Moreland87e69dc2017-09-12 18:14:28 -0700594 Type* fromImport = lookupTypeFromImports(autofilled);
Yifan Hong87ff8232017-01-09 12:07:05 -0800595
596 if (local != nullptr && fromImport != nullptr && local != fromImport) {
597 // Something bad happen; two types have the same FQName.
598 std::cerr << "ERROR: Unable to resolve type name '"
599 << fqName.string()
600 << "' (i.e. '"
601 << autofilled.string()
602 << "'), multiple definitions found.\n";
603
604 return UNKNOWN_ERROR;
605 }
606 if (local != nullptr) {
607 *returnedType = local;
608 return OK;
609 }
610 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
611 *returnedType = fromImport;
612 return OK;
613}
614
615// Rule 2: look at imports
616Type *AST::lookupTypeFromImports(const FQName &fqName) {
617
Andreas Huber39fa7182016-08-19 14:27:33 -0700618 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700619 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700620 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700621
Andreas Huber39fa7182016-08-19 14:27:33 -0700622 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700623 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
624 // ignore single type imports
625 continue;
626 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700627 FQName matchingName;
628 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700629
Andreas Huber39fa7182016-08-19 14:27:33 -0700630 if (match != nullptr) {
631 if (resolvedType != nullptr) {
632 std::cerr << "ERROR: Unable to resolve type name '"
633 << fqName.string()
634 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700635
Andreas Huber39fa7182016-08-19 14:27:33 -0700636 std::cerr << " " << resolvedName.string() << "\n";
637 std::cerr << " " << matchingName.string() << "\n";
638
Yifan Hong1977ea32016-10-05 12:49:08 -0700639 return nullptr;
640 }
641
642 resolvedType = match;
643 returnedType = resolvedType;
644 resolvedName = matchingName;
645
646 // Keep going even after finding a match.
647 }
648 }
649
650 for (const auto &pair : mImportedTypes) {
651 AST *importedAST = pair.first;
652 std::set<Type *> importedTypes = pair.second;
653
654 FQName matchingName;
655 Type *match = importedAST->findDefinedType(fqName, &matchingName);
656 if (match != nullptr &&
657 importedTypes.find(match) != importedTypes.end()) {
658 if (resolvedType != nullptr) {
659 std::cerr << "ERROR: Unable to resolve type name '"
660 << fqName.string()
661 << "', multiple matches found:\n";
662
663 std::cerr << " " << resolvedName.string() << "\n";
664 std::cerr << " " << matchingName.string() << "\n";
665
666 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700667 }
668
669 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700670 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700671 resolvedName = matchingName;
672
673 // Keep going even after finding a match.
674 }
675 }
676
677 if (resolvedType) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700678 returnedType = resolvedType;
679
680 // If the resolved type is not an interface, we need to determine
681 // whether it is defined in types.hal, or in some other interface. In
682 // the latter case, we need to emit a dependency for the interface in
683 // which the type is defined.
684 //
685 // Consider the following:
686 // android.hardware.tests.foo@1.0::Record
687 // android.hardware.tests.foo@1.0::IFoo.Folder
688 // android.hardware.tests.foo@1.0::Folder
689 //
690 // If Record is an interface, then we keep track of it for the purpose
691 // of emitting dependencies in the target language (for example #include
692 // in C++). If Record is a UDT, then we assume it is defined in
693 // types.hal in android.hardware.tests.foo@1.0.
694 //
695 // In the case of IFoo.Folder, the same applies. If IFoo is an
696 // interface, we need to track this for the purpose of emitting
697 // dependencies. If not, then it must have been defined in types.hal.
698 //
699 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800700 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700701 // above applies.
702
703 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800704 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700705 for (const auto &importedAST : mImportedASTs) {
706 FQName matchingName;
707 Type *match = importedAST->findDefinedType(ifc, &matchingName);
708 if (match != nullptr && match->isInterface()) {
709 resolvedType = match;
710 }
711 }
712 }
713
Andreas Huber39fa7182016-08-19 14:27:33 -0700714 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700715 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800716 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700717
Andreas Huber0e00de42016-08-03 09:56:02 -0700718 mImportedNames.insert(typesName);
719 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700720 // Do _not_ use fqName, i.e. the name we used to look up the type,
721 // but instead use the name of the interface we found.
722 // This is necessary because if fqName pointed to a typedef which
723 // in turn referenced the found interface we'd mistakenly use the
724 // name of the typedef instead of the proper name of the interface.
725
Andreas Huber4ba5c972017-11-29 11:06:25 -0800726 const FQName &typeName =
727 static_cast<Interface *>(resolvedType)->fqName();
728
729 mImportedNames.insert(typeName);
Andreas Huber0e00de42016-08-03 09:56:02 -0700730 }
Andreas Huber737080b2016-08-02 15:38:04 -0700731 }
732
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700733 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700734}
735
Andreas Huber4ba5c972017-11-29 11:06:25 -0800736void AST::addToImportedNamesGranular(const FQName &fqName) {
737 if (fqName.package() == package().package()
738 && fqName.version() == package().version()) {
739 // Our own names are _defined_ here, not imported.
740 return;
741 }
742
743 mImportedNamesGranular.insert(fqName);
744}
745
Andreas Huber39fa7182016-08-19 14:27:33 -0700746Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700747 for (const auto &pair : mDefinedTypesByFullName) {
748 const FQName &key = pair.first;
749 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700750
Andreas Huber39fa7182016-08-19 14:27:33 -0700751 if (key.endsWith(fqName)) {
752 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700753 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700754 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700755 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700756
757 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700758}
759
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700760void AST::getImportedPackages(std::set<FQName> *importSet) const {
Steven Moreland06a81cf2018-01-17 11:13:46 -0800761 for (const auto& fqName : mImportedNamesGranular) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800762 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700763
764 if (packageName == mPackage) {
765 // We only care about external imports, not our own package.
766 continue;
767 }
768
769 importSet->insert(packageName);
770 }
771}
772
Yifan Hong40a373d2016-11-30 15:16:47 -0800773void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
774 getImportedPackages(importSet);
Steven Moreland06a81cf2018-01-17 11:13:46 -0800775
Yifan Hong40a373d2016-11-30 15:16:47 -0800776 std::set<FQName> newSet;
777 for (const auto &ast : mImportedASTs) {
778 if (importSet->find(ast->package()) != importSet->end()) {
779 ast->getImportedPackagesHierarchy(&newSet);
780 }
781 }
782 importSet->insert(newSet.begin(), newSet.end());
783}
784
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800785void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
786 for (const auto& name : mImportedNames) {
787 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700788 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800789 ast->getAllImportedNames(allImportNames);
790 }
791}
792
Andreas Huber4ba5c972017-11-29 11:06:25 -0800793void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
794 for (const auto& fqName : mImportedNamesGranular) {
795 if (fqName.name() == "types") {
796 // A package will export everything _defined_ but will not
797 // re-export anything it itself imported.
798 AST* ast = mCoordinator->parse(
799 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
800
801 ast->addDefinedTypes(allImportNames);
802 } else {
803 allImportNames->insert(fqName);
804 }
805 }
806}
807
Andreas Huber0fa9e392016-08-31 09:05:44 -0700808bool AST::isJavaCompatible() const {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700809 return mRootScope.isJavaCompatible();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700810}
811
Andreas Huber019d21d2016-10-03 12:59:47 -0700812void AST::appendToExportedTypesVector(
813 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700814 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700815}
816
Yifan Hongc8934042016-11-17 17:10:52 -0800817bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700818 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800819 return iface != nullptr && iface->isIBase();
820}
821
Yifan Hong78b38d12017-02-13 18:14:46 +0000822const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700823 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000824}
825
Steven Moreland19f11b52017-05-12 18:22:21 -0700826std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700827 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700828
829 return iface ? iface->getBaseName() : "types";
830}
831
Andreas Huber308d8a22017-11-06 14:46:52 -0800832void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
833 std::for_each(
834 mDefinedTypesByFullName.begin(),
835 mDefinedTypesByFullName.end(),
836 [definedTypes](const auto &elem) {
837 if (!elem.second->isTypeDef()) {
838 definedTypes->insert(elem.first);
839 }
840 });
841}
842
843void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
844 std::for_each(
845 mReferencedTypeNames.begin(),
846 mReferencedTypeNames.end(),
847 [referencedTypes](const auto &fqName) {
848 referencedTypes->insert(fqName);
849 });
850}
851
Neel Mehta0ee353f2019-05-30 17:40:29 -0700852bool AST::addMethod(Method* method, Interface* iface) {
853 if (iface->isIBase()) {
854 if (!mAllReservedMethods.emplace(method->name(), method).second) {
855 std::cerr << "ERROR: hidl-gen encountered duplicated reserved method " << method->name()
856 << std::endl;
857 return false;
858 }
859
860 // methods will be added to iface in addAllReservedMethodsToInterface
861 return true;
862 }
863
864 iface->addUserDefinedMethod(method);
865
866 return true;
867}
868
869bool AST::addAllReservedMethodsToInterface(Interface* iface) {
870 std::map<std::string, Method*> allReservedMethods(mAllReservedMethods);
871 // Looking for the IBase AST which is imported for all interfaces that are not IBase
872 for (const AST* importedAST : mImportedASTs) {
873 allReservedMethods.insert(importedAST->mAllReservedMethods.begin(),
874 importedAST->mAllReservedMethods.end());
875 }
876
877 return iface->addAllReservedMethods(allReservedMethods);
878}
879
Andreas Huberc9410c72016-07-28 12:18:40 -0700880} // namespace android;