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