private CharSequence toName(boolean internal, @Nullable StringBuilder out) {
   if (DEFAULT_PACKAGE.equals(this)) {
     return "";
   }
   // We build in reverse so that we don't have to recurse to parent.
   StringBuilder sb = out;
   if (sb == null) {
     sb = new StringBuilder();
   }
   int startPosition = sb.length();
   switch (type) {
     case PACKAGE:
       // Treat package names as directories to disambiguate those namespaces.
       if (internal) {
         sb.append('/');
       }
       break;
     case METHOD:
     case CONSTRUCTOR:
       // Disambiguate callables and fields.
       // Constructors are disambiguated from methods by the presence of
       // angle brackets in the name: <init> and <clinit>.
       sb.append(")(");
       break;
     case FIELD:
     case CLASS:
       break;
   }
   ApiElement el = this;
   while (true) {
     ApiElement parentEl = el.parent.get();
     appendInReverse(el.name, sb);
     if (DEFAULT_PACKAGE.equals(parentEl)) {
       break;
     }
     switch (el.type) {
       case CLASS:
         sb.append(internal ? (parentEl.type == ApiElementType.CLASS ? '$' : '/') : '.');
         break;
       case PACKAGE:
         sb.append(internal ? '/' : '.');
         break;
       case CONSTRUCTOR:
       case METHOD:
       case FIELD:
         sb.append(internal ? '#' : '.');
         break;
     }
     el = parentEl;
   }
   reverse(sb, startPosition, sb.length());
   return sb;
 }
 /**
  * @param name a JVM internal class name.
  * @return An API element such that name equals {@link #toInternalName}.
  */
 public static ApiElement fromInternalClassName(String name) {
   try {
     ApiElement apiElement = ApiElement.DEFAULT_PACKAGE;
     String[] nameParts = name.split("/");
     for (int i = 0, n = nameParts.length; i < n - 1; ++i) {
       apiElement = apiElement.child(nameParts[i], ApiElementType.PACKAGE);
     }
     String className = nameParts[nameParts.length - 1];
     for (String classNamePart : splitClassName(className)) {
       apiElement = apiElement.child(classNamePart, ApiElementType.CLASS);
     }
     return apiElement;
   } catch (RuntimeException ex) {
     // Make sure the trace includes the whole input.
     throw new IllegalArgumentException("Bad internal class name `" + name + "`", ex);
   }
 }
 static ApiElement method(String name, ApiElement parent) {
   return parent.child(name, ApiElementType.METHOD);
 }
 static ApiElement field(String name, ApiElement parent) {
   return parent.child(name, ApiElementType.FIELD);
 }
 static ApiElement clazz(String name, ApiElement parent) {
   return parent.child(name, ApiElementType.CLASS);
 }
 static ApiElement pkg(String name, ApiElement parent) {
   return parent.child(name, ApiElementType.PACKAGE);
 }