mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Add RawStringOstream for slightly simpler streaming to strings (#4817)
This adds a RawStringOstream. Versus TestRawOstream, which is
consolidated over to RawStringOstream, it uses a string for storage
instead of a vector, mainly to support move-to-string semantics. Versus
llvm::raw_string_ostream, it owns the string and supports pwrite (which
is needed for driver and its fd_ostream compatibility requirement).
This converts most uses of llvm::raw_string_ostream, leaving behind a
few in InstNamer that explicitly cannot own the string, such as:
```
llvm::raw_string_ostream(name)
<< "_" << tree.tokens().GetColumnNumber(token);
```
I have this as its own library so that it can use CHECK.
Yes this doesn't save much code, but it's code we repeatedly write.
---------
Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
co-authored by
Geoff Romer
parent
ef6e035e7d
commit
4c4c4a4d2c
+1
-22
@@ -53,6 +53,7 @@ cc_library(
|
||||
deps = [
|
||||
"//common:check",
|
||||
"//common:map",
|
||||
"//common:raw_string_ostream",
|
||||
"//common:set",
|
||||
"//toolchain/lex:token_kind",
|
||||
"@abseil-cpp//absl/random",
|
||||
@@ -90,28 +91,6 @@ cc_binary(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "test_raw_ostream",
|
||||
testonly = 1,
|
||||
hdrs = ["test_raw_ostream.h"],
|
||||
deps = [
|
||||
"//common:ostream",
|
||||
"@googletest//:gtest",
|
||||
"@llvm-project//llvm:Support",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "test_raw_ostream_test",
|
||||
size = "small",
|
||||
srcs = ["test_raw_ostream_test.cpp"],
|
||||
deps = [
|
||||
":test_raw_ostream",
|
||||
"//testing/base:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "global_exe_path",
|
||||
testonly = 1,
|
||||
|
||||
+15
-13
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "common/raw_string_ostream.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Sequence.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@@ -311,8 +312,7 @@ static auto EstimateAvgClassDefLines(SourceGen::ClassParams params) -> double {
|
||||
auto SourceGen::GenAPIFileDenseDecls(int target_lines,
|
||||
const DenseDeclParams& params)
|
||||
-> std::string {
|
||||
std::string source;
|
||||
llvm::raw_string_ostream os(source);
|
||||
RawStringOstream source;
|
||||
|
||||
// Figure out how many classes fit in our target lines, each separated by a
|
||||
// blank line. We need to account the comment lines below to start the file.
|
||||
@@ -327,27 +327,29 @@ auto SourceGen::GenAPIFileDenseDecls(int target_lines,
|
||||
int expected_lines =
|
||||
NumFileCommentLines + num_classes * (avg_class_lines + 1);
|
||||
|
||||
os << "// Generated " << (!IsCpp() ? "Carbon" : "C++") << " source file.\n";
|
||||
os << llvm::formatv("// {0} target lines: {1} classes, {2} expected lines",
|
||||
target_lines, num_classes, expected_lines)
|
||||
<< "\n";
|
||||
os << "//\n// Generating as an API file with dense declarations.\n";
|
||||
source << "// Generated " << (!IsCpp() ? "Carbon" : "C++")
|
||||
<< " source file.\n";
|
||||
source << llvm::formatv(
|
||||
"// {0} target lines: {1} classes, {2} expected lines",
|
||||
target_lines, num_classes, expected_lines)
|
||||
<< "\n";
|
||||
source << "//\n// Generating as an API file with dense declarations.\n";
|
||||
|
||||
// Carbon uses an implicitly imported prelude to get builtin types, but C++
|
||||
// requires header files so include those.
|
||||
if (IsCpp()) {
|
||||
os << "\n";
|
||||
source << "\n";
|
||||
// Header for specific integer types like `std::int64_t`.
|
||||
os << "#include <cstdint>\n";
|
||||
source << "#include <cstdint>\n";
|
||||
// Header for `std::pair`.
|
||||
os << "#include <utility>\n";
|
||||
source << "#include <utility>\n";
|
||||
}
|
||||
|
||||
auto class_gen_state = ClassGenState(*this, num_classes, params.class_params,
|
||||
params.type_use_params);
|
||||
for ([[maybe_unused]] int _ : llvm::seq(num_classes)) {
|
||||
os << "\n";
|
||||
GenerateClassDef(params.class_params, class_gen_state, os);
|
||||
source << "\n";
|
||||
GenerateClassDef(params.class_params, class_gen_state, source);
|
||||
}
|
||||
|
||||
// Make sure we consumed all the state.
|
||||
@@ -358,7 +360,7 @@ auto SourceGen::GenAPIFileDenseDecls(int target_lines,
|
||||
CARBON_CHECK(class_gen_state.class_names().empty());
|
||||
CARBON_CHECK(class_gen_state.type_names().empty());
|
||||
|
||||
return source;
|
||||
return source.TakeStr();
|
||||
}
|
||||
|
||||
auto SourceGen::GetShuffledIdentifiers(int number, int min_length,
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#ifndef CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_
|
||||
#define CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/ostream.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
|
||||
namespace Carbon::Testing {
|
||||
|
||||
// A raw_ostream that makes it easy to repeatedly check streamed output.
|
||||
class TestRawOstream : public llvm::raw_svector_ostream {
|
||||
public:
|
||||
explicit TestRawOstream() : llvm::raw_svector_ostream(buffer_) {}
|
||||
|
||||
~TestRawOstream() override {
|
||||
if (!buffer_.empty()) {
|
||||
ADD_FAILURE() << "Unchecked output:\n" << buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
// Flushes the stream and returns the contents so far, clearing the stream
|
||||
// back to empty.
|
||||
auto TakeStr() -> std::string {
|
||||
std::string result = buffer_.str().str();
|
||||
buffer_.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::SmallString<16> buffer_;
|
||||
};
|
||||
|
||||
} // namespace Carbon::Testing
|
||||
|
||||
#endif // CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_
|
||||
@@ -1,63 +0,0 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "testing/base/test_raw_ostream.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Carbon::Testing {
|
||||
namespace {
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::StrEq;
|
||||
|
||||
TEST(TestRawOstreamTest, Basics) {
|
||||
TestRawOstream os;
|
||||
|
||||
os << "test 1";
|
||||
EXPECT_THAT(os.TakeStr(), StrEq("test 1"));
|
||||
|
||||
os << "test"
|
||||
<< " "
|
||||
<< "2";
|
||||
EXPECT_THAT(os.TakeStr(), StrEq("test 2"));
|
||||
|
||||
os << "test";
|
||||
os << " ";
|
||||
os << "3";
|
||||
EXPECT_THAT(os.TakeStr(), StrEq("test 3"));
|
||||
}
|
||||
|
||||
TEST(TestRawOstreamTest, MultipleStreams) {
|
||||
TestRawOstream os1;
|
||||
TestRawOstream os2;
|
||||
|
||||
os1 << "test ";
|
||||
os2 << "test stream 2";
|
||||
os1 << "stream 1";
|
||||
EXPECT_THAT(os1.TakeStr(), StrEq("test stream 1"));
|
||||
EXPECT_THAT(os2.TakeStr(), StrEq("test stream 2"));
|
||||
}
|
||||
|
||||
TEST(TestRawOstreamTest, MultipleLines) {
|
||||
TestRawOstream os;
|
||||
|
||||
os << "test line 1\n";
|
||||
os << "test line 2\n";
|
||||
os << "test line 3\n";
|
||||
EXPECT_THAT(os.TakeStr(), StrEq("test line 1\ntest line 2\ntest line 3\n"));
|
||||
}
|
||||
|
||||
TEST(TestRawOstreamTest, Substring) {
|
||||
TestRawOstream os;
|
||||
|
||||
os << "test line 1\n";
|
||||
os << "test line 2\n";
|
||||
os << "test line 3\n";
|
||||
EXPECT_THAT(os.TakeStr(), HasSubstr("test line 2"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Carbon::Testing
|
||||
@@ -18,6 +18,7 @@ cc_library(
|
||||
deps = [
|
||||
"//common:check",
|
||||
"//common:ostream",
|
||||
"//common:raw_string_ostream",
|
||||
"@abseil-cpp//absl/strings:string_view",
|
||||
"@llvm-project//llvm:Support",
|
||||
"@re2",
|
||||
@@ -36,6 +37,7 @@ cc_library(
|
||||
"//common:exe_path",
|
||||
"//common:init_llvm",
|
||||
"//common:ostream",
|
||||
"//common:raw_string_ostream",
|
||||
"@abseil-cpp//absl/flags:flag",
|
||||
"@abseil-cpp//absl/flags:parse",
|
||||
"@googletest//:gtest",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "common/check.h"
|
||||
#include "common/ostream.h"
|
||||
#include "common/raw_string_ostream.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
@@ -363,11 +364,11 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool {
|
||||
}
|
||||
|
||||
// Generate the autoupdated file.
|
||||
std::string new_content;
|
||||
llvm::raw_string_ostream new_content_stream(new_content);
|
||||
RawStringOstream new_content_stream;
|
||||
for (const auto& line : new_lines_) {
|
||||
new_content_stream << *line << '\n';
|
||||
}
|
||||
std::string new_content = new_content_stream.TakeStr();
|
||||
|
||||
// Update the file on disk if needed.
|
||||
if (new_content == input_content_) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "common/error.h"
|
||||
#include "common/exe_path.h"
|
||||
#include "common/init_llvm.h"
|
||||
#include "common/raw_string_ostream.h"
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
@@ -108,8 +109,7 @@ enum class BazelMode : uint8_t {
|
||||
// Returns the requested bazel command string for the given execution mode.
|
||||
static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name)
|
||||
-> std::string {
|
||||
std::string args_str;
|
||||
llvm::raw_string_ostream args(args_str);
|
||||
RawStringOstream args;
|
||||
|
||||
const char* target = getenv("TEST_TARGET");
|
||||
args << "bazel " << ((mode == BazelMode::Test) ? "test" : "run") << " "
|
||||
@@ -131,7 +131,7 @@ static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name)
|
||||
|
||||
args << "--file_tests=";
|
||||
args << test_name;
|
||||
return args_str;
|
||||
return args.TakeStr();
|
||||
}
|
||||
|
||||
// Runs a test and compares output. This keeps output split by line so that
|
||||
|
||||
Reference in New Issue
Block a user