public DeclaredFunctionType withTypeInfoFromSuper(DeclaredFunctionType superType) { FunctionTypeBuilder builder = new FunctionTypeBuilder(); int i = 0; for (JSType formal : requiredFormals) { builder.addReqFormal(formal != null ? formal : superType.getFormalType(i)); i++; } for (JSType formal : optionalFormals) { builder.addOptFormal(formal != null ? formal : superType.getFormalType(i)); i++; } if (restFormals != null) { builder.addRestFormals(restFormals); } else if (superType.hasRestFormals()) { builder.addRestFormals(superType.restFormals); } builder.addRetType(returnType != null ? returnType : superType.returnType); builder.addNominalType(nominalType); builder.addReceiverType(receiverType); builder.addTypeParameters(typeParameters); return builder.buildDeclaration(); }
private static DeclaredFunctionType meet(DeclaredFunctionType f1, DeclaredFunctionType f2) { if (f1.equals(f2)) { return f1; } FunctionTypeBuilder builder = new FunctionTypeBuilder(); int minRequiredArity = Math.min(f1.requiredFormals.size(), f2.requiredFormals.size()); for (int i = 0; i < minRequiredArity; i++) { builder.addReqFormal(nullAcceptingJoin(f1.getFormalType(i), f2.getFormalType(i))); } int maxTotalArity = Math.max( f1.requiredFormals.size() + f1.optionalFormals.size(), f2.requiredFormals.size() + f2.optionalFormals.size()); for (int i = minRequiredArity; i < maxTotalArity; i++) { builder.addOptFormal(nullAcceptingJoin(f1.getFormalType(i), f2.getFormalType(i))); } if (f1.restFormals != null || f2.restFormals != null) { builder.addRestFormals(nullAcceptingJoin(f1.restFormals, f2.restFormals)); } builder.addRetType(nullAcceptingMeet(f1.returnType, f2.returnType)); return builder.buildDeclaration(); }
private DeclaredFunctionType getFunTypeFromTypicalFunctionJsdoc( JSDocInfo jsdoc, String functionName, Node funNode, RawNominalType constructorType, RawNominalType ownerType, DeclaredTypeRegistry registry, FunctionTypeBuilder builder) { ImmutableList.Builder<String> typeParamsBuilder = ImmutableList.builder(); ImmutableList<String> typeParameters = ImmutableList.of(); Node parent = funNode.getParent(); // TODO(dimvar): need more @template warnings // - warn for multiple @template annotations // - warn for @template annotation w/out usage boolean ignoreJsdoc = false; if (jsdoc != null) { if (constructorType != null) { // We have created new names for these type variables in GTI, don't // create new ones here. typeParamsBuilder.addAll(constructorType.getTypeParameters()); } else { for (String typeParam : jsdoc.getTemplateTypeNames()) { typeParamsBuilder.add(this.nameGen.getNextName(typeParam)); } } // We don't properly support the type transformation language; we treat // its type variables as ordinary type variables. for (String typeParam : jsdoc.getTypeTransformations().keySet()) { typeParamsBuilder.add(this.nameGen.getNextName(typeParam)); } typeParameters = typeParamsBuilder.build(); if (!typeParameters.isEmpty()) { if (parent.isSetterDef() || parent.isGetterDef()) { ignoreJsdoc = true; jsdoc = null; warnings.add(JSError.make(funNode, TEMPLATED_GETTER_SETTER)); } else { builder.addTypeParameters(typeParameters); } } } if (ownerType != null) { typeParamsBuilder.addAll(ownerType.getTypeParameters()); typeParameters = typeParamsBuilder.build(); } fillInFormalParameterTypes(jsdoc, funNode, typeParameters, registry, builder, ignoreJsdoc); fillInReturnType(jsdoc, funNode, parent, typeParameters, registry, builder, ignoreJsdoc); if (jsdoc == null) { return builder.buildDeclaration(); } // Look at other annotations, eg, @constructor NominalType parentClass = getMaybeParentClass(jsdoc, functionName, funNode, typeParameters, registry); ImmutableSet<NominalType> implementedIntfs = getImplementedInterfaces(jsdoc, registry, typeParameters); if (constructorType == null && jsdoc.isConstructorOrInterface()) { // Anonymous type, don't register it. return builder.buildDeclaration(); } else if (jsdoc.isConstructor()) { handleConstructorAnnotation( functionName, funNode, constructorType, parentClass, implementedIntfs, registry, builder); } else if (jsdoc.isInterface()) { handleInterfaceAnnotation( jsdoc, functionName, funNode, constructorType, implementedIntfs, typeParameters, registry, builder); } else if (!implementedIntfs.isEmpty()) { warnings.add(JSError.make(funNode, IMPLEMENTS_WITHOUT_CONSTRUCTOR, functionName)); } if (jsdoc.hasThisType()) { Node thisRoot = jsdoc.getThisType().getRoot(); Preconditions.checkState(thisRoot.getType() == Token.BANG); builder.addReceiverType(getThisOrNewType(thisRoot.getFirstChild(), registry, typeParameters)); } return builder.buildDeclaration(); }