Repository: carbon-language/carbon-lang
File: testing/file_test/test_file.cpp (C++)

Code before:
  // Form the JSON.
  std::string buffer;
  llvm::raw_string_ostream buffer_os(buffer);
  llvm::json::OStream json(buffer_os);

  json.object([&] {
    json.attribute("jsonrpc", "2.0");
    json.attribute(method_or_id_label, method_or_id);

    if (use_call_id) {
      json.attribute("id", ++lsp_call_id);
    }
    if (parsed_extra_content != nullptr) {
      if (!extra_content_label.empty()) {
        json.attribute(extra_content_label, parsed_extra_content);
      } else {
        for (const auto& [key, value] : *parsed_extra_content.getAsObject()) {
          json.attribute(key, value);
        }
      }
    }
  });

  // Add the Content-Length header. The `2` accounts for extra newlines.
  auto json_with_header =
      llvm::formatv("Content-Length: {0}\n\n{1}\n", buffer.size() + 2, buffer)
          .str();
  int keyword_len =
      (body_start.data() + body_end + LspEnd.size()) - keyword.data();
  content->replace(keyword_pos, keyword_len, json_with_header);
  return keyword_pos + json_with_header.size();
}

// Replaces the keyword at the given position. Returns the position to start a
// find for the next keyword.
static auto ReplaceContentKeywordAt(std::string* content, size_t keyword_pos,
                                    llvm::StringRef test_name, int& lsp_call_id,
                                    llvm::ArrayRef<TestFile::Split> splits)
    -> ErrorOr<size_t> {
  auto keyword = llvm::StringRef(*content).substr(keyword_pos);

  // Line replacements aren't handled here.
  static constexpr llvm::StringLiteral Line = "[[@LINE";
  if (keyword.starts_with(Line)) {
    // Just move past the prefix to find the next one.
    return keyword_pos + Line.size();
  }

  // Replaced with the actual test name.
  static constexpr llvm::StringLiteral TestName = "[[@TEST_NAME]]";
  if (keyword.starts_with(TestName)) {

Review comment (suggestion):
```suggestion
      llvm::formatv("Content-Length: {0}\n\n{1}\n", buffer.size() + 2, buffer.TakeStr())
```

Continuing on RawStringOstream comment -- note this works because of the order of params

Code after:
  }

  // Form the JSON.
  RawStringOstream buffer;
  llvm::json::OStream json(buffer);

  json.object([&] {
    json.attribute("jsonrpc", "2.0");
    json.attribute(method_or_id_label, method_or_id);

    if (use_call_id) {
      json.attribute("id", ++lsp_call_id);
    }
    if (parsed_extra_content != nullptr) {
      if (!extra_content_label.empty()) {
        json.attribute(extra_content_label, parsed_extra_content);
      } else {
        for (const auto& [key, value] : *parsed_extra_content.getAsObject()) {
          json.attribute(key, value);
        }
      }
    }
  });

  // Add the Content-Length header. The `2` accounts for extra newlines.
  int content_length = buffer.size() + 2;
  auto json_with_header = llvm::formatv("Content-Length: {0}\n\n{1}\n",
                                        content_length, buffer.TakeStr())
                              .str();
  int keyword_len =
      (body_start.data() + body_end + LspEnd.size()) - keyword.data();
  content->replace(keyword_pos, keyword_len, json_with_header);
  return keyword_pos + json_with_header.size();
}

// Replaces the keyword at the given position. Returns the position to start a
// find for the next keyword.
static auto ReplaceContentKeywordAt(std::string* content, size_t keyword_pos,
                                    llvm::StringRef test_name, int& lsp_call_id,
                                    llvm::ArrayRef<TestFile::Split> splits)
    -> ErrorOr<size_t> {
  auto keyword = llvm::StringRef(*content).substr(keyword_pos);

  // Line replacements aren't handled here.
  static constexpr llvm::StringLiteral Line = "[[@LINE";
  if (keyword.starts_with(Line)) {
    // Just move past the prefix to find the next one.
    return keyword_pos + Line.size();
  }

  // Replaced with the actual test name.