Avoid unnecessary joining and splitting of qualified names

MOE_MIGRATED_REVID=136376050
diff --git a/java/com/google/turbine/binder/Binder.java b/java/com/google/turbine/binder/Binder.java
index 9860b2a..dfbcaab 100644
--- a/java/com/google/turbine/binder/Binder.java
+++ b/java/com/google/turbine/binder/Binder.java
@@ -18,8 +18,8 @@
 
 import static com.google.common.base.Verify.verifyNotNull;
 
+import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
-import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -112,7 +112,7 @@
     for (CompUnit unit : units) {
       String packagename;
       if (unit.pkg().isPresent()) {
-        packagename = unit.pkg().get().name().replace('.', '/') + '/';
+        packagename = Joiner.on('/').join(unit.pkg().get().name()) + '/';
       } else {
         packagename = "";
       }
@@ -164,11 +164,8 @@
     CompoundScope topLevel = CompoundScope.base(tli).append(javaLang);
     for (Map.Entry<CompUnit, Collection<ClassSymbol>> entry : classes.asMap().entrySet()) {
       CompUnit unit = entry.getKey();
-      // TODO(cushon): split this in the parser?
       Iterable<String> packagename =
-          unit.pkg().isPresent()
-              ? Splitter.on('.').split(unit.pkg().get().name())
-              : ImmutableList.<String>of();
+          unit.pkg().isPresent() ? unit.pkg().get().name() : ImmutableList.of();
       Scope packageScope = tli.lookupPackage(packagename);
       Scope importScope =
           ImportIndex.create(
diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java
index 76c1c6a..af52489 100644
--- a/java/com/google/turbine/binder/ConstEvaluator.java
+++ b/java/com/google/turbine/binder/ConstEvaluator.java
@@ -20,7 +20,6 @@
 import static com.google.common.base.Verify.verifyNotNull;
 
 import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.turbine.binder.bound.SourceTypeBoundClass;
@@ -832,7 +831,7 @@
   }
 
   private Const.AnnotationValue evalAnno(Tree.Anno t) {
-    LookupResult result = owner.scope().lookup(new LookupKey(Splitter.on('.').split(t.name())));
+    LookupResult result = owner.scope().lookup(new LookupKey(t.name()));
     ClassSymbol sym = (ClassSymbol) result.sym();
     for (String name : result.remaining()) {
       sym = Resolve.resolve(env, sym, name);
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java
index bc0d808..f141002 100644
--- a/java/com/google/turbine/binder/TypeBinder.java
+++ b/java/com/google/turbine/binder/TypeBinder.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.base.Verify.verify;
 
-import com.google.common.base.Splitter;
 import com.google.common.base.Verify;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -506,7 +505,7 @@
       Env<ClassSymbol, HeaderBoundClass> env, CompoundScope scope, ImmutableList<Tree.Anno> trees) {
     ImmutableList.Builder<TypeBoundClass.AnnoInfo> result = ImmutableList.builder();
     for (Tree.Anno tree : trees) {
-      LookupResult lookupResult = scope.lookup(new LookupKey(Splitter.on('.').split(tree.name())));
+      LookupResult lookupResult = scope.lookup(new LookupKey(tree.name()));
       ClassSymbol sym = (ClassSymbol) lookupResult.sym();
       for (String name : lookupResult.remaining()) {
         sym = Resolve.resolve(env, sym, name);
diff --git a/java/com/google/turbine/binder/lookup/ImportIndex.java b/java/com/google/turbine/binder/lookup/ImportIndex.java
index 2df497a..0f3c609 100644
--- a/java/com/google/turbine/binder/lookup/ImportIndex.java
+++ b/java/com/google/turbine/binder/lookup/ImportIndex.java
@@ -16,7 +16,6 @@
 
 package com.google.turbine.binder.lookup;
 
-import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
@@ -25,7 +24,6 @@
 import com.google.turbine.binder.env.Env;
 import com.google.turbine.binder.sym.ClassSymbol;
 import com.google.turbine.tree.Tree;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -57,10 +55,8 @@
         // types are not supported
         continue;
       }
-      // TODO(cushon): split names in the AST?
-      final List<String> bits = Splitter.on('.').splitToList(i.type());
-      final String last = bits.get(bits.size() - 1);
-      final LookupKey lookup = new LookupKey(bits);
+      final String last = i.type().get(i.type().size() - 1);
+      final LookupKey lookup = new LookupKey(i.type());
       thunks.put(
           last,
           Suppliers.memoize(
diff --git a/java/com/google/turbine/binder/lookup/MemberImportIndex.java b/java/com/google/turbine/binder/lookup/MemberImportIndex.java
index c0a3d81..322f28a 100644
--- a/java/com/google/turbine/binder/lookup/MemberImportIndex.java
+++ b/java/com/google/turbine/binder/lookup/MemberImportIndex.java
@@ -16,14 +16,12 @@
 
 package com.google.turbine.binder.lookup;
 
-import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.turbine.tree.Tree.ImportDecl;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 /** An index for statically imported members, in particular constant variables. */
@@ -37,10 +35,9 @@
       if (!i.stat()) {
         continue;
       }
-      List<String> bits = Splitter.on('.').splitToList(i.type());
-      LookupKey lookup = new LookupKey(bits);
+      LookupKey lookup = new LookupKey(i.type());
       cache.put(
-          Iterables.getLast(bits),
+          Iterables.getLast(i.type()),
           Suppliers.memoize(
               new Supplier<LookupResult>() {
                 @Override
diff --git a/java/com/google/turbine/parse/ConstExpressionParser.java b/java/com/google/turbine/parse/ConstExpressionParser.java
index aa08bfc..c3e4e88 100644
--- a/java/com/google/turbine/parse/ConstExpressionParser.java
+++ b/java/com/google/turbine/parse/ConstExpressionParser.java
@@ -519,7 +519,7 @@
       throw new AssertionError();
     }
     eat();
-    Tree.Expression name = qualIdent();
+    ImmutableList<String> name = ((Tree.ConstVarName) qualIdent()).name();
     ImmutableList.Builder<Tree.Expression> args = ImmutableList.builder();
     if (token == Token.LPAREN) {
       eat();
@@ -539,8 +539,7 @@
         eat();
       }
     }
-    // TODO(cushon): avoid stringifying names
-    return new Tree.AnnoExpr(new Tree.Anno(name.toString(), args.build()));
+    return new Tree.AnnoExpr(new Tree.Anno(name, args.build()));
   }
 
   private ParseError error(Object message) {
diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java
index 170540d..00ea7a1 100644
--- a/java/com/google/turbine/parse/Parser.java
+++ b/java/com/google/turbine/parse/Parser.java
@@ -1018,15 +1018,14 @@
   private ImportDecl importDeclaration() {
     boolean stat = maybe(Token.STATIC);
 
-    StringBuilder sb = new StringBuilder();
-    sb.append(eatIdent());
+    ImmutableList.Builder<String> type = ImmutableList.builder();
+    type.add(eatIdent());
     boolean wild = false;
     OUTER:
     while (maybe(Token.DOT)) {
-      sb.append('.');
       switch (token) {
         case IDENT:
-          sb.append(eatIdent());
+          type.add(eatIdent());
           break;
         case MULT:
           if (disallowWild) {
@@ -1039,12 +1038,11 @@
           break;
       }
     }
-    String type = sb.toString();
     eat(Token.SEMI);
     if (wild) {
       return null;
     }
-    return new ImportDecl(type, stat);
+    return new ImportDecl(type.build(), stat);
   }
 
   private PkgDecl packageDeclaration() {
@@ -1053,17 +1051,17 @@
     return result;
   }
 
-  private String qualIdent() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(eatIdent());
+  private ImmutableList<String> qualIdent() {
+    ImmutableList.Builder<String> name = ImmutableList.builder();
+    name.add(eatIdent());
     while (maybe(Token.DOT)) {
-      sb.append('.').append(eatIdent());
+      name.add(eatIdent());
     }
-    return sb.toString();
+    return name.build();
   }
 
   private Anno annotation() {
-    String name = qualIdent();
+    ImmutableList<String> name = qualIdent();
 
     ImmutableList.Builder<Expression> args = ImmutableList.builder();
     if (token == Token.LPAREN) {
diff --git a/java/com/google/turbine/tree/Pretty.java b/java/com/google/turbine/tree/Pretty.java
index 8fa3f63..ec51232 100644
--- a/java/com/google/turbine/tree/Pretty.java
+++ b/java/com/google/turbine/tree/Pretty.java
@@ -245,7 +245,7 @@
     if (importDecl.stat()) {
       append("static ");
     }
-    append(importDecl.type()).append(";").append('\n');
+    append(Joiner.on('.').join(importDecl.type())).append(";").append('\n');
     return null;
   }
 
@@ -321,7 +321,7 @@
   @Override
   public Void visitAnno(Tree.Anno anno, Void input) {
     append('@');
-    append(anno.name());
+    append(Joiner.on('.').join(anno.name()));
     if (!anno.args().isEmpty()) {
       append('(');
       boolean first = true;
@@ -484,7 +484,7 @@
 
   @Override
   public Void visitPkgDecl(Tree.PkgDecl pkgDecl, Void input) {
-    append("package ").append(pkgDecl.name()).append(';');
+    append("package ").append(Joiner.on('.').join(pkgDecl.name())).append(';');
     return null;
   }
 }
diff --git a/java/com/google/turbine/tree/Tree.java b/java/com/google/turbine/tree/Tree.java
index 9ee02b6..0512997 100644
--- a/java/com/google/turbine/tree/Tree.java
+++ b/java/com/google/turbine/tree/Tree.java
@@ -530,10 +530,10 @@
 
   /** A JLS 7.5 import declaration. */
   public static class ImportDecl extends Tree {
-    private final String type;
+    private final ImmutableList<String> type;
     private final boolean stat;
 
-    public ImportDecl(String type, boolean stat) {
+    public ImportDecl(ImmutableList<String> type, boolean stat) {
       this.type = type;
       this.stat = stat;
     }
@@ -548,7 +548,7 @@
       return visitor.visitImportDecl(this, input);
     }
 
-    public String type() {
+    public ImmutableList<String> type() {
       return type;
     }
 
@@ -684,10 +684,10 @@
 
   /** A JLS 9.7 annotation. */
   public static class Anno extends Tree {
-    private final String name;
+    private final ImmutableList<String> name;
     private final ImmutableList<Expression> args;
 
-    public Anno(String name, ImmutableList<Expression> args) {
+    public Anno(ImmutableList<String> name, ImmutableList<Expression> args) {
       this.name = name;
       this.args = args;
     }
@@ -702,7 +702,7 @@
       return visitor.visitAnno(this, input);
     }
 
-    public String name() {
+    public ImmutableList<String> name() {
       return name;
     }
 
@@ -843,9 +843,9 @@
 
   /** A JLS 7.4 package declaration. */
   public static class PkgDecl extends Tree {
-    private final String name;
+    private final ImmutableList<String> name;
 
-    public PkgDecl(String name) {
+    public PkgDecl(ImmutableList<String> name) {
       this.name = name;
     }
 
@@ -859,7 +859,7 @@
       return visitor.visitPkgDecl(this, input);
     }
 
-    public String name() {
+    public ImmutableList<String> name() {
       return name;
     }
   }