Program: 27886
Project: 27886
Buggy source:
/** 
 * Tries to attach currentJsdoc to n or one of its descendants. If the jsdoc starts after n, we return null. If the jsdoc is attached, we return the node on which it was attached. Last, if it was contained in n but didn't get attached, we return some node close to where the comment would get attached. The node that gets returned from this function is where the search for attaching the next comment will start from. A comment never gets attached to a node that appears before it in the code.
 * @param parapos n's parent's absolute position; we calculate it manuallyb/c it's slow to call getAbsolutePosition for every node.
 */
private NodePos attachComment(AstNode n,int parapos){
  int napos=parapos + n.getPosition();
  if (finishesAfterJsdoc(n,napos)) {
    if (capos < napos && !attachToChildren(n,napos)) {
      return setJsdoc(n,napos);
    }
  }
 else {
    return null;
  }
  int ntype=n.getType();
  NodePos res;
switch (ntype) {
case Token.BREAK:
case Token.CONTINUE:
    return new NodePos(n,napos);
case Token.CASE:
  SwitchCase cas=(SwitchCase)n;
if (!cas.isDefault()) {
  res=attachComment(cas.getExpression(),napos);
  if (res != null) {
    return res;
  }
}
if (cas.getStatements() != null) {
for (AstNode stm : cas.getStatements()) {
  res=attachComment(stm,napos);
  if (res != null) {
    return res;
  }
}
}
return new NodePos(n,napos);
case Token.DO:
DoLoop dl=(DoLoop)n;
res=attachComment(dl.getBody(),napos);
if (res != null) {
return res;
}
if (capos < dl.getWhilePosition()) {
return new NodePos(n,napos);
}
res=attachComment(dl.getCondition(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.EXPR_RESULT:
case Token.EXPR_VOID:
if (n instanceof ExpressionStatement) {
res=attachComment(((ExpressionStatement)n).getExpression(),napos);
}
 else {
res=attachComment(((LabeledStatement)n).getStatement(),napos);
}
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.FOR:
Loop loop=(Loop)n;
if (n instanceof ForInLoop) {
res=attachForInHeader((ForInLoop)loop,napos);
}
 else {
res=attachForLoopHeader((ForLoop)loop,napos);
}
if (res != null) {
return res;
}
res=attachComment(loop.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.IF:
IfStatement ifstm=(IfStatement)n;
res=attachComment(ifstm.getCondition(),napos);
if (res != null) {
return res;
}
res=attachComment(ifstm.getThenPart(),napos);
if (res != null) {
return res;
}
if (capos < ifstm.getElsePosition()) {
return new NodePos(n,napos);
}
res=attachComment(ifstm.getElsePart(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.FUNCTION:
FunctionNode fun=(FunctionNode)n;
Name nam=fun.getFunctionName();
if (nam != null) {
res=attachComment(nam,napos);
if (res != null) {
return res;
}
}
for (AstNode param : fun.getParams()) {
res=attachComment(param,napos);
if (res != null) {
return res;
}
}
res=attachComment(fun.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.RETURN:
res=attachComment(((ReturnStatement)n).getReturnValue(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.SWITCH:
SwitchStatement sw=(SwitchStatement)n;
res=attachComment(sw.getExpression(),napos);
if (res != null) {
return res;
}
for (SwitchCase c : sw.getCases()) {
res=attachComment(c,napos);
}
return new NodePos(n,napos);
case Token.THROW:
res=attachComment(((ThrowStatement)n).getExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.TRY:
TryStatement t=(TryStatement)n;
res=attachComment(t.getTryBlock(),napos);
if (res != null) {
return res;
}
for (CatchClause cc : t.getCatchClauses()) {
int catchstart=napos + cc.getPosition();
if (capos < catchstart) {
return new NodePos(n,napos);
}
res=attachComment(cc.getVarName(),catchstart);
if (res != null) {
return res;
}
res=attachComment(cc.getBody(),catchstart);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.VAR:
if (n instanceof VariableDeclaration) {
for (VariableInitializer vi : ((VariableDeclaration)n).getVariables()) {
res=attachComment(vi,napos);
if (res != null) {
return res;
}
}
}
 else {
res=attachComment(((VariableInitializer)n).getInitializer(),napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.WHILE:
WhileLoop wh=(WhileLoop)n;
res=attachComment(wh.getCondition(),napos);
if (res != null) {
return res;
}
if (capos < wh.getRp()) {
return new NodePos(n,napos);
}
res=attachComment(wh.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.WITH:
WithStatement w=(WithStatement)n;
res=attachComment(w.getExpression(),napos);
if (res != null) {
return res;
}
if (capos < w.getRp()) {
return new NodePos(n,napos);
}
res=attachComment(w.getStatement(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.ADD:
case Token.AND:
case Token.ASSIGN:
case Token.ASSIGN_ADD:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_DIV:
case Token.ASSIGN_LSH:
case Token.ASSIGN_MOD:
case Token.ASSIGN_MUL:
case Token.ASSIGN_RSH:
case Token.ASSIGN_SUB:
case Token.ASSIGN_URSH:
case Token.BITAND:
case Token.BITOR:
case Token.BITXOR:
case Token.COLON:
case Token.COMMA:
case Token.DIV:
case Token.EQ:
case Token.GE:
case Token.GET:
case Token.GETPROP:
case Token.GT:
case Token.IN:
case Token.INSTANCEOF:
case Token.LE:
case Token.LSH:
case Token.LT:
case Token.MOD:
case Token.MUL:
case Token.NE:
case Token.OR:
case Token.RSH:
case Token.SET:
case Token.SHEQ:
case Token.SHNE:
case Token.SUB:
case Token.URSH:
InfixExpression ie=(InfixExpression)n;
res=attachComment(ie.getLeft(),napos);
if (res != null) {
return res;
}
if (capos < ie.getOperatorPosition()) {
return new NodePos(n,napos);
}
res=attachComment(ie.getRight(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.ARRAYLIT:
for (AstNode elm : ((ArrayLiteral)n).getElements()) {
res=attachComment(elm,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.BITNOT:
case Token.DEC:
case Token.DELPROP:
case Token.INC:
case Token.NEG:
case Token.NOT:
case Token.POS:
case Token.TYPEOF:
case Token.VOID:
UnaryExpression ue=(UnaryExpression)n;
res=attachComment(ue.getOperand(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.CALL:
case Token.NEW:
FunctionCall call=(FunctionCall)n;
res=attachComment(call.getTarget(),napos);
if (res != null) {
return res;
}
if (capos < call.getLp()) {
return new NodePos(n,napos);
}
for (AstNode param : call.getArguments()) {
res=attachComment(param,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.GETELEM:
ElementGet elm=(ElementGet)n;
res=attachComment(elm.getTarget(),napos);
if (res != null) {
return res;
}
if (capos < elm.getLb()) {
return new NodePos(n,napos);
}
res=attachComment(elm.getElement(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.HOOK:
ConditionalExpression hook=(ConditionalExpression)n;
res=attachComment(hook.getTestExpression(),napos);
if (res != null) {
return res;
}
if (capos < hook.getQuestionMarkPosition()) {
return new NodePos(n,napos);
}
res=attachComment(hook.getTrueExpression(),napos);
if (res != null) {
return res;
}
if (capos < hook.getColonPosition()) {
return new NodePos(n,napos);
}
res=attachComment(hook.getFalseExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.LP:
res=attachComment(((ParenthesizedExpression)n).getExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.OBJECTLIT:
for (InfixExpression prop : ((ObjectLiteral)n).getElements()) {
res=attachComment(prop,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.BLOCK:
case Token.SCRIPT:
AstNode kid=(AstNode)n.getFirstChild();
while (kid != null) {
res=attachComment(kid,napos);
if (res != null) {
return res;
}
kid=(AstNode)kid.getNext();
}
return new NodePos(n,napos);
default :
throw new RuntimeException("String_Node_Str" + ntype);
}
}

Fixed version (ground truth):
/** 
 * Tries to attach currentJsdoc to n or one of its descendants. If the jsdoc starts after n, we return null. If the jsdoc is attached, we return the node on which it was attached. Last, if it was contained in n but didn't get attached, we return some node close to where the comment would get attached. The node that gets returned from this function is where the search for attaching the next comment will start from. A comment never gets attached to a node that appears before it in the code.
 * @param parapos n's parent's absolute position; we calculate it manuallyb/c it's slow to call getAbsolutePosition for every node.
 */
private NodePos attachComment(AstNode n,int parapos){
  int napos=parapos + n.getPosition();
  if (finishesAfterJsdoc(n,napos)) {
    if (capos < napos && !attachToChildren(n,napos)) {
      return setJsdoc(n,napos);
    }
  }
 else {
    return null;
  }
  int ntype=n.getType();
  NodePos res;
switch (ntype) {
case Token.BREAK:
case Token.CONTINUE:
    return new NodePos(n,napos);
case Token.CASE:
  SwitchCase cas=(SwitchCase)n;
if (!cas.isDefault()) {
  res=attachComment(cas.getExpression(),napos);
  if (res != null) {
    return res;
  }
}
if (cas.getStatements() != null) {
for (AstNode stm : cas.getStatements()) {
  res=attachComment(stm,napos);
  if (res != null) {
    return res;
  }
}
}
return new NodePos(n,napos);
case Token.DO:
DoLoop dl=(DoLoop)n;
res=attachComment(dl.getBody(),napos);
if (res != null) {
return res;
}
if (capos < dl.getWhilePosition()) {
return new NodePos(n,napos);
}
res=attachComment(dl.getCondition(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.EXPR_RESULT:
case Token.EXPR_VOID:
if (n instanceof ExpressionStatement) {
res=attachComment(((ExpressionStatement)n).getExpression(),napos);
}
 else {
res=attachComment(((LabeledStatement)n).getStatement(),napos);
}
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.FOR:
Loop loop=(Loop)n;
if (n instanceof ForInLoop) {
res=attachForInHeader((ForInLoop)loop,napos);
}
 else {
res=attachForLoopHeader((ForLoop)loop,napos);
}
if (res != null) {
return res;
}
res=attachComment(loop.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.IF:
IfStatement ifstm=(IfStatement)n;
res=attachComment(ifstm.getCondition(),napos);
if (res != null) {
return res;
}
res=attachComment(ifstm.getThenPart(),napos);
if (res != null) {
return res;
}
if (capos < ifstm.getElsePosition()) {
return new NodePos(n,napos);
}
res=attachComment(ifstm.getElsePart(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.FUNCTION:
FunctionNode fun=(FunctionNode)n;
Name nam=fun.getFunctionName();
if (nam != null) {
res=attachComment(nam,napos);
if (res != null) {
return res;
}
}
for (AstNode param : fun.getParams()) {
res=attachComment(param,napos);
if (res != null) {
return res;
}
}
res=attachComment(fun.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.RETURN:
res=attachComment(((ReturnStatement)n).getReturnValue(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.SWITCH:
SwitchStatement sw=(SwitchStatement)n;
res=attachComment(sw.getExpression(),napos);
if (res != null) {
return res;
}
for (SwitchCase c : sw.getCases()) {
res=attachComment(c,napos);
}
return new NodePos(n,napos);
case Token.THROW:
res=attachComment(((ThrowStatement)n).getExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.TRY:
TryStatement t=(TryStatement)n;
res=attachComment(t.getTryBlock(),napos);
if (res != null) {
return res;
}
for (CatchClause cc : t.getCatchClauses()) {
int catchstart=napos + cc.getPosition();
if (capos < catchstart) {
return new NodePos(n,napos);
}
res=attachComment(cc.getVarName(),catchstart);
if (res != null) {
return res;
}
res=attachComment(cc.getBody(),catchstart);
if (res != null) {
return res;
}
}
int finpos=t.getFinallyPosition();
if (finpos != -1) {
if (capos < finpos) {
return new NodePos(n,napos);
}
res=attachComment(t.getFinallyBlock(),napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.VAR:
if (n instanceof VariableDeclaration) {
for (VariableInitializer vi : ((VariableDeclaration)n).getVariables()) {
res=attachComment(vi,napos);
if (res != null) {
return res;
}
}
}
 else {
res=attachComment(((VariableInitializer)n).getInitializer(),napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.WHILE:
WhileLoop wh=(WhileLoop)n;
res=attachComment(wh.getCondition(),napos);
if (res != null) {
return res;
}
if (capos < wh.getRp()) {
return new NodePos(n,napos);
}
res=attachComment(wh.getBody(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.WITH:
WithStatement w=(WithStatement)n;
res=attachComment(w.getExpression(),napos);
if (res != null) {
return res;
}
if (capos < w.getRp()) {
return new NodePos(n,napos);
}
res=attachComment(w.getStatement(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.ADD:
case Token.AND:
case Token.ASSIGN:
case Token.ASSIGN_ADD:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_DIV:
case Token.ASSIGN_LSH:
case Token.ASSIGN_MOD:
case Token.ASSIGN_MUL:
case Token.ASSIGN_RSH:
case Token.ASSIGN_SUB:
case Token.ASSIGN_URSH:
case Token.BITAND:
case Token.BITOR:
case Token.BITXOR:
case Token.COLON:
case Token.COMMA:
case Token.DIV:
case Token.EQ:
case Token.GE:
case Token.GET:
case Token.GETPROP:
case Token.GT:
case Token.IN:
case Token.INSTANCEOF:
case Token.LE:
case Token.LSH:
case Token.LT:
case Token.MOD:
case Token.MUL:
case Token.NE:
case Token.OR:
case Token.RSH:
case Token.SET:
case Token.SHEQ:
case Token.SHNE:
case Token.SUB:
case Token.URSH:
InfixExpression ie=(InfixExpression)n;
res=attachComment(ie.getLeft(),napos);
if (res != null) {
return res;
}
if (capos < ie.getOperatorPosition()) {
return new NodePos(n,napos);
}
res=attachComment(ie.getRight(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.ARRAYLIT:
for (AstNode elm : ((ArrayLiteral)n).getElements()) {
res=attachComment(elm,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.BITNOT:
case Token.DEC:
case Token.DELPROP:
case Token.INC:
case Token.NEG:
case Token.NOT:
case Token.POS:
case Token.TYPEOF:
case Token.VOID:
UnaryExpression ue=(UnaryExpression)n;
res=attachComment(ue.getOperand(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.CALL:
case Token.NEW:
FunctionCall call=(FunctionCall)n;
res=attachComment(call.getTarget(),napos);
if (res != null) {
return res;
}
if (capos < call.getLp()) {
return new NodePos(n,napos);
}
for (AstNode param : call.getArguments()) {
res=attachComment(param,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.GETELEM:
ElementGet elm=(ElementGet)n;
res=attachComment(elm.getTarget(),napos);
if (res != null) {
return res;
}
if (capos < elm.getLb()) {
return new NodePos(n,napos);
}
res=attachComment(elm.getElement(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.HOOK:
ConditionalExpression hook=(ConditionalExpression)n;
res=attachComment(hook.getTestExpression(),napos);
if (res != null) {
return res;
}
if (capos < hook.getQuestionMarkPosition()) {
return new NodePos(n,napos);
}
res=attachComment(hook.getTrueExpression(),napos);
if (res != null) {
return res;
}
if (capos < hook.getColonPosition()) {
return new NodePos(n,napos);
}
res=attachComment(hook.getFalseExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.LP:
res=attachComment(((ParenthesizedExpression)n).getExpression(),napos);
if (res != null) {
return res;
}
return new NodePos(n,napos);
case Token.OBJECTLIT:
for (InfixExpression prop : ((ObjectLiteral)n).getElements()) {
res=attachComment(prop,napos);
if (res != null) {
return res;
}
}
return new NodePos(n,napos);
case Token.BLOCK:
case Token.SCRIPT:
AstNode kid=(AstNode)n.getFirstChild();
while (kid != null) {
res=attachComment(kid,napos);
if (res != null) {
return res;
}
kid=(AstNode)kid.getNext();
}
return new NodePos(n,napos);
default :
throw new RuntimeException("String_Node_Str" + ntype);
}
}