void process() {
    if (startType.getKind().isPrimitive()) {
      // taking a shortcut for primitives
      String typeName = Ascii.toLowerCase(startType.getKind().name());
      this.rawTypeName = typeName;
      this.returnTypeName = typeName;
      List<? extends AnnotationMirror> annotations = AnnotationMirrors.from(startType);
      if (!annotations.isEmpty()) {
        returnTypeName = typeAnnotationsToBuffer(annotations, false).append(typeName).toString();
      }
    } else {
      this.buffer = new StringBuilder(100);
      caseType(startType);

      if (workaroundTypeString != null) {
        // to not mix the mess, we just replace buffer with workaround produced type string
        this.buffer = new StringBuilder(workaroundTypeString);
      }

      // It seems that array type annotations are not exposed in javac
      // Nested type argument's type annotations are not exposed as well (in javac)
      // So currently we insert only for top level, declared type (here),
      // and primitives (see above)
      TypeKind k = startType.getKind();
      if (k == TypeKind.DECLARED || k == TypeKind.ERROR) {
        insertTypeAnnotationsIfPresent(startType, 0, rawTypeName.length());
      }

      this.returnTypeName = buffer.toString();
    }
  }
Encapsulates routines and various hacks for get relevant strings for the raw types and type
parameters, while attempting to resolve unresolved types using source imports.
value-processor/src/org/immutables/value/processor/meta/TypeStringProvider.java