Use colon syntax for FQNames for enum values.

example: android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK

In constant expressions they are emitted as-is, so the emit code won't
compile.

Also split regex rule 4 into two rules in FQName.cpp, to single out
the case for identifiers.

Test: not tested. This CL require child CLs to work.

Bug: 31682916

Change-Id: Ib376dc8c4a27894f7b0eb6d017d9f69242d25b45
diff --git a/FQName.cpp b/FQName.cpp
index a477cb2..5d9c326 100644
--- a/FQName.cpp
+++ b/FQName.cpp
@@ -29,37 +29,54 @@
 static const std::regex kRE1("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH ")");
 static const std::regex kRE2("(" RE_VERSION ")::(" RE_PATH ")");
 static const std::regex kRE3("(" RE_PATH ")(" RE_VERSION ")");
-static const std::regex kRE4(RE_PATH);
+static const std::regex kRE4("(" RE_COMPONENT ")([.]" RE_COMPONENT ")+");
+static const std::regex kRE5("(" RE_COMPONENT ")");
+
+static const std::regex kRE6("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH "):(" RE_COMPONENT ")");
+static const std::regex kRE7("(" RE_VERSION ")::(" RE_PATH "):(" RE_COMPONENT ")");
+static const std::regex kRE8("(" RE_PATH "):(" RE_COMPONENT ")");
 
 namespace android {
 
 FQName::FQName()
-    : mValid(false) {
+    : mValid(false), mIsIdentifier(false) {
 }
 
 FQName::FQName(const std::string &s)
-    : mValid(false) {
+    : mValid(false), mIsIdentifier(false) {
     setTo(s);
 }
 
 FQName::FQName(
         const std::string &package,
         const std::string &version,
-        const std::string &name)
+        const std::string &name,
+        const std::string &valueName)
     : mValid(true),
+      mIsIdentifier(false),
       mPackage(package),
       mVersion(version),
-      mName(name) {
+      mName(name),
+      mValueName(valueName) {
 }
 
 bool FQName::isValid() const {
     return mValid;
 }
 
+bool FQName::isIdentifier() const {
+    return mIsIdentifier;
+}
+
 bool FQName::isFullyQualified() const {
     return !mPackage.empty() && !mVersion.empty() && !mName.empty();
 }
 
+bool FQName::isValidValueName() const {
+    return mIsIdentifier
+        || (!mName.empty() && !mValueName.empty());
+}
+
 bool FQName::setTo(const std::string &s) {
     mPackage.clear();
     mVersion.clear();
@@ -86,10 +103,36 @@
         mVersion = match.str(3);
     } else if (std::regex_match(s, match, kRE4)) {
         mName = match.str(0);
+    } else if (std::regex_match(s, match, kRE5)) {
+        mIsIdentifier = true;
+        mName = match.str(0);
+    } else if (std::regex_match(s, match, kRE6)) {
+        CHECK_EQ(match.size(), 7u);
+
+        mPackage = match.str(1);
+        mVersion = match.str(3);
+        mName = match.str(4);
+        mValueName = match.str(6);
+    } else if (std::regex_match(s, match, kRE7)) {
+        CHECK_EQ(match.size(), 5u);
+
+        mVersion = match.str(1);
+        mName = match.str(2);
+        mValueName = match.str(4);
+    } else if (std::regex_match(s, match, kRE8)) {
+        CHECK_EQ(match.size(), 4u);
+
+        mName = match.str(1);
+        mValueName = match.str(3);
     } else {
         mValid = false;
     }
 
+    // mValueName must go with mName.
+    if (!mValueName.empty()) {
+        CHECK(!mName.empty());
+    }
+
     return isValid();
 }
 
@@ -115,6 +158,14 @@
     return res;
 }
 
+std::string FQName::valueName() const {
+    return mValueName;
+}
+
+FQName FQName::typeName() const {
+    return FQName(mPackage, mVersion, mName);
+}
+
 void FQName::applyDefaults(
         const std::string &defaultPackage,
         const std::string &defaultVersion) {
@@ -138,6 +189,11 @@
             out.append("::");
         }
         out.append(mName);
+
+        if (!mValueName.empty()) {
+            out.append(":");
+            out.append(mValueName);
+        }
     }
 
     return out;
@@ -204,7 +260,8 @@
     std::vector<std::string> components;
     StringHelper::SplitString(mName, '.', &components);
 
-    return StringHelper::JoinStrings(components, "::");
+    return StringHelper::JoinStrings(components, "::")
+            + (mValueName.empty() ? "" : ("::" + mValueName));
 }
 
 std::string FQName::cppName() const {
@@ -214,6 +271,9 @@
     StringHelper::SplitString(name(), '.', &components);
     out += "::";
     out += StringHelper::JoinStrings(components, "::");
+    if (!mValueName.empty()) {
+        out  += "::" + mValueName;
+    }
 
     return out;
 }
@@ -226,7 +286,8 @@
 }
 
 std::string FQName::javaName() const {
-    return javaPackage() + "." + name();
+    return javaPackage() + "." + name()
+            + (mValueName.empty() ? "" : ("." + mValueName));
 }
 
 void FQName::getPackageComponents(std::vector<std::string> *components) const {