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 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 49 Scope* AST::getMutableRootScope() { 50 return &mRootScope; 51 } 52 53 const Scope& AST::getRootScope() const { 54 return mRootScope; 55 } 56 57 // used by the parser. 58 void AST::addSyntaxError() { 59 mSyntaxErrors++; 60 } 61 62 size_t AST::syntaxErrors() const { 63 return mSyntaxErrors; 64 } 65 66 const std::string& AST::getFilename() const { 67 return mFileHash->getPath(); 68 } 69 const Hash* AST::getFileHash() const { 70 return mFileHash; 71 } 72 73 const Coordinator& AST::getCoordinator() const { 74 return *mCoordinator; 75 } 76 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 91 FQName AST::package() const { 92 return mPackage; 93 } 94 95 bool AST::isInterface() const { 96 return mRootScope.getInterface() != nullptr; 97 } 98 99 bool AST::definesInterfaces() const { 100 return mRootScope.definesInterfaces(); 101 } 102 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 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 173 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 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 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 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 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 289 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 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 309 status_t AST::validateConstantExpressions() const { 310 return constantExpressionRecursivePass( 311 [](const ConstantExpression* ce) { return ce->validate(); }, 312 true /* processBeforeDependencies */); 313 } 314 315 status_t AST::evaluateConstantExpressions() { 316 return constantExpressionRecursivePass( 317 [](ConstantExpression* ce) { 318 ce->evaluate(); 319 return OK; 320 }, 321 false /* processBeforeDependencies */); 322 } 323 324 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 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 347 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 364 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 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 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 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 496 void AST::addImportedAST(AST *ast) { 497 mImportedASTs.insert(ast); 498 } 499 500 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 512 void AST::addScopedType(NamedType* type, Scope* scope) { 513 scope->addType(type); 514 mDefinedTypesByFullName[type->fqName()] = type; 515 } 516 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 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 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 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 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 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 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 774 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 788 const std::vector<ImportStatement>& AST::getImportStatements() const { 789 return mImportStatements; 790 } 791 792 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 805 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 817 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 825 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 843 bool AST::isJavaCompatible() const { 844 return mRootScope.isJavaCompatible(); 845 } 846 847 void AST::appendToExportedTypesVector( 848 std::vector<const Type *> *exportedTypes) const { 849 mRootScope.appendToExportedTypesVector(exportedTypes); 850 } 851 852 bool AST::isIBase() const { 853 Interface* iface = mRootScope.getInterface(); 854 return iface != nullptr && iface->isIBase(); 855 } 856 857 const Interface *AST::getInterface() const { 858 return mRootScope.getInterface(); 859 } 860 861 std::string AST::getBaseName() const { 862 const Interface* iface = mRootScope.getInterface(); 863 864 return iface ? iface->getBaseName() : "types"; 865 } 866 867 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 878 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 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 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 915 void AST::setHeader(const DocComment* header) { 916 mHeader = header; 917 } 918 919 const DocComment* AST::getHeader() const { 920 return mHeader; 921 } 922 923 void AST::addUnhandledComment(const DocComment* docComment) { 924 if (docComment != nullptr) mUnhandledComments.push_back(docComment); 925 } 926 927 const std::vector<const DocComment*> AST::getUnhandledComments() const { 928 return mUnhandledComments; 929 } 930 931 } // namespace android; 932