blob: 224387d324607b23b3f623b9474ceb269f5732ab [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
18
Andreas Huber5345ec22016-07-29 13:33:27 -070019#include "Coordinator.h"
Andreas Huber84f89de2016-07-28 15:39:51 -070020#include "FQName.h"
Andreas Hubereb1081f2016-07-28 13:13:24 -070021#include "HandleType.h"
Andreas Huberbfd76212016-08-09 11:12:16 -070022#include "Interface.h"
Andreas Huber4b2cf352016-08-31 13:58:19 -070023#include "PredefinedType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070024#include "Scope.h"
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070025#include "TypeDef.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070026
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/Formatter.h>
Andreas Hubereb1081f2016-07-28 13:13:24 -070028#include <android-base/logging.h>
Andreas Huber39fa7182016-08-19 14:27:33 -070029#include <iostream>
Andreas Huberc9410c72016-07-28 12:18:40 -070030#include <stdlib.h>
31
Andreas Huberc9410c72016-07-28 12:18:40 -070032namespace android {
33
Andreas Huber0d0f9a22016-08-17 10:26:11 -070034AST::AST(Coordinator *coordinator, const std::string &path)
Andreas Huber5345ec22016-07-29 13:33:27 -070035 : mCoordinator(coordinator),
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036 mPath(path),
Andreas Huber5345ec22016-07-29 13:33:27 -070037 mScanner(NULL),
Andreas Huber9ed827c2016-08-22 12:31:13 -070038 mRootScope(new Scope("" /* localName */)) {
Andreas Huberc9410c72016-07-28 12:18:40 -070039 enterScope(mRootScope);
40}
41
42AST::~AST() {
Andreas Huberc9410c72016-07-28 12:18:40 -070043 delete mRootScope;
44 mRootScope = NULL;
45
Andreas Hubereb1081f2016-07-28 13:13:24 -070046 CHECK(mScanner == NULL);
Andreas Huberc9410c72016-07-28 12:18:40 -070047
Andreas Huber5345ec22016-07-29 13:33:27 -070048 // Ownership of "coordinator" was NOT transferred.
Andreas Huberc9410c72016-07-28 12:18:40 -070049}
50
51void *AST::scanner() {
52 return mScanner;
53}
54
55void AST::setScanner(void *scanner) {
56 mScanner = scanner;
57}
58
Andreas Huber0d0f9a22016-08-17 10:26:11 -070059const std::string &AST::getFilename() const {
60 return mPath;
61}
62
Andreas Huber84f89de2016-07-28 15:39:51 -070063bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070064 mPackage.setTo(package);
65 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070066
Andreas Huberda51b8e2016-07-28 16:00:57 -070067 if (mPackage.package().empty()
68 || mPackage.version().empty()
69 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070070 return false;
71 }
72
Andreas Huber84f89de2016-07-28 15:39:51 -070073 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070074}
75
Andreas Hubera2723d22016-07-29 15:36:07 -070076FQName AST::package() const {
77 return mPackage;
78}
79
80bool AST::isInterface(std::string *ifaceName) const {
81 return mRootScope->containsSingleInterface(ifaceName);
82}
83
Andreas Huber5345ec22016-07-29 13:33:27 -070084bool AST::addImport(const char *import) {
85 FQName fqName(import);
86 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -070087
Andreas Huber5345ec22016-07-29 13:33:27 -070088 fqName.applyDefaults(mPackage.package(), mPackage.version());
89
Andreas Huber68f24592016-07-29 14:53:48 -070090 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -070091
92 if (fqName.name().empty()) {
Andreas Huberd2943e12016-08-05 11:59:31 -070093 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -070094
Andreas Huberd2943e12016-08-05 11:59:31 -070095 status_t err =
Iliyan Malchev5bb14022016-08-09 15:04:39 -070096 mCoordinator->appendPackageInterfacesToSet(fqName,
97 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -070098
99 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700100 return false;
101 }
102
Andreas Huberd2943e12016-08-05 11:59:31 -0700103 for (const auto &subFQName : packageInterfaces) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700104 AST *ast = mCoordinator->parse(subFQName, &mImportedASTs);
105 if (ast == NULL) {
Andreas Huber68f24592016-07-29 14:53:48 -0700106 return false;
107 }
108 }
109
110 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700111 }
112
Andreas Huber39fa7182016-08-19 14:27:33 -0700113 AST *importAST = mCoordinator->parse(fqName, &mImportedASTs);
Andreas Huber5345ec22016-07-29 13:33:27 -0700114
Andreas Huber68f24592016-07-29 14:53:48 -0700115 if (importAST == NULL) {
116 return false;
117 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700118
119 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700120}
121
Andreas Huber39fa7182016-08-19 14:27:33 -0700122void AST::addImportedAST(AST *ast) {
123 mImportedASTs.insert(ast);
124}
125
Andreas Huberc9410c72016-07-28 12:18:40 -0700126void AST::enterScope(Scope *container) {
127 mScopePath.push_back(container);
128}
129
130void AST::leaveScope() {
Steven Morelandd537ab02016-09-12 10:32:01 -0700131 mScopePath.pop_back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700132}
133
134Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700135 CHECK(!mScopePath.empty());
Steven Morelandd537ab02016-09-12 10:32:01 -0700136 return mScopePath.back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700137}
138
Andreas Huber39fa7182016-08-19 14:27:33 -0700139bool AST::addTypeDef(
140 const char *localName, Type *type, std::string *errorMsg) {
141 // The reason we wrap the given type in a TypeDef is simply to suppress
142 // emitting any type definitions later on, since this is just an alias
143 // to a type defined elsewhere.
144 return addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700145 new TypeDef(localName, type), errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700146}
147
Andreas Huber9ed827c2016-08-22 12:31:13 -0700148bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700149 return addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700150 type, errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700151}
152
153bool AST::addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700154 NamedType *type,
155 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700156
Steven Morelandd537ab02016-09-12 10:32:01 -0700157 bool success = scope()->addType(type, errorMsg);
Andreas Huber5a545442016-08-03 10:44:56 -0700158 if (!success) {
159 return false;
160 }
161
Andreas Huber31629bc2016-08-03 09:06:40 -0700162 std::string path;
163 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700164 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700165 path.append(".");
166 }
Steven Morelandd537ab02016-09-12 10:32:01 -0700167 path.append(type->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700168
Andreas Huber31629bc2016-08-03 09:06:40 -0700169 FQName fqName(mPackage.package(), mPackage.version(), path);
Andreas Huber39fa7182016-08-19 14:27:33 -0700170
Steven Morelandd537ab02016-09-12 10:32:01 -0700171 type->setFullName(fqName);
Andreas Huber39fa7182016-08-19 14:27:33 -0700172
Steven Morelandd537ab02016-09-12 10:32:01 -0700173 mDefinedTypesByFullName[fqName] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700174
Andreas Huber5a545442016-08-03 10:44:56 -0700175 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700176}
177
Yifan Hongae16eed2016-09-23 13:25:25 -0700178Type *AST::lookupType(const FQName &fqName) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700179 CHECK(fqName.isValid());
180
Andreas Huberda51b8e2016-07-28 16:00:57 -0700181 if (fqName.name().empty()) {
182 // Given a package and version???
183 return NULL;
184 }
185
Andreas Huber84f89de2016-07-28 15:39:51 -0700186 if (fqName.package().empty() && fqName.version().empty()) {
187 // This is just a plain identifier, resolve locally first if possible.
188
189 for (size_t i = mScopePath.size(); i-- > 0;) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700190 Type *type = mScopePath[i]->lookupType(fqName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700191
192 if (type != NULL) {
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700193 // Resolve typeDefs to the target type.
194 while (type->isTypeDef()) {
195 type = static_cast<TypeDef *>(type)->referencedType();
196 }
197
Andreas Huberfd4afab2016-08-03 13:02:57 -0700198 return type->ref();
Andreas Huber84f89de2016-07-28 15:39:51 -0700199 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700200 }
201 }
202
Andreas Huber39fa7182016-08-19 14:27:33 -0700203 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700204 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700205 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700206
Andreas Huber39fa7182016-08-19 14:27:33 -0700207 for (const auto &importedAST : mImportedASTs) {
208 FQName matchingName;
209 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700210
Andreas Huber39fa7182016-08-19 14:27:33 -0700211 if (match != nullptr) {
212 if (resolvedType != nullptr) {
213 std::cerr << "ERROR: Unable to resolve type name '"
214 << fqName.string()
215 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700216
Andreas Huber39fa7182016-08-19 14:27:33 -0700217 std::cerr << " " << resolvedName.string() << "\n";
218 std::cerr << " " << matchingName.string() << "\n";
219
220 return NULL;
221 }
222
223 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700224 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700225 resolvedName = matchingName;
226
227 // Keep going even after finding a match.
228 }
229 }
230
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700231 if (resolvedType == nullptr
232 && fqName.package().empty()
233 && fqName.version().empty()
234 && fqName.name() == "MQDescriptor") {
235 return new PredefinedType("::android::hardware::MQDescriptor");
236 }
237
Andreas Huber39fa7182016-08-19 14:27:33 -0700238 if (resolvedType) {
239#if 0
240 LOG(INFO) << "found '"
241 << resolvedName.string()
242 << "' after looking for '"
243 << fqName.string()
244 << "'.";
245#endif
246
247 // Resolve typeDefs to the target type.
248 while (resolvedType->isTypeDef()) {
249 resolvedType =
250 static_cast<TypeDef *>(resolvedType)->referencedType();
251 }
252
Iliyan Malchev800273d2016-09-02 15:25:07 -0700253 returnedType = resolvedType;
254
255 // If the resolved type is not an interface, we need to determine
256 // whether it is defined in types.hal, or in some other interface. In
257 // the latter case, we need to emit a dependency for the interface in
258 // which the type is defined.
259 //
260 // Consider the following:
261 // android.hardware.tests.foo@1.0::Record
262 // android.hardware.tests.foo@1.0::IFoo.Folder
263 // android.hardware.tests.foo@1.0::Folder
264 //
265 // If Record is an interface, then we keep track of it for the purpose
266 // of emitting dependencies in the target language (for example #include
267 // in C++). If Record is a UDT, then we assume it is defined in
268 // types.hal in android.hardware.tests.foo@1.0.
269 //
270 // In the case of IFoo.Folder, the same applies. If IFoo is an
271 // interface, we need to track this for the purpose of emitting
272 // dependencies. If not, then it must have been defined in types.hal.
273 //
274 // In the case of just specifying Folder, the resolved type is
275 // android.hardware.tests.foo@1.0::IFoo.Folder, and the same logic as
276 // above applies.
277
278 if (!resolvedType->isInterface()) {
279 FQName ifc(resolvedName.package(),
280 resolvedName.version(),
281 resolvedName.names().at(0));
282 for (const auto &importedAST : mImportedASTs) {
283 FQName matchingName;
284 Type *match = importedAST->findDefinedType(ifc, &matchingName);
285 if (match != nullptr && match->isInterface()) {
286 resolvedType = match;
287 }
288 }
289 }
290
Andreas Huber39fa7182016-08-19 14:27:33 -0700291 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700292 // Non-interface types are declared in the associated types header.
Andreas Huber39fa7182016-08-19 14:27:33 -0700293 FQName typesName(
294 resolvedName.package(), resolvedName.version(), "types");
295
Andreas Huber0e00de42016-08-03 09:56:02 -0700296 mImportedNames.insert(typesName);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700297
Steven Morelandd537ab02016-09-12 10:32:01 -0700298 if (resolvedType->isNamedType() && !resolvedType->isTypeDef()) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700299 mImportedNamesForJava.insert(
300 static_cast<NamedType *>(resolvedType)->fqName());
301 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700302 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700303 // Do _not_ use fqName, i.e. the name we used to look up the type,
304 // but instead use the name of the interface we found.
305 // This is necessary because if fqName pointed to a typedef which
306 // in turn referenced the found interface we'd mistakenly use the
307 // name of the typedef instead of the proper name of the interface.
308
309 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700310 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber85eabdb2016-08-25 11:24:49 -0700311
312 mImportedNamesForJava.insert(
313 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700314 }
Andreas Huber737080b2016-08-02 15:38:04 -0700315 }
316
Iliyan Malchev800273d2016-09-02 15:25:07 -0700317 return returnedType->ref();
Andreas Huber5345ec22016-07-29 13:33:27 -0700318}
319
Andreas Huber39fa7182016-08-19 14:27:33 -0700320Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700321 for (const auto &pair : mDefinedTypesByFullName) {
322 const FQName &key = pair.first;
323 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700324
Andreas Huber39fa7182016-08-19 14:27:33 -0700325 if (key.endsWith(fqName)) {
326 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700327 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700328 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700329 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700330
331 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700332}
333
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700334void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700335 for (const auto &fqName : mImportedNames) {
336 FQName packageName(fqName.package(), fqName.version(), "");
337
338 if (packageName == mPackage) {
339 // We only care about external imports, not our own package.
340 continue;
341 }
342
343 importSet->insert(packageName);
344 }
345}
346
Andreas Huber0fa9e392016-08-31 09:05:44 -0700347bool AST::isJavaCompatible() const {
348 std::string ifaceName;
349 if (!AST::isInterface(&ifaceName)) {
Steven Morelandd537ab02016-09-12 10:32:01 -0700350 for (const auto *type : mRootScope->getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700351 if (!type->isJavaCompatible()) {
352 return false;
353 }
354 }
355
356 return true;
357 }
358
359 const Interface *iface = mRootScope->getInterface();
360 return iface->isJavaCompatible();
361}
362
Andreas Huberc9410c72016-07-28 12:18:40 -0700363} // namespace android;