check-flagged-apis: add Symbol value class

check-flagged-apis will read contents from various sources, which use
different formats to represent the same piece information (e.g.
"class#field" or "<class><field>").

Introduce a Symbol value class to represent any API (i.e. a class, field
or method) in a unified format.

Bug: 334870672
Test: m check-flagged-apis && check-flagged-apis
Change-Id: Id9404294a87b23a9d43e5e13ce39ea5a92608e33
diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
index ecb2675..31495d6 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -20,6 +20,43 @@
 import com.github.ajalt.clikt.core.CliktCommand
 import com.github.ajalt.clikt.core.ProgramResult
 
+/**
+ * Class representing the fully qualified name of a class, method or field.
+ *
+ * This tool reads a multitude of input formats all of which represents the fully qualified path to
+ * a Java symbol slightly differently. To keep things consistent, all parsed APIs are converted to
+ * Symbols.
+ *
+ * All parts of the fully qualified name of the Symbol are separated by a dot, e.g.:
+ * <pre>
+ *   package.class.inner-class.field
+ * </pre>
+ */
+@JvmInline
+internal value class Symbol(val name: String) {
+  companion object {
+    private val FORBIDDEN_CHARS = listOf('/', '#', '$')
+
+    /** Create a new Symbol from a String that may include delimiters other than dot. */
+    fun create(name: String): Symbol {
+      var sanitizedName = name
+      for (ch in FORBIDDEN_CHARS) {
+        sanitizedName = sanitizedName.replace(ch, '.')
+      }
+      return Symbol(sanitizedName)
+    }
+  }
+
+  init {
+    require(!name.isEmpty()) { "empty string" }
+    for (ch in FORBIDDEN_CHARS) {
+      require(!name.contains(ch)) { "$name: contains $ch" }
+    }
+  }
+
+  override fun toString(): String = name.toString()
+}
+
 class CheckCommand : CliktCommand() {
   override fun run() {
     println("hello world")