1 /*
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
17 #include "AST.h"
18
19 #include "Coordinator.h"
20 #include "EnumType.h"
21 #include "FmqType.h"
22 #include "HandleType.h"
23 #include "Interface.h"
24 #include "Location.h"
25 #include "Method.h"
26 #include "Scope.h"
27 #include "TypeDef.h"
28
29 #include <android-base/logging.h>
30 #include <hidl-util/FQName.h>
31 #include <hidl-util/Formatter.h>
32 #include <hidl-util/StringHelper.h>
33 #include <stdlib.h>
34
35 #include <algorithm>
36 #include <iostream>
37 #include <map>
38 #include <string>
39
40 namespace android {
41
AST(const Coordinator * coordinator,const Hash * fileHash)42 AST::AST(const Coordinator* coordinator, const Hash* fileHash)
43 : mCoordinator(coordinator),
44 mFileHash(fileHash),
45 mRootScope("(root scope)", FQName(),
46 Location::startOf(coordinator->makeRelative(fileHash->getPath())),
47 nullptr /* parent */) {}
48
getMutableRootScope()49 Scope* AST::getMutableRootScope() {
50 return &mRootScope;
51 }
52
getRootScope() const53 const Scope& AST::getRootScope() const {
54 return mRootScope;
55 }
56
57 // used by the parser.
addSyntaxError()58 void AST::addSyntaxError() {
59 mSyntaxErrors++;
60 }
61
syntaxErrors() const62 size_t AST::syntaxErrors() const {
63 return mSyntaxErrors;
64 }
65
getFilename() const66 const std::string& AST::getFilename() const {
67 return mFileHash->getPath();
68 }
getFileHash() const69 const Hash* AST::getFileHash() const {
70 return mFileHash;
71 }
72
getCoordinator() const73 const Coordinator& AST::getCoordinator() const {
74 return *mCoordinator;
75 }
76
setPackage(const char * package)77 bool AST::setPackage(const char *package) {
78 if (!mPackage.setTo(package)) {
79 return false;
80 }
81
82 if (mPackage.package().empty()
83 || mPackage.version().empty()
84 || !mPackage.name().empty()) {
85 return false;
86 }
87
88 return true;
89 }
90
package() const91 FQName AST::package() const {
92 return mPackage;
93 }
94
isInterface() const95 bool AST::isInterface() const {
96 return mRootScope.getInterface() != nullptr;
97 }
98
definesInterfaces() const99 bool AST::definesInterfaces() const {
100 return mRootScope.definesInterfaces();
101 }
102
postParse()103 status_t AST::postParse() {
104 status_t err;
105
106 // lookupTypes is the first pass for references to be resolved.
107 err = lookupTypes();
108 if (err != OK) return err;
109
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
114 // validateDefinedTypesUniqueNames is the first call
115 // after lookup, as other errors could appear because
116 // user meant different type than we assumed.
117 err = validateDefinedTypesUniqueNames();
118 if (err != OK) return err;
119 // topologicalReorder is before resolveInheritance, as we
120 // need to have no cycle while getting parent class.
121 err = topologicalReorder();
122 if (err != OK) return err;
123 err = resolveInheritance();
124 if (err != OK) return err;
125 err = lookupConstantExpressions();
126 if (err != OK) return err;
127 // checkAcyclicConstantExpressions is after resolveInheritance,
128 // as resolveInheritance autofills enum values.
129 err = checkAcyclicConstantExpressions();
130 if (err != OK) return err;
131 err = validateConstantExpressions();
132 if (err != OK) return err;
133 err = evaluateConstantExpressions();
134 if (err != OK) return err;
135 err = validate();
136 if (err != OK) return err;
137 err = checkForwardReferenceRestrictions();
138 if (err != OK) return err;
139 err = gatherReferencedTypes();
140 if (err != OK) return err;
141
142 // Make future packages not to call passes
143 // for processed types and expressions
144 constantExpressionRecursivePass(
145 [](ConstantExpression* ce) {
146 ce->setPostParseCompleted();
147 return OK;
148 },
149 true /* processBeforeDependencies */);
150
151 err = setParseStage(Type::ParseStage::POST_PARSE, Type::ParseStage::COMPLETED);
152 if (err != OK) return err;
153
154 return OK;
155 }
156
constantExpressionRecursivePass(const std::function<status_t (ConstantExpression *)> & func,bool processBeforeDependencies)157 status_t AST::constantExpressionRecursivePass(
158 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) {
159 std::unordered_set<const Type*> visitedTypes;
160 std::unordered_set<const ConstantExpression*> visitedCE;
161 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
constantExpressionRecursivePass(const std::function<status_t (const ConstantExpression *)> & func,bool processBeforeDependencies) const173 status_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
setParseStage(Type::ParseStage oldStage,Type::ParseStage newStage)190 status_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);
199 }
200
lookupTypes()201 status_t AST::lookupTypes() {
202 std::unordered_set<const Type*> visited;
203 return mRootScope.recursivePass(
204 Type::ParseStage::PARSE,
205 [&](Type* type) -> status_t {
206 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent();
207
208 for (auto* nextRef : type->getReferences()) {
209 if (nextRef->isResolved()) {
210 continue;
211 }
212
213 Type* nextType = lookupType(nextRef->getLookupFqName(), scope);
214 if (nextType == nullptr) {
215 std::cerr << "ERROR: Failed to lookup type '"
216 << nextRef->getLookupFqName().string() << "' at "
217 << nextRef->location()
218 << " (is it imported and spelled correctly?)\n";
219 return UNKNOWN_ERROR;
220 }
221 nextRef->set(nextType);
222 }
223
224 return OK;
225 },
226 &visited);
227 }
228
gatherReferencedTypes()229 status_t AST::gatherReferencedTypes() {
230 std::unordered_set<const Type*> visited;
231 return mRootScope.recursivePass(
232 Type::ParseStage::POST_PARSE,
233 [&](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
lookupConstantExpressions()247 status_t AST::lookupConstantExpressions() {
248 std::unordered_set<const Type*> visitedTypes;
249 std::unordered_set<const ConstantExpression*> visitedCE;
250
251 return mRootScope.recursivePass(
252 Type::ParseStage::POST_PARSE,
253 [&](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 }
266 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 }
278 return OK;
279 },
280 &visitedCE, true /* processBeforeDependencies */);
281 if (err != OK) return err;
282 }
283
284 return OK;
285 },
286 &visitedTypes);
287 }
288
validateDefinedTypesUniqueNames() const289 status_t AST::validateDefinedTypesUniqueNames() const {
290 std::unordered_set<const Type*> visited;
291 return mRootScope.recursivePass(
292 Type::ParseStage::POST_PARSE,
293 [&](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
resolveInheritance()303 status_t AST::resolveInheritance() {
304 std::unordered_set<const Type*> visited;
305 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::resolveInheritance,
306 &visited);
307 }
308
validateConstantExpressions() const309 status_t AST::validateConstantExpressions() const {
310 return constantExpressionRecursivePass(
311 [](const ConstantExpression* ce) { return ce->validate(); },
312 true /* processBeforeDependencies */);
313 }
314
evaluateConstantExpressions()315 status_t AST::evaluateConstantExpressions() {
316 return constantExpressionRecursivePass(
317 [](ConstantExpression* ce) {
318 ce->evaluate();
319 return OK;
320 },
321 false /* processBeforeDependencies */);
322 }
323
validate() const324 status_t AST::validate() const {
325 std::unordered_set<const Type*> visited;
326 return mRootScope.recursivePass(Type::ParseStage::POST_PARSE, &Type::validate, &visited);
327 }
328
topologicalReorder()329 status_t AST::topologicalReorder() {
330 std::unordered_map<const Type*, size_t> reversedOrder;
331 std::unordered_set<const Type*> stack;
332 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status;
333 if (err != OK) return err;
334
335 std::unordered_set<const Type*> visited;
336 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);
344 return OK;
345 }
346
checkAcyclicConstantExpressions() const347 status_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;
351 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);
362 }
363
checkForwardReferenceRestrictions() const364 status_t AST::checkForwardReferenceRestrictions() const {
365 std::unordered_set<const Type*> visited;
366 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);
376 }
377
importFQName(const FQName & fqName)378 bool AST::importFQName(const FQName& fqName) {
379 if (fqName.name().empty()) {
380 // import a package
381
382 std::vector<FQName> packageInterfaces;
383
384 status_t err = mCoordinator->appendPackageInterfacesToVector(fqName, &packageInterfaces);
385
386 if (err != OK) {
387 return false;
388 }
389
390 for (const auto& subFQName : packageInterfaces) {
391 // Do not enforce restrictions on imports.
392 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
393 if (ast == nullptr) {
394 return false;
395 }
396 addToImportedNamesGranular(subFQName);
397
398 // all previous single type imports are ignored.
399 mImportedTypes.erase(ast);
400 }
401
402 return true;
403 }
404
405 // 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();
410 // Do not enforce restrictions on imports.
411 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
416
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);
426 addToImportedNamesGranular(fqName);
427 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;
433 Type* match = importAST->findDefinedType(fqName, &matchingName);
434 if (match == nullptr) {
435 return false;
436 }
437 // will automatically create a set if it does not exist
438 mImportedTypes[importAST].insert(match);
439 addToImportedNamesGranular(fqName);
440 return true;
441 }
442
443 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
444 FQName typesFQName = fqName.getTypesForPackage();
445
446 // Do not enforce restrictions on imports.
447 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
448
449 if (importAST != nullptr) {
450 // Attempt to find Abc.Internal in types.
451 FQName matchingName;
452 Type* match = importAST->findDefinedType(fqName, &matchingName);
453 if (match == nullptr) {
454 return false;
455 }
456 // will automatically create a set if not exist
457 mImportedTypes[importAST].insert(match);
458 addToImportedNamesGranular(fqName);
459 return true;
460 }
461
462 // can't find an appropriate AST for fqName.
463 return false;
464 }
465
addImplicitImport(const FQName & fqName)466 bool 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
addImport(const char * import,const Location & location)477 bool 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 std::cerr << "while importing " << import << " at " << location << "." << std::endl;
492
493 return false;
494 }
495
addImportedAST(AST * ast)496 void AST::addImportedAST(AST *ast) {
497 mImportedASTs.insert(ast);
498 }
499
makeFullName(const char * localName,Scope * scope) const500 FQName AST::makeFullName(const char* localName, Scope* scope) const {
501 std::vector<std::string> pathComponents{{localName}};
502 for (; scope != &mRootScope; scope = scope->parent()) {
503 pathComponents.push_back(scope->definedName());
504 }
505
506 std::reverse(pathComponents.begin(), pathComponents.end());
507 std::string path = StringHelper::JoinStrings(pathComponents, ".");
508
509 return FQName(mPackage.package(), mPackage.version(), path);
510 }
511
addScopedType(NamedType * type,Scope * scope)512 void AST::addScopedType(NamedType* type, Scope* scope) {
513 scope->addType(type);
514 mDefinedTypesByFullName[type->fqName()] = type;
515 }
516
lookupLocalIdentifier(const Reference<LocalIdentifier> & ref,const Scope * scope)517 LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref,
518 const Scope* scope) {
519 const FQName& fqName = ref.getLookupFqName();
520
521 if (fqName.isIdentifier()) {
522 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
523 if (iden == nullptr) {
524 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
525 << ref.location() << "\n";
526 return nullptr;
527 }
528 return iden;
529 } else {
530 std::string errorMsg;
531 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
532 if (enumValue == nullptr) {
533 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
534 return nullptr;
535 }
536 return enumValue;
537 }
538 }
539
lookupEnumValue(const FQName & fqName,std::string * errorMsg,const Scope * scope)540 EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, const Scope* scope) {
541 FQName enumTypeName = fqName.typeName();
542 std::string enumValueName = fqName.valueName();
543
544 CHECK(!enumValueName.empty());
545
546 Type* type = lookupType(enumTypeName, scope);
547 if(type == nullptr) {
548 *errorMsg = "Cannot find type " + enumTypeName.string();
549 return nullptr;
550 }
551 type = type->resolve();
552 if(!type->isEnum()) {
553 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
554 return nullptr;
555 }
556
557 EnumType *enumType = static_cast<EnumType *>(type);
558 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
559 if(v == nullptr) {
560 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
561 return nullptr;
562 }
563
564 mReferencedTypeNames.insert(enumType->fqName());
565
566 return v;
567 }
568
lookupType(const FQName & fqName,const Scope * scope)569 Type* AST::lookupType(const FQName& fqName, const Scope* scope) {
570 if (fqName.name().empty()) {
571 // Given a package and version???
572 return nullptr;
573 }
574
575 Type *returnedType = nullptr;
576
577 if (fqName.package().empty() && fqName.version().empty()) {
578 // resolve locally first if possible.
579 returnedType = lookupTypeLocally(fqName, scope);
580 if (returnedType != nullptr) {
581 return returnedType;
582 }
583 }
584
585 status_t status = lookupAutofilledType(fqName, &returnedType);
586 if (status != OK) {
587 return nullptr;
588 }
589 if (returnedType != nullptr) {
590 return returnedType;
591 }
592
593 return lookupTypeFromImports(fqName);
594 }
595
596 // Rule 0: try resolve locally
lookupTypeLocally(const FQName & fqName,const Scope * scope)597 Type* AST::lookupTypeLocally(const FQName& fqName, const Scope* scope) {
598 CHECK(fqName.package().empty() && fqName.version().empty()
599 && !fqName.name().empty() && fqName.valueName().empty());
600
601 for (; scope != nullptr; scope = scope->parent()) {
602 Type* type = scope->lookupType(fqName);
603 if (type != nullptr) {
604 return type;
605 }
606 }
607
608 return nullptr;
609 }
610
611 // Rule 1: auto-fill with current package
lookupAutofilledType(const FQName & fqName,Type ** returnedType)612 status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
613 CHECK(!fqName.name().empty() && fqName.valueName().empty());
614
615 FQName autofilled = fqName;
616 autofilled.applyDefaults(mPackage.package(), mPackage.version());
617 FQName matchingName;
618 // Given this fully-qualified name, the type may be defined in this AST, or other files
619 // in import.
620 Type *local = findDefinedType(autofilled, &matchingName);
621 CHECK(local == nullptr || autofilled == matchingName);
622 Type* fromImport = lookupTypeFromImports(autofilled);
623
624 if (local != nullptr && fromImport != nullptr && local != fromImport) {
625 // Something bad happen; two types have the same FQName.
626 std::cerr << "ERROR: Unable to resolve type name '"
627 << fqName.string()
628 << "' (i.e. '"
629 << autofilled.string()
630 << "'), multiple definitions found.\n";
631
632 return UNKNOWN_ERROR;
633 }
634 if (local != nullptr) {
635 *returnedType = local;
636 return OK;
637 }
638 // If fromImport is nullptr as well, return nullptr to fall through to next rule.
639 *returnedType = fromImport;
640 return OK;
641 }
642
643 // Rule 2: look at imports
lookupTypeFromImports(const FQName & fqName)644 Type *AST::lookupTypeFromImports(const FQName &fqName) {
645
646 Type *resolvedType = nullptr;
647 Type *returnedType = nullptr;
648 FQName resolvedName;
649
650 for (const auto &importedAST : mImportedASTs) {
651 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
652 // ignore single type imports
653 continue;
654 }
655 FQName matchingName;
656 Type *match = importedAST->findDefinedType(fqName, &matchingName);
657
658 if (match != nullptr) {
659 if (resolvedType != nullptr) {
660 std::cerr << "ERROR: Unable to resolve type name '"
661 << fqName.string()
662 << "', multiple matches found:\n";
663
664 std::cerr << " " << resolvedName.string() << "\n";
665 std::cerr << " " << matchingName.string() << "\n";
666
667 return nullptr;
668 }
669
670 resolvedType = match;
671 returnedType = resolvedType;
672 resolvedName = matchingName;
673
674 // Keep going even after finding a match.
675 }
676 }
677
678 for (const auto &pair : mImportedTypes) {
679 AST *importedAST = pair.first;
680 std::set<Type *> importedTypes = pair.second;
681
682 FQName matchingName;
683 Type *match = importedAST->findDefinedType(fqName, &matchingName);
684 if (match != nullptr &&
685 importedTypes.find(match) != importedTypes.end()) {
686 if (resolvedType != nullptr) {
687 std::cerr << "ERROR: Unable to resolve type name '"
688 << fqName.string()
689 << "', multiple matches found:\n";
690
691 std::cerr << " " << resolvedName.string() << "\n";
692 std::cerr << " " << matchingName.string() << "\n";
693
694 return nullptr;
695 }
696
697 resolvedType = match;
698 returnedType = resolvedType;
699 resolvedName = matchingName;
700
701 // Keep going even after finding a match.
702 }
703 }
704
705 if (resolvedType) {
706 returnedType = resolvedType;
707
708 // If the resolved type is not an interface, we need to determine
709 // whether it is defined in types.hal, or in some other interface. In
710 // the latter case, we need to emit a dependency for the interface in
711 // which the type is defined.
712 //
713 // Consider the following:
714 // android.hardware.tests.foo@1.0::Record
715 // android.hardware.tests.foo@1.0::IFoo.Folder
716 // android.hardware.tests.foo@1.0::Folder
717 //
718 // If Record is an interface, then we keep track of it for the purpose
719 // of emitting dependencies in the target language (for example #include
720 // in C++). If Record is a UDT, then we assume it is defined in
721 // types.hal in android.hardware.tests.foo@1.0.
722 //
723 // In the case of IFoo.Folder, the same applies. If IFoo is an
724 // interface, we need to track this for the purpose of emitting
725 // dependencies. If not, then it must have been defined in types.hal.
726 //
727 // In the case of just specifying Folder, the resolved type is
728 // android.hardware.tests.foo@1.0::Folder, and the same logic as
729 // above applies.
730
731 if (!resolvedType->isInterface()) {
732 FQName ifc = resolvedName.getTopLevelType();
733 for (const auto &importedAST : mImportedASTs) {
734 FQName matchingName;
735 Type *match = importedAST->findDefinedType(ifc, &matchingName);
736 if (match != nullptr && match->isInterface()) {
737 resolvedType = match;
738 }
739 }
740 }
741
742 if (!resolvedType->isInterface()) {
743 // Non-interface types are declared in the associated types header.
744 FQName typesName = resolvedName.getTypesForPackage();
745
746 mImportedNames.insert(typesName);
747 } else {
748 // Do _not_ use fqName, i.e. the name we used to look up the type,
749 // but instead use the name of the interface we found.
750 // This is necessary because if fqName pointed to a typedef which
751 // in turn referenced the found interface we'd mistakenly use the
752 // name of the typedef instead of the proper name of the interface.
753
754 const FQName &typeName =
755 static_cast<Interface *>(resolvedType)->fqName();
756
757 mImportedNames.insert(typeName);
758 }
759 }
760
761 return returnedType;
762 }
763
addToImportedNamesGranular(const FQName & fqName)764 void AST::addToImportedNamesGranular(const FQName &fqName) {
765 if (fqName.package() == package().package()
766 && fqName.version() == package().version()) {
767 // Our own names are _defined_ here, not imported.
768 return;
769 }
770
771 mImportedNamesGranular.insert(fqName);
772 }
773
findDefinedType(const FQName & fqName,FQName * matchingName) const774 Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
775 for (const auto &pair : mDefinedTypesByFullName) {
776 const FQName &key = pair.first;
777 Type* type = pair.second;
778
779 if (key.endsWith(fqName)) {
780 *matchingName = key;
781 return type;
782 }
783 }
784
785 return nullptr;
786 }
787
getImportStatements() const788 const std::vector<ImportStatement>& AST::getImportStatements() const {
789 return mImportStatements;
790 }
791
getImportedPackages(std::set<FQName> * importSet) const792 void AST::getImportedPackages(std::set<FQName> *importSet) const {
793 for (const auto& fqName : mImportedNamesGranular) {
794 FQName packageName = fqName.getPackageAndVersion();
795
796 if (packageName == mPackage) {
797 // We only care about external imports, not our own package.
798 continue;
799 }
800
801 importSet->insert(packageName);
802 }
803 }
804
getImportedPackagesHierarchy(std::set<FQName> * importSet) const805 void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
806 getImportedPackages(importSet);
807
808 std::set<FQName> newSet;
809 for (const auto &ast : mImportedASTs) {
810 if (importSet->find(ast->package()) != importSet->end()) {
811 ast->getImportedPackagesHierarchy(&newSet);
812 }
813 }
814 importSet->insert(newSet.begin(), newSet.end());
815 }
816
getAllImportedNames(std::set<FQName> * allImportNames) const817 void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
818 for (const auto& name : mImportedNames) {
819 allImportNames->insert(name);
820 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
821 ast->getAllImportedNames(allImportNames);
822 }
823 }
824
getAllImportedNamesGranular(std::set<FQName> * allImportNames) const825 void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
826 for (const auto& fqName : mImportedNamesGranular) {
827 if (fqName.name() == "types") {
828 // A package will export everything _defined_ but will not
829 // re-export anything it itself imported.
830 AST* ast = mCoordinator->parse(
831 fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
832
833 // imported names must have already been validated
834 CHECK(ast != nullptr) << fqName.string();
835
836 ast->addDefinedTypes(allImportNames);
837 } else {
838 allImportNames->insert(fqName);
839 }
840 }
841 }
842
isJavaCompatible() const843 bool AST::isJavaCompatible() const {
844 return mRootScope.isJavaCompatible();
845 }
846
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const847 void AST::appendToExportedTypesVector(
848 std::vector<const Type *> *exportedTypes) const {
849 mRootScope.appendToExportedTypesVector(exportedTypes);
850 }
851
isIBase() const852 bool AST::isIBase() const {
853 Interface* iface = mRootScope.getInterface();
854 return iface != nullptr && iface->isIBase();
855 }
856
getInterface() const857 const Interface *AST::getInterface() const {
858 return mRootScope.getInterface();
859 }
860
getBaseName() const861 std::string AST::getBaseName() const {
862 const Interface* iface = mRootScope.getInterface();
863
864 return iface ? iface->getBaseName() : "types";
865 }
866
addDefinedTypes(std::set<FQName> * definedTypes) const867 void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
868 std::for_each(
869 mDefinedTypesByFullName.begin(),
870 mDefinedTypesByFullName.end(),
871 [definedTypes](const auto &elem) {
872 if (!elem.second->isTypeDef()) {
873 definedTypes->insert(elem.first);
874 }
875 });
876 }
877
addReferencedTypes(std::set<FQName> * referencedTypes) const878 void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
879 std::for_each(
880 mReferencedTypeNames.begin(),
881 mReferencedTypeNames.end(),
882 [referencedTypes](const auto &fqName) {
883 referencedTypes->insert(fqName);
884 });
885 }
886
addMethod(Method * method,Interface * iface)887 bool AST::addMethod(Method* method, Interface* iface) {
888 if (iface->isIBase()) {
889 if (!mAllReservedMethods.emplace(method->name(), method).second) {
890 std::cerr << "ERROR: hidl-gen encountered duplicated reserved method " << method->name()
891 << std::endl;
892 return false;
893 }
894
895 // methods will be added to iface in addAllReservedMethodsToInterface
896 return true;
897 }
898
899 iface->addUserDefinedMethod(method);
900
901 return true;
902 }
903
addAllReservedMethodsToInterface(Interface * iface)904 bool AST::addAllReservedMethodsToInterface(Interface* iface) {
905 std::map<std::string, Method*> allReservedMethods(mAllReservedMethods);
906 // Looking for the IBase AST which is imported for all interfaces that are not IBase
907 for (const AST* importedAST : mImportedASTs) {
908 allReservedMethods.insert(importedAST->mAllReservedMethods.begin(),
909 importedAST->mAllReservedMethods.end());
910 }
911
912 return iface->addAllReservedMethods(allReservedMethods);
913 }
914
setHeader(const DocComment * header)915 void AST::setHeader(const DocComment* header) {
916 mHeader = header;
917 }
918
getHeader() const919 const DocComment* AST::getHeader() const {
920 return mHeader;
921 }
922
addUnhandledComment(const DocComment * docComment)923 void AST::addUnhandledComment(const DocComment* docComment) {
924 if (docComment != nullptr) mUnhandledComments.push_back(docComment);
925 }
926
getUnhandledComments() const927 const std::vector<const DocComment*> AST::getUnhandledComments() const {
928 return mUnhandledComments;
929 }
930
931 } // namespace android;
932