Program: 160751
Project: 160751
Buggy source:
/** 
 * This function reads lines from the nodeReader, file by file. 1. It first continuously adds lines that have the same funcid as the funcid currently on top of the funcIdStack to the CSVAST on top of the csvStack. 2. Upon finding a function declaration: [<outdated> a) It adds the line to the CSVAST on top of the csvStack, since the declaration as such is indeed part of the outer scope and belongs there. </outdated>] UPDATE: 2a) does not hold anymore! We now only add function declarations once, as root node of the CSVAST that corresponds to this function itself. b) It pushes a new CSVAST on top of  the csvStack and that function's id on top of the funcIdStack. The line is also added to this new CSVAST. [<outdated> Do note that this means that we intentionally duplicate a line by adding it to two separate CSVAST instances. This second addition is needed for technical reasons, because the line contains meta-information about the function (e.g., its name) that we will need when converting the CSVAST to an ast.functionDef.FunctionDef node using the CSV2AST class. </outdated>] UPDATE: So now, this line is not duplicated anymore. The line is *only added to new new CSVAST. 3. Upon finding a funcId different from the one on top of the funcIdStack, it looks for that funcId within the stack. In a valid CSV file, this funcId must have been previously declared by a function declaration. a) If it is not found, an exception is thrown. b) If it is found, we know that we finished scanning at least one function (since we got back to the "outer" scope). The distance from the top of the stack to the csvAST that corresponds to the current funcId is the number of functions that we finished scanning. We pop the csvStack (and the funcIdStack) that many times and put the popped CSVAST's in the csvFifoQueue.
 */
private void addNodeRowsUntilNextFile() throws InvalidCSVFile {
  while (nodeReader.hasNextRow()) {
    KeyedCSVRow currNodeRow=nodeReader.getNextRow();
    System.out.println(currNodeRow);
    String currType=currNodeRow.getFieldForKey(PHPCSVNodeTypes.TYPE);
    if (currType.equals(PHPCSVNodeTypes.TYPE_DIRECTORY))     continue;
    if (currType.equals(PHPCSVNodeTypes.TYPE_FILE)) {
      if (!csvStack.isEmpty())       break;
 else       continue;
    }
    if (currType.equals(PHPCSVNodeTypes.TYPE_CFG_ENTRY) || currType.equals(PHPCSVNodeTypes.TYPE_CFG_EXIT))     continue;
    if (currType.equals(PHPCSVNodeTypes.TYPE_TOPLEVEL) && currNodeRow.getFieldForKey(PHPCSVNodeTypes.FLAGS).contains(PHPCSVNodeTypes.FLAG_TOPLEVEL_FILE)) {
      if (!csvStack.empty())       throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str"+ "String_Node_Str");
      String topLevelFuncId=currNodeRow.getFieldForKey(PHPCSVNodeTypes.NODE_ID);
      initCSVAST(topLevelFuncId);
      addRowToTopCSVAST(currNodeRow);
      continue;
    }
    if (csvStack.empty())     throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str");
    String currFuncId=currNodeRow.getFieldForKey(PHPCSVNodeTypes.FUNCID);
    int finishedFunctions=funcIdStack.search(currFuncId) - 1;
    if (finishedFunctions < 0)     throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str"+ currFuncId+ "String_Node_Str");
    for (int i=0; i < finishedFunctions; i++) {
      csvFifoQueue.add(csvStack.pop());
      funcIdStack.pop();
    }
    addRowAndInitASTForFuncType(currNodeRow);
  }
  while (!csvStack.empty()) {
    csvFifoQueue.add(csvStack.pop());
    funcIdStack.pop();
  }
}

Fixed version (ground truth):
/** 
 * This function reads lines from the nodeReader, file by file. 1. It first continuously adds lines that have the same funcid as the funcid currently on top of the funcIdStack to the CSVAST on top of the csvStack. 2. Upon finding a function declaration: [<outdated> a) It adds the line to the CSVAST on top of the csvStack, since the declaration as such is indeed part of the outer scope and belongs there. </outdated>] UPDATE: 2a) does not hold anymore! We now only add function declarations once, as root node of the CSVAST that corresponds to this function itself. b) It pushes a new CSVAST on top of  the csvStack and that function's id on top of the funcIdStack. The line is also added to this new CSVAST. [<outdated> Do note that this means that we intentionally duplicate a line by adding it to two separate CSVAST instances. This second addition is needed for technical reasons, because the line contains meta-information about the function (e.g., its name) that we will need when converting the CSVAST to an ast.functionDef.FunctionDef node using the CSV2AST class. </outdated>] UPDATE: So now, this line is not duplicated anymore. The line is *only added to new new CSVAST. 3. Upon finding a funcId different from the one on top of the funcIdStack, it looks for that funcId within the stack. In a valid CSV file, this funcId must have been previously declared by a function declaration. a) If it is not found, an exception is thrown. b) If it is found, we know that we finished scanning at least one function (since we got back to the "outer" scope). The distance from the top of the stack to the csvAST that corresponds to the current funcId is the number of functions that we finished scanning. We pop the csvStack (and the funcIdStack) that many times and put the popped CSVAST's in the csvFifoQueue.
 */
private void addNodeRowsUntilNextFile() throws InvalidCSVFile {
  while (nodeReader.hasNextRow()) {
    KeyedCSVRow currNodeRow=nodeReader.getNextRow();
    String currType=currNodeRow.getFieldForKey(PHPCSVNodeTypes.TYPE);
    if (currType.equals(PHPCSVNodeTypes.TYPE_DIRECTORY))     continue;
    if (currType.equals(PHPCSVNodeTypes.TYPE_FILE)) {
      if (!csvStack.isEmpty())       break;
 else       continue;
    }
    if (currType.equals(PHPCSVNodeTypes.TYPE_CFG_ENTRY) || currType.equals(PHPCSVNodeTypes.TYPE_CFG_EXIT))     continue;
    if (currType.equals(PHPCSVNodeTypes.TYPE_TOPLEVEL) && currNodeRow.getFieldForKey(PHPCSVNodeTypes.FLAGS).contains(PHPCSVNodeTypes.FLAG_TOPLEVEL_FILE)) {
      if (!csvStack.empty())       throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str"+ "String_Node_Str");
      String topLevelFuncId=currNodeRow.getFieldForKey(PHPCSVNodeTypes.NODE_ID);
      initCSVAST(topLevelFuncId);
      addRowToTopCSVAST(currNodeRow);
      continue;
    }
    if (csvStack.empty())     throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str");
    String currFuncId=currNodeRow.getFieldForKey(PHPCSVNodeTypes.FUNCID);
    int finishedFunctions=funcIdStack.search(currFuncId) - 1;
    if (finishedFunctions < 0)     throw new InvalidCSVFile("String_Node_Str" + nodeReader.getCurrentLineNumber() + "String_Node_Str"+ "String_Node_Str"+ currFuncId+ "String_Node_Str");
    for (int i=0; i < finishedFunctions; i++) {
      csvFifoQueue.add(csvStack.pop());
      funcIdStack.pop();
    }
    addRowAndInitASTForFuncType(currNodeRow);
  }
  while (!csvStack.empty()) {
    csvFifoQueue.add(csvStack.pop());
    funcIdStack.pop();
  }
}