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