private JSType getNominalTypeHelper( RawNominalType rawType, Node n, DeclaredTypeRegistry registry, ImmutableList<String> outerTypeParameters) throws UnknownTypeException { NominalType uninstantiated = rawType.getAsNominalType(); if (!rawType.isGeneric() && !n.hasChildren()) { return rawType.getInstanceWithNullability(NULLABLE_TYPES_BY_DEFAULT); } ImmutableList.Builder<JSType> typeList = ImmutableList.builder(); if (n.hasChildren()) { // Compute instantiation of polymorphic class/interface. Preconditions.checkState(n.getFirstChild().isBlock(), n); for (Node child : n.getFirstChild().children()) { typeList.add(getTypeFromCommentHelper(child, registry, outerTypeParameters)); } } ImmutableList<JSType> typeArguments = typeList.build(); ImmutableList<String> typeParameters = rawType.getTypeParameters(); int typeArgsSize = typeArguments.size(); int typeParamsSize = typeParameters.size(); if (typeArgsSize != typeParamsSize) { // We used to also warn when (typeArgsSize < typeParamsSize), but it // happens so often that we stopped. Array, Object and goog.Promise are // common culprits, but many other types as well. if (typeArgsSize > typeParamsSize) { warnings.add( JSError.make( n, INVALID_GENERICS_INSTANTIATION, uninstantiated.getName(), String.valueOf(typeParamsSize), String.valueOf(typeArgsSize))); } return maybeMakeNullable( JSType.fromObjectType( ObjectType.fromNominalType( uninstantiated.instantiateGenerics( fixLengthOfTypeList(typeParameters.size(), typeArguments))))); } return maybeMakeNullable( JSType.fromObjectType( ObjectType.fromNominalType(uninstantiated.instantiateGenerics(typeArguments)))); }
StringBuilder appendTo(StringBuilder builder) { if (!hasNonPrototypeProperties()) { if (fn != null) { return fn.appendTo(builder); } else if (getNominalType() != null) { return getNominalType().appendTo(builder); } } if (nominalType != null && !nominalType.getName().equals("Function")) { nominalType.appendTo(builder); } else if (isStruct()) { builder.append("struct"); } else if (isDict()) { builder.append("dict"); } if (fn != null) { builder.append("<|"); fn.appendTo(builder); builder.append("|>"); } if (nominalType == null || !props.isEmpty()) { builder.append('{'); boolean firstIteration = true; for (String pname : new TreeSet<>(props.keySet())) { if (firstIteration) { firstIteration = false; } else { builder.append(", "); } builder.append(pname); builder.append(':'); props.get(pname).appendTo(builder); } builder.append('}'); } if (isLoose) { builder.append(" (loose)"); } return builder; }