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
25namespace android {
26
27Scope::Scope(const char *localName,
28        const Location &location)
29    : NamedType(localName, location) {
30}
31Scope::~Scope(){}
32
33bool 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
53NamedType *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
82LocalIdentifier *Scope::lookupIdentifier(const std::string & /*name*/) const {
83    return NULL;
84}
85
86bool Scope::isScope() const {
87    return true;
88}
89
90Interface *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
98bool 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
109bool Scope::containsInterfaces() const {
110    for (const NamedType *type : mTypes) {
111        if (type->isInterface()) {
112            return true;
113        }
114    }
115
116    return false;
117}
118
119status_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
131status_t Scope::emitTypeDeclarations(Formatter &out) const {
132    return forEachType([&](Type *type) {
133        return type->emitTypeDeclarations(out);
134    });
135}
136
137status_t Scope::emitGlobalTypeDeclarations(Formatter &out) const {
138    return forEachType([&](Type *type) {
139        return type->emitGlobalTypeDeclarations(out);
140    });
141}
142
143status_t Scope::emitGlobalHwDeclarations(Formatter &out) const {
144    return forEachType([&](Type *type) {
145        return type->emitGlobalHwDeclarations(out);
146    });
147}
148
149status_t Scope::emitJavaTypeDeclarations(
150        Formatter &out, bool atTopLevel) const {
151    return forEachType([&](Type *type) {
152        return type->emitJavaTypeDeclarations(out, atTopLevel);
153    });
154}
155
156status_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
163const std::vector<NamedType *> &Scope::getSubTypes() const {
164    return mTypes;
165}
166
167status_t Scope::emitVtsTypeDeclarations(Formatter &out) const {
168    return forEachType([&](Type *type) {
169        return type->emitVtsTypeDeclarations(out);
170    });
171}
172
173bool Scope::isJavaCompatible() const {
174    for (const auto &type : mTypes) {
175        if (!type->isJavaCompatible()) {
176            return false;
177        }
178    }
179
180    return true;
181}
182
183bool Scope::containsPointer() const {
184    for (const auto &type : mTypes) {
185        if (type->containsPointer()) {
186            return true;
187        }
188    }
189
190    return false;
191}
192
193void Scope::appendToExportedTypesVector(
194        std::vector<const Type *> *exportedTypes) const {
195    forEachType([&](Type *type) {
196        type->appendToExportedTypesVector(exportedTypes);
197        return OK;
198    });
199}
200
201LocalIdentifier::LocalIdentifier(){}
202LocalIdentifier::~LocalIdentifier(){}
203
204bool LocalIdentifier::isEnumValue() const {
205    return false;
206}
207
208}  // namespace android
209
210