code: @Override
    StringBuilder appendTo(StringBuilder sb, boolean forAnnotations) {
      if (!isPrettyPrint() || this == registry.getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE)) {
        return sb.append(forAnnotations ? "!Function" : "Function");
      }
  
      if (hasInstanceType() && getSource() != null) {
        // Render function types known to be type definitions as "(typeof Foo)". This includes types
        // defined like "/** @constructor */ function Foo() { }" but not to those defined like "@param
        // {function(new:Foo)}". Only the former will have a source node.
        sb.append("(typeof ");
        getInstanceType().appendTo(sb, forAnnotations);
        sb.append(")");
        return sb;
      }
  
      setPrettyPrint(false);
  
      sb.append("function(");
      int paramNum = call.parameters.getChildCount();
      boolean hasKnownTypeOfThis = !(typeOfThis instanceof UnknownType);
      if (hasKnownTypeOfThis) {
        if (isConstructor()) {
          sb.append("new:");
        } else {
          sb.append("this:");
        }
        typeOfThis.appendTo(sb, forAnnotations);
      }
      if (paramNum > 0) {
        if (hasKnownTypeOfThis) {
          sb.append(", ");
        }
        Node p = call.parameters.getFirstChild();
        appendArgString(sb, p, forAnnotations);
  
        p = p.getNext();
        while (p != null) {
          sb.append(", ");
          appendArgString(sb, p, forAnnotations);
          p = p.getNext();
        }
      }
      sb.append("): ");
      call.returnType.appendAsNonNull(sb, forAnnotations);
  
      setPrettyPrint(true);
      return sb;
    }
docs: Informally, a function is represented by {@code function (params): returnType} where the {@code
  params} is a comma separated list of types, the first one being a special {@code this:T} if the
  function expects a known type for {@code this}.