private void fillInFormalParameterTypes( JSDocInfo jsdoc, Node funNode, ImmutableList<String> typeParameters, DeclaredTypeRegistry registry, FunctionTypeBuilder builder, boolean ignoreJsdoc /* for when the jsdoc is malformed */) { boolean ignoreFunNode = !funNode.isFunction(); Node params = ignoreFunNode ? null : funNode.getSecondChild(); ParamIterator iterator = new ParamIterator(params, jsdoc); while (iterator.hasNext()) { String pname = iterator.nextString(); Node param = iterator.getNode(); ParameterKind p = ParameterKind.REQUIRED; if (param != null && convention.isOptionalParameter(param)) { p = ParameterKind.OPTIONAL; } else if (param != null && convention.isVarArgsParameter(param)) { p = ParameterKind.REST; } ParameterType inlineParamType = (ignoreJsdoc || ignoreFunNode || param.getJSDocInfo() == null) ? null : parseParameter(param.getJSDocInfo().getType(), p, registry, typeParameters); ParameterType fnParamType = inlineParamType; JSTypeExpression jsdocExp = jsdoc == null ? null : jsdoc.getParameterType(pname); if (jsdocExp != null) { if (inlineParamType == null) { fnParamType = parseParameter(jsdocExp, p, registry, typeParameters); } else { warnings.add(JSError.make(param, TWO_JSDOCS, "formal parameter " + pname)); } } JSType t = null; if (fnParamType != null) { p = fnParamType.kind; t = fnParamType.type; } switch (p) { case REQUIRED: builder.addReqFormal(t); break; case OPTIONAL: builder.addOptFormal(t); break; case REST: builder.addRestFormals(t != null ? t : JSType.UNKNOWN); break; } } }
private void fillInFunTypeBuilder( Node jsdocNode, RawNominalType ownerType, DeclaredTypeRegistry registry, ImmutableList<String> typeParameters, FunctionTypeBuilder builder) throws UnknownTypeException { Node child = jsdocNode.getFirstChild(); if (child.getType() == Token.THIS) { if (ownerType == null) { builder.addReceiverType(getThisOrNewType(child.getFirstChild(), registry, typeParameters)); } child = child.getNext(); } else if (child.getType() == Token.NEW) { Node newTypeNode = child.getFirstChild(); JSType t = getThisOrNewType(newTypeNode, registry, typeParameters); if (!t.isSubtypeOf(JSType.TOP_OBJECT) && (!t.hasTypeVariable() || t.hasScalar())) { warnings.add(JSError.make(newTypeNode, NEW_EXPECTS_OBJECT_OR_TYPEVAR, t.toString())); } builder.addNominalType(t); child = child.getNext(); } if (child.getType() == Token.PARAM_LIST) { for (Node arg = child.getFirstChild(); arg != null; arg = arg.getNext()) { try { switch (arg.getType()) { case Token.EQUALS: builder.addOptFormal( getTypeFromCommentHelper(arg.getFirstChild(), registry, typeParameters)); break; case Token.ELLIPSIS: Node restNode = arg.getFirstChild(); builder.addRestFormals( restNode == null ? JSType.UNKNOWN : getTypeFromCommentHelper(restNode, registry, typeParameters)); break; default: builder.addReqFormal(getTypeFromCommentHelper(arg, registry, typeParameters)); break; } } catch (FunctionTypeBuilder.WrongParameterOrderException e) { warnings.add(JSError.make(jsdocNode, WRONG_PARAMETER_ORDER)); builder.addPlaceholderFormal(); } } child = child.getNext(); } builder.addRetType(getTypeFromCommentHelper(child, registry, typeParameters)); }
public FunctionType toFunctionType() { FunctionTypeBuilder builder = new FunctionTypeBuilder(); for (JSType formal : requiredFormals) { builder.addReqFormal(formal == null ? JSType.UNKNOWN : formal); } for (JSType formal : optionalFormals) { builder.addOptFormal(formal == null ? JSType.UNKNOWN : formal); } builder.addRestFormals(restFormals); builder.addRetType(returnType == null ? JSType.UNKNOWN : returnType); builder.addNominalType(nominalType); builder.addReceiverType(receiverType); builder.addTypeParameters(typeParameters); return builder.buildFunction(); }
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(); }