Merge "Fix code generation for nested structs."
diff --git a/AST.cpp b/AST.cpp
index 016204b..810633f 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -42,7 +42,7 @@
AST::~AST() {
delete mRootScope;
- mRootScope = NULL;
+ mRootScope = nullptr;
CHECK(mScanner == NULL);
@@ -95,6 +95,7 @@
// LOG(INFO) << "importing " << fqName.string();
if (fqName.name().empty()) {
+ // import a package
std::vector<FQName> packageInterfaces;
status_t err =
@@ -107,21 +108,67 @@
for (const auto &subFQName : packageInterfaces) {
AST *ast = mCoordinator->parse(subFQName, &mImportedASTs);
- if (ast == NULL) {
+ if (ast == nullptr) {
return false;
}
+ // all previous single type imports are ignored.
+ mImportedTypes.erase(ast);
}
return true;
}
- AST *importAST = mCoordinator->parse(fqName, &mImportedASTs);
+ AST *importAST;
- if (importAST == NULL) {
- return false;
+ // cases like android.hardware.foo@1.0::IFoo.Internal
+ // android.hardware.foo@1.0::Abc.Internal
+
+ // assume it is an interface, and try to import it.
+ const FQName interfaceName = fqName.getTopLevelType();
+ importAST = mCoordinator->parse(interfaceName, &mImportedASTs);
+
+ if (importAST != nullptr) {
+ // cases like android.hardware.foo@1.0::IFoo.Internal
+ // and android.hardware.foo@1.0::IFoo
+ if (fqName == interfaceName) {
+ // import a single file.
+ // all previous single type imports are ignored.
+ // cases like android.hardware.foo@1.0::IFoo
+ // and android.hardware.foo@1.0::types
+ mImportedTypes.erase(importAST);
+ return true;
+ }
+
+ // import a single type from this file
+ // cases like android.hardware.foo@1.0::IFoo.Internal
+ FQName matchingName;
+ Type *match = importAST->findDefinedType(fqName, &matchingName);
+ if (match == nullptr) {
+ return false;
+ }
+ // will automatically create a set if it does not exist
+ mImportedTypes[importAST].insert(match);
+ return true;
}
- return true;
+ // probably a type in types.hal, like android.hardware.foo@1.0::Abc.Internal
+ FQName typesFQName = fqName.getTypesForPackage();
+ importAST = mCoordinator->parse(typesFQName, &mImportedASTs);
+
+ if (importAST != nullptr) {
+ // Attempt to find Abc.Internal in types.
+ FQName matchingName;
+ Type *match = importAST->findDefinedType(fqName, &matchingName);
+ if (match == nullptr) {
+ return false;
+ }
+ // will automatically create a set if not exist
+ mImportedTypes[importAST].insert(match);
+ return true;
+ }
+
+ // can't find an appropriate AST for fqName.
+ return false;
}
void AST::addImportedAST(AST *ast) {
@@ -212,7 +259,7 @@
if (fqName.name().empty()) {
// Given a package and version???
- return NULL;
+ return nullptr;
}
if (fqName.package().empty() && fqName.version().empty()) {
@@ -221,7 +268,7 @@
for (size_t i = mScopePath.size(); i-- > 0;) {
Type *type = mScopePath[i]->lookupType(fqName);
- if (type != NULL) {
+ if (type != nullptr) {
// Resolve typeDefs to the target type.
while (type->isTypeDef()) {
type = static_cast<TypeDef *>(type)->referencedType();
@@ -237,6 +284,10 @@
FQName resolvedName;
for (const auto &importedAST : mImportedASTs) {
+ if (mImportedTypes.find(importedAST) != mImportedTypes.end()) {
+ // ignore single type imports
+ continue;
+ }
FQName matchingName;
Type *match = importedAST->findDefinedType(fqName, &matchingName);
@@ -249,7 +300,34 @@
std::cerr << " " << resolvedName.string() << "\n";
std::cerr << " " << matchingName.string() << "\n";
- return NULL;
+ return nullptr;
+ }
+
+ resolvedType = match;
+ returnedType = resolvedType;
+ resolvedName = matchingName;
+
+ // Keep going even after finding a match.
+ }
+ }
+
+ for (const auto &pair : mImportedTypes) {
+ AST *importedAST = pair.first;
+ std::set<Type *> importedTypes = pair.second;
+
+ FQName matchingName;
+ Type *match = importedAST->findDefinedType(fqName, &matchingName);
+ if (match != nullptr &&
+ importedTypes.find(match) != importedTypes.end()) {
+ if (resolvedType != nullptr) {
+ std::cerr << "ERROR: Unable to resolve type name '"
+ << fqName.string()
+ << "', multiple matches found:\n";
+
+ std::cerr << " " << resolvedName.string() << "\n";
+ std::cerr << " " << matchingName.string() << "\n";
+
+ return nullptr;
}
resolvedType = match;
diff --git a/AST.h b/AST.h
index 5195532..1f9b02f 100644
--- a/AST.h
+++ b/AST.h
@@ -123,6 +123,12 @@
// A set of all ASTs we explicitly or implicitly (types.hal) import.
std::set<AST *> mImportedASTs;
+ // If a single type (instead of the whole AST) is imported, the AST will be
+ // present as a key to this map, with the value being a list of types
+ // imported from this AST. If an AST appears in mImportedASTs but not in
+ // mImportedTypes, then the whole AST is imported.
+ std::map<AST *, std::set<Type *>> mImportedTypes;
+
// Types keyed by full names defined in this AST.
std::map<FQName, Type *> mDefinedTypesByFullName;
diff --git a/EnumType.cpp b/EnumType.cpp
index d5abf6d..5513596 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -329,6 +329,16 @@
name = quotedString.substr(1, quotedString.size() - 2);
}
+ std::string valuePrefix;
+
+ const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
+ if (prefixParam != nullptr) {
+ CHECK_EQ(prefixParam->getValues()->size(), 1u);
+
+ std::string quotedString = prefixParam->getValues()->at(0);
+ valuePrefix = quotedString.substr(1, quotedString.size() - 2);
+ }
+
const ScalarType *scalarType = mStorageType->resolveToScalarType();
CHECK(scalarType != NULL);
@@ -349,7 +359,7 @@
const auto &type = *it;
for (const auto &entry : type->values()) {
- out << entry->name();
+ out << valuePrefix << entry->name();
std::string value = entry->cppValue(scalarType->getKind());
CHECK(!value.empty()); // use autofilled values for c++.
diff --git a/FQName.cpp b/FQName.cpp
index 9bc271b..0169e0c 100644
--- a/FQName.cpp
+++ b/FQName.cpp
@@ -241,6 +241,10 @@
return mName.substr(1);
}
+FQName FQName::getTypesForPackage() const {
+ return FQName(package(), version(), "types");
+}
+
const FQName FQName::getTopLevelType() const {
auto idx = mName.find('.');
diff --git a/FQName.h b/FQName.h
index e2d0159..391ba3d 100644
--- a/FQName.h
+++ b/FQName.h
@@ -99,11 +99,16 @@
// -> Bar
std::string getInterfaceBaseName() const;
+ // Replace whatever after :: with "types"
+ // android.hardware.foo@1.0::Abc.Type:VALUE
+ // -> android.hardware.foo@1.0::types
+ FQName getTypesForPackage() const;
+
// the following comments all assume that the FQName
- // is ::android::hardware::Foo::V1_0::IBar::Baz
+ // is android.hardware.foo@1.0::IBar.Baz.Bam
// returns highest type in the hidl namespace, i.e.
- // ::android::hardware::Foo::V1_0::IBar
+ // android.hardware.foo@1.0::IBar
const FQName getTopLevelType() const;
// returns an unambiguous fully qualified name which can be