Program: 27782
Project: 27782
Buggy source:
/** 
 * Creates a new function type, based on the given nodes. This handles two cases that are semantically very different, but are not mutually exclusive: - A function literal that needs a type attached to it. - An assignment expression with function-type info in the JsDoc. All parameters are optional, and we will do the best we can to create a function type. This function will always create a function type, so only call it if you're sure that's what you want.
 * @param rValue The function node.
 * @param name the function's name
 * @param info the {@link JSDocInfo} attached to the function definition
 * @param lvalueNode The node where this function is beingassigned. For example,  {@code A.prototype.foo = ...} would be used todetermine that this function is a method of A.prototype. May be null to indicate that this is not being assigned to a qualified name.
 */
private FunctionType createFunctionTypeFromNodes(@Nullable Node rValue,@Nullable String name,@Nullable JSDocInfo info,@Nullable Node lvalueNode){
  FunctionType functionType=null;
  if (rValue != null && rValue.isQualifiedName() && scope.isGlobal()) {
    Var var=scope.getVar(rValue.getQualifiedName());
    if (var != null && var.getType() != null && var.getType().isFunctionType()) {
      FunctionType aliasedType=var.getType().toMaybeFunctionType();
      if ((aliasedType.isConstructor() || aliasedType.isInterface()) && !aliasedType.isNativeObjectType()) {
        functionType=aliasedType;
        if (name != null && scope.isGlobal()) {
          typeRegistry.declareType(name,functionType.getInstanceType());
        }
      }
    }
  }
  if (functionType == null) {
    Node errorRoot=rValue == null ? lvalueNode : rValue;
    boolean isFnLiteral=rValue != null && rValue.isFunction();
    Node fnRoot=isFnLiteral ? rValue : null;
    Node parametersNode=isFnLiteral ? rValue.getFirstChild().getNext() : null;
    if (info != null && info.hasType()) {
      JSType type=info.getType().evaluate(scope,typeRegistry);
      type=type.restrictByNotNullOrUndefined();
      if (type.isFunctionType()) {
        functionType=type.toMaybeFunctionType();
        functionType.setJSDocInfo(info);
      }
    }
    if (functionType == null) {
      Node ownerNode=NodeUtil.getBestLValueOwner(lvalueNode);
      String ownerName=NodeUtil.getBestLValueName(ownerNode);
      Var ownerVar=null;
      String propName=null;
      ObjectType ownerType=null;
      if (ownerName != null) {
        ownerVar=scope.getVar(ownerName);
        if (ownerVar != null) {
          ownerType=ObjectType.cast(ownerVar.getType());
        }
        if (name != null) {
          propName=name.substring(ownerName.length() + 1);
        }
      }
      ObjectType prototypeOwner=getPrototypeOwnerType(ownerType);
      TemplateTypeMap prototypeOwnerTypeMap=null;
      if (prototypeOwner != null && prototypeOwner.getTypeOfThis() != null) {
        prototypeOwnerTypeMap=prototypeOwner.getTypeOfThis().getTemplateTypeMap();
      }
      FunctionType overriddenType=null;
      if (ownerType != null && propName != null) {
        overriddenType=findOverriddenFunction(ownerType,propName,prototypeOwnerTypeMap);
      }
      FunctionTypeBuilder builder=new FunctionTypeBuilder(name,compiler,errorRoot,sourceName,scope).setContents(getFunctionAnalysisResults(fnRoot)).inferFromOverriddenFunction(overriddenType,parametersNode).inferTemplateTypeName(info,prototypeOwner).inferInheritance(info);
      if (info == null || !info.hasReturnType()) {
        if (rValue != null && rValue.isFunction() && rValue.getFirstChild() != null) {
          JSDocInfo nameDocInfo=rValue.getFirstChild().getJSDocInfo();
          builder.inferReturnType(nameDocInfo,true);
        }
      }
 else {
        builder.inferReturnType(info,false);
      }
      boolean searchedForThisType=false;
      if (ownerType != null && ownerType.isFunctionPrototypeType() && ownerType.getOwnerFunction().hasInstanceType()) {
        builder.inferThisType(info,ownerType.getOwnerFunction().getInstanceType());
        searchedForThisType=true;
      }
 else       if (ownerNode != null && ownerNode.isThis()) {
        JSType injectedThisType=ownerNode.getJSType();
        builder.inferThisType(info,injectedThisType == null ? scope.getTypeOfThis() : injectedThisType);
        searchedForThisType=true;
      }
      if (!searchedForThisType) {
        builder.inferThisType(info);
      }
      functionType=builder.inferParameterTypes(parametersNode,info).buildAndRegister();
    }
  }
  return functionType;
}

Fixed version (ground truth):
/** 
 * Creates a new function type, based on the given nodes. This handles two cases that are semantically very different, but are not mutually exclusive: - A function literal that needs a type attached to it. - An assignment expression with function-type info in the JsDoc. All parameters are optional, and we will do the best we can to create a function type. This function will always create a function type, so only call it if you're sure that's what you want.
 * @param rValue The function node.
 * @param name the function's name
 * @param info the {@link JSDocInfo} attached to the function definition
 * @param lvalueNode The node where this function is beingassigned. For example,  {@code A.prototype.foo = ...} would be used todetermine that this function is a method of A.prototype. May be null to indicate that this is not being assigned to a qualified name.
 */
private FunctionType createFunctionTypeFromNodes(@Nullable Node rValue,@Nullable String name,@Nullable JSDocInfo info,@Nullable Node lvalueNode){
  FunctionType functionType=null;
  if (rValue != null && rValue.isQualifiedName() && scope.isGlobal()) {
    Var var=scope.getVar(rValue.getQualifiedName());
    if (var != null && var.getType() != null && var.getType().isFunctionType()) {
      FunctionType aliasedType=var.getType().toMaybeFunctionType();
      if ((aliasedType.isConstructor() || aliasedType.isInterface()) && !aliasedType.isNativeObjectType()) {
        functionType=aliasedType;
        if (name != null && scope.isGlobal()) {
          typeRegistry.declareType(name,functionType.getInstanceType());
        }
      }
    }
  }
  if (functionType == null) {
    Node errorRoot=rValue == null ? lvalueNode : rValue;
    boolean isFnLiteral=rValue != null && rValue.isFunction();
    Node fnRoot=isFnLiteral ? rValue : null;
    Node parametersNode=isFnLiteral ? rValue.getFirstChild().getNext() : null;
    if (info != null && info.hasType()) {
      JSType type=info.getType().evaluate(scope,typeRegistry);
      type=type.restrictByNotNullOrUndefined();
      if (type.isFunctionType()) {
        functionType=type.toMaybeFunctionType();
        functionType.setJSDocInfo(info);
      }
    }
    if (functionType == null) {
      Node ownerNode=NodeUtil.getBestLValueOwner(lvalueNode);
      String ownerName=NodeUtil.getBestLValueName(ownerNode);
      Var ownerVar=null;
      String propName=null;
      ObjectType ownerType=null;
      if (ownerName != null) {
        ownerVar=scope.getVar(ownerName);
        if (ownerVar != null) {
          ownerType=ObjectType.cast(ownerVar.getType());
        }
        if (name != null) {
          propName=name.substring(ownerName.length() + 1);
        }
      }
      ObjectType prototypeOwner=getPrototypeOwnerType(ownerType);
      TemplateTypeMap prototypeOwnerTypeMap=null;
      if (prototypeOwner != null && prototypeOwner.getTypeOfThis() != null) {
        prototypeOwnerTypeMap=prototypeOwner.getTypeOfThis().getTemplateTypeMap();
      }
      FunctionType overriddenType=null;
      if (ownerType != null && propName != null) {
        overriddenType=findOverriddenFunction(ownerType,propName,prototypeOwnerTypeMap);
      }
      FunctionTypeBuilder builder=new FunctionTypeBuilder(name,compiler,errorRoot,sourceName,scope).setContents(getFunctionAnalysisResults(fnRoot)).inferFromOverriddenFunction(overriddenType,parametersNode).inferTemplateTypeName(info,prototypeOwner).inferInheritance(info);
      if (info == null || !info.hasReturnType()) {
        if (rValue != null && rValue.isFunction() && rValue.getFirstChild() != null) {
          JSDocInfo nameDocInfo=rValue.getFirstChild().getJSDocInfo();
          builder.inferReturnType(nameDocInfo,true);
        }
      }
 else {
        builder.inferReturnType(info,false);
      }
      boolean searchedForThisType=false;
      if (ownerType != null && ownerType.isFunctionPrototypeType() && ownerType.getOwnerFunction().hasInstanceType()) {
        builder.inferThisType(info,ownerType.getOwnerFunction().getInstanceType());
        searchedForThisType=true;
      }
 else       if (ownerNode != null && ownerNode.isThis()) {
        JSType injectedThisType=ownerNode.getJSType();
        builder.inferThisType(info,scope.getTypeOfThis());
        searchedForThisType=true;
      }
      if (!searchedForThisType) {
        builder.inferThisType(info);
      }
      functionType=builder.inferParameterTypes(parametersNode,info).buildAndRegister();
    }
  }
  return functionType;
}