Home | History | Annotate | Download | only in hidl
      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