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 "Scope.h"
18 
19 #include "Interface.h"
20 
21 #include <android-base/logging.h>
22 #include <hidl-util/Formatter.h>
23 #include <vector>
24 
25 namespace android {
26 
Scope(const char * localName,const Location & location)27 Scope::Scope(const char *localName,
28         const Location &location)
29     : NamedType(localName, location) {
30 }
~Scope()31 Scope::~Scope(){}
32 
addType(NamedType * type,std::string * errorMsg)33 bool Scope::addType(NamedType *type, std::string *errorMsg) {
34     const std::string &localName = type->localName();
35 
36     auto it = mTypeIndexByName.find(localName);
37 
38     if (it != mTypeIndexByName.end()) {
39         *errorMsg = "A type named '";
40         (*errorMsg) += localName;
41         (*errorMsg) += "' is already declared in the  current scope.";
42 
43         return false;
44     }
45 
46     size_t index = mTypes.size();
47     mTypes.push_back(type);
48     mTypeIndexByName[localName] = index;
49 
50     return true;
51 }
52 
lookupType(const FQName & fqName) const53 NamedType *Scope::lookupType(const FQName &fqName) const {
54     CHECK(fqName.package().empty() && fqName.version().empty());
55     if (!fqName.valueName().empty()) {
56         LOG(WARNING) << fqName.string() << " does not refer to a type.";
57         return nullptr;
58     }
59     std::vector<std::string> names = fqName.names();
60     CHECK_GT(names.size(), 0u);
61     auto it = mTypeIndexByName.find(names[0]);
62 
63     if (it == mTypeIndexByName.end()) {
64         return nullptr;
65     }
66 
67     NamedType *outerType = mTypes[it->second];
68     if (names.size() == 1) {
69         return outerType;
70     }
71     if (!outerType->isScope()) {
72         // more than one names, but the first name is not a scope
73         return nullptr;
74     }
75     Scope *outerScope = static_cast<Scope *>(outerType);
76     // *slowly* pop first element
77     names.erase(names.begin());
78     FQName innerName(names);
79     return outerScope->lookupType(innerName);
80 }
81 
lookupIdentifier(const std::string &) const82 LocalIdentifier *Scope::lookupIdentifier(const std::string & /*name*/) const {
83     return NULL;
84 }
85 
isScope() const86 bool Scope::isScope() const {
87     return true;
88 }
89 
getInterface() const90 Interface *Scope::getInterface() const {
91     if (mTypes.size() == 1 && mTypes[0]->isInterface()) {
92         return static_cast<Interface *>(mTypes[0]);
93     }
94 
95     return NULL;
96 }
97 
containsSingleInterface(std::string * ifaceName) const98 bool Scope::containsSingleInterface(std::string *ifaceName) const {
99     Interface *iface = getInterface();
100 
101     if (iface != NULL) {
102         *ifaceName = iface->localName();
103         return true;
104     }
105 
106     return false;
107 }
108 
containsInterfaces() const109 bool Scope::containsInterfaces() const {
110     for (const NamedType *type : mTypes) {
111         if (type->isInterface()) {
112             return true;
113         }
114     }
115 
116     return false;
117 }
118 
forEachType(std::function<status_t (Type *)> func) const119 status_t Scope::forEachType(std::function<status_t(Type *)> func) const {
120     for (size_t i = 0; i < mTypes.size(); ++i) {
121         status_t err = func(mTypes[i]);
122 
123         if (err != OK) {
124             return err;
125         }
126     }
127 
128     return OK;
129 }
130 
emitTypeDeclarations(Formatter & out) const131 status_t Scope::emitTypeDeclarations(Formatter &out) const {
132     return forEachType([&](Type *type) {
133         return type->emitTypeDeclarations(out);
134     });
135 }
136 
emitGlobalTypeDeclarations(Formatter & out) const137 status_t Scope::emitGlobalTypeDeclarations(Formatter &out) const {
138     return forEachType([&](Type *type) {
139         return type->emitGlobalTypeDeclarations(out);
140     });
141 }
142 
emitGlobalHwDeclarations(Formatter & out) const143 status_t Scope::emitGlobalHwDeclarations(Formatter &out) const {
144     return forEachType([&](Type *type) {
145         return type->emitGlobalHwDeclarations(out);
146     });
147 }
148 
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const149 status_t Scope::emitJavaTypeDeclarations(
150         Formatter &out, bool atTopLevel) const {
151     return forEachType([&](Type *type) {
152         return type->emitJavaTypeDeclarations(out, atTopLevel);
153     });
154 }
155 
emitTypeDefinitions(Formatter & out,const std::string prefix) const156 status_t Scope::emitTypeDefinitions(
157         Formatter &out, const std::string prefix) const {
158     return forEachType([&](Type *type) {
159         return type->emitTypeDefinitions(out, prefix);
160     });
161 }
162 
getSubTypes() const163 const std::vector<NamedType *> &Scope::getSubTypes() const {
164     return mTypes;
165 }
166 
emitVtsTypeDeclarations(Formatter & out) const167 status_t Scope::emitVtsTypeDeclarations(Formatter &out) const {
168     return forEachType([&](Type *type) {
169         return type->emitVtsTypeDeclarations(out);
170     });
171 }
172 
isJavaCompatible() const173 bool Scope::isJavaCompatible() const {
174     for (const auto &type : mTypes) {
175         if (!type->isJavaCompatible()) {
176             return false;
177         }
178     }
179 
180     return true;
181 }
182 
containsPointer() const183 bool Scope::containsPointer() const {
184     for (const auto &type : mTypes) {
185         if (type->containsPointer()) {
186             return true;
187         }
188     }
189 
190     return false;
191 }
192 
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const193 void Scope::appendToExportedTypesVector(
194         std::vector<const Type *> *exportedTypes) const {
195     forEachType([&](Type *type) {
196         type->appendToExportedTypesVector(exportedTypes);
197         return OK;
198     });
199 }
200 
LocalIdentifier()201 LocalIdentifier::LocalIdentifier(){}
~LocalIdentifier()202 LocalIdentifier::~LocalIdentifier(){}
203 
isEnumValue() const204 bool LocalIdentifier::isEnumValue() const {
205     return false;
206 }
207 
208 }  // namespace android
209 
210