|  | /* | 
|  | * Copyright (C) 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include "Scope.h" | 
|  |  | 
|  | #include "Annotation.h" | 
|  | #include "ConstantExpression.h" | 
|  | #include "Interface.h" | 
|  |  | 
|  | #include <android-base/logging.h> | 
|  | #include <hidl-util/Formatter.h> | 
|  | #include <hidl-util/StringHelper.h> | 
|  | #include <algorithm> | 
|  | #include <iostream> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | Scope::Scope(const std::string& localName, const FQName& fullName, const Location& location, | 
|  | Scope* parent) | 
|  | : NamedType(localName, fullName, location, parent) {} | 
|  | Scope::~Scope(){} | 
|  |  | 
|  | void Scope::addType(NamedType* type) { | 
|  | size_t index = mTypes.size(); | 
|  | mTypes.push_back(type); | 
|  | mTypeIndexByName[type->definedName()] = index; | 
|  | } | 
|  |  | 
|  | status_t Scope::validateUniqueNames() const { | 
|  | for (const auto* type : mTypes) { | 
|  | if (mTypes[mTypeIndexByName.at(type->definedName())] != type) { | 
|  | std::cerr << "ERROR: A type named '" << type->definedName() | 
|  | << "' is already declared in the scope at " << type->location() << std::endl; | 
|  | return UNKNOWN_ERROR; | 
|  | } | 
|  | } | 
|  | return OK; | 
|  | } | 
|  |  | 
|  | NamedType *Scope::lookupType(const FQName &fqName) const { | 
|  | CHECK(fqName.package().empty() && fqName.version().empty()); | 
|  | if (!fqName.valueName().empty()) { | 
|  | std::cerr << "ERROR: " << fqName.string() << " does not refer to a type." << std::endl; | 
|  | return nullptr; | 
|  | } | 
|  | std::vector<std::string> names = fqName.names(); | 
|  | CHECK_GT(names.size(), 0u); | 
|  | auto it = mTypeIndexByName.find(names[0]); | 
|  |  | 
|  | if (it == mTypeIndexByName.end()) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | NamedType *outerType = mTypes[it->second]; | 
|  | if (names.size() == 1) { | 
|  | return outerType; | 
|  | } | 
|  | if (!outerType->isScope()) { | 
|  | // more than one names, but the first name is not a scope | 
|  | return nullptr; | 
|  | } | 
|  | Scope *outerScope = static_cast<Scope *>(outerType); | 
|  | // *slowly* pop first element | 
|  | names.erase(names.begin()); | 
|  | FQName innerName; | 
|  | CHECK(FQName::parse(StringHelper::JoinStrings(names, "."), &innerName)); | 
|  | return outerScope->lookupType(innerName); | 
|  | } | 
|  |  | 
|  | LocalIdentifier *Scope::lookupIdentifier(const std::string & /*name*/) const { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | bool Scope::isScope() const { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | Interface *Scope::getInterface() const { | 
|  | if (mTypes.size() == 1 && mTypes[0]->isInterface()) { | 
|  | return static_cast<Interface *>(mTypes[0]); | 
|  | } | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | bool Scope::definesInterfaces() const { | 
|  | for (const NamedType *type : mTypes) { | 
|  | if (type->isInterface()) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const std::vector<Annotation*>& Scope::annotations() const { | 
|  | return mAnnotations; | 
|  | } | 
|  |  | 
|  | void Scope::setAnnotations(std::vector<Annotation*>* annotations) { | 
|  | CHECK(mAnnotations.empty()); | 
|  | CHECK(annotations != nullptr); | 
|  | mAnnotations = *annotations; | 
|  | } | 
|  |  | 
|  | std::vector<const Type*> Scope::getDefinedTypes() const { | 
|  | std::vector<const Type*> ret; | 
|  | ret.insert(ret.end(), mTypes.begin(), mTypes.end()); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | std::vector<const NamedType*> Scope::getSortedDefinedTypes() const { | 
|  | std::vector<const NamedType*> ret; | 
|  | ret.insert(ret.end(), mTypes.begin(), mTypes.end()); | 
|  |  | 
|  | std::sort(ret.begin(), ret.end(), [](const NamedType* lhs, const NamedType* rhs) -> bool { | 
|  | return lhs->location() < rhs->location(); | 
|  | }); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | void Scope::topologicalReorder(const std::unordered_map<const Type*, size_t>& reversedOrder) { | 
|  | auto less = [&](const Type* lhs, const Type* rhs) { | 
|  | return reversedOrder.at(lhs) < reversedOrder.at(rhs); | 
|  | }; | 
|  |  | 
|  | if (std::is_sorted(mTypes.begin(), mTypes.end(), less)) return; | 
|  |  | 
|  | mTypeOrderChanged = true; | 
|  | std::sort(mTypes.begin(), mTypes.end(), less); | 
|  |  | 
|  | for (size_t i = 0; i != mTypes.size(); ++i) { | 
|  | mTypeIndexByName.at(mTypes[i]->definedName()) = i; | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitHidlDefinition(Formatter& out) const { | 
|  | const std::vector<const NamedType*>& definedTypes = getSortedDefinedTypes(); | 
|  | out.join(definedTypes.begin(), definedTypes.end(), "\n", | 
|  | [&](auto t) { t->emitHidlDefinition(out); }); | 
|  | } | 
|  |  | 
|  | void Scope::emitTypeDeclarations(Formatter& out) const { | 
|  | if (mTypes.empty()) return; | 
|  |  | 
|  | out << "// Forward declaration for forward reference support:\n"; | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitTypeForwardDeclaration(out); | 
|  | } | 
|  | out << "\n"; | 
|  |  | 
|  | if (mTypeOrderChanged) { | 
|  | out << "// Order of inner types was changed for forward reference support.\n\n"; | 
|  | } | 
|  |  | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitDocComment(out); | 
|  | type->emitTypeDeclarations(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitGlobalTypeDeclarations(Formatter& out) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitGlobalTypeDeclarations(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitPackageTypeDeclarations(Formatter& out) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitPackageTypeDeclarations(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitPackageTypeHeaderDefinitions(Formatter& out) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitPackageTypeHeaderDefinitions(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitPackageHwDeclarations(Formatter& out) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitPackageHwDeclarations(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const { | 
|  | if (mTypeOrderChanged) { | 
|  | out << "// Order of inner types was changed for forward reference support.\n\n"; | 
|  | } | 
|  |  | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitDocComment(out); | 
|  | type->emitJavaTypeDeclarations(out, atTopLevel); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Scope::emitTypeDefinitions(Formatter& out, const std::string& prefix) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitTypeDefinitions(out, prefix); | 
|  | } | 
|  | } | 
|  |  | 
|  | const std::vector<NamedType *> &Scope::getSubTypes() const { | 
|  | return mTypes; | 
|  | } | 
|  |  | 
|  | void Scope::emitVtsTypeDeclarations(Formatter& out) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->emitVtsTypeDeclarations(out); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool Scope::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const { | 
|  | for (const Type* type : mTypes) { | 
|  | // Java compatibility focuses on types that are actually used by interfaces. | 
|  | // Declarations of java-incompatible types are simply omitted from | 
|  | // corresponding Java libraries. | 
|  | if (type->isInterface() && !type->isJavaCompatible(visited)) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return Type::deepIsJavaCompatible(visited); | 
|  | } | 
|  |  | 
|  | void Scope::appendToExportedTypesVector( | 
|  | std::vector<const Type *> *exportedTypes) const { | 
|  | for (const Type* type : mTypes) { | 
|  | type->appendToExportedTypesVector(exportedTypes); | 
|  | } | 
|  | } | 
|  |  | 
|  | //////////////////////////////////////// | 
|  |  | 
|  | RootScope::RootScope(const char* localName, const FQName& fullName, const Location& location, | 
|  | Scope* parent) | 
|  | : Scope(localName, fullName, location, parent) {} | 
|  | RootScope::~RootScope() {} | 
|  |  | 
|  | std::string RootScope::typeName() const { | 
|  | return "(root scope)"; | 
|  | } | 
|  |  | 
|  | status_t RootScope::validate() const { | 
|  | CHECK(annotations().empty()); | 
|  | return Scope::validate(); | 
|  | } | 
|  |  | 
|  | //////////////////////////////////////// | 
|  |  | 
|  | LocalIdentifier::LocalIdentifier(){} | 
|  | LocalIdentifier::~LocalIdentifier(){} | 
|  |  | 
|  | bool LocalIdentifier::isEnumValue() const { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const LocalIdentifier* LocalIdentifier::resolve() const { | 
|  | return this; | 
|  | } | 
|  |  | 
|  | LocalIdentifier* LocalIdentifier::resolve() { | 
|  | return this; | 
|  | } | 
|  |  | 
|  | ConstantExpression* LocalIdentifier::constExpr() const { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | }  // namespace android | 
|  |  |