SEXP SourceFileManager::getFunctionSrcref()

in src/debugger/SourceFileManager.cpp [95:136]


SEXP SourceFileManager::getFunctionSrcref(SEXP _func, std::function<std::string()> const& suggestName) {
  ShieldSEXP func = _func;
  PrSEXP srcref = Rf_getAttrib(func, RI->srcrefAttr);
  if (isSrcrefProcessed(srcref)) return srcref;
  if (func.type() == CLOSXP) {
    srcref = Rf_getAttrib(BODY_EXPR(func), RI->srcrefAttr);
    if (srcref.type() == VECSXP) {
      srcref = srcref[0];
    }
    if (isSrcrefProcessed(srcref)) return srcref;
  }
  if (srcref != R_NilValue) {
    PrSEXP srcfile = Rf_getAttrib(srcref, RI->srcfileAttr);
    if (TYPEOF(srcfile) == ENVSXP) {
      registerSrcfile(srcfile);
      return srcref;
    }
  }

  WithDebuggerEnabled with(false);
  std::string libraryFunctionName = getLibraryFunctionName(func);
  TextBuilder builder;
  if (!libraryFunctionName.empty()) {
    builder.addText("# ");
    builder.addText(libraryFunctionName);
    builder.addText("\n");
  }
  builder.build(func);
  ShieldSEXP lines = makeCharacterVector(splitByLines(builder.getText()));
  ShieldSEXP srcfile = RI->srcfilecopy.invokeInEnv(R_BaseEnv, "<text>", lines);
  builder.setSrcrefs(srcfile);
  Rf_setAttrib(func, RI->srcrefAttr, srcref = builder.getWholeSrcref(srcfile));
  VirtualFileInfoPtr virtualFile = registerSrcfile(srcfile);
  virtualFile->isGenerated = true;
  if (!libraryFunctionName.empty()) {
    virtualFile->generatedName = libraryFunctionName;
  } else if (suggestName) {
    virtualFile->generatedName = suggestName();
  }
  if (TYPEOF(func) == CLOSXP) SourceFileManager::preprocessSrcrefs(BODY_EXPR(func));
  return srcref;
}