blob: 68554a05a8d57c7dcc2b34414bc6a5f77e3d84ec [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
Neel Mehta55c065e2019-05-31 13:30:12 -0700372bool AST::addImport(const char* import, const Location& location) {
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
Neel Mehta55c065e2019-05-31 13:30:12 -0700381 mImportStatements.push_back({fqName, location});
382
Andreas Huber5345ec22016-07-29 13:33:27 -0700383 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700384 // import a package
Andreas Huber4ba5c972017-11-29 11:06:25 -0800385
Andreas Huberd2943e12016-08-05 11:59:31 -0700386 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700387
Andreas Huberd2943e12016-08-05 11:59:31 -0700388 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700389 mCoordinator->appendPackageInterfacesToVector(fqName,
390 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700391
392 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700393 return false;
394 }
395
Andreas Huberd2943e12016-08-05 11:59:31 -0700396 for (const auto &subFQName : packageInterfaces) {
Andreas Huber4ba5c972017-11-29 11:06:25 -0800397 addToImportedNamesGranular(subFQName);
398
Yifan Hongf619fc72017-04-07 15:40:06 -0700399 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700400 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700401 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700402 return false;
403 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700404 // all previous single type imports are ignored.
405 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700406 }
407
408 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700409 }
410
Andreas Huber4ba5c972017-11-29 11:06:25 -0800411 addToImportedNamesGranular(fqName);
412
Yifan Hong1977ea32016-10-05 12:49:08 -0700413 // cases like android.hardware.foo@1.0::IFoo.Internal
414 // android.hardware.foo@1.0::Abc.Internal
415
416 // assume it is an interface, and try to import it.
417 const FQName interfaceName = fqName.getTopLevelType();
Yifan Hongf619fc72017-04-07 15:40:06 -0700418 // Do not enforce restrictions on imports.
Steven Moreland71f09132018-02-20 12:24:30 -0800419 AST* importAST;
420 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
421 Coordinator::Enforce::NONE);
422 if (err != OK) return false;
423 // importAST nullptr == file doesn't exist
Yifan Hong1977ea32016-10-05 12:49:08 -0700424
425 if (importAST != nullptr) {
426 // cases like android.hardware.foo@1.0::IFoo.Internal
427 // and android.hardware.foo@1.0::IFoo
428 if (fqName == interfaceName) {
429 // import a single file.
430 // all previous single type imports are ignored.
431 // cases like android.hardware.foo@1.0::IFoo
432 // and android.hardware.foo@1.0::types
433 mImportedTypes.erase(importAST);
434 return true;
435 }
436
437 // import a single type from this file
438 // cases like android.hardware.foo@1.0::IFoo.Internal
439 FQName matchingName;
440 Type *match = importAST->findDefinedType(fqName, &matchingName);
441 if (match == nullptr) {
442 return false;
443 }
444 // will automatically create a set if it does not exist
445 mImportedTypes[importAST].insert(match);
446 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700447 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700448
Yifan Hong1977ea32016-10-05 12:49:08 -0700449 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
450 FQName typesFQName = fqName.getTypesForPackage();
Yifan Hongf619fc72017-04-07 15:40:06 -0700451
452 // Do not enforce restrictions on imports.
Steven Morelandc59326e2017-06-20 15:19:30 -0700453 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
Yifan Hong1977ea32016-10-05 12:49:08 -0700454
455 if (importAST != nullptr) {
456 // Attempt to find Abc.Internal in types.
457 FQName matchingName;
458 Type *match = importAST->findDefinedType(fqName, &matchingName);
459 if (match == nullptr) {
460 return false;
461 }
462 // will automatically create a set if not exist
463 mImportedTypes[importAST].insert(match);
464 return true;
465 }
466
467 // can't find an appropriate AST for fqName.
468 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700469}
470
Andreas Huber39fa7182016-08-19 14:27:33 -0700471void AST::addImportedAST(AST *ast) {
472 mImportedASTs.insert(ast);
473}
474
Timur Iskhakov565b0132017-09-06 18:07:11 -0700475FQName AST::makeFullName(const char* localName, Scope* scope) const {
476 std::vector<std::string> pathComponents{{localName}};
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700477 for (; scope != &mRootScope; scope = scope->parent()) {
478 pathComponents.push_back(scope->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700479 }
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700480
481 std::reverse(pathComponents.begin(), pathComponents.end());
482 std::string path = StringHelper::JoinStrings(pathComponents, ".");
Andreas Huber31629bc2016-08-03 09:06:40 -0700483
Timur Iskhakov565b0132017-09-06 18:07:11 -0700484 return FQName(mPackage.package(), mPackage.version(), path);
485}
Andreas Huber39fa7182016-08-19 14:27:33 -0700486
Timur Iskhakov565b0132017-09-06 18:07:11 -0700487void AST::addScopedType(NamedType* type, Scope* scope) {
488 scope->addType(type);
489 mDefinedTypesByFullName[type->fqName()] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700490}
491
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700492LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) {
493 const FQName& fqName = ref.getLookupFqName();
494
495 if (fqName.isIdentifier()) {
496 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
497 if (iden == nullptr) {
498 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
499 << ref.location() << "\n";
500 return nullptr;
501 }
502 return iden;
503 } else {
504 std::string errorMsg;
505 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
506 if (enumValue == nullptr) {
507 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
508 return nullptr;
509 }
510 return enumValue;
511 }
512}
513
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700514EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700515 FQName enumTypeName = fqName.typeName();
516 std::string enumValueName = fqName.valueName();
517
Yifan Hongf24fa852016-09-23 11:03:15 -0700518 CHECK(!enumValueName.empty());
519
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700520 Type* type = lookupType(enumTypeName, scope);
Yifan Hongf24fa852016-09-23 11:03:15 -0700521 if(type == nullptr) {
522 *errorMsg = "Cannot find type " + enumTypeName.string();
523 return nullptr;
524 }
Steven Morelandd965ce92017-11-27 16:05:34 -0800525 type = type->resolve();
Yifan Hongf24fa852016-09-23 11:03:15 -0700526 if(!type->isEnum()) {
527 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
528 return nullptr;
529 }
530
531 EnumType *enumType = static_cast<EnumType *>(type);
532 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
533 if(v == nullptr) {
534 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
535 return nullptr;
536 }
Andreas Huber4ba5c972017-11-29 11:06:25 -0800537
538 mReferencedTypeNames.insert(enumType->fqName());
539
Yifan Hongf24fa852016-09-23 11:03:15 -0700540 return v;
541}
542
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700543Type* AST::lookupType(const FQName& fqName, Scope* scope) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700544 if (fqName.name().empty()) {
545 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700546 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700547 }
548
Yifan Hong87ff8232017-01-09 12:07:05 -0800549 Type *returnedType = nullptr;
550
Andreas Huber84f89de2016-07-28 15:39:51 -0700551 if (fqName.package().empty() && fqName.version().empty()) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800552 // resolve locally first if possible.
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700553 returnedType = lookupTypeLocally(fqName, scope);
Yifan Hong87ff8232017-01-09 12:07:05 -0800554 if (returnedType != nullptr) {
555 return returnedType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700556 }
557 }
558
Steven Moreland87e69dc2017-09-12 18:14:28 -0700559 status_t status = lookupAutofilledType(fqName, &returnedType);
560 if (status != OK) {
561 return nullptr;
562 }
563 if (returnedType != nullptr) {
564 return returnedType;
Yifan Hong87ff8232017-01-09 12:07:05 -0800565 }
566
567 return lookupTypeFromImports(fqName);
568}
569
570// Rule 0: try resolve locally
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700571Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800572 CHECK(fqName.package().empty() && fqName.version().empty()
573 && !fqName.name().empty() && fqName.valueName().empty());
574
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700575 for (; scope != nullptr; scope = scope->parent()) {
576 Type* type = scope->lookupType(fqName);
Yifan Hong87ff8232017-01-09 12:07:05 -0800577 if (type != nullptr) {
Yifan Hong87ff8232017-01-09 12:07:05 -0800578 return type;
579 }
580 }
581
582 return nullptr;
583}
584
585// Rule 1: auto-fill with current package
586status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
Steven Moreland87e69dc2017-09-12 18:14:28 -0700587 CHECK(!fqName.name().empty() && fqName.valueName().empty());
Yifan Hong87ff8232017-01-09 12:07:05 -0800588
589 FQName autofilled = fqName;
590 autofilled.applyDefaults(mPackage.package(), mPackage.version());
591 FQName matchingName;
592 // Given this fully-qualified name, the type may be defined in this AST, or other files
593 // in import.
594 Type *local = findDefinedType(autofilled, &matchingName);
595 CHECK(local == nullptr || autofilled == matchingName);
Steven Moreland87e69dc2017-09-12 18:14:28 -0700596 Type* fromImport = lookupTypeFromImports(autofilled);
Yifan Hong87ff8232017-01-09 12:07:05 -0800597
598 if (local != nullptr && fromImport != nullptr && local != fromImport) {
599 // Something bad happen; two types have the same FQName.
600 std::cerr << "ERROR: Unable to resolve type name '"
601 << fqName.string()
602 << "' (i.e. '"
603 << autofilled.string()
604 << "'), multiple definitions found.\n";
605
606 return UNKNOWN_ERROR;
607 }
608 if (local != nullptr) {
609 *returnedType = local;
610 return OK;
611 }
612 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
613 *returnedType = fromImport;
614 return OK;
615}
616
617// Rule 2: look at imports
618Type *AST::lookupTypeFromImports(const FQName &fqName) {
619
Andreas Huber39fa7182016-08-19 14:27:33 -0700620 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700621 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700622 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700623
Andreas Huber39fa7182016-08-19 14:27:33 -0700624 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700625 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
626 // ignore single type imports
627 continue;
628 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700629 FQName matchingName;
630 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700631
Andreas Huber39fa7182016-08-19 14:27:33 -0700632 if (match != nullptr) {
633 if (resolvedType != nullptr) {
634 std::cerr << "ERROR: Unable to resolve type name '"
635 << fqName.string()
636 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700637
Andreas Huber39fa7182016-08-19 14:27:33 -0700638 std::cerr << " " << resolvedName.string() << "\n";
639 std::cerr << " " << matchingName.string() << "\n";
640
Yifan Hong1977ea32016-10-05 12:49:08 -0700641 return nullptr;
642 }
643
644 resolvedType = match;
645 returnedType = resolvedType;
646 resolvedName = matchingName;
647
648 // Keep going even after finding a match.
649 }
650 }
651
652 for (const auto &pair : mImportedTypes) {
653 AST *importedAST = pair.first;
654 std::set<Type *> importedTypes = pair.second;
655
656 FQName matchingName;
657 Type *match = importedAST->findDefinedType(fqName, &matchingName);
658 if (match != nullptr &&
659 importedTypes.find(match) != importedTypes.end()) {
660 if (resolvedType != nullptr) {
661 std::cerr << "ERROR: Unable to resolve type name '"
662 << fqName.string()
663 << "', multiple matches found:\n";
664
665 std::cerr << " " << resolvedName.string() << "\n";
666 std::cerr << " " << matchingName.string() << "\n";
667
668 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700669 }
670
671 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700672 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700673 resolvedName = matchingName;
674
675 // Keep going even after finding a match.
676 }
677 }
678
679 if (resolvedType) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700680 returnedType = resolvedType;
681
682 // If the resolved type is not an interface, we need to determine
683 // whether it is defined in types.hal, or in some other interface. In
684 // the latter case, we need to emit a dependency for the interface in
685 // which the type is defined.
686 //
687 // Consider the following:
688 // android.hardware.tests.foo@1.0::Record
689 // android.hardware.tests.foo@1.0::IFoo.Folder
690 // android.hardware.tests.foo@1.0::Folder
691 //
692 // If Record is an interface, then we keep track of it for the purpose
693 // of emitting dependencies in the target language (for example #include
694 // in C++). If Record is a UDT, then we assume it is defined in
695 // types.hal in android.hardware.tests.foo@1.0.
696 //
697 // In the case of IFoo.Folder, the same applies. If IFoo is an
698 // interface, we need to track this for the purpose of emitting
699 // dependencies. If not, then it must have been defined in types.hal.
700 //
701 // In the case of just specifying Folder, the resolved type is
Yifan Hongfece6ec2017-01-12 17:04:04 -0800702 // android.hardware.tests.foo@1.0::Folder, and the same logic as
Iliyan Malchev800273d2016-09-02 15:25:07 -0700703 // above applies.
704
705 if (!resolvedType->isInterface()) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800706 FQName ifc = resolvedName.getTopLevelType();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700707 for (const auto &importedAST : mImportedASTs) {
708 FQName matchingName;
709 Type *match = importedAST->findDefinedType(ifc, &matchingName);
710 if (match != nullptr && match->isInterface()) {
711 resolvedType = match;
712 }
713 }
714 }
715
Andreas Huber39fa7182016-08-19 14:27:33 -0700716 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700717 // Non-interface types are declared in the associated types header.
Yifan Hongfece6ec2017-01-12 17:04:04 -0800718 FQName typesName = resolvedName.getTypesForPackage();
Andreas Huber39fa7182016-08-19 14:27:33 -0700719
Andreas Huber0e00de42016-08-03 09:56:02 -0700720 mImportedNames.insert(typesName);
721 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700722 // Do _not_ use fqName, i.e. the name we used to look up the type,
723 // but instead use the name of the interface we found.
724 // This is necessary because if fqName pointed to a typedef which
725 // in turn referenced the found interface we'd mistakenly use the
726 // name of the typedef instead of the proper name of the interface.
727
Andreas Huber4ba5c972017-11-29 11:06:25 -0800728 const FQName &typeName =
729 static_cast<Interface *>(resolvedType)->fqName();
730
731 mImportedNames.insert(typeName);
Andreas Huber0e00de42016-08-03 09:56:02 -0700732 }
Andreas Huber737080b2016-08-02 15:38:04 -0700733 }
734
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700735 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700736}
737
Andreas Huber4ba5c972017-11-29 11:06:25 -0800738void AST::addToImportedNamesGranular(const FQName &fqName) {
739 if (fqName.package() == package().package()
740 && fqName.version() == package().version()) {
741 // Our own names are _defined_ here, not imported.
742 return;
743 }
744
745 mImportedNamesGranular.insert(fqName);
746}
747
Andreas Huber39fa7182016-08-19 14:27:33 -0700748Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700749 for (const auto &pair : mDefinedTypesByFullName) {
750 const FQName &key = pair.first;
751 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700752
Andreas Huber39fa7182016-08-19 14:27:33 -0700753 if (key.endsWith(fqName)) {
754 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700755 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700756 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700757 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700758
759 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700760}
761
Neel Mehta55c065e2019-05-31 13:30:12 -0700762const std::vector<ImportStatement>& AST::getImportStatements() const {
763 return mImportStatements;
764}
765
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700766void AST::getImportedPackages(std::set<FQName> *importSet) const {
Steven Moreland06a81cf2018-01-17 11:13:46 -0800767 for (const auto& fqName : mImportedNamesGranular) {
Yifan Hongfece6ec2017-01-12 17:04:04 -0800768 FQName packageName = fqName.getPackageAndVersion();
Andreas Huberd2943e12016-08-05 11:59:31 -0700769
770 if (packageName == mPackage) {
771 // We only care about external imports, not our own package.
772 continue;
773 }
774
775 importSet->insert(packageName);
776 }
777}
778
Yifan Hong40a373d2016-11-30 15:16:47 -0800779void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
780 getImportedPackages(importSet);
Steven Moreland06a81cf2018-01-17 11:13:46 -0800781
Yifan Hong40a373d2016-11-30 15:16:47 -0800782 std::set<FQName> newSet;
783 for (const auto &ast : mImportedASTs) {
784 if (importSet->find(ast->package()) != importSet->end()) {
785 ast->getImportedPackagesHierarchy(&newSet);
786 }
787 }
788 importSet->insert(newSet.begin(), newSet.end());
789}
790
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800791void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
792 for (const auto& name : mImportedNames) {
793 allImportNames->insert(name);
Steven Morelandc59326e2017-06-20 15:19:30 -0700794 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800795 ast->getAllImportedNames(allImportNames);
796 }
797}
798
Andreas Huber4ba5c972017-11-29 11:06:25 -0800799void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
800 for (const auto& fqName : mImportedNamesGranular) {
801 if (fqName.name() == "types") {
802 // A package will export everything _defined_ but will not
803 // re-export anything it itself imported.
804 AST* ast = mCoordinator->parse(
805 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
806
807 ast->addDefinedTypes(allImportNames);
808 } else {
809 allImportNames->insert(fqName);
810 }
811 }
812}
813
Andreas Huber0fa9e392016-08-31 09:05:44 -0700814bool AST::isJavaCompatible() const {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700815 return mRootScope.isJavaCompatible();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700816}
817
Andreas Huber019d21d2016-10-03 12:59:47 -0700818void AST::appendToExportedTypesVector(
819 std::vector<const Type *> *exportedTypes) const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700820 mRootScope.appendToExportedTypesVector(exportedTypes);
Andreas Huber019d21d2016-10-03 12:59:47 -0700821}
822
Yifan Hongc8934042016-11-17 17:10:52 -0800823bool AST::isIBase() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700824 Interface* iface = mRootScope.getInterface();
Yifan Hongc8934042016-11-17 17:10:52 -0800825 return iface != nullptr && iface->isIBase();
826}
827
Yifan Hong78b38d12017-02-13 18:14:46 +0000828const Interface *AST::getInterface() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700829 return mRootScope.getInterface();
Yifan Hong78b38d12017-02-13 18:14:46 +0000830}
831
Steven Moreland19f11b52017-05-12 18:22:21 -0700832std::string AST::getBaseName() const {
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700833 const Interface* iface = mRootScope.getInterface();
Steven Moreland19f11b52017-05-12 18:22:21 -0700834
835 return iface ? iface->getBaseName() : "types";
836}
837
Andreas Huber308d8a22017-11-06 14:46:52 -0800838void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
839 std::for_each(
840 mDefinedTypesByFullName.begin(),
841 mDefinedTypesByFullName.end(),
842 [definedTypes](const auto &elem) {
843 if (!elem.second->isTypeDef()) {
844 definedTypes->insert(elem.first);
845 }
846 });
847}
848
849void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
850 std::for_each(
851 mReferencedTypeNames.begin(),
852 mReferencedTypeNames.end(),
853 [referencedTypes](const auto &fqName) {
854 referencedTypes->insert(fqName);
855 });
856}
857
Neel Mehta0ee353f2019-05-30 17:40:29 -0700858bool AST::addMethod(Method* method, Interface* iface) {
859 if (iface->isIBase()) {
860 if (!mAllReservedMethods.emplace(method->name(), method).second) {
861 std::cerr << "ERROR: hidl-gen encountered duplicated reserved method " << method->name()
862 << std::endl;
863 return false;
864 }
865
866 // methods will be added to iface in addAllReservedMethodsToInterface
867 return true;
868 }
869
870 iface->addUserDefinedMethod(method);
871
872 return true;
873}
874
875bool AST::addAllReservedMethodsToInterface(Interface* iface) {
876 std::map<std::string, Method*> allReservedMethods(mAllReservedMethods);
877 // Looking for the IBase AST which is imported for all interfaces that are not IBase
878 for (const AST* importedAST : mImportedASTs) {
879 allReservedMethods.insert(importedAST->mAllReservedMethods.begin(),
880 importedAST->mAllReservedMethods.end());
881 }
882
883 return iface->addAllReservedMethods(allReservedMethods);
884}
885
Andreas Huberc9410c72016-07-28 12:18:40 -0700886} // namespace android;