blob: f9a65159675a7e0d153d177011a44dc067ed2f69 [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"
Yifan Hongf24fa852016-09-23 11:03:15 -070020#include "EnumType.h"
Andreas Huber84f89de2016-07-28 15:39:51 -070021#include "FQName.h"
Andreas Hubereb1081f2016-07-28 13:13:24 -070022#include "HandleType.h"
Andreas Huberbfd76212016-08-09 11:12:16 -070023#include "Interface.h"
Yifan Honga4b53d02016-10-31 17:29:10 -070024#include "Location.h"
Andreas Huber4b2cf352016-08-31 13:58:19 -070025#include "PredefinedType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070026#include "Scope.h"
Andreas Huber8d3ac0c2016-08-04 14:49:23 -070027#include "TypeDef.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070028
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070029#include <hidl-util/Formatter.h>
Andreas Hubereb1081f2016-07-28 13:13:24 -070030#include <android-base/logging.h>
Andreas Huber39fa7182016-08-19 14:27:33 -070031#include <iostream>
Andreas Huberc9410c72016-07-28 12:18:40 -070032#include <stdlib.h>
33
Andreas Huberc9410c72016-07-28 12:18:40 -070034namespace android {
35
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036AST::AST(Coordinator *coordinator, const std::string &path)
Andreas Huber5345ec22016-07-29 13:33:27 -070037 : mCoordinator(coordinator),
Andreas Huber0d0f9a22016-08-17 10:26:11 -070038 mPath(path),
Andreas Huber5345ec22016-07-29 13:33:27 -070039 mScanner(NULL),
Yifan Honga4b53d02016-10-31 17:29:10 -070040 mRootScope(new Scope("" /* localName */, Location::startOf(path))) {
Andreas Huberc9410c72016-07-28 12:18:40 -070041 enterScope(mRootScope);
42}
43
44AST::~AST() {
Andreas Huberc9410c72016-07-28 12:18:40 -070045 delete mRootScope;
Yifan Hong1977ea32016-10-05 12:49:08 -070046 mRootScope = nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -070047
Andreas Hubereb1081f2016-07-28 13:13:24 -070048 CHECK(mScanner == NULL);
Andreas Huberc9410c72016-07-28 12:18:40 -070049
Andreas Huber5345ec22016-07-29 13:33:27 -070050 // Ownership of "coordinator" was NOT transferred.
Andreas Huberc9410c72016-07-28 12:18:40 -070051}
52
53void *AST::scanner() {
54 return mScanner;
55}
56
57void AST::setScanner(void *scanner) {
58 mScanner = scanner;
59}
60
Andreas Huber0d0f9a22016-08-17 10:26:11 -070061const std::string &AST::getFilename() const {
62 return mPath;
63}
64
Andreas Huber84f89de2016-07-28 15:39:51 -070065bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070066 mPackage.setTo(package);
67 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070068
Andreas Huberda51b8e2016-07-28 16:00:57 -070069 if (mPackage.package().empty()
70 || mPackage.version().empty()
71 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070072 return false;
73 }
74
Andreas Huber84f89de2016-07-28 15:39:51 -070075 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070076}
77
Andreas Hubera2723d22016-07-29 15:36:07 -070078FQName AST::package() const {
79 return mPackage;
80}
81
82bool AST::isInterface(std::string *ifaceName) const {
83 return mRootScope->containsSingleInterface(ifaceName);
84}
85
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070086bool AST::containsInterfaces() const {
87 return mRootScope->containsInterfaces();
88}
89
Andreas Huber5345ec22016-07-29 13:33:27 -070090bool AST::addImport(const char *import) {
91 FQName fqName(import);
92 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -070093
Andreas Huber5345ec22016-07-29 13:33:27 -070094 fqName.applyDefaults(mPackage.package(), mPackage.version());
95
Andreas Huber68f24592016-07-29 14:53:48 -070096 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -070097
98 if (fqName.name().empty()) {
Yifan Hong1977ea32016-10-05 12:49:08 -070099 // import a package
Andreas Huberd2943e12016-08-05 11:59:31 -0700100 std::vector<FQName> packageInterfaces;
Andreas Huber68f24592016-07-29 14:53:48 -0700101
Andreas Huberd2943e12016-08-05 11:59:31 -0700102 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700103 mCoordinator->appendPackageInterfacesToVector(fqName,
104 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700105
106 if (err != OK) {
Andreas Huber68f24592016-07-29 14:53:48 -0700107 return false;
108 }
109
Andreas Huberd2943e12016-08-05 11:59:31 -0700110 for (const auto &subFQName : packageInterfaces) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700111 AST *ast = mCoordinator->parse(subFQName, &mImportedASTs);
Yifan Hong1977ea32016-10-05 12:49:08 -0700112 if (ast == nullptr) {
Andreas Huber68f24592016-07-29 14:53:48 -0700113 return false;
114 }
Yifan Hong1977ea32016-10-05 12:49:08 -0700115 // all previous single type imports are ignored.
116 mImportedTypes.erase(ast);
Andreas Huber68f24592016-07-29 14:53:48 -0700117 }
118
119 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700120 }
121
Yifan Hong1977ea32016-10-05 12:49:08 -0700122 AST *importAST;
Andreas Huber5345ec22016-07-29 13:33:27 -0700123
Yifan Hong1977ea32016-10-05 12:49:08 -0700124 // cases like android.hardware.foo@1.0::IFoo.Internal
125 // android.hardware.foo@1.0::Abc.Internal
126
127 // assume it is an interface, and try to import it.
128 const FQName interfaceName = fqName.getTopLevelType();
129 importAST = mCoordinator->parse(interfaceName, &mImportedASTs);
130
131 if (importAST != nullptr) {
132 // cases like android.hardware.foo@1.0::IFoo.Internal
133 // and android.hardware.foo@1.0::IFoo
134 if (fqName == interfaceName) {
135 // import a single file.
136 // all previous single type imports are ignored.
137 // cases like android.hardware.foo@1.0::IFoo
138 // and android.hardware.foo@1.0::types
139 mImportedTypes.erase(importAST);
140 return true;
141 }
142
143 // import a single type from this file
144 // cases like android.hardware.foo@1.0::IFoo.Internal
145 FQName matchingName;
146 Type *match = importAST->findDefinedType(fqName, &matchingName);
147 if (match == nullptr) {
148 return false;
149 }
150 // will automatically create a set if it does not exist
151 mImportedTypes[importAST].insert(match);
152 return true;
Andreas Huber68f24592016-07-29 14:53:48 -0700153 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700154
Yifan Hong1977ea32016-10-05 12:49:08 -0700155 // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
156 FQName typesFQName = fqName.getTypesForPackage();
157 importAST = mCoordinator->parse(typesFQName, &mImportedASTs);
158
159 if (importAST != nullptr) {
160 // Attempt to find Abc.Internal in types.
161 FQName matchingName;
162 Type *match = importAST->findDefinedType(fqName, &matchingName);
163 if (match == nullptr) {
164 return false;
165 }
166 // will automatically create a set if not exist
167 mImportedTypes[importAST].insert(match);
168 return true;
169 }
170
171 // can't find an appropriate AST for fqName.
172 return false;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700173}
174
Andreas Huber39fa7182016-08-19 14:27:33 -0700175void AST::addImportedAST(AST *ast) {
176 mImportedASTs.insert(ast);
177}
178
Andreas Huberc9410c72016-07-28 12:18:40 -0700179void AST::enterScope(Scope *container) {
180 mScopePath.push_back(container);
181}
182
183void AST::leaveScope() {
Steven Morelandd537ab02016-09-12 10:32:01 -0700184 mScopePath.pop_back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700185}
186
187Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700188 CHECK(!mScopePath.empty());
Steven Morelandd537ab02016-09-12 10:32:01 -0700189 return mScopePath.back();
Andreas Huberc9410c72016-07-28 12:18:40 -0700190}
191
Yifan Honga4b53d02016-10-31 17:29:10 -0700192bool AST::addTypeDef(const char *localName, Type *type, const Location &location,
193 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700194 // The reason we wrap the given type in a TypeDef is simply to suppress
195 // emitting any type definitions later on, since this is just an alias
196 // to a type defined elsewhere.
197 return addScopedTypeInternal(
Yifan Honga4b53d02016-10-31 17:29:10 -0700198 new TypeDef(localName, location, type), errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700199}
200
Andreas Huber9ed827c2016-08-22 12:31:13 -0700201bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700202 return addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700203 type, errorMsg);
Andreas Huber39fa7182016-08-19 14:27:33 -0700204}
205
206bool AST::addScopedTypeInternal(
Steven Morelandd537ab02016-09-12 10:32:01 -0700207 NamedType *type,
208 std::string *errorMsg) {
Andreas Huber39fa7182016-08-19 14:27:33 -0700209
Steven Morelandd537ab02016-09-12 10:32:01 -0700210 bool success = scope()->addType(type, errorMsg);
Andreas Huber5a545442016-08-03 10:44:56 -0700211 if (!success) {
212 return false;
213 }
214
Andreas Huber31629bc2016-08-03 09:06:40 -0700215 std::string path;
216 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700217 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700218 path.append(".");
219 }
Steven Morelandd537ab02016-09-12 10:32:01 -0700220 path.append(type->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700221
Andreas Huber31629bc2016-08-03 09:06:40 -0700222 FQName fqName(mPackage.package(), mPackage.version(), path);
Andreas Huber39fa7182016-08-19 14:27:33 -0700223
Steven Morelandd537ab02016-09-12 10:32:01 -0700224 type->setFullName(fqName);
Andreas Huber39fa7182016-08-19 14:27:33 -0700225
Steven Morelandd537ab02016-09-12 10:32:01 -0700226 mDefinedTypesByFullName[fqName] = type;
Andreas Huber31629bc2016-08-03 09:06:40 -0700227
Andreas Huber5a545442016-08-03 10:44:56 -0700228 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700229}
230
Yifan Hongf24fa852016-09-23 11:03:15 -0700231EnumValue *AST::lookupEnumValue(const FQName &fqName, std::string *errorMsg) {
232
233 FQName enumTypeName = fqName.typeName();
234 std::string enumValueName = fqName.valueName();
235
236 CHECK(enumTypeName.isValid());
237 CHECK(!enumValueName.empty());
238
239 Type *type = lookupType(enumTypeName);
240 if(type == nullptr) {
241 *errorMsg = "Cannot find type " + enumTypeName.string();
242 return nullptr;
243 }
244 if(!type->isEnum()) {
245 *errorMsg = "Type " + enumTypeName.string() + " is not an enum type";
246 return nullptr;
247 }
248
249 EnumType *enumType = static_cast<EnumType *>(type);
250 EnumValue *v = static_cast<EnumValue *>(enumType->lookupIdentifier(enumValueName));
251 if(v == nullptr) {
252 *errorMsg = "Enum type " + enumTypeName.string() + " does not have " + enumValueName;
253 return nullptr;
254 }
255 return v;
256}
257
Yifan Hongae16eed2016-09-23 13:25:25 -0700258Type *AST::lookupType(const FQName &fqName) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700259 CHECK(fqName.isValid());
260
Andreas Huberda51b8e2016-07-28 16:00:57 -0700261 if (fqName.name().empty()) {
262 // Given a package and version???
Yifan Hong1977ea32016-10-05 12:49:08 -0700263 return nullptr;
Andreas Huberda51b8e2016-07-28 16:00:57 -0700264 }
265
Andreas Huber84f89de2016-07-28 15:39:51 -0700266 if (fqName.package().empty() && fqName.version().empty()) {
267 // This is just a plain identifier, resolve locally first if possible.
268
269 for (size_t i = mScopePath.size(); i-- > 0;) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700270 Type *type = mScopePath[i]->lookupType(fqName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700271
Yifan Hong1977ea32016-10-05 12:49:08 -0700272 if (type != nullptr) {
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700273 // Resolve typeDefs to the target type.
274 while (type->isTypeDef()) {
275 type = static_cast<TypeDef *>(type)->referencedType();
276 }
277
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700278 return type;
Andreas Huber84f89de2016-07-28 15:39:51 -0700279 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700280 }
281 }
282
Andreas Huber39fa7182016-08-19 14:27:33 -0700283 Type *resolvedType = nullptr;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700284 Type *returnedType = nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700285 FQName resolvedName;
Andreas Huber84f89de2016-07-28 15:39:51 -0700286
Andreas Huber39fa7182016-08-19 14:27:33 -0700287 for (const auto &importedAST : mImportedASTs) {
Yifan Hong1977ea32016-10-05 12:49:08 -0700288 if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
289 // ignore single type imports
290 continue;
291 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700292 FQName matchingName;
293 Type *match = importedAST->findDefinedType(fqName, &matchingName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700294
Andreas Huber39fa7182016-08-19 14:27:33 -0700295 if (match != nullptr) {
296 if (resolvedType != nullptr) {
297 std::cerr << "ERROR: Unable to resolve type name '"
298 << fqName.string()
299 << "', multiple matches found:\n";
Andreas Huber737080b2016-08-02 15:38:04 -0700300
Andreas Huber39fa7182016-08-19 14:27:33 -0700301 std::cerr << " " << resolvedName.string() << "\n";
302 std::cerr << " " << matchingName.string() << "\n";
303
Yifan Hong1977ea32016-10-05 12:49:08 -0700304 return nullptr;
305 }
306
307 resolvedType = match;
308 returnedType = resolvedType;
309 resolvedName = matchingName;
310
311 // Keep going even after finding a match.
312 }
313 }
314
315 for (const auto &pair : mImportedTypes) {
316 AST *importedAST = pair.first;
317 std::set<Type *> importedTypes = pair.second;
318
319 FQName matchingName;
320 Type *match = importedAST->findDefinedType(fqName, &matchingName);
321 if (match != nullptr &&
322 importedTypes.find(match) != importedTypes.end()) {
323 if (resolvedType != nullptr) {
324 std::cerr << "ERROR: Unable to resolve type name '"
325 << fqName.string()
326 << "', multiple matches found:\n";
327
328 std::cerr << " " << resolvedName.string() << "\n";
329 std::cerr << " " << matchingName.string() << "\n";
330
331 return nullptr;
Andreas Huber39fa7182016-08-19 14:27:33 -0700332 }
333
334 resolvedType = match;
Iliyan Malchev800273d2016-09-02 15:25:07 -0700335 returnedType = resolvedType;
Andreas Huber39fa7182016-08-19 14:27:33 -0700336 resolvedName = matchingName;
337
338 // Keep going even after finding a match.
339 }
340 }
341
342 if (resolvedType) {
343#if 0
344 LOG(INFO) << "found '"
345 << resolvedName.string()
346 << "' after looking for '"
347 << fqName.string()
348 << "'.";
349#endif
350
351 // Resolve typeDefs to the target type.
352 while (resolvedType->isTypeDef()) {
353 resolvedType =
354 static_cast<TypeDef *>(resolvedType)->referencedType();
355 }
356
Iliyan Malchev800273d2016-09-02 15:25:07 -0700357 returnedType = resolvedType;
358
359 // If the resolved type is not an interface, we need to determine
360 // whether it is defined in types.hal, or in some other interface. In
361 // the latter case, we need to emit a dependency for the interface in
362 // which the type is defined.
363 //
364 // Consider the following:
365 // android.hardware.tests.foo@1.0::Record
366 // android.hardware.tests.foo@1.0::IFoo.Folder
367 // android.hardware.tests.foo@1.0::Folder
368 //
369 // If Record is an interface, then we keep track of it for the purpose
370 // of emitting dependencies in the target language (for example #include
371 // in C++). If Record is a UDT, then we assume it is defined in
372 // types.hal in android.hardware.tests.foo@1.0.
373 //
374 // In the case of IFoo.Folder, the same applies. If IFoo is an
375 // interface, we need to track this for the purpose of emitting
376 // dependencies. If not, then it must have been defined in types.hal.
377 //
378 // In the case of just specifying Folder, the resolved type is
379 // android.hardware.tests.foo@1.0::IFoo.Folder, and the same logic as
380 // above applies.
381
382 if (!resolvedType->isInterface()) {
383 FQName ifc(resolvedName.package(),
384 resolvedName.version(),
385 resolvedName.names().at(0));
386 for (const auto &importedAST : mImportedASTs) {
387 FQName matchingName;
388 Type *match = importedAST->findDefinedType(ifc, &matchingName);
389 if (match != nullptr && match->isInterface()) {
390 resolvedType = match;
391 }
392 }
393 }
394
Andreas Huber39fa7182016-08-19 14:27:33 -0700395 if (!resolvedType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700396 // Non-interface types are declared in the associated types header.
Andreas Huber39fa7182016-08-19 14:27:33 -0700397 FQName typesName(
398 resolvedName.package(), resolvedName.version(), "types");
399
Andreas Huber0e00de42016-08-03 09:56:02 -0700400 mImportedNames.insert(typesName);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700401
Steven Morelandd537ab02016-09-12 10:32:01 -0700402 if (resolvedType->isNamedType() && !resolvedType->isTypeDef()) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700403 mImportedNamesForJava.insert(
404 static_cast<NamedType *>(resolvedType)->fqName());
405 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700406 } else {
Andreas Huberbfd76212016-08-09 11:12:16 -0700407 // Do _not_ use fqName, i.e. the name we used to look up the type,
408 // but instead use the name of the interface we found.
409 // This is necessary because if fqName pointed to a typedef which
410 // in turn referenced the found interface we'd mistakenly use the
411 // name of the typedef instead of the proper name of the interface.
412
413 mImportedNames.insert(
Andreas Huber39fa7182016-08-19 14:27:33 -0700414 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber85eabdb2016-08-25 11:24:49 -0700415
416 mImportedNamesForJava.insert(
417 static_cast<Interface *>(resolvedType)->fqName());
Andreas Huber0e00de42016-08-03 09:56:02 -0700418 }
Andreas Huber737080b2016-08-02 15:38:04 -0700419 }
420
Steven Morelandbb5c80b2016-10-05 11:07:36 -0700421 return returnedType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700422}
423
Andreas Huber39fa7182016-08-19 14:27:33 -0700424Type *AST::findDefinedType(const FQName &fqName, FQName *matchingName) const {
Steven Morelandd537ab02016-09-12 10:32:01 -0700425 for (const auto &pair : mDefinedTypesByFullName) {
426 const FQName &key = pair.first;
427 Type* type = pair.second;
Andreas Huber5345ec22016-07-29 13:33:27 -0700428
Andreas Huber39fa7182016-08-19 14:27:33 -0700429 if (key.endsWith(fqName)) {
430 *matchingName = key;
Steven Morelandd537ab02016-09-12 10:32:01 -0700431 return type;
Andreas Huber5345ec22016-07-29 13:33:27 -0700432 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700433 }
Andreas Huber39fa7182016-08-19 14:27:33 -0700434
435 return nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700436}
437
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700438void AST::getImportedPackages(std::set<FQName> *importSet) const {
Andreas Huberd2943e12016-08-05 11:59:31 -0700439 for (const auto &fqName : mImportedNames) {
440 FQName packageName(fqName.package(), fqName.version(), "");
441
442 if (packageName == mPackage) {
443 // We only care about external imports, not our own package.
444 continue;
445 }
446
447 importSet->insert(packageName);
448 }
449}
450
Andreas Huber0fa9e392016-08-31 09:05:44 -0700451bool AST::isJavaCompatible() const {
452 std::string ifaceName;
453 if (!AST::isInterface(&ifaceName)) {
Steven Morelandd537ab02016-09-12 10:32:01 -0700454 for (const auto *type : mRootScope->getSubTypes()) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700455 if (!type->isJavaCompatible()) {
456 return false;
457 }
458 }
459
460 return true;
461 }
462
463 const Interface *iface = mRootScope->getInterface();
464 return iface->isJavaCompatible();
465}
466
Andreas Huber019d21d2016-10-03 12:59:47 -0700467void AST::appendToExportedTypesVector(
468 std::vector<const Type *> *exportedTypes) const {
469 mRootScope->appendToExportedTypesVector(exportedTypes);
470}
471
Andreas Huberc9410c72016-07-28 12:18:40 -0700472} // namespace android;