Refactor AST::addScopedType.

Makes NamedType receive full name in constructor.
Adds test that defined type names are unique within one scope.

Test: mma
Test: hidl_error_test
Change-Id: If218e1febc2af9f44c5908408f67e772efdda18e
diff --git a/AST.cpp b/AST.cpp
index cef3c4b..ed58a37 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -38,7 +38,7 @@
 AST::AST(const Coordinator* coordinator, const std::string& path)
     : mCoordinator(coordinator),
       mPath(path),
-      mRootScope("(root scope)", Location::startOf(path), nullptr /* parent */) {}
+      mRootScope("(root scope)", FQName(), Location::startOf(path), nullptr /* parent */) {}
 
 Scope* AST::getRootScope() {
     return &mRootScope;
@@ -84,6 +84,11 @@
 
 status_t AST::postParse() {
     status_t err;
+    // validateDefinedTypesUniqueNames is the first call,
+    // as other errors could appear because user meant
+    // different type than we assumed.
+    err = validateDefinedTypesUniqueNames();
+    if (err != OK) return err;
     // checkAcyclicTypes is before resolveInheritance, as we
     // need to have no cycle while getting parent class.
     err = checkAcyclicTypes();
@@ -133,6 +138,19 @@
         &visitedTypes);
 }
 
+status_t AST::validateDefinedTypesUniqueNames() const {
+    std::unordered_set<const Type*> visited;
+    return mRootScope.recursivePass(
+        [&](const Type* type) -> status_t {
+            // We only want to validate type definition names in this place.
+            if (type->isScope()) {
+                return static_cast<const Scope*>(type)->validateUniqueNames();
+            }
+            return OK;
+        },
+        &visited);
+}
+
 status_t AST::resolveInheritance() {
     std::unordered_set<const Type*> visited;
     return mRootScope.recursivePass(&Type::resolveInheritance, &visited);
@@ -278,13 +296,8 @@
     mImportedASTs.insert(ast);
 }
 
-bool AST::addScopedType(NamedType* type, std::string* errorMsg, Scope* scope) {
-    bool success = scope->addType(type, errorMsg);
-    if (!success) {
-        return false;
-    }
-
-    std::vector<std::string> pathComponents{{type->localName()}};
+FQName AST::makeFullName(const char* localName, Scope* scope) const {
+    std::vector<std::string> pathComponents{{localName}};
     for (; scope != &mRootScope; scope = scope->parent()) {
         pathComponents.push_back(scope->localName());
     }
@@ -292,12 +305,12 @@
     std::reverse(pathComponents.begin(), pathComponents.end());
     std::string path = StringHelper::JoinStrings(pathComponents, ".");
 
-    FQName fqName(mPackage.package(), mPackage.version(), path);
-    type->setFullName(fqName);
+    return FQName(mPackage.package(), mPackage.version(), path);
+}
 
-    mDefinedTypesByFullName[fqName] = type;
-
-    return true;
+void AST::addScopedType(NamedType* type, Scope* scope) {
+    scope->addType(type);
+    mDefinedTypesByFullName[type->fqName()] = type;
 }
 
 EnumValue* AST::lookupEnumValue(const FQName& fqName, std::string* errorMsg, Scope* scope) {