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