• 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.valueName().empty()) {
380         std::cerr << "WARNING: must import type, but importing value: " << fqName.string()
381                   << ". Did you mean to use '::' instead of ':'?" << std::endl;
382         // TODO(b/146215188): consider as error
383     }
384 
385     if (fqName.name().empty()) {
386         // import a package
387 
388         std::vector<FQName> packageInterfaces;
389 
390         status_t err = mCoordinator->appendPackageInterfacesToVector(fqName, &packageInterfaces);
391 
392         if (err != OK) {
393             return false;
394         }
395 
396         for (const auto& subFQName : packageInterfaces) {
397             // Do not enforce restrictions on imports.
398             AST* ast = mCoordinator->parse(subFQName, &mImportedASTs, Coordinator::Enforce::NONE);
399             if (ast == nullptr) {
400                 return false;
401             }
402             addToImportedNamesGranular(subFQName);
403 
404             // all previous single type imports are ignored.
405             mImportedTypes.erase(ast);
406         }
407 
408         return true;
409     }
410 
411     // cases like android.hardware.foo@1.0::IFoo.Internal
412     //            android.hardware.foo@1.0::Abc.Internal
413 
414     // assume it is an interface, and try to import it.
415     const FQName interfaceName = fqName.getTopLevelType();
416     // Do not enforce restrictions on imports.
417     AST* importAST;
418     status_t err = mCoordinator->parseOptional(interfaceName, &importAST, &mImportedASTs,
419                                                Coordinator::Enforce::NONE);
420     if (err != OK) return false;
421     // importAST nullptr == file doesn't exist
422 
423     if (importAST != nullptr) {
424         // cases like android.hardware.foo@1.0::IFoo.Internal
425         //        and android.hardware.foo@1.0::IFoo
426         if (fqName == interfaceName) {
427             // import a single file.
428             // all previous single type imports are ignored.
429             // cases like android.hardware.foo@1.0::IFoo
430             //        and android.hardware.foo@1.0::types
431             mImportedTypes.erase(importAST);
432             addToImportedNamesGranular(fqName);
433             return true;
434         }
435 
436         // import a single type from this file
437         // cases like android.hardware.foo@1.0::IFoo.Internal
438         FQName matchingName;
439         Type* match = importAST->findDefinedType(fqName, &matchingName);
440         if (match == nullptr) {
441             return false;
442         }
443         // will automatically create a set if it does not exist
444         mImportedTypes[importAST].insert(match);
445         addToImportedNamesGranular(fqName);
446         return true;
447     }
448 
449     // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
450     FQName typesFQName = fqName.getTypesForPackage();
451 
452     // Do not enforce restrictions on imports.
453     importAST = mCoordinator->parse(typesFQName, &mImportedASTs, Coordinator::Enforce::NONE);
454 
455     if (importAST != nullptr) {
456         // Attempt to find Abc.Internal in types.
457         FQName matchingName;
458         Type* match = importAST->findDefinedType(fqName, &matchingName);
459         if (match == nullptr) {
460             return false;
461         }
462         // will automatically create a set if not exist
463         mImportedTypes[importAST].insert(match);
464         addToImportedNamesGranular(fqName);
465         return true;
466     }
467 
468     // can't find an appropriate AST for fqName.
469     return false;
470 }
471 
addImplicitImport(const FQName & fqName)472 bool AST::addImplicitImport(const FQName& fqName) {
473     CHECK(fqName.isFullyQualified());
474 
475     if (importFQName(fqName)) {
476         mImplicitImports.push_back(fqName);
477         return true;
478     }
479 
480     return false;
481 }
482 
addImport(const char * import,const Location & location)483 bool AST::addImport(const char* import, const Location& location) {
484     FQName fqName;
485     if (!FQName::parse(import, &fqName)) {
486         std::cerr << "ERROR: '" << import << "' is an invalid fully-qualified name." << std::endl;
487         return false;
488     }
489 
490     fqName.applyDefaults(mPackage.package(), mPackage.version());
491 
492     if (importFQName(fqName)) {
493         mImportStatements.push_back({fqName, location});
494         return true;
495     }
496 
497     std::cerr << "while importing " << import << " at " << location << "." << std::endl;
498 
499     return false;
500 }
501 
addImportedAST(AST * ast)502 void AST::addImportedAST(AST *ast) {
503     mImportedASTs.insert(ast);
504 }
505 
makeFullName(const char * localName,Scope * scope) const506 FQName AST::makeFullName(const char* localName, Scope* scope) const {
507     std::vector<std::string> pathComponents{{localName}};
508     for (; scope != &mRootScope; scope = scope->parent()) {
509         pathComponents.push_back(scope->definedName());
510     }
511 
512     std::reverse(pathComponents.begin(), pathComponents.end());
513     std::string path = StringHelper::JoinStrings(pathComponents, ".");
514 
515     return FQName(mPackage.package(), mPackage.version(), path);
516 }
517 
addScopedType(NamedType * type,Scope * scope)518 void AST::addScopedType(NamedType* type, Scope* scope) {
519     scope->addType(type);
520     mDefinedTypesByFullName[type->fqName()] = type;
521 }
522 
lookupLocalIdentifier(const Reference<LocalIdentifier> & ref,const Scope * scope)523 LocalIdentifier* AST::lookupLocalIdentifier(const Reference<LocalIdentifier>& ref,
524                                             const Scope* scope) {
525     const FQName& fqName = ref.getLookupFqName();
526 
527     if (fqName.isIdentifier()) {
528         LocalIdentifier* iden = scope->lookupIdentifier(fqName.name());
529         if (iden == nullptr) {
530             std::cerr << "ERROR: identifier " << fqName.string() << " could not be found at "
531                       << ref.location() << "\n";
532             return nullptr;
533         }
534         return iden;
535     } else {
536         std::string errorMsg;
537         EnumValue* enumValue = lookupEnumValue(fqName, &errorMsg, scope);
538         if (enumValue == nullptr) {
539             std::cerr << "ERROR: " << errorMsg << " at " << ref.location() << "\n";
540             return nullptr;
541         }
542         return enumValue;
543     }
544 }
545 
lookupEnumValue(const FQName & fqName,std::string * errorMsg,const Scope * scope)546 EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, const Scope* scope) {
547     FQName enumTypeName = fqName.typeName();
548     std::string enumValueName = fqName.valueName();
549 
550     CHECK(!enumValueName.empty());
551 
552     Type* type = lookupType(enumTypeName, scope);
553     if(type == nullptr) {
554         *errorMsg = "Cannot find type " + enumTypeName.string();
555         return nullptr;
556     }
557     type = type->resolve();
558     if(!type->isEnum()) {
559         *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
560         return nullptr;
561     }
562 
563     EnumType *enumType = static_cast<EnumType *>(type);
564     EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
565     if(v == nullptr) {
566         *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
567         return nullptr;
568     }
569 
570     mReferencedTypeNames.insert(enumType->fqName());
571 
572     return v;
573 }
574 
lookupType(const FQName & fqName,const Scope * scope)575 Type* AST::lookupType(const FQName& fqName, const Scope* scope) {
576     if (fqName.name().empty()) {
577         // Given a package and version???
578         return nullptr;
579     }
580 
581     Type *returnedType = nullptr;
582 
583     if (fqName.package().empty() && fqName.version().empty()) {
584         // resolve locally first if possible.
585         returnedType = lookupTypeLocally(fqName, scope);
586         if (returnedType != nullptr) {
587             return returnedType;
588         }
589     }
590 
591     status_t status = lookupAutofilledType(fqName, &returnedType);
592     if (status != OK) {
593         return nullptr;
594     }
595     if (returnedType != nullptr) {
596         return returnedType;
597     }
598 
599     return lookupTypeFromImports(fqName);
600 }
601 
602 // Rule 0: try resolve locally
lookupTypeLocally(const FQName & fqName,const Scope * scope)603 Type* AST::lookupTypeLocally(const FQName& fqName, const Scope* scope) {
604     CHECK(fqName.package().empty() && fqName.version().empty()
605         && !fqName.name().empty() && fqName.valueName().empty());
606 
607     for (; scope != nullptr; scope = scope->parent()) {
608         Type* type = scope->lookupType(fqName);
609         if (type != nullptr) {
610             return type;
611         }
612     }
613 
614     return nullptr;
615 }
616 
617 // Rule 1: auto-fill with current package
lookupAutofilledType(const FQName & fqName,Type ** returnedType)618 status_t AST::lookupAutofilledType(const FQName &fqName, Type **returnedType) {
619     CHECK(!fqName.name().empty() && fqName.valueName().empty());
620 
621     FQName autofilled = fqName;
622     autofilled.applyDefaults(mPackage.package(), mPackage.version());
623     FQName matchingName;
624     // Given this fully-qualified name, the type may be defined in this AST, or other files
625     // in import.
626     Type *local = findDefinedType(autofilled, &matchingName);
627     CHECK(local == nullptr || autofilled == matchingName);
628     Type* fromImport = lookupTypeFromImports(autofilled);
629 
630     if (local != nullptr && fromImport != nullptr && local != fromImport) {
631         // Something bad happen; two types have the same FQName.
632         std::cerr << "ERROR: Unable to resolve type name '"
633                   << fqName.string()
634                   << "' (i.e. '"
635                   << autofilled.string()
636                   << "'), multiple definitions found.\n";
637 
638         return UNKNOWN_ERROR;
639     }
640     if (local != nullptr) {
641         *returnedType = local;
642         return OK;
643     }
644     // If fromImport is nullptr as well, return nullptr to fall through to next rule.
645     *returnedType = fromImport;
646     return OK;
647 }
648 
649 // Rule 2: look at imports
lookupTypeFromImports(const FQName & fqName)650 Type *AST::lookupTypeFromImports(const FQName &fqName) {
651 
652     Type *resolvedType = nullptr;
653     Type *returnedType = nullptr;
654     FQName resolvedName;
655 
656     for (const auto &importedAST : mImportedASTs) {
657         if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
658             // ignore single type imports
659             continue;
660         }
661         FQName matchingName;
662         Type *match = importedAST->findDefinedType(fqName, &matchingName);
663 
664         if (match != nullptr) {
665             if (resolvedType != nullptr) {
666                 std::cerr << "ERROR: Unable to resolve type name '"
667                           << fqName.string()
668                           << "', multiple matches found:\n";
669 
670                 std::cerr << "  " << resolvedName.string() << "\n";
671                 std::cerr << "  " << matchingName.string() << "\n";
672 
673                 return nullptr;
674             }
675 
676             resolvedType = match;
677             returnedType = resolvedType;
678             resolvedName = matchingName;
679 
680             // Keep going even after finding a match.
681         }
682     }
683 
684     for (const auto &pair : mImportedTypes) {
685         AST *importedAST = pair.first;
686         std::set<Type *> importedTypes = pair.second;
687 
688         FQName matchingName;
689         Type *match = importedAST->findDefinedType(fqName, &matchingName);
690         if (match != nullptr &&
691                 importedTypes.find(match) != importedTypes.end()) {
692             if (resolvedType != nullptr) {
693                 std::cerr << "ERROR: Unable to resolve type name '"
694                           << fqName.string()
695                           << "', multiple matches found:\n";
696 
697                 std::cerr << "  " << resolvedName.string() << "\n";
698                 std::cerr << "  " << matchingName.string() << "\n";
699 
700                 return nullptr;
701             }
702 
703             resolvedType = match;
704             returnedType = resolvedType;
705             resolvedName = matchingName;
706 
707             // Keep going even after finding a match.
708         }
709     }
710 
711     if (resolvedType) {
712         returnedType = resolvedType;
713 
714         // If the resolved type is not an interface, we need to determine
715         // whether it is defined in types.hal, or in some other interface.  In
716         // the latter case, we need to emit a dependency for the interface in
717         // which the type is defined.
718         //
719         // Consider the following:
720         //    android.hardware.tests.foo@1.0::Record
721         //    android.hardware.tests.foo@1.0::IFoo.Folder
722         //    android.hardware.tests.foo@1.0::Folder
723         //
724         // If Record is an interface, then we keep track of it for the purpose
725         // of emitting dependencies in the target language (for example #include
726         // in C++).  If Record is a UDT, then we assume it is defined in
727         // types.hal in android.hardware.tests.foo@1.0.
728         //
729         // In the case of IFoo.Folder, the same applies.  If IFoo is an
730         // interface, we need to track this for the purpose of emitting
731         // dependencies.  If not, then it must have been defined in types.hal.
732         //
733         // In the case of just specifying Folder, the resolved type is
734         // android.hardware.tests.foo@1.0::Folder, and the same logic as
735         // above applies.
736 
737         if (!resolvedType->isInterface()) {
738             FQName ifc = resolvedName.getTopLevelType();
739             for (const auto &importedAST : mImportedASTs) {
740                 FQName matchingName;
741                 Type *match = importedAST->findDefinedType(ifc, &matchingName);
742                 if (match != nullptr && match->isInterface()) {
743                     resolvedType = match;
744                 }
745             }
746         }
747 
748         if (!resolvedType->isInterface()) {
749             // Non-interface types are declared in the associated types header.
750             FQName typesName = resolvedName.getTypesForPackage();
751 
752             mImportedNames.insert(typesName);
753         } else {
754             // Do _not_ use fqName, i.e. the name we used to look up the type,
755             // but instead use the name of the interface we found.
756             // This is necessary because if fqName pointed to a typedef which
757             // in turn referenced the found interface we'd mistakenly use the
758             // name of the typedef instead of the proper name of the interface.
759 
760             const FQName &typeName =
761                 static_cast<Interface *>(resolvedType)->fqName();
762 
763             mImportedNames.insert(typeName);
764         }
765     }
766 
767     return returnedType;
768 }
769 
addToImportedNamesGranular(const FQName & fqName)770 void AST::addToImportedNamesGranular(const FQName &fqName) {
771     if (fqName.package() == package().package()
772             && fqName.version() == package().version()) {
773         // Our own names are _defined_ here, not imported.
774         return;
775     }
776 
777     mImportedNamesGranular.insert(fqName);
778 }
779 
findDefinedType(const FQName & fqName,FQName * matchingName) const780 Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
781     for (const auto &pair : mDefinedTypesByFullName) {
782         const FQName &key = pair.first;
783         Type* type = pair.second;
784 
785         if (key.endsWith(fqName)) {
786             *matchingName = key;
787             return type;
788         }
789     }
790 
791     return nullptr;
792 }
793 
getImportStatements() const794 const std::vector<ImportStatement>& AST::getImportStatements() const {
795     return mImportStatements;
796 }
797 
getImportedPackages(std::set<FQName> * importSet) const798 void AST::getImportedPackages(std::set<FQName> *importSet) const {
799     for (const auto& fqName : mImportedNamesGranular) {
800         FQName packageName = fqName.getPackageAndVersion();
801 
802         if (packageName == mPackage) {
803             // We only care about external imports, not our own package.
804             continue;
805         }
806 
807         importSet->insert(packageName);
808     }
809 }
810 
getImportedPackagesHierarchy(std::set<FQName> * importSet) const811 void AST::getImportedPackagesHierarchy(std::set<FQName> *importSet) const {
812     getImportedPackages(importSet);
813 
814     std::set<FQName> newSet;
815     for (const auto &ast : mImportedASTs) {
816         if (importSet->find(ast->package()) != importSet->end()) {
817             ast->getImportedPackagesHierarchy(&newSet);
818         }
819     }
820     importSet->insert(newSet.begin(), newSet.end());
821 }
822 
getAllImportedNames(std::set<FQName> * allImportNames) const823 void AST::getAllImportedNames(std::set<FQName> *allImportNames) const {
824     for (const auto& name : mImportedNames) {
825         allImportNames->insert(name);
826         AST* ast = mCoordinator->parse(name, nullptr /* imported */, Coordinator::Enforce::NONE);
827         ast->getAllImportedNames(allImportNames);
828     }
829 }
830 
getAllImportedNamesGranular(std::set<FQName> * allImportNames) const831 void AST::getAllImportedNamesGranular(std::set<FQName> *allImportNames) const {
832     for (const auto& fqName : mImportedNamesGranular) {
833         if (fqName.name() == "types") {
834             // A package will export everything _defined_ but will not
835             // re-export anything it itself imported.
836             AST* ast = mCoordinator->parse(
837                     fqName, nullptr /* imported */, Coordinator::Enforce::NONE);
838 
839             // imported names must have already been validated
840             CHECK(ast != nullptr) << fqName.string();
841 
842             ast->addDefinedTypes(allImportNames);
843         } else {
844             allImportNames->insert(fqName);
845         }
846     }
847 }
848 
isJavaCompatible() const849 bool AST::isJavaCompatible() const {
850     static const std::vector<std::string> keywords({
851             "abstract",  "continue",  "for",      "new",          "switch",  "assert",
852             "default",   "goto",      "package",  "synchronized", "boolean", "do",
853             "if",        "private",   "this",     "break",        "double",  "implements",
854             "protected", "throw",     "byte",     "else",         "import",  "public",
855             "throws",    "case",      "enum",     "instanceof",   "return",  "transient",
856             "catch",     "extends",   "int",      "short",        "try",     "char",
857             "final",     "interface", "static",   "void",         "class",   "finally",
858             "long",      "strictfp",  "volatile", "const",        "float",   "native",
859             "super",     "while",
860     });
861     // java package shouldn't contain java keywords
862     for (const auto& comp : mPackage.getPackageComponents()) {
863         if (std::find(keywords.begin(), keywords.end(), comp) != keywords.end()) {
864             return false;
865         }
866     }
867     return mRootScope.isJavaCompatible();
868 }
869 
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const870 void AST::appendToExportedTypesVector(
871         std::vector<const Type *> *exportedTypes) const {
872     mRootScope.appendToExportedTypesVector(exportedTypes);
873 }
874 
isIBase() const875 bool AST::isIBase() const {
876     Interface* iface = mRootScope.getInterface();
877     return iface != nullptr && iface->isIBase();
878 }
879 
getInterface() const880 const Interface *AST::getInterface() const {
881     return mRootScope.getInterface();
882 }
883 
getBaseName() const884 std::string AST::getBaseName() const {
885     const Interface* iface = mRootScope.getInterface();
886 
887     return iface ? iface->getBaseName() : "types";
888 }
889 
addDefinedTypes(std::set<FQName> * definedTypes) const890 void AST::addDefinedTypes(std::set<FQName> *definedTypes) const {
891     std::for_each(
892             mDefinedTypesByFullName.begin(),
893             mDefinedTypesByFullName.end(),
894             [definedTypes](const auto &elem) {
895                 if (!elem.second->isTypeDef()) {
896                     definedTypes->insert(elem.first);
897                 }
898             });
899 }
900 
addReferencedTypes(std::set<FQName> * referencedTypes) const901 void AST::addReferencedTypes(std::set<FQName> *referencedTypes) const {
902     std::for_each(
903             mReferencedTypeNames.begin(),
904             mReferencedTypeNames.end(),
905             [referencedTypes](const auto &fqName) {
906                 referencedTypes->insert(fqName);
907             });
908 }
909 
addMethod(Method * method,Interface * iface)910 bool AST::addMethod(Method* method, Interface* iface) {
911     if (iface->isIBase()) {
912         if (!mAllReservedMethods.emplace(method->name(), method).second) {
913             std::cerr << "ERROR: hidl-gen encountered duplicated reserved method " << method->name()
914                       << std::endl;
915             return false;
916         }
917 
918         // methods will be added to iface in addAllReservedMethodsToInterface
919         return true;
920     }
921 
922     iface->addUserDefinedMethod(method);
923 
924     return true;
925 }
926 
addAllReservedMethodsToInterface(Interface * iface)927 bool AST::addAllReservedMethodsToInterface(Interface* iface) {
928     std::map<std::string, Method*> allReservedMethods(mAllReservedMethods);
929     // Looking for the IBase AST which is imported for all interfaces that are not IBase
930     for (const AST* importedAST : mImportedASTs) {
931         allReservedMethods.insert(importedAST->mAllReservedMethods.begin(),
932                                   importedAST->mAllReservedMethods.end());
933     }
934 
935     return iface->addAllReservedMethods(allReservedMethods);
936 }
937 
setHeader(const DocComment * header)938 void AST::setHeader(const DocComment* header) {
939     mHeader = header;
940 }
941 
getHeader() const942 const DocComment* AST::getHeader() const {
943     return mHeader;
944 }
945 
addUnhandledComment(const DocComment * docComment)946 void AST::addUnhandledComment(const DocComment* docComment) {
947     if (docComment != nullptr) mUnhandledComments.push_back(docComment);
948 }
949 
getUnhandledComments() const950 const std::vector<const DocComment*> AST::getUnhandledComments() const {
951     return mUnhandledComments;
952 }
953 
954 }  // namespace android;
955