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 "Scope.h" 26 #include "TypeDef.h" 27 28 #include <android-base/logging.h> 29 #include <hidl-util/FQName.h> 30 #include <hidl-util/Formatter.h> 31 #include <hidl-util/StringHelper.h> 32 #include <stdlib.h> 33 #include <algorithm> 34 #include <iostream> 35 36 namespace android { 37 38 AST::AST(const Coordinator* coordinator, const Hash* fileHash) 39 : mCoordinator(coordinator), 40 mFileHash(fileHash), 41 mRootScope("(root scope)", FQName(), Location::startOf(fileHash->getPath()), 42 nullptr /* parent */) {} 43 44 Scope* AST::getRootScope() { 45 return &mRootScope; 46 } 47 48 // used by the parser. 49 void AST::addSyntaxError() { 50 mSyntaxErrors++; 51 } 52 53 size_t AST::syntaxErrors() const { 54 return mSyntaxErrors; 55 } 56 57 const std::string& AST::getFilename() const { 58 return mFileHash->getPath(); 59 } 60 const Hash* AST::getFileHash() const { 61 return mFileHash; 62 } 63 64 bool AST::setPackage(const char *package) { 65 if (!mPackage.setTo(package)) { 66 return false; 67 } 68 69 if (mPackage.package().empty() 70 || mPackage.version().empty() 71 || !mPackage.name().empty()) { 72 return false; 73 } 74 75 return true; 76 } 77 78 FQName AST::package() const { 79 return mPackage; 80 } 81 82 bool AST::isInterface() const { 83 return mRootScope.getInterface() != nullptr; 84 } 85 86 bool AST::containsInterfaces() const { 87 return mRootScope.containsInterfaces(); 88 } 89 90 status_t AST::postParse() { 91 status_t err; 92 93 // lookupTypes is the first pass. 94 err = lookupTypes(); 95 if (err != OK) return err; 96 // validateDefinedTypesUniqueNames is the first call 97 // after lookup, as other errors could appear because 98 // user meant different type than we assumed. 99 err = validateDefinedTypesUniqueNames(); 100 if (err != OK) return err; 101 // topologicalReorder is before resolveInheritance, as we 102 // need to have no cycle while getting parent class. 103 err = topologicalReorder(); 104 if (err != OK) return err; 105 err = resolveInheritance(); 106 if (err != OK) return err; 107 err = lookupLocalIdentifiers(); 108 if (err != OK) return err; 109 // checkAcyclicConstantExpressions is after resolveInheritance, 110 // as resolveInheritance autofills enum values. 111 err = checkAcyclicConstantExpressions(); 112 if (err != OK) return err; 113 err = evaluate(); 114 if (err != OK) return err; 115 err = validate(); 116 if (err != OK) return err; 117 err = checkForwardReferenceRestrictions(); 118 if (err != OK) return err; 119 err = gatherReferencedTypes(); 120 if (err != OK) return err; 121 122 // Make future packages not to call passes 123 // for processed types and expressions 124 constantExpressionRecursivePass( 125 [](ConstantExpression* ce) { 126 ce->setPostParseCompleted(); 127 return OK; 128 }, 129 true /* processBeforeDependencies */); 130 std::unordered_set<const Type*> visited; 131 mRootScope.recursivePass( 132 [](Type* type) { 133 type->setPostParseCompleted(); 134 return OK; 135 }, 136 &visited); 137 138 return OK; 139 } 140 141 status_t AST::constantExpressionRecursivePass( 142 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies) { 143 std::unordered_set<const Type*> visitedTypes; 144 std::unordered_set<const ConstantExpression*> visitedCE; 145 return mRootScope.recursivePass( 146 [&](Type* type) -> status_t { 147 for (auto* ce : type->getConstantExpressions()) { 148 status_t err = ce->recursivePass(func, &visitedCE, processBeforeDependencies); 149 if (err != OK) return err; 150 } 151 return OK; 152 }, 153 &visitedTypes); 154 } 155 156 status_t AST::lookupTypes() { 157 std::unordered_set<const Type*> visited; 158 return mRootScope.recursivePass( 159 [&](Type* type) -> status_t { 160 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent(); 161 162 for (auto* nextRef : type->getReferences()) { 163 if (nextRef->isResolved()) { 164 continue; 165 } 166 167 Type* nextType = lookupType(nextRef->getLookupFqName(), scope); 168 if (nextType == nullptr) { 169 std::cerr << "ERROR: Failed to lookup type '" 170 << nextRef->getLookupFqName().string() << "' at " 171 << nextRef->location() << "\n"; 172 return UNKNOWN_ERROR; 173 } 174 nextRef->set(nextType); 175 } 176 177 return OK; 178 }, 179 &visited); 180 } 181 182 status_t AST::gatherReferencedTypes() { 183 std::unordered_set<const Type*> visited; 184 return mRootScope.recursivePass( 185 [&](Type* type) -> status_t { 186 for (auto* nextRef : type->getReferences()) { 187 const Type *targetType = nextRef->get(); 188 if (targetType->isNamedType()) { 189 mReferencedTypeNames.insert( 190 static_cast<const NamedType *>(targetType)->fqName()); 191 } 192 } 193 194 return OK; 195 }, 196 &visited); 197 } 198 199 status_t AST::lookupLocalIdentifiers() { 200 std::unordered_set<const Type*> visitedTypes; 201 std::unordered_set<const ConstantExpression*> visitedCE; 202 203 return mRootScope.recursivePass( 204 [&](Type* type) -> status_t { 205 Scope* scope = type->isScope() ? static_cast<Scope*>(type) : type->parent(); 206 207 for (auto* ce : type->getConstantExpressions()) { 208 status_t err = ce->recursivePass( 209 [&](ConstantExpression* ce) { 210 for (auto* nextRef : ce->getReferences()) { 211 if (nextRef->isResolved()) continue; 212 213 LocalIdentifier* iden = lookupLocalIdentifier(*nextRef, scope); 214 if (iden == nullptr) return UNKNOWN_ERROR; 215 nextRef->set(iden); 216 } 217 return OK; 218 }, 219 &visitedCE, true /* processBeforeDependencies */); 220 if (err != OK) return err; 221 } 222 223 return OK; 224 }, 225 &visitedTypes); 226 } 227 228 status_t AST::validateDefinedTypesUniqueNames() const { 229 std::unordered_set<const Type*> visited; 230 return mRootScope.recursivePass( 231 [&](const Type* type) -> status_t { 232 // We only want to validate type definition names in this place. 233 if (type->isScope()) { 234 return static_cast<const Scope*>(type)->validateUniqueNames(); 235 } 236 return OK; 237 }, 238 &visited); 239 } 240 241 status_t AST::resolveInheritance() { 242 std::unordered_set<const Type*> visited; 243 return mRootScope.recursivePass(&Type::resolveInheritance, &visited); 244 } 245 246 status_t AST::evaluate() { 247 return constantExpressionRecursivePass( 248 [](ConstantExpression* ce) { 249 ce->evaluate(); 250 return OK; 251 }, 252 false /* processBeforeDependencies */); 253 } 254 255 status_t AST::validate() const { 256 std::unordered_set<const Type*> visited; 257 return mRootScope.recursivePass(&Type::validate, &visited); 258 } 259 260 status_t AST::topologicalReorder() { 261 std::unordered_map<const Type*, size_t> reversedOrder; 262 std::unordered_set<const Type*> stack; 263 status_t err = mRootScope.topologicalOrder(&reversedOrder, &stack).status; 264 if (err != OK) return err; 265 266 std::unordered_set<const Type*> visited; 267 mRootScope.recursivePass( 268 [&](Type* type) { 269 if (type->isScope()) { 270 static_cast<Scope*>(type)->topologicalReorder(reversedOrder); 271 } 272 return OK; 273 }, 274 &visited); 275 return OK; 276 } 277 278 status_t AST::checkAcyclicConstantExpressions() const { 279 std::unordered_set<const Type*> visitedTypes; 280 std::unordered_set<const ConstantExpression*> visitedCE; 281 std::unordered_set<const ConstantExpression*> stack; 282 return mRootScope.recursivePass( 283 [&](const Type* type) -> status_t { 284 for (auto* ce : type->getConstantExpressions()) { 285 status_t err = ce->checkAcyclic(&visitedCE, &stack).status; 286 CHECK(err != OK || stack.empty()); 287 if (err != OK) return err; 288 } 289 return OK; 290 }, 291 &visitedTypes); 292 } 293 294 status_t AST::checkForwardReferenceRestrictions() const { 295 std::unordered_set<const Type*> visited; 296 return mRootScope.recursivePass( 297 [](const Type* type) -> status_t { 298 for (const Reference<Type>* ref : type->getReferences()) { 299 status_t err = type->checkForwardReferenceRestrictions(*ref); 300 if (err != OK) return err; 301 } 302 return OK; 303 }, 304 &visited); 305 } 306 307 bool AST::addImport(const char *import) { 308 FQName fqName; 309 if (!FQName::parse(import, &fqName)) { 310 std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl; 311 return false; 312 } 313 314 fqName.applyDefaults(mPackage.package(), mPackage.version()); 315 316 if (fqName.name().empty()) { 317 // import a package 318 319 std::vector<FQName> packageInterfaces; 320 321 status_t err = 322 mCoordinator->appendPackageInterfacesToVector(fqName, 323 &packageInterfaces); 324 325 if (err != OK) { 326 return false; 327 } 328 329 for (const auto &subFQName : packageInterfaces) { 330 addToImportedNamesGranular(subFQName); 331 332 // Do not enforce restrictions on imports. 333 AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE); 334 if (ast == nullptr) { 335 return false; 336 } 337 // all previous single type imports are ignored. 338 mImportedTypes.erase(ast); 339 } 340 341 return true; 342 } 343 344 addToImportedNamesGranular(fqName); 345 346 // cases like android.hardware.foo (at) 1.0::IFoo.Internal 347 // android.hardware.foo (at) 1.0::Abc.Internal 348 349 // assume it is an interface, and try to import it. 350 const FQName interfaceName = fqName.getTopLevelType(); 351 // Do not enforce restrictions on imports. 352 AST* importAST; 353 status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs, 354 Coordinator::Enforce::NONE); 355 if (err != OK) return false; 356 // importAST nullptr == file doesn't exist 357 358 if (importAST != nullptr) { 359 // cases like android.hardware.foo (at) 1.0::IFoo.Internal 360 // and android.hardware.foo (at) 1.0::IFoo 361 if (fqName == interfaceName) { 362 // import a single file. 363 // all previous single type imports are ignored. 364 // cases like android.hardware.foo (at) 1.0::IFoo 365 // and android.hardware.foo (at) 1.0::types 366 mImportedTypes.erase(importAST); 367 return true; 368 } 369 370 // import a single type from this file 371 // cases like android.hardware.foo (at) 1.0::IFoo.Internal 372 FQName matchingName; 373 Type *match = importAST->findDefinedType(fqName, &matchingName); 374 if (match == nullptr) { 375 return false; 376 } 377 // will automatically create a set if it does not exist 378 mImportedTypes[importAST].insert(match); 379 return true; 380 } 381 382 // probably a type in types.hal, like android.hardware.foo (at) 1.0::Abc.Internal 383 FQName typesFQName = fqName.getTypesForPackage(); 384 385 // Do not enforce restrictions on imports. 386 importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE); 387 388 if (importAST != nullptr) { 389 // Attempt to find Abc.Internal in types. 390 FQName matchingName; 391 Type *match = importAST->findDefinedType(fqName, &matchingName); 392 if (match == nullptr) { 393 return false; 394 } 395 // will automatically create a set if not exist 396 mImportedTypes[importAST].insert(match); 397 return true; 398 } 399 400 // can't find an appropriate AST for fqName. 401 return false; 402 } 403 404 void AST::addImportedAST(AST *ast) { 405 mImportedASTs.insert(ast); 406 } 407 408 FQName AST::makeFullName(const char* localName, Scope* scope) const { 409 std::vector<std::string> pathComponents{{localName}}; 410 for (; scope != &mRootScope; scope = scope->parent()) { 411 pathComponents.push_back(scope->localName()); 412 } 413 414 std::reverse(pathComponents.begin(), pathComponents.end()); 415 std::string path = StringHelper::JoinStrings(pathComponents, "."); 416 417 return FQName(mPackage.package(), mPackage.version(), path); 418 } 419 420 void AST::addScopedType(NamedType* type, Scope* scope) { 421 scope->addType(type); 422 mDefinedTypesByFullName[type->fqName()] = type; 423 } 424 425 LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, Scope* scope) { 426 const FQName& fqName = ref.getLookupFqName(); 427 428 if (fqName.isIdentifier()) { 429 LocalIdentifier* iden = scope->lookupIdentifier(fqName.name()); 430 if (iden == nullptr) { 431 std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at " 432 << ref.location() << "\n"; 433 return nullptr; 434 } 435 return iden; 436 } else { 437 std::string errorMsg; 438 EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope); 439 if (enumValue == nullptr) { 440 std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n"; 441 return nullptr; 442 } 443 return enumValue; 444 } 445 } 446 447 EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) { 448 FQName enumTypeName = fqName.typeName(); 449 std::string enumValueName = fqName.valueName(); 450 451 CHECK(enumTypeName.isValid()); 452 CHECK(!enumValueName.empty()); 453 454 Type* type = lookupType(enumTypeName, scope); 455 if(type == nullptr) { 456 *errorMsg = "Cannot find type " + enumTypeName.string(); 457 return nullptr; 458 } 459 type = type->resolve(); 460 if(!type->isEnum()) { 461 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type"; 462 return nullptr; 463 } 464 465 EnumType *enumType = static_cast<EnumType *>(type); 466 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName)); 467 if(v == nullptr) { 468 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName; 469 return nullptr; 470 } 471 472 mReferencedTypeNames.insert(enumType->fqName()); 473 474 return v; 475 } 476 477 Type* AST::lookupType(const FQName& fqName, Scope* scope) { 478 CHECK(fqName.isValid()); 479 480 if (fqName.name().empty()) { 481 // Given a package and version??? 482 return nullptr; 483 } 484 485 Type *returnedType = nullptr; 486 487 if (fqName.package().empty() && fqName.version().empty()) { 488 // resolve locally first if possible. 489 returnedType = lookupTypeLocally(fqName, scope); 490 if (returnedType != nullptr) { 491 return returnedType; 492 } 493 } 494 495 status_t status = lookupAutofilledType(fqName, &returnedType); 496 if (status != OK) { 497 return nullptr; 498 } 499 if (returnedType != nullptr) { 500 return returnedType; 501 } 502 503 return lookupTypeFromImports(fqName); 504 } 505 506 // Rule 0: try resolve locally 507 Type* AST::lookupTypeLocally(const FQName& fqName, Scope* scope) { 508 CHECK(fqName.package().empty() && fqName.version().empty() 509 && !fqName.name().empty() && fqName.valueName().empty()); 510 511 for (; scope != nullptr; scope = scope->parent()) { 512 Type* type = scope->lookupType(fqName); 513 if (type != nullptr) { 514 return type; 515 } 516 } 517 518 return nullptr; 519 } 520 521 // Rule 1: auto-fill with current package 522 status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) { 523 CHECK(!fqName.name().empty() && fqName.valueName().empty()); 524 525 FQName autofilled = fqName; 526 autofilled.applyDefaults(mPackage.package(), mPackage.version()); 527 FQName matchingName; 528 // Given this fully-qualified name, the type may be defined in this AST, or other files 529 // in import. 530 Type *local = findDefinedType(autofilled, &matchingName); 531 CHECK(local == nullptr || autofilled == matchingName); 532 Type* fromImport = lookupTypeFromImports(autofilled); 533 534 if (local != nullptr && fromImport != nullptr && local != fromImport) { 535 // Something bad happen; two types have the same FQName. 536 std::cerr << "ERROR: Unable to resolve type name '" 537 << fqName.string() 538 << "' (i.e. '" 539 << autofilled.string() 540 << "'), multiple definitions found.\n"; 541 542 return UNKNOWN_ERROR; 543 } 544 if (local != nullptr) { 545 *returnedType = local; 546 return OK; 547 } 548 // If fromImport is nullptr as well, return nullptr to fall through to next rule. 549 *returnedType = fromImport; 550 return OK; 551 } 552 553 // Rule 2: look at imports 554 Type *AST::lookupTypeFromImports(const FQName &fqName) { 555 556 Type *resolvedType = nullptr; 557 Type *returnedType = nullptr; 558 FQName resolvedName; 559 560 for (const auto &importedAST : mImportedASTs) { 561 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) { 562 // ignore single type imports 563 continue; 564 } 565 FQName matchingName; 566 Type *match = importedAST->findDefinedType(fqName, &matchingName); 567 568 if (match != nullptr) { 569 if (resolvedType != nullptr) { 570 std::cerr << "ERROR: Unable to resolve type name '" 571 << fqName.string() 572 << "', multiple matches found:\n"; 573 574 std::cerr << " " << resolvedName.string() << "\n"; 575 std::cerr << " " << matchingName.string() << "\n"; 576 577 return nullptr; 578 } 579 580 resolvedType = match; 581 returnedType = resolvedType; 582 resolvedName = matchingName; 583 584 // Keep going even after finding a match. 585 } 586 } 587 588 for (const auto &pair : mImportedTypes) { 589 AST *importedAST = pair.first; 590 std::set<Type *> importedTypes = pair.second; 591 592 FQName matchingName; 593 Type *match = importedAST->findDefinedType(fqName, &matchingName); 594 if (match != nullptr && 595 importedTypes.find(match) != importedTypes.end()) { 596 if (resolvedType != nullptr) { 597 std::cerr << "ERROR: Unable to resolve type name '" 598 << fqName.string() 599 << "', multiple matches found:\n"; 600 601 std::cerr << " " << resolvedName.string() << "\n"; 602 std::cerr << " " << matchingName.string() << "\n"; 603 604 return nullptr; 605 } 606 607 resolvedType = match; 608 returnedType = resolvedType; 609 resolvedName = matchingName; 610 611 // Keep going even after finding a match. 612 } 613 } 614 615 if (resolvedType) { 616 returnedType = resolvedType; 617 618 // If the resolved type is not an interface, we need to determine 619 // whether it is defined in types.hal, or in some other interface. In 620 // the latter case, we need to emit a dependency for the interface in 621 // which the type is defined. 622 // 623 // Consider the following: 624 // android.hardware.tests.foo (at) 1.0::Record 625 // android.hardware.tests.foo (at) 1.0::IFoo.Folder 626 // android.hardware.tests.foo (at) 1.0::Folder 627 // 628 // If Record is an interface, then we keep track of it for the purpose 629 // of emitting dependencies in the target language (for example #include 630 // in C++). If Record is a UDT, then we assume it is defined in 631 // types.hal in android.hardware.tests.foo (at) 1.0. 632 // 633 // In the case of IFoo.Folder, the same applies. If IFoo is an 634 // interface, we need to track this for the purpose of emitting 635 // dependencies. If not, then it must have been defined in types.hal. 636 // 637 // In the case of just specifying Folder, the resolved type is 638 // android.hardware.tests.foo (at) 1.0::Folder, and the same logic as 639 // above applies. 640 641 if (!resolvedType->isInterface()) { 642 FQName ifc = resolvedName.getTopLevelType(); 643 for (const auto &importedAST : mImportedASTs) { 644 FQName matchingName; 645 Type *match = importedAST->findDefinedType(ifc, &matchingName); 646 if (match != nullptr && match->isInterface()) { 647 resolvedType = match; 648 } 649 } 650 } 651 652 if (!resolvedType->isInterface()) { 653 // Non-interface types are declared in the associated types header. 654 FQName typesName = resolvedName.getTypesForPackage(); 655 656 mImportedNames.insert(typesName); 657 } else { 658 // Do _not_ use fqName, i.e. the name we used to look up the type, 659 // but instead use the name of the interface we found. 660 // This is necessary because if fqName pointed to a typedef which 661 // in turn referenced the found interface we'd mistakenly use the 662 // name of the typedef instead of the proper name of the interface. 663 664 const FQName &typeName = 665 static_cast<Interface *>(resolvedType)->fqName(); 666 667 mImportedNames.insert(typeName); 668 } 669 } 670 671 return returnedType; 672 } 673 674 void AST::addToImportedNamesGranular(const FQName &fqName) { 675 if (fqName.package() == package().package() 676 && fqName.version() == package().version()) { 677 // Our own names are _defined_ here, not imported. 678 return; 679 } 680 681 mImportedNamesGranular.insert(fqName); 682 } 683 684 Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const { 685 for (const auto &pair : mDefinedTypesByFullName) { 686 const FQName &key = pair.first; 687 Type* type = pair.second; 688 689 if (key.endsWith(fqName)) { 690 *matchingName = key; 691 return type; 692 } 693 } 694 695 return nullptr; 696 } 697 698 void AST::getImportedPackages(std::set<FQName> *importSet) const { 699 for (const auto& fqName : mImportedNamesGranular) { 700 FQName packageName = fqName.getPackageAndVersion(); 701 702 if (packageName == mPackage) { 703 // We only care about external imports, not our own package. 704 continue; 705 } 706 707 importSet->insert(packageName); 708 } 709 } 710 711 void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const { 712 getImportedPackages(importSet); 713 714 std::set<FQName> newSet; 715 for (const auto &ast : mImportedASTs) { 716 if (importSet->find(ast->package()) != importSet->end()) { 717 ast->getImportedPackagesHierarchy(&newSet); 718 } 719 } 720 importSet->insert(newSet.begin(), newSet.end()); 721 } 722 723 void AST::getAllImportedNames(std::set<FQName> *allImportNames) const { 724 for (const auto& name : mImportedNames) { 725 allImportNames->insert(name); 726 AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE); 727 ast->getAllImportedNames(allImportNames); 728 } 729 } 730 731 void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const { 732 for (const auto& fqName : mImportedNamesGranular) { 733 if (fqName.name() == "types") { 734 // A package will export everything _defined_ but will not 735 // re-export anything it itself imported. 736 AST* ast = mCoordinator->parse( 737 fqName, nullptr /* imported */, Coordinator::Enforce::NONE); 738 739 ast->addDefinedTypes(allImportNames); 740 } else { 741 allImportNames->insert(fqName); 742 } 743 } 744 } 745 746 bool AST::isJavaCompatible() const { 747 return mRootScope.isJavaCompatible(); 748 } 749 750 void AST::appendToExportedTypesVector( 751 std::vector<const Type *> *exportedTypes) const { 752 mRootScope.appendToExportedTypesVector(exportedTypes); 753 } 754 755 bool AST::isIBase() const { 756 Interface* iface = mRootScope.getInterface(); 757 return iface != nullptr && iface->isIBase(); 758 } 759 760 const Interface *AST::getInterface() const { 761 return mRootScope.getInterface(); 762 } 763 764 std::string AST::getBaseName() const { 765 const Interface* iface = mRootScope.getInterface(); 766 767 return iface ? iface->getBaseName() : "types"; 768 } 769 770 void AST::addDefinedTypes(std::set<FQName> *definedTypes) const { 771 std::for_each( 772 mDefinedTypesByFullName.begin(), 773 mDefinedTypesByFullName.end(), 774 [definedTypes](const auto &elem) { 775 if (!elem.second->isTypeDef()) { 776 definedTypes->insert(elem.first); 777 } 778 }); 779 } 780 781 void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const { 782 std::for_each( 783 mReferencedTypeNames.begin(), 784 mReferencedTypeNames.end(), 785 [referencedTypes](const auto &fqName) { 786 referencedTypes->insert(fqName); 787 }); 788 } 789 790 } // namespace android; 791