private void appendResolved(DeclaredType type) {
    TypeElement typeElement = (TypeElement) type.asElement();
    String typeName = typeElement.getQualifiedName().toString();

    if (unresolvedTypeHasOccured) {
      if (type == startType && forAttribute) {
        // special routine for top level type, opportunistically
        // resolving not yet generated type assuming it can be found in imports
        typeName = importsResolver.resolveTopForAttribute(typeName);
      } else {
        typeName = importsResolver.apply(typeName);
      }
      if (type != startType && importsResolver.unresolved && unresolvedYetArguments != null) {
        unresolvedYetArguments.add(typeName);
      }

      hasMaybeUnresolvedYetAfter |= importsResolver.unresolved;
    } else if (typeName.startsWith("java.lang.")) {// saves on concat & other ops
      // Because java.lang is automatically imported,
      // you can have type names that are "resolved,"
      // but aren't the names that are actually imported in the source file
      String simpleName = typeElement.getSimpleName().toString();
      // The only problem I might worry about is
      // if we have java.lang.Something.Inner.InThere, however unlikely,
      // and my brain is unable to understand if that is relevant or not for this case
      if (typeName.equals("java.lang." + simpleName)) {
        String guessedName = importsResolver.apply(simpleName);
        if (!importsResolver.unresolved) {
          typeName = guessedName;
        }
      }
    }

    buffer.append(typeName);
    if (startType == type) {
      rawTypeName = typeName;
    }
  }
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