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
|
||||
Reference in New Issue
Block a user