diff --git a/explorer/file_test.cpp b/explorer/file_test.cpp index 9107de492748..10f2c696c2cf 100644 --- a/explorer/file_test.cpp +++ b/explorer/file_test.cpp @@ -75,15 +75,12 @@ class ExplorerFileTest : public FileTestBase { return args; } - auto GetLineNumberReplacement(llvm::ArrayRef filenames) - -> LineNumberReplacement override { + auto GetLineNumberReplacements(llvm::ArrayRef filenames) + -> llvm::SmallVector override { if (check_trace_output()) { - return {.has_file = false, - .pattern = R"((DO NOT MATCH))", - // The `{{{{` becomes `{{`. - .line_formatv = "{{{{ *}}{0}"}; + return {}; } - return FileTestBase::GetLineNumberReplacement(filenames); + return FileTestBase::GetLineNumberReplacements(filenames); } auto DoExtraCheckReplacements(std::string& check_line) -> void override { diff --git a/testing/file_test/autoupdate.cpp b/testing/file_test/autoupdate.cpp index b945e42feea6..b7a87f369c8d 100644 --- a/testing/file_test/autoupdate.cpp +++ b/testing/file_test/autoupdate.cpp @@ -13,7 +13,6 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/FormatVariadic.h" -#include "re2/re2.h" namespace Carbon::Testing { @@ -26,20 +25,34 @@ static auto ParseLineNumber(absl::string_view matched_line_number) -> int { trimmed = trimmed.trim(); // NOLINTNEXTLINE(google-runtime-int): API requirement. long long val; - CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val)); + CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val)) + << matched_line_number; return val; } +// The file and line number that a CHECK line refers to, and the +// replacement from which they were determined, if any. +struct FileAndLineNumber { + explicit FileAndLineNumber(int file_number) : file_number(file_number) {} + + explicit FileAndLineNumber(const FileTestLineNumberReplacement* replacement, + int file_number, absl::string_view line_number) + : replacement(replacement), + file_number(file_number), + line_number(ParseLineNumber(line_number)) {} + + const FileTestLineNumberReplacement* replacement = nullptr; + int file_number; + int line_number = -1; +}; + class CheckLine : public FileTestLineBase { public: // RE2 is passed by a pointer because it doesn't support std::optional. - explicit CheckLine(int file_number, int line_number, - bool line_number_re_has_file, const RE2* line_number_re, - std::string line) - : FileTestLineBase(line_number), - file_number_(file_number), - line_number_re_has_file_(line_number_re_has_file), - line_number_re_(line_number_re), + explicit CheckLine(FileAndLineNumber file_and_line_number, std::string line) + : FileTestLineBase(file_and_line_number.line_number), + file_number_(file_and_line_number.file_number), + replacement_(file_and_line_number.replacement), line_(std::move(line)) {} auto Print(llvm::raw_ostream& out) const -> void override { @@ -57,32 +70,31 @@ class CheckLine : public FileTestLineBase { // When the location of all lines in a file are known, we can set the line // offset based on the target line. - auto RemapLineNumbers(const std::string& line_formatv, - llvm::function_ref line_remap) -> void { - // Only need to do remappings when there's a regex. - if (!line_number_re_) { - return; - } - - // If the CHECK was written to a different file from the file that it refers - // to, leave behind an absolute line reference rather than a cross-file - // offset. - // TODO: We should also remap cross-file line references so that we don't - // need multiple runs of autoupdate for the output to stabilize. - if (output_file_number_ != file_number_) { + auto RemapLineNumbers( + const llvm::DenseMap, int>& output_line_remap, + const llvm::SmallVector& new_last_line_numbers) -> void { + // Only need to do remappings when there's a line number replacement. + if (!replacement_) { return; } bool found_one = false; + // Use a cursor for the line so that we can't keep matching the same + // content, which may occur when we keep a literal line number. + int line_offset = 0; while (true) { + // Rebuild the cursor each time because we're editing the line, which + // could cause a reallocation. + absl::string_view line_cursor = line_; + line_cursor.remove_prefix(line_offset); // Look for a line number to replace. There may be multiple, so we // repeatedly check. absl::string_view matched_line_number; - if (line_number_re_has_file_) { - RE2::PartialMatch(line_, *line_number_re_, nullptr, + if (replacement_->has_file) { + RE2::PartialMatch(line_cursor, *replacement_->re, nullptr, &matched_line_number); } else { - RE2::PartialMatch(line_, *line_number_re_, &matched_line_number); + RE2::PartialMatch(line_cursor, *replacement_->re, &matched_line_number); } if (matched_line_number.empty()) { CARBON_CHECK(found_one) << line_; @@ -90,29 +102,50 @@ class CheckLine : public FileTestLineBase { } found_one = true; - // Calculate the offset from the CHECK line to the new line number - // (possibly with new CHECK lines added, or some removed). - int new_line_number = line_remap(ParseLineNumber(matched_line_number)); - int offset = new_line_number - output_line_number_; + // Update the cursor offset from the match. + line_offset = matched_line_number.begin() - line_.c_str(); - // Update the line offset in the CHECK line. - const char* offset_prefix = offset < 0 ? "" : "+"; - std::string replacement = llvm::formatv( - line_formatv.c_str(), - llvm::formatv("[[@LINE{0}{1}]]", offset_prefix, offset)); + // Calculate the new line number (possibly with new CHECK lines added, or + // some removed). + int old_line_number = ParseLineNumber(matched_line_number); + int new_line_number = -1; + if (auto remapped = + output_line_remap.find({file_number_, old_line_number}); + remapped != output_line_remap.end()) { + // Map old non-check lines to their new line numbers. + new_line_number = remapped->second; + } else { + // We assume unmapped references point to the end-of-file. + new_line_number = new_last_line_numbers[file_number_]; + } + + std::string replacement; + if (output_file_number_ == file_number_) { + int offset = new_line_number - output_line_number_; + // Update the line offset in the CHECK line. + const char* offset_prefix = offset < 0 ? "" : "+"; + replacement = llvm::formatv( + replacement_->line_formatv.c_str(), + llvm::formatv("[[@LINE{0}{1}]]", offset_prefix, offset)); + } else { + // If the CHECK was written to a different file from the file that it + // refers to, leave behind an absolute line reference rather than a + // cross-file offset. + replacement = + llvm::formatv(replacement_->line_formatv.c_str(), new_line_number); + } line_.replace(matched_line_number.data() - line_.data(), matched_line_number.size(), replacement); } } - int file_number() const { return file_number_; } + auto file_number() const -> int { return file_number_; } auto is_blank() const -> bool override { return false; } private: int file_number_; - bool line_number_re_has_file_; - const RE2* line_number_re_; + const FileTestLineNumberReplacement* replacement_; std::string line_; llvm::StringRef indent_; int output_file_number_ = -1; @@ -121,11 +154,45 @@ class CheckLine : public FileTestLineBase { } // namespace +// Looks for the patterns in the line. Returns the first match, or defaulted +// information if not found. +static auto GetFileAndLineNumber( + const llvm::SmallVector& replacements, + llvm::DenseMap file_to_number_map, + int default_file_number, const std::string& check_line) + -> FileAndLineNumber { + for (const auto& replacement : replacements) { + if (replacement.has_file) { + absl::string_view filename; + absl::string_view line_number; + if (RE2::PartialMatch(check_line, *replacement.re, &filename, + &line_number)) { + if (auto it = file_to_number_map.find(filename); + it != file_to_number_map.end()) { + return FileAndLineNumber(&replacement, it->second, line_number); + } else { + return FileAndLineNumber(default_file_number); + } + } + } else { + // There's no file association, so we only look at the line, and assume + // it refers to the default file. + absl::string_view line_number; + if (RE2::PartialMatch(check_line, *replacement.re, &line_number)) { + return FileAndLineNumber(&replacement, default_file_number, + line_number); + } + } + } + return FileAndLineNumber(default_file_number); +} + // Builds CheckLine lists for autoupdate. static auto BuildCheckLines( llvm::StringRef output, const char* label, const llvm::SmallVector& filenames, - bool line_number_re_has_file, const RE2& line_number_re, + const std::optional& default_file_re, + const llvm::SmallVector& replacements, std::function do_extra_check_replacements) -> llvm::SmallVector { llvm::SmallVector check_lines; @@ -157,6 +224,9 @@ static auto BuildCheckLines( // End-of-line whitespace is replaced with a regex matcher to make it visible. RE2 end_of_line_whitespace_re(R"((\s+)$)"); + // The default file number for when no specific file is found. + int default_file_number = 0; + for (const auto& line : lines) { std::string check_line = llvm::formatv("// CHECK:{0}:{1}{2}", label, line.empty() ? "" : " ", line); @@ -171,32 +241,19 @@ static auto BuildCheckLines( do_extra_check_replacements(check_line); - // Look for line information in the output. use_line_number is only set if - // the match is correct. - std::optional use_line_number; - absl::string_view match_line_number; - int file_number = 0; - if (line_number_re_has_file) { - absl::string_view match_filename; - if (RE2::PartialMatch(check_line, line_number_re, &match_filename, - &match_line_number)) { - if (auto it = file_to_number_map.find(match_filename); - it != file_to_number_map.end()) { - file_number = it->second; - use_line_number = match_line_number; - } - } - } else { - // There's no file association, so we only look at the line, and assume it - // refers to the main file. - if (RE2::PartialMatch(check_line, line_number_re, &match_line_number)) { - use_line_number = match_line_number; + if (default_file_re) { + absl::string_view filename; + if (RE2::PartialMatch(line, *default_file_re, &filename)) { + auto it = file_to_number_map.find(filename); + CARBON_CHECK(it != file_to_number_map.end()) + << "default_file_re had unexpected match in '" << line << "' (`" + << default_file_re->pattern() << "`)"; + default_file_number = it->second; } } - int line_number = use_line_number ? ParseLineNumber(*use_line_number) : -1; - check_lines.push_back( - CheckLine(file_number, line_number, line_number_re_has_file, - use_line_number ? &line_number_re : nullptr, check_line)); + auto file_and_line = GetFileAndLineNumber(replacements, file_to_number_map, + default_file_number, check_line); + check_lines.push_back(CheckLine(file_and_line, check_line)); } return check_lines; @@ -206,21 +263,27 @@ auto AutoupdateFileTest( const std::filesystem::path& file_test_path, llvm::StringRef input_content, const llvm::SmallVector& filenames, int autoupdate_line_number, - llvm::SmallVector>& non_check_lines, + const llvm::SmallVector>& non_check_lines, llvm::StringRef stdout, llvm::StringRef stderr, - FileTestLineNumberReplacement line_number_replacement, + const std::optional& default_file_re, + const llvm::SmallVector& + line_number_replacements, std::function do_extra_check_replacements) -> bool { - RE2 line_number_re(line_number_replacement.pattern); - CARBON_CHECK(line_number_re.ok()) << "Invalid line replacement RE2: `" - << line_number_replacement.pattern << "`"; + for (const auto& replacement : line_number_replacements) { + CARBON_CHECK(replacement.has_file || default_file_re) + << "For replacement with pattern `" << replacement.re->pattern() + << "` to have has_file=false, override GetDefaultFileRE."; + CARBON_CHECK(replacement.re->ok()) + << "Invalid line replacement RE2: " << replacement.re->error(); + } // Prepare CHECK lines. - llvm::SmallVector stdout_check_lines = BuildCheckLines( - stdout, "STDOUT", filenames, line_number_replacement.has_file, - line_number_re, do_extra_check_replacements); - llvm::SmallVector stderr_check_lines = BuildCheckLines( - stderr, "STDERR", filenames, line_number_replacement.has_file, - line_number_re, do_extra_check_replacements); + llvm::SmallVector stdout_check_lines = + BuildCheckLines(stdout, "STDOUT", filenames, default_file_re, + line_number_replacements, do_extra_check_replacements); + llvm::SmallVector stderr_check_lines = + BuildCheckLines(stderr, "STDERR", filenames, default_file_re, + line_number_replacements, do_extra_check_replacements); auto* stdout_check_line = stdout_check_lines.begin(); auto* stderr_check_line = stderr_check_lines.begin(); @@ -233,15 +296,23 @@ auto AutoupdateFileTest( const FileTestLine blank_line(-1, ""); + // Maps {file_number, original line number} to a new line number. + llvm::DenseMap, int> output_line_remap; + + // Tracks the new last line numbers for each file. + llvm::SmallVector new_last_line_numbers; + new_last_line_numbers.reserve(filenames.size()); + // Stitch together content. llvm::SmallVector new_lines; for (auto [file_number_as_size_t, filename, non_check_file] : llvm::enumerate(filenames, non_check_lines)) { auto file_number = static_cast(file_number_as_size_t); - llvm::DenseMap output_line_remap; - llvm::SmallVector check_lines_this_file; int output_line_number = 0; + // Track the offset in new_lines to later determine the line count. + int file_offset_in_new_lines = new_lines.size(); + // Add all check lines from the given vector until we reach a check line // attached to a line later than `to_line_number`. auto add_check_lines = [&](const llvm::SmallVector& lines, @@ -253,7 +324,6 @@ auto AutoupdateFileTest( ++line) { new_lines.push_back(line); line->SetOutputLine(indent, file_number, ++output_line_number); - check_lines_this_file.push_back(line); } }; @@ -264,6 +334,10 @@ auto AutoupdateFileTest( // something like a split directive which shouldn't increment // output_line_number. if (non_check_line.line_number() < 1) { + // These are ignored when calculating line counts. + CARBON_CHECK(file_offset_in_new_lines == + static_cast(new_lines.size())); + ++file_offset_in_new_lines; new_lines.push_back(&non_check_line); continue; } @@ -281,10 +355,10 @@ auto AutoupdateFileTest( } new_lines.push_back(&non_check_line); - CARBON_CHECK( - output_line_remap - .insert({non_check_line.line_number(), ++output_line_number}) - .second); + CARBON_CHECK(output_line_remap + .insert({{file_number, non_check_line.line_number()}, + ++output_line_number}) + .second); // If we just added the AUTOUPDATE line, include any early STDERR lines // now, so that the initial batch of CHECK lines have STDERR before @@ -306,11 +380,12 @@ auto AutoupdateFileTest( // This should always be true after the first file is processed. CARBON_CHECK(reached_autoupdate); - // At the end of the last file, print remaining check lines which -- for - // whatever reason -- come after all original lines. - if (file_number == static_cast(filenames.size()) - 1 && - (stderr_check_line != stderr_check_lines.end() || - stdout_check_line != stdout_check_lines.end())) { + // At the end of each file, print any remaining lines which are associated + // with the file. + if ((stderr_check_line != stderr_check_lines.end() && + stderr_check_line->file_number() == file_number) || + (stdout_check_line != stdout_check_lines.end() && + stdout_check_line->file_number() == file_number)) { // Ensure there's a blank line before any trailing CHECKs. if (!new_lines.empty() && !new_lines.back()->is_blank()) { new_lines.push_back(&blank_line); @@ -321,30 +396,15 @@ auto AutoupdateFileTest( add_check_lines(stdout_check_lines, stdout_check_line, INT_MAX, ""); } - // Update all remapped lines in CHECK output. - for (auto* offset_check_line : check_lines_this_file) { - int last_non_check_line = non_check_file.back().line_number(); - offset_check_line->RemapLineNumbers( - line_number_replacement.line_formatv, [&](int old_line_number) { - // Map old non-check lines to their new line numbers. - auto remapped = output_line_remap.find(old_line_number); - if (remapped != output_line_remap.end()) { - return remapped->second; - } + new_last_line_numbers.push_back(new_lines.size() - + file_offset_in_new_lines); + } - // Map any reference to a line past the final non-check line to - // the new end-of-file. We assume that any such reference is - // referring to the end of file, not to some specific CHECK - // comment. - if (old_line_number > last_non_check_line) { - return output_line_number; - } - - // Line didn't get remapped; maybe it refers to a CHECK line. - // We can't express that as an offset, just leave it as-is. - return old_line_number; - }); - } + for (auto& check_line : stdout_check_lines) { + check_line.RemapLineNumbers(output_line_remap, new_last_line_numbers); + } + for (auto& check_line : stderr_check_lines) { + check_line.RemapLineNumbers(output_line_remap, new_last_line_numbers); } // Generate the autoupdated file. diff --git a/testing/file_test/autoupdate.h b/testing/file_test/autoupdate.h index c0c81165795a..cdc4956cfc6d 100644 --- a/testing/file_test/autoupdate.h +++ b/testing/file_test/autoupdate.h @@ -9,6 +9,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "re2/re2.h" #include "testing/file_test/line.h" namespace Carbon::Testing { @@ -17,8 +18,11 @@ struct FileTestLineNumberReplacement { bool has_file; // The line replacement. The pattern should match lines. If has_file, pattern - // should have a file and line group; otherwise, only a line group. - std::string pattern; + // should have a file and line group; otherwise, only a line group, but + // default_file_re should be provided. + // + // Uses shared_ptr for storage in SmallVector. + std::shared_ptr re; // line_formatv should provide {0} to substitute with [[@LINE...]] deltas. std::string line_formatv; @@ -29,9 +33,11 @@ auto AutoupdateFileTest( const std::filesystem::path& file_test_path, llvm::StringRef input_content, const llvm::SmallVector& filenames, int autoupdate_line_number, - llvm::SmallVector>& non_check_lines, + const llvm::SmallVector>& non_check_lines, llvm::StringRef stdout, llvm::StringRef stderr, - FileTestLineNumberReplacement line_number_replacement, + const std::optional& default_file_re, + const llvm::SmallVector& + line_number_replacements, std::function do_extra_check_replacements) -> bool; } // namespace Carbon::Testing diff --git a/testing/file_test/autoupdate_testdata.sh b/testing/file_test/autoupdate_testdata.sh new file mode 100755 index 000000000000..cbf3312de1ff --- /dev/null +++ b/testing/file_test/autoupdate_testdata.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# 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 + +bazel run -c opt //testing/file_test:file_test_base_test -- --autoupdate "$@" diff --git a/testing/file_test/file_test_base.cpp b/testing/file_test/file_test_base.cpp index 087042864f9e..c7ca372771fd 100644 --- a/testing/file_test/file_test_base.cpp +++ b/testing/file_test/file_test_base.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -109,25 +110,26 @@ auto FileTestBase::Autoupdate() -> ErrorOr { filenames.push_back(file.filename); } - llvm::ArrayRef filenames_for_line_number = filenames; + llvm::ArrayRef expected_filenames = filenames; if (filenames.size() > 1) { - filenames_for_line_number = filenames_for_line_number.drop_front(); + expected_filenames = expected_filenames.drop_front(); } return AutoupdateFileTest( std::filesystem::absolute(test_name_.str()), context.input_content, filenames, *context.autoupdate_line_number, context.non_check_lines, - context.stdout, context.stderr, - GetLineNumberReplacement(filenames_for_line_number), + context.stdout, context.stderr, GetDefaultFileRE(expected_filenames), + GetLineNumberReplacements(expected_filenames), [&](std::string& line) { DoExtraCheckReplacements(line); }); } -auto FileTestBase::GetLineNumberReplacement( - llvm::ArrayRef filenames) -> LineNumberReplacement { - return { - .has_file = true, - .pattern = llvm::formatv(R"(({0}):(\d+))", llvm::join(filenames, "|")), - .line_formatv = R"({0})"}; +auto FileTestBase::GetLineNumberReplacements( + llvm::ArrayRef filenames) + -> llvm::SmallVector { + return {{.has_file = true, + .re = std::make_shared( + llvm::formatv(R"(({0}):(\d+))", llvm::join(filenames, "|"))), + .line_formatv = R"({0})"}}; } auto FileTestBase::ProcessTestFileAndRun(TestContext& context) @@ -501,4 +503,6 @@ static auto Main(int argc, char** argv) -> int { } // namespace Carbon::Testing -auto main(int argc, char** argv) -> int { Carbon::Testing::Main(argc, argv); } +auto main(int argc, char** argv) -> int { + return Carbon::Testing::Main(argc, argv); +} diff --git a/testing/file_test/file_test_base.h b/testing/file_test/file_test_base.h index a4c3f39d4381..9d008dfc7b34 100644 --- a/testing/file_test/file_test_base.h +++ b/testing/file_test/file_test_base.h @@ -66,10 +66,19 @@ class FileTestBase : public testing::Test { // Returns default arguments. Only called when a file doesn't set ARGS. virtual auto GetDefaultArgs() -> llvm::SmallVector = 0; + // Returns a regex to match the default file when a line may not be present. + // May return nullptr if unused. If GetLineNumberReplacements returns an entry + // with has_file=false, this is required. + virtual auto GetDefaultFileRE(llvm::ArrayRef /*filenames*/) + -> std::optional { + return std::nullopt; + } + // Returns replacement information for line numbers. See LineReplacement for // construction. - virtual auto GetLineNumberReplacement( - llvm::ArrayRef filenames) -> LineNumberReplacement; + virtual auto GetLineNumberReplacements( + llvm::ArrayRef filenames) + -> llvm::SmallVector; // Optionally allows children to provide extra replacements for autoupdate. virtual auto DoExtraCheckReplacements(std::string& /*check_line*/) -> void {} diff --git a/testing/file_test/file_test_base_test.cpp b/testing/file_test/file_test_base_test.cpp index 7231bc3506f9..8a8270dcf86f 100644 --- a/testing/file_test/file_test_base_test.cpp +++ b/testing/file_test/file_test_base_test.cpp @@ -9,12 +9,11 @@ #include "common/ostream.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/FormatVariadic.h" namespace Carbon::Testing { namespace { -using ::testing::Eq; - class FileTestBaseTest : public FileTestBase { public: using FileTestBase::FileTestBase; @@ -96,6 +95,27 @@ class FileTestBaseTest : public FileTestBase { stderr << "unattached message 3\n" << "unattached message 4\n"; return true; + } else if (filename == "file_only_re_one_file.carbon") { + stdout << "unattached message 1\n" + << "file: file_only_re_one_file.carbon\n" + << "line: 1\n" + << "unattached message 2\n"; + return true; + } else if (filename == "file_only_re_multi_file.carbon") { + int msg_count = 0; + stdout << "unattached message " << ++msg_count << "\n" + << "file: a.carbon\n" + << "unattached message " << ++msg_count << "\n" + << "line: 1: attached message " << ++msg_count << "\n" + << "unattached message " << ++msg_count << "\n" + << "line: 8: late message " << ++msg_count << "\n" + << "unattached message " << ++msg_count << "\n" + << "file: b.carbon\n" + << "line: 1: attached message " << ++msg_count << "\n" + << "unattached message " << ++msg_count << "\n" + << "line: 7: late message " << ++msg_count << "\n" + << "unattached message " << ++msg_count << "\n"; + return true; } else { return ErrorBuilder() << "Unexpected file: " << filename; } @@ -104,6 +124,24 @@ class FileTestBaseTest : public FileTestBase { auto GetDefaultArgs() -> llvm::SmallVector override { return {"default_args", "%s"}; } + + auto GetDefaultFileRE(llvm::ArrayRef filenames) + -> std::optional override { + return std::make_optional( + llvm::formatv(R"(file: ({0}))", llvm::join(filenames, "|"))); + } + + auto GetLineNumberReplacements(llvm::ArrayRef filenames) + -> llvm::SmallVector override { + auto replacements = FileTestBase::GetLineNumberReplacements(filenames); + auto filename = std::filesystem::path(test_name().str()).filename(); + if (llvm::StringRef(filename).startswith("file_only_re_")) { + replacements.push_back({.has_file = false, + .re = std::make_shared(R"(line: (\d+))"), + .line_formatv = "{0}"}); + } + return replacements; + } }; } // namespace diff --git a/testing/file_test/testdata/file_only_re_multi_file.carbon b/testing/file_test/testdata/file_only_re_multi_file.carbon new file mode 100644 index 000000000000..e979b8c8d3d7 --- /dev/null +++ b/testing/file_test/testdata/file_only_re_multi_file.carbon @@ -0,0 +1,25 @@ +// 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 + +// AUTOUPDATE +// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon` +// CHECK:STDOUT: unattached message 1 + +// --- a.carbon +aaa +// CHECK:STDOUT: file: a.carbon +// CHECK:STDOUT: unattached message 2 +// CHECK:STDOUT: line: [[@LINE-3]]: attached message 3 +// CHECK:STDOUT: unattached message 4 + +// CHECK:STDOUT: line: [[@LINE+1]]: late message 5 +// CHECK:STDOUT: unattached message 6 +// --- b.carbon +bbb +// CHECK:STDOUT: file: b.carbon +// CHECK:STDOUT: line: [[@LINE-2]]: attached message 7 +// CHECK:STDOUT: unattached message 8 + +// CHECK:STDOUT: line: [[@LINE+1]]: late message 9 +// CHECK:STDOUT: unattached message 10 diff --git a/testing/file_test/testdata/file_only_re_one_file.carbon b/testing/file_test/testdata/file_only_re_one_file.carbon new file mode 100644 index 000000000000..cd081ca3430b --- /dev/null +++ b/testing/file_test/testdata/file_only_re_one_file.carbon @@ -0,0 +1,10 @@ +// 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 + +// AUTOUPDATE +// CHECK:STDOUT: 2 args: `default_args`, `file_only_re_one_file.carbon` +// CHECK:STDOUT: unattached message 1 +// CHECK:STDOUT: file: file_only_re_one_file.carbon +// CHECK:STDOUT: line: [[@LINE-8]] +// CHECK:STDOUT: unattached message 2 diff --git a/testing/file_test/testdata/unattached_multi_file.carbon b/testing/file_test/testdata/unattached_multi_file.carbon index 7c54423489e3..3366a997a623 100644 --- a/testing/file_test/testdata/unattached_multi_file.carbon +++ b/testing/file_test/testdata/unattached_multi_file.carbon @@ -6,12 +6,11 @@ // CHECK:STDERR: unattached message 3 // CHECK:STDERR: unattached message 4 +// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon` +// CHECK:STDOUT: unattached message 1 +// CHECK:STDOUT: unattached message 2 // --- a.carbon aaa // --- b.carbon bbb - -// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon` -// CHECK:STDOUT: unattached message 1 -// CHECK:STDOUT: unattached message 2 diff --git a/toolchain/autoupdate_testdata.py b/toolchain/autoupdate_testdata.py index 93c135e2f6d8..6e0b20173b94 100755 --- a/toolchain/autoupdate_testdata.py +++ b/toolchain/autoupdate_testdata.py @@ -26,13 +26,13 @@ def main() -> None: # Support specifying tests to update, such as: # ./autoupdate_testdata.py lex/**/* if len(sys.argv) > 1: - repo_root = Path(__file__).parent.parent + repo_root = Path(__file__).resolve().parent.parent file_tests = [] # Filter down to just test files. for f in sys.argv[1:]: if f.endswith(".carbon"): - path = str(Path(f).absolute().relative_to(repo_root)) - if path.find("/testdata/"): + path = str(Path(f).resolve().relative_to(repo_root)) + if path.count("/testdata/"): file_tests.append(path) if not file_tests: sys.exit( diff --git a/toolchain/driver/driver_test.cpp b/toolchain/driver/driver_test.cpp index 420b891405eb..e681b694766d 100644 --- a/toolchain/driver/driver_test.cpp +++ b/toolchain/driver/driver_test.cpp @@ -15,13 +15,11 @@ #include "llvm/Object/Binary.h" #include "llvm/Support/FormatVariadic.h" #include "testing/base/test_raw_ostream.h" -#include "toolchain/base/yaml_test_helpers.h" namespace Carbon::Testing { namespace { using ::testing::ContainsRegex; -using ::testing::ElementsAre; using ::testing::HasSubstr; using ::testing::StrEq; @@ -126,32 +124,8 @@ TEST_F(DriverTest, DumpTokens) { EXPECT_TRUE( driver_.RunCommand({"compile", "--phase=lex", "--dump-tokens", file})); EXPECT_THAT(test_error_stream_.TakeStr(), StrEq("")); - auto tokenized_text = test_output_stream_.TakeStr(); - - EXPECT_THAT(Yaml::Value::FromText(tokenized_text), - ElementsAre(Yaml::SequenceValue{ - Yaml::MappingValue{{"index", "0"}, - {"kind", "Identifier"}, - {"line", "1"}, - {"column", "1"}, - {"indent", "1"}, - {"spelling", "Hello"}, - {"identifier", "0"}, - {"has_trailing_space", "true"}}, - Yaml::MappingValue{{"index", "1"}, - {"kind", "Identifier"}, - {"line", "1"}, - {"column", "7"}, - {"indent", "1"}, - {"spelling", "World"}, - {"identifier", "1"}, - {"has_trailing_space", "true"}}, - Yaml::MappingValue{{"index", "2"}, - {"kind", "EndOfFile"}, - {"line", "1"}, - {"column", "12"}, - {"indent", "1"}, - {"spelling", ""}}})); + // Verify there is output without examining it. + EXPECT_FALSE(test_output_stream_.TakeStr().empty()); } TEST_F(DriverTest, DumpParseTree) { diff --git a/toolchain/lex/testdata/basic_syntax.carbon b/toolchain/lex/testdata/basic_syntax.carbon index 8c46028a1f40..8643fffd84bf 100644 --- a/toolchain/lex/testdata/basic_syntax.carbon +++ b/toolchain/lex/testdata/basic_syntax.carbon @@ -3,22 +3,23 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: basic_syntax.carbon +// CHECK:STDOUT: tokens: [ fn run(String program) { -// CHECK:STDOUT: { index: 0, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: 'run', identifier: 0 }, -// CHECK:STDOUT: { index: 2, kind: 'OpenParen', line: {{ *}}[[@LINE-3]], column: 7, indent: 1, spelling: '(', closing_token: 5 }, -// CHECK:STDOUT: { index: 3, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-4]], column: 8, indent: 1, spelling: 'String', has_trailing_space: true }, -// CHECK:STDOUT: { index: 4, kind: 'Identifier', line: {{ *}}[[@LINE-5]], column: 15, indent: 1, spelling: 'program', identifier: 1 }, -// CHECK:STDOUT: { index: 5, kind: 'CloseParen', line: {{ *}}[[@LINE-6]], column: 22, indent: 1, spelling: ')', opening_token: 2, has_trailing_space: true }, -// CHECK:STDOUT: { index: 6, kind: 'OpenCurlyBrace', line: {{ *}}[[@LINE-7]], column: 24, indent: 1, spelling: '{', closing_token: 10, has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, +// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: 'run', identifier: 0 }, +// CHECK:STDOUT: { index: 2, kind: 'OpenParen', line: {{ *}}[[@LINE-3]], column: 7, indent: 1, spelling: '(', closing_token: 5 }, +// CHECK:STDOUT: { index: 3, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-4]], column: 8, indent: 1, spelling: 'String', has_trailing_space: true }, +// CHECK:STDOUT: { index: 4, kind: 'Identifier', line: {{ *}}[[@LINE-5]], column: 15, indent: 1, spelling: 'program', identifier: 1 }, +// CHECK:STDOUT: { index: 5, kind: 'CloseParen', line: {{ *}}[[@LINE-6]], column: 22, indent: 1, spelling: ')', opening_token: 2, has_trailing_space: true }, +// CHECK:STDOUT: { index: 6, kind: 'OpenCurlyBrace', line: {{ *}}[[@LINE-7]], column: 24, indent: 1, spelling: '{', closing_token: 10, has_trailing_space: true }, return True; - // CHECK:STDOUT: { index: 7, kind: 'Return', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'return', has_trailing_space: true }, - // CHECK:STDOUT: { index: 8, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 10, indent: 3, spelling: 'True', identifier: 2 }, - // CHECK:STDOUT: { index: 9, kind: 'Semi', line: {{ *}}[[@LINE-3]], column: 14, indent: 3, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 7, kind: 'Return', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'return', has_trailing_space: true }, + // CHECK:STDOUT: { index: 8, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 10, indent: 3, spelling: 'True', identifier: 2 }, + // CHECK:STDOUT: { index: 9, kind: 'Semi', line: {{ *}}[[@LINE-3]], column: 14, indent: 3, spelling: ';', has_trailing_space: true }, } -// CHECK:STDOUT: { index: 10, kind: 'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '}', opening_token: 6, has_trailing_space: true }, +// CHECK:STDOUT: { index: 10, kind: 'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '}', opening_token: 6, has_trailing_space: true }, -// CHECK:STDOUT: { index: 11, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 11, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/fail_block_string_second_line.carbon b/toolchain/lex/testdata/fail_block_string_second_line.carbon index 338c4f95ccf7..c95b7e289def 100644 --- a/toolchain/lex/testdata/fail_block_string_second_line.carbon +++ b/toolchain/lex/testdata/fail_block_string_second_line.carbon @@ -4,20 +4,21 @@ // // An autoupdate wants to put the CHECK in the middle of the block string. // NOAUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: fail_block_string_second_line.carbon +// CHECK:STDOUT: tokens: [ // CHECK:STDERR: fail_block_string_second_line.carbon:[[@LINE+4]]:3: Only whitespace is permitted before the closing `'''` of a multi-line string. // CHECK:STDERR: error here: ''' // CHECK:STDERR: ^ var s: String = ''' error here: ''' -// CHECK:STDOUT: { index: 0, kind: 'Var', line: {{ *}}[[@LINE-2]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: 's', identifier: 0 }, -// CHECK:STDOUT: { index: 2, kind: 'Colon', line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: ':', has_trailing_space: true }, -// CHECK:STDOUT: { index: 3, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: 'String', has_trailing_space: true }, -// CHECK:STDOUT: { index: 4, kind: 'Equal', line: {{ *}}[[@LINE-6]], column: 15, indent: 1, spelling: '=', has_trailing_space: true }, -// CHECK:STDOUT: { index: 5, kind: 'StringLiteral', line: {{ *}}[[@LINE-7]], column: 17, indent: 1, spelling: '''' +// CHECK:STDOUT: { index: 0, kind: 'Var', line: {{ *}}[[@LINE-2]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true }, +// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: 's', identifier: 0 }, +// CHECK:STDOUT: { index: 2, kind: 'Colon', line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: ':', has_trailing_space: true }, +// CHECK:STDOUT: { index: 3, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: 'String', has_trailing_space: true }, +// CHECK:STDOUT: { index: 4, kind: 'Equal', line: {{ *}}[[@LINE-6]], column: 15, indent: 1, spelling: '=', has_trailing_space: true }, +// CHECK:STDOUT: { index: 5, kind: 'StringLiteral', line: {{ *}}[[@LINE-7]], column: 17, indent: 1, spelling: '''' // CHECK:STDOUT: error here: '''', value: `error here: `, has_trailing_space: true }, -// CHECK:STDOUT: { index: 6, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 6, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/fail_multifile.carbon b/toolchain/lex/testdata/fail_multifile.carbon new file mode 100644 index 000000000000..d3870e2737ad --- /dev/null +++ b/toolchain/lex/testdata/fail_multifile.carbon @@ -0,0 +1,28 @@ +// 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 +// +// AUTOUPDATE + +// --- a.carbon +// CHECK:STDERR: a.carbon:[[@LINE+3]]:3: Empty digit sequence in numeric literal. +// CHECK:STDERR: 1.a +// CHECK:STDERR: ^ +1.a +// CHECK:STDOUT: - filename: a.carbon +// CHECK:STDOUT: tokens: [ +// CHECK:STDOUT: { index: 0, kind: 'Error', line: {{ *}}[[@LINE-3]], column: 1, indent: 1, spelling: '1.a', has_trailing_space: true }, + +// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] +// --- b.carbon +// CHECK:STDERR: b.carbon:[[@LINE+3]]:3: Empty digit sequence in numeric literal. +// CHECK:STDERR: 2.b +// CHECK:STDERR: ^ +2.b +// CHECK:STDOUT: - filename: b.carbon +// CHECK:STDOUT: tokens: [ +// CHECK:STDOUT: { index: 0, kind: 'Error', line: {{ *}}[[@LINE-3]], column: 1, indent: 1, spelling: '2.b', has_trailing_space: true }, + +// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/keywords.carbon b/toolchain/lex/testdata/keywords.carbon index 4ac9c142a034..f12ec5ea8e57 100644 --- a/toolchain/lex/testdata/keywords.carbon +++ b/toolchain/lex/testdata/keywords.carbon @@ -3,133 +3,134 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: keywords.carbon +// CHECK:STDOUT: tokens: [ abstract -// CHECK:STDOUT: { index: 0, kind: 'Abstract', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'abstract', has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'Abstract', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'abstract', has_trailing_space: true }, adapt -// CHECK:STDOUT: { index: 1, kind: 'Adapt', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'adapt', has_trailing_space: true }, +// CHECK:STDOUT: { index: 1, kind: 'Adapt', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'adapt', has_trailing_space: true }, addr -// CHECK:STDOUT: { index: 2, kind: 'Addr', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'addr', has_trailing_space: true }, +// CHECK:STDOUT: { index: 2, kind: 'Addr', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'addr', has_trailing_space: true }, alias -// CHECK:STDOUT: { index: 3, kind: 'Alias', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'alias', has_trailing_space: true }, +// CHECK:STDOUT: { index: 3, kind: 'Alias', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'alias', has_trailing_space: true }, and -// CHECK:STDOUT: { index: 4, kind: 'And', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'and', has_trailing_space: true }, +// CHECK:STDOUT: { index: 4, kind: 'And', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'and', has_trailing_space: true }, api -// CHECK:STDOUT: { index: 5, kind: 'Api', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'api', has_trailing_space: true }, +// CHECK:STDOUT: { index: 5, kind: 'Api', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'api', has_trailing_space: true }, as -// CHECK:STDOUT: { index: 6, kind: 'As', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'as', has_trailing_space: true }, +// CHECK:STDOUT: { index: 6, kind: 'As', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'as', has_trailing_space: true }, auto -// CHECK:STDOUT: { index: 7, kind: 'Auto', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'auto', has_trailing_space: true }, +// CHECK:STDOUT: { index: 7, kind: 'Auto', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'auto', has_trailing_space: true }, base -// CHECK:STDOUT: { index: 8, kind: 'Base', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'base', has_trailing_space: true }, +// CHECK:STDOUT: { index: 8, kind: 'Base', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'base', has_trailing_space: true }, bool -// CHECK:STDOUT: { index: 9, kind: 'Bool', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'bool', has_trailing_space: true }, +// CHECK:STDOUT: { index: 9, kind: 'Bool', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'bool', has_trailing_space: true }, break -// CHECK:STDOUT: { index: 10, kind: 'Break', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'break', has_trailing_space: true }, +// CHECK:STDOUT: { index: 10, kind: 'Break', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'break', has_trailing_space: true }, case -// CHECK:STDOUT: { index: 11, kind: 'Case', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'case', has_trailing_space: true }, +// CHECK:STDOUT: { index: 11, kind: 'Case', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'case', has_trailing_space: true }, choice -// CHECK:STDOUT: { index: 12, kind: 'Choice', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'choice', has_trailing_space: true }, +// CHECK:STDOUT: { index: 12, kind: 'Choice', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'choice', has_trailing_space: true }, class -// CHECK:STDOUT: { index: 13, kind: 'Class', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'class', has_trailing_space: true }, +// CHECK:STDOUT: { index: 13, kind: 'Class', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'class', has_trailing_space: true }, const -// CHECK:STDOUT: { index: 14, kind: 'Const', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'const', has_trailing_space: true }, +// CHECK:STDOUT: { index: 14, kind: 'Const', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'const', has_trailing_space: true }, constraint -// CHECK:STDOUT: { index: 15, kind: 'Constraint', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'constraint', has_trailing_space: true }, +// CHECK:STDOUT: { index: 15, kind: 'Constraint', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'constraint', has_trailing_space: true }, continue -// CHECK:STDOUT: { index: 16, kind: 'Continue', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'continue', has_trailing_space: true }, +// CHECK:STDOUT: { index: 16, kind: 'Continue', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'continue', has_trailing_space: true }, default -// CHECK:STDOUT: { index: 17, kind: 'Default', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'default', has_trailing_space: true }, +// CHECK:STDOUT: { index: 17, kind: 'Default', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'default', has_trailing_space: true }, destructor -// CHECK:STDOUT: { index: 18, kind: 'Destructor', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'destructor', has_trailing_space: true }, +// CHECK:STDOUT: { index: 18, kind: 'Destructor', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'destructor', has_trailing_space: true }, else -// CHECK:STDOUT: { index: 19, kind: 'Else', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'else', has_trailing_space: true }, +// CHECK:STDOUT: { index: 19, kind: 'Else', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'else', has_trailing_space: true }, extend -// CHECK:STDOUT: { index: 20, kind: 'Extend', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'extend', has_trailing_space: true }, +// CHECK:STDOUT: { index: 20, kind: 'Extend', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'extend', has_trailing_space: true }, false -// CHECK:STDOUT: { index: 21, kind: 'False', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'false', has_trailing_space: true }, +// CHECK:STDOUT: { index: 21, kind: 'False', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'false', has_trailing_space: true }, final -// CHECK:STDOUT: { index: 22, kind: 'Final', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'final', has_trailing_space: true }, +// CHECK:STDOUT: { index: 22, kind: 'Final', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'final', has_trailing_space: true }, fn -// CHECK:STDOUT: { index: 23, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, +// CHECK:STDOUT: { index: 23, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, for -// CHECK:STDOUT: { index: 24, kind: 'For', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'for', has_trailing_space: true }, +// CHECK:STDOUT: { index: 24, kind: 'For', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'for', has_trailing_space: true }, forall -// CHECK:STDOUT: { index: 25, kind: 'Forall', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'forall', has_trailing_space: true }, +// CHECK:STDOUT: { index: 25, kind: 'Forall', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'forall', has_trailing_space: true }, friend -// CHECK:STDOUT: { index: 26, kind: 'Friend', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'friend', has_trailing_space: true }, +// CHECK:STDOUT: { index: 26, kind: 'Friend', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'friend', has_trailing_space: true }, if -// CHECK:STDOUT: { index: 27, kind: 'If', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'if', has_trailing_space: true }, +// CHECK:STDOUT: { index: 27, kind: 'If', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'if', has_trailing_space: true }, impl -// CHECK:STDOUT: { index: 28, kind: 'Impl', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'impl', has_trailing_space: true }, +// CHECK:STDOUT: { index: 28, kind: 'Impl', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'impl', has_trailing_space: true }, impls -// CHECK:STDOUT: { index: 29, kind: 'Impls', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'impls', has_trailing_space: true }, +// CHECK:STDOUT: { index: 29, kind: 'Impls', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'impls', has_trailing_space: true }, import -// CHECK:STDOUT: { index: 30, kind: 'Import', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'import', has_trailing_space: true }, +// CHECK:STDOUT: { index: 30, kind: 'Import', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'import', has_trailing_space: true }, in -// CHECK:STDOUT: { index: 31, kind: 'In', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'in', has_trailing_space: true }, +// CHECK:STDOUT: { index: 31, kind: 'In', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'in', has_trailing_space: true }, interface -// CHECK:STDOUT: { index: 32, kind: 'Interface', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'interface', has_trailing_space: true }, +// CHECK:STDOUT: { index: 32, kind: 'Interface', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'interface', has_trailing_space: true }, let -// CHECK:STDOUT: { index: 33, kind: 'Let', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'let', has_trailing_space: true }, +// CHECK:STDOUT: { index: 33, kind: 'Let', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'let', has_trailing_space: true }, library -// CHECK:STDOUT: { index: 34, kind: 'Library', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'library', has_trailing_space: true }, +// CHECK:STDOUT: { index: 34, kind: 'Library', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'library', has_trailing_space: true }, like -// CHECK:STDOUT: { index: 35, kind: 'Like', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'like', has_trailing_space: true }, +// CHECK:STDOUT: { index: 35, kind: 'Like', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'like', has_trailing_space: true }, match -// CHECK:STDOUT: { index: 36, kind: 'Match', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'match', has_trailing_space: true }, +// CHECK:STDOUT: { index: 36, kind: 'Match', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'match', has_trailing_space: true }, namespace -// CHECK:STDOUT: { index: 37, kind: 'Namespace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'namespace', has_trailing_space: true }, +// CHECK:STDOUT: { index: 37, kind: 'Namespace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'namespace', has_trailing_space: true }, not -// CHECK:STDOUT: { index: 38, kind: 'Not', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'not', has_trailing_space: true }, +// CHECK:STDOUT: { index: 38, kind: 'Not', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'not', has_trailing_space: true }, observe -// CHECK:STDOUT: { index: 39, kind: 'Observe', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'observe', has_trailing_space: true }, +// CHECK:STDOUT: { index: 39, kind: 'Observe', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'observe', has_trailing_space: true }, or -// CHECK:STDOUT: { index: 40, kind: 'Or', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'or', has_trailing_space: true }, +// CHECK:STDOUT: { index: 40, kind: 'Or', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'or', has_trailing_space: true }, override -// CHECK:STDOUT: { index: 41, kind: 'Override', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'override', has_trailing_space: true }, +// CHECK:STDOUT: { index: 41, kind: 'Override', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'override', has_trailing_space: true }, package -// CHECK:STDOUT: { index: 42, kind: 'Package', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'package', has_trailing_space: true }, +// CHECK:STDOUT: { index: 42, kind: 'Package', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'package', has_trailing_space: true }, partial -// CHECK:STDOUT: { index: 43, kind: 'Partial', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'partial', has_trailing_space: true }, +// CHECK:STDOUT: { index: 43, kind: 'Partial', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'partial', has_trailing_space: true }, private -// CHECK:STDOUT: { index: 44, kind: 'Private', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'private', has_trailing_space: true }, +// CHECK:STDOUT: { index: 44, kind: 'Private', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'private', has_trailing_space: true }, protected -// CHECK:STDOUT: { index: 45, kind: 'Protected', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'protected', has_trailing_space: true }, +// CHECK:STDOUT: { index: 45, kind: 'Protected', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'protected', has_trailing_space: true }, require -// CHECK:STDOUT: { index: 46, kind: 'Require', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'require', has_trailing_space: true }, +// CHECK:STDOUT: { index: 46, kind: 'Require', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'require', has_trailing_space: true }, return -// CHECK:STDOUT: { index: 47, kind: 'Return', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'return', has_trailing_space: true }, +// CHECK:STDOUT: { index: 47, kind: 'Return', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'return', has_trailing_space: true }, returned -// CHECK:STDOUT: { index: 48, kind: 'Returned', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'returned', has_trailing_space: true }, +// CHECK:STDOUT: { index: 48, kind: 'Returned', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'returned', has_trailing_space: true }, Self -// CHECK:STDOUT: { index: 49, kind: 'SelfTypeIdentifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'Self', has_trailing_space: true }, +// CHECK:STDOUT: { index: 49, kind: 'SelfTypeIdentifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'Self', has_trailing_space: true }, self -// CHECK:STDOUT: { index: 50, kind: 'SelfValueIdentifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'self', has_trailing_space: true }, +// CHECK:STDOUT: { index: 50, kind: 'SelfValueIdentifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'self', has_trailing_space: true }, String -// CHECK:STDOUT: { index: 51, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'String', has_trailing_space: true }, +// CHECK:STDOUT: { index: 51, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'String', has_trailing_space: true }, template -// CHECK:STDOUT: { index: 52, kind: 'Template', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'template', has_trailing_space: true }, +// CHECK:STDOUT: { index: 52, kind: 'Template', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'template', has_trailing_space: true }, then -// CHECK:STDOUT: { index: 53, kind: 'Then', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'then', has_trailing_space: true }, +// CHECK:STDOUT: { index: 53, kind: 'Then', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'then', has_trailing_space: true }, true -// CHECK:STDOUT: { index: 54, kind: 'True', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'true', has_trailing_space: true }, +// CHECK:STDOUT: { index: 54, kind: 'True', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'true', has_trailing_space: true }, type -// CHECK:STDOUT: { index: 55, kind: 'Type', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'type', has_trailing_space: true }, +// CHECK:STDOUT: { index: 55, kind: 'Type', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'type', has_trailing_space: true }, _ -// CHECK:STDOUT: { index: 56, kind: 'Underscore', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '_', has_trailing_space: true }, +// CHECK:STDOUT: { index: 56, kind: 'Underscore', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '_', has_trailing_space: true }, var -// CHECK:STDOUT: { index: 57, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true }, +// CHECK:STDOUT: { index: 57, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true }, virtual -// CHECK:STDOUT: { index: 58, kind: 'Virtual', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'virtual', has_trailing_space: true }, +// CHECK:STDOUT: { index: 58, kind: 'Virtual', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'virtual', has_trailing_space: true }, where -// CHECK:STDOUT: { index: 59, kind: 'Where', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'where', has_trailing_space: true }, +// CHECK:STDOUT: { index: 59, kind: 'Where', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'where', has_trailing_space: true }, while -// CHECK:STDOUT: { index: 60, kind: 'While', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'while', has_trailing_space: true }, +// CHECK:STDOUT: { index: 60, kind: 'While', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'while', has_trailing_space: true }, notakeyword -// CHECK:STDOUT: { index: 61, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'notakeyword', identifier: 0, has_trailing_space: true }, +// CHECK:STDOUT: { index: 61, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'notakeyword', identifier: 0, has_trailing_space: true }, -// CHECK:STDOUT: { index: 62, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 62, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/multifile.carbon b/toolchain/lex/testdata/multifile.carbon new file mode 100644 index 000000000000..2afc00084e9f --- /dev/null +++ b/toolchain/lex/testdata/multifile.carbon @@ -0,0 +1,26 @@ +// 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 +// +// AUTOUPDATE + +// --- a.carbon + +// CHECK:STDOUT: - filename: a.carbon +// CHECK:STDOUT: tokens: [ +a; +// CHECK:STDOUT: { index: 0, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'a', identifier: 0 }, +// CHECK:STDOUT: { index: 1, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: ';', has_trailing_space: true }, + +// CHECK:STDOUT: { index: 2, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] +// --- b.carbon + +// CHECK:STDOUT: - filename: b.carbon +// CHECK:STDOUT: tokens: [ +b; +// CHECK:STDOUT: { index: 0, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'b', identifier: 0 }, +// CHECK:STDOUT: { index: 1, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: ';', has_trailing_space: true }, + +// CHECK:STDOUT: { index: 2, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/numeric_literals.carbon b/toolchain/lex/testdata/numeric_literals.carbon index 97899466487d..a8d567b6d702 100644 --- a/toolchain/lex/testdata/numeric_literals.carbon +++ b/toolchain/lex/testdata/numeric_literals.carbon @@ -3,82 +3,83 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: numeric_literals.carbon +// CHECK:STDOUT: tokens: [ fn F() { -// CHECK:STDOUT: { index: 0, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: 'F', identifier: 0 }, -// CHECK:STDOUT: { index: 2, kind: 'OpenParen', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: '(', closing_token: 3 }, -// CHECK:STDOUT: { index: 3, kind: 'CloseParen', line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: ')', opening_token: 2, has_trailing_space: true }, -// CHECK:STDOUT: { index: 4, kind: 'OpenCurlyBrace', line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: '{', closing_token: 53, has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'Fn', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true }, +// CHECK:STDOUT: { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: 'F', identifier: 0 }, +// CHECK:STDOUT: { index: 2, kind: 'OpenParen', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: '(', closing_token: 3 }, +// CHECK:STDOUT: { index: 3, kind: 'CloseParen', line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: ')', opening_token: 2, has_trailing_space: true }, +// CHECK:STDOUT: { index: 4, kind: 'OpenCurlyBrace', line: {{ *}}[[@LINE-5]], column: 8, indent: 1, spelling: '{', closing_token: 53, has_trailing_space: true }, // 8 and 9 trigger special behavior in APInt when mishandling signed versus // unsigned, so we pay extra attention to those. var ints: [i32; 5] = ( - // CHECK:STDOUT: { index: 5, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'var', has_trailing_space: true }, - // CHECK:STDOUT: { index: 6, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: 'ints', identifier: 1 }, - // CHECK:STDOUT: { index: 7, kind: 'Colon', line: {{ *}}[[@LINE-3]], column: 11, indent: 3, spelling: ':', has_trailing_space: true }, - // CHECK:STDOUT: { index: 8, kind: 'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 13, indent: 3, spelling: '[', closing_token: 12 }, - // CHECK:STDOUT: { index: 9, kind: 'IntegerTypeLiteral', line: {{ *}}[[@LINE-5]], column: 14, indent: 3, spelling: 'i32' }, - // CHECK:STDOUT: { index: 10, kind: 'Semi', line: {{ *}}[[@LINE-6]], column: 17, indent: 3, spelling: ';', has_trailing_space: true }, - // CHECK:STDOUT: { index: 11, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-7]], column: 19, indent: 3, spelling: '5', value: `5` }, - // CHECK:STDOUT: { index: 12, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 20, indent: 3, spelling: ']', opening_token: 8, has_trailing_space: true }, - // CHECK:STDOUT: { index: 13, kind: 'Equal', line: {{ *}}[[@LINE-9]], column: 22, indent: 3, spelling: '=', has_trailing_space: true }, - // CHECK:STDOUT: { index: 14, kind: 'OpenParen', line: {{ *}}[[@LINE-10]], column: 24, indent: 3, spelling: '(', closing_token: 25, has_trailing_space: true }, + // CHECK:STDOUT: { index: 5, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'var', has_trailing_space: true }, + // CHECK:STDOUT: { index: 6, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: 'ints', identifier: 1 }, + // CHECK:STDOUT: { index: 7, kind: 'Colon', line: {{ *}}[[@LINE-3]], column: 11, indent: 3, spelling: ':', has_trailing_space: true }, + // CHECK:STDOUT: { index: 8, kind: 'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 13, indent: 3, spelling: '[', closing_token: 12 }, + // CHECK:STDOUT: { index: 9, kind: 'IntegerTypeLiteral', line: {{ *}}[[@LINE-5]], column: 14, indent: 3, spelling: 'i32' }, + // CHECK:STDOUT: { index: 10, kind: 'Semi', line: {{ *}}[[@LINE-6]], column: 17, indent: 3, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 11, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-7]], column: 19, indent: 3, spelling: '5', value: `5` }, + // CHECK:STDOUT: { index: 12, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 20, indent: 3, spelling: ']', opening_token: 8, has_trailing_space: true }, + // CHECK:STDOUT: { index: 13, kind: 'Equal', line: {{ *}}[[@LINE-9]], column: 22, indent: 3, spelling: '=', has_trailing_space: true }, + // CHECK:STDOUT: { index: 14, kind: 'OpenParen', line: {{ *}}[[@LINE-10]], column: 24, indent: 3, spelling: '(', closing_token: 25, has_trailing_space: true }, 8, - // CHECK:STDOUT: { index: 15, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '8', value: `8` }, - // CHECK:STDOUT: { index: 16, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 6, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 15, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '8', value: `8` }, + // CHECK:STDOUT: { index: 16, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 6, indent: 5, spelling: ',', has_trailing_space: true }, 9, - // CHECK:STDOUT: { index: 17, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '9', value: `9` }, - // CHECK:STDOUT: { index: 18, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 6, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 17, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '9', value: `9` }, + // CHECK:STDOUT: { index: 18, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 6, indent: 5, spelling: ',', has_trailing_space: true }, 0x8, - // CHECK:STDOUT: { index: 19, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0x8', value: `8` }, - // CHECK:STDOUT: { index: 20, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 19, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0x8', value: `8` }, + // CHECK:STDOUT: { index: 20, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, 0b1000, - // CHECK:STDOUT: { index: 21, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0b1000', value: `8` }, - // CHECK:STDOUT: { index: 22, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 21, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0b1000', value: `8` }, + // CHECK:STDOUT: { index: 22, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',', has_trailing_space: true }, 39999999999999999993, - // CHECK:STDOUT: { index: 23, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '39999999999999999993', value: `39999999999999999993` }, - // CHECK:STDOUT: { index: 24, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 23, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '39999999999999999993', value: `39999999999999999993` }, + // CHECK:STDOUT: { index: 24, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: ',', has_trailing_space: true }, ); - // CHECK:STDOUT: { index: 25, kind: 'CloseParen', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ')', opening_token: 14 }, - // CHECK:STDOUT: { index: 26, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 25, kind: 'CloseParen', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ')', opening_token: 14 }, + // CHECK:STDOUT: { index: 26, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ';', has_trailing_space: true }, var floats: [f64; 7] = ( - // CHECK:STDOUT: { index: 27, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'var', has_trailing_space: true }, - // CHECK:STDOUT: { index: 28, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: 'floats', identifier: 2 }, - // CHECK:STDOUT: { index: 29, kind: 'Colon', line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ':', has_trailing_space: true }, - // CHECK:STDOUT: { index: 30, kind: 'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: '[', closing_token: 34 }, - // CHECK:STDOUT: { index: 31, kind: 'FloatingPointTypeLiteral', line: {{ *}}[[@LINE-5]], column: 16, indent: 3, spelling: 'f64' }, - // CHECK:STDOUT: { index: 32, kind: 'Semi', line: {{ *}}[[@LINE-6]], column: 19, indent: 3, spelling: ';', has_trailing_space: true }, - // CHECK:STDOUT: { index: 33, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-7]], column: 21, indent: 3, spelling: '7', value: `7` }, - // CHECK:STDOUT: { index: 34, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 22, indent: 3, spelling: ']', opening_token: 30, has_trailing_space: true }, - // CHECK:STDOUT: { index: 35, kind: 'Equal', line: {{ *}}[[@LINE-9]], column: 24, indent: 3, spelling: '=', has_trailing_space: true }, - // CHECK:STDOUT: { index: 36, kind: 'OpenParen', line: {{ *}}[[@LINE-10]], column: 26, indent: 3, spelling: '(', closing_token: 51, has_trailing_space: true }, + // CHECK:STDOUT: { index: 27, kind: 'Var', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: 'var', has_trailing_space: true }, + // CHECK:STDOUT: { index: 28, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column: 7, indent: 3, spelling: 'floats', identifier: 2 }, + // CHECK:STDOUT: { index: 29, kind: 'Colon', line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ':', has_trailing_space: true }, + // CHECK:STDOUT: { index: 30, kind: 'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: '[', closing_token: 34 }, + // CHECK:STDOUT: { index: 31, kind: 'FloatingPointTypeLiteral', line: {{ *}}[[@LINE-5]], column: 16, indent: 3, spelling: 'f64' }, + // CHECK:STDOUT: { index: 32, kind: 'Semi', line: {{ *}}[[@LINE-6]], column: 19, indent: 3, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 33, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-7]], column: 21, indent: 3, spelling: '7', value: `7` }, + // CHECK:STDOUT: { index: 34, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 22, indent: 3, spelling: ']', opening_token: 30, has_trailing_space: true }, + // CHECK:STDOUT: { index: 35, kind: 'Equal', line: {{ *}}[[@LINE-9]], column: 24, indent: 3, spelling: '=', has_trailing_space: true }, + // CHECK:STDOUT: { index: 36, kind: 'OpenParen', line: {{ *}}[[@LINE-10]], column: 26, indent: 3, spelling: '(', closing_token: 51, has_trailing_space: true }, 0.9, - // CHECK:STDOUT: { index: 37, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0.9', value: `9*10^-1` }, - // CHECK:STDOUT: { index: 38, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 37, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '0.9', value: `9*10^-1` }, + // CHECK:STDOUT: { index: 38, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, 8.0, - // CHECK:STDOUT: { index: 39, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '8.0', value: `80*10^-1` }, - // CHECK:STDOUT: { index: 40, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 39, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '8.0', value: `80*10^-1` }, + // CHECK:STDOUT: { index: 40, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 8, indent: 5, spelling: ',', has_trailing_space: true }, 80.0, - // CHECK:STDOUT: { index: 41, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '80.0', value: `800*10^-1` }, - // CHECK:STDOUT: { index: 42, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 9, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 41, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '80.0', value: `800*10^-1` }, + // CHECK:STDOUT: { index: 42, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 9, indent: 5, spelling: ',', has_trailing_space: true }, 1.0e7, - // CHECK:STDOUT: { index: 43, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e7', value: `10*10^6` }, - // CHECK:STDOUT: { index: 44, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 43, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e7', value: `10*10^6` }, + // CHECK:STDOUT: { index: 44, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',', has_trailing_space: true }, 1.0e8, - // CHECK:STDOUT: { index: 45, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e8', value: `10*10^7` }, - // CHECK:STDOUT: { index: 46, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 45, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e8', value: `10*10^7` }, + // CHECK:STDOUT: { index: 46, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',', has_trailing_space: true }, 1.0e-8, - // CHECK:STDOUT: { index: 47, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e-8', value: `10*10^-9` }, - // CHECK:STDOUT: { index: 48, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 47, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '1.0e-8', value: `10*10^-9` }, + // CHECK:STDOUT: { index: 48, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',', has_trailing_space: true }, 39999999999999999993.0e39999999999999999993, - // CHECK:STDOUT: { index: 49, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '39999999999999999993.0e39999999999999999993', value: `399999999999999999930*10^39999999999999999992` }, - // CHECK:STDOUT: { index: 50, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: ',', has_trailing_space: true }, + // CHECK:STDOUT: { index: 49, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 5, indent: 5, spelling: '39999999999999999993.0e39999999999999999993', value: `399999999999999999930*10^39999999999999999992` }, + // CHECK:STDOUT: { index: 50, kind: 'Comma', line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: ',', has_trailing_space: true }, ); - // CHECK:STDOUT: { index: 51, kind: 'CloseParen', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ')', opening_token: 36 }, - // CHECK:STDOUT: { index: 52, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 51, kind: 'CloseParen', line: {{ *}}[[@LINE-1]], column: 3, indent: 3, spelling: ')', opening_token: 36 }, + // CHECK:STDOUT: { index: 52, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 4, indent: 3, spelling: ';', has_trailing_space: true }, } -// CHECK:STDOUT: { index: 53, kind: 'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '}', opening_token: 4, has_trailing_space: true }, +// CHECK:STDOUT: { index: 53, kind: 'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '}', opening_token: 4, has_trailing_space: true }, -// CHECK:STDOUT: { index: 54, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 54, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/printing_digit_padding.carbon b/toolchain/lex/testdata/printing_digit_padding.carbon index 02b198a5506c..c3fa210458d4 100644 --- a/toolchain/lex/testdata/printing_digit_padding.carbon +++ b/toolchain/lex/testdata/printing_digit_padding.carbon @@ -3,16 +3,17 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: printing_digit_padding.carbon +// CHECK:STDOUT: tokens: [ ; -// CHECK:STDOUT: { index: 0, kind: 'Semi', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: ';', has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'Semi', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: ';', has_trailing_space: true }, // Test digit padding with values of 9, 10, and 11. ;;; - // CHECK:STDOUT: { index: 1, kind: 'Semi', line: {{ *}}[[@LINE-1]], column: 9, indent: 9, spelling: ';' }, - // CHECK:STDOUT: { index: 2, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 10, indent: 9, spelling: ';' }, - // CHECK:STDOUT: { index: 3, kind: 'Semi', line: {{ *}}[[@LINE-3]], column: 11, indent: 9, spelling: ';', has_trailing_space: true }, + // CHECK:STDOUT: { index: 1, kind: 'Semi', line: {{ *}}[[@LINE-1]], column: 9, indent: 9, spelling: ';' }, + // CHECK:STDOUT: { index: 2, kind: 'Semi', line: {{ *}}[[@LINE-2]], column: 10, indent: 9, spelling: ';' }, + // CHECK:STDOUT: { index: 3, kind: 'Semi', line: {{ *}}[[@LINE-3]], column: 11, indent: 9, spelling: ';', has_trailing_space: true }, -// CHECK:STDOUT: { index: 4, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 4, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/printing_integer_literal.carbon b/toolchain/lex/testdata/printing_integer_literal.carbon index dfc56e15fd09..b0da32c83d8d 100644 --- a/toolchain/lex/testdata/printing_integer_literal.carbon +++ b/toolchain/lex/testdata/printing_integer_literal.carbon @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: printing_integer_literal.carbon +// CHECK:STDOUT: tokens: [ 123 -// CHECK:STDOUT: { index: 0, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '123', value: `123`, has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '123', value: `123`, has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/printing_real_literal.carbon b/toolchain/lex/testdata/printing_real_literal.carbon index 75350459cb03..4f1bcfb39cdf 100644 --- a/toolchain/lex/testdata/printing_real_literal.carbon +++ b/toolchain/lex/testdata/printing_real_literal.carbon @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: printing_real_literal.carbon +// CHECK:STDOUT: tokens: [ 2.5 -// CHECK:STDOUT: { index: 0, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '2.5', value: `25*10^-1`, has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '2.5', value: `25*10^-1`, has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/testdata/printing_token.carbon b/toolchain/lex/testdata/printing_token.carbon index 923c4fe7b77d..8ab728a490de 100644 --- a/toolchain/lex/testdata/printing_token.carbon +++ b/toolchain/lex/testdata/printing_token.carbon @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDOUT: [ +// CHECK:STDOUT: - filename: printing_token.carbon +// CHECK:STDOUT: tokens: [ 0x9 -// CHECK:STDOUT: { index: 0, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '0x9', value: `9`, has_trailing_space: true }, +// CHECK:STDOUT: { index: 0, kind: 'IntegerLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '0x9', value: `9`, has_trailing_space: true }, -// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, -// CHECK:STDOUT: ] +// CHECK:STDOUT: { index: 1, kind: 'EndOfFile', line: {{ *}}[[@LINE+1]], column: {{ *\d+}}, indent: 1, spelling: '' }, +// CHECK:STDOUT: ] diff --git a/toolchain/lex/tokenized_buffer.cpp b/toolchain/lex/tokenized_buffer.cpp index 880761c1473c..3bc12f17b816 100644 --- a/toolchain/lex/tokenized_buffer.cpp +++ b/toolchain/lex/tokenized_buffer.cpp @@ -1045,18 +1045,20 @@ auto TokenizedBuffer::Print(llvm::raw_ostream& output_stream) const -> void { return; } + output_stream << "- filename: " << source_->filename() << "\n" + << " tokens: [\n"; + PrintWidths widths = {}; widths.index = ComputeDecimalPrintedWidth((token_infos_.size())); for (Token token : tokens()) { widths.Widen(GetTokenPrintWidths(token)); } - output_stream << "[\n"; for (Token token : tokens()) { PrintToken(output_stream, token, widths); output_stream << "\n"; } - output_stream << "]\n"; + output_stream << " ]\n"; } auto TokenizedBuffer::PrintToken(llvm::raw_ostream& output_stream, @@ -1075,7 +1077,7 @@ auto TokenizedBuffer::PrintToken(llvm::raw_ostream& output_stream, Token token, // justification manually in order to use the dynamically computed widths // and get the quotes included. output_stream << llvm::formatv( - "{ index: {0}, kind: {1}, line: {2}, column: {3}, indent: {4}, " + " { index: {0}, kind: {1}, line: {2}, column: {3}, indent: {4}, " "spelling: '{5}'", llvm::format_decimal(token_index, widths.index), llvm::right_justify(llvm::formatv("'{0}'", token_info.kind.name()).str(), diff --git a/toolchain/lex/tokenized_buffer_test.cpp b/toolchain/lex/tokenized_buffer_test.cpp index 6300e1d5daa9..e32e467b5ffc 100644 --- a/toolchain/lex/tokenized_buffer_test.cpp +++ b/toolchain/lex/tokenized_buffer_test.cpp @@ -1001,35 +1001,38 @@ TEST_F(LexerTest, PrintingAsYaml) { TestRawOstream print_stream; buffer.Print(print_stream); - EXPECT_THAT(Yaml::Value::FromText(print_stream.TakeStr()), - ElementsAre(Yaml::SequenceValue{ - Yaml::MappingValue{{"index", "0"}, - {"kind", "Semi"}, - {"line", "2"}, - {"column", "2"}, - {"indent", "2"}, - {"spelling", ";"}, - {"has_trailing_space", "true"}}, - Yaml::MappingValue{{"index", "1"}, - {"kind", "Semi"}, - {"line", "5"}, - {"column", "1"}, - {"indent", "1"}, - {"spelling", ";"}, - {"has_trailing_space", "true"}}, - Yaml::MappingValue{{"index", "2"}, - {"kind", "Semi"}, - {"line", "5"}, - {"column", "3"}, - {"indent", "1"}, - {"spelling", ";"}, - {"has_trailing_space", "true"}}, - Yaml::MappingValue{{"index", "3"}, - {"kind", "EndOfFile"}, - {"line", "15"}, - {"column", "1"}, - {"indent", "1"}, - {"spelling", ""}}})); + EXPECT_THAT( + Yaml::Value::FromText(print_stream.TakeStr()), + ElementsAre(Yaml::SequenceValue{Yaml::MappingValue{ + {"filename", Yaml::ScalarValue{source_storage_.front().filename()}}, + {"tokens", Yaml::SequenceValue{ + Yaml::MappingValue{{"index", "0"}, + {"kind", "Semi"}, + {"line", "2"}, + {"column", "2"}, + {"indent", "2"}, + {"spelling", ";"}, + {"has_trailing_space", "true"}}, + Yaml::MappingValue{{"index", "1"}, + {"kind", "Semi"}, + {"line", "5"}, + {"column", "1"}, + {"indent", "1"}, + {"spelling", ";"}, + {"has_trailing_space", "true"}}, + Yaml::MappingValue{{"index", "2"}, + {"kind", "Semi"}, + {"line", "5"}, + {"column", "3"}, + {"indent", "1"}, + {"spelling", ";"}, + {"has_trailing_space", "true"}}, + Yaml::MappingValue{{"index", "3"}, + {"kind", "EndOfFile"}, + {"line", "15"}, + {"column", "1"}, + {"indent", "1"}, + {"spelling", ""}}}}}})); } } // namespace diff --git a/toolchain/testing/file_test.cpp b/toolchain/testing/file_test.cpp index e3f65d64e7fd..696d22387ece 100644 --- a/toolchain/testing/file_test.cpp +++ b/toolchain/testing/file_test.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/VirtualFileSystem.h" #include "testing/file_test/file_test_base.h" #include "toolchain/driver/driver.h" @@ -47,16 +48,25 @@ class ToolchainFileTest : public FileTestBase { } } - auto GetLineNumberReplacement(llvm::ArrayRef filenames) - -> LineNumberReplacement override { + auto GetDefaultFileRE(llvm::ArrayRef filenames) + -> std::optional override { if (component_ == "lex") { - return {.has_file = false, - .pattern = R"(line: (\s*\d+))", - // The `{{{{` becomes `{{`. - .line_formatv = "{{{{ *}}{0}"}; - } else { - return FileTestBase::GetLineNumberReplacement(filenames); + return std::make_optional( + llvm::formatv(R"(^- filename: ({0})$)", llvm::join(filenames, "|"))); } + return FileTestBase::GetDefaultFileRE(filenames); + } + + auto GetLineNumberReplacements(llvm::ArrayRef filenames) + -> llvm::SmallVector override { + auto replacements = FileTestBase::GetLineNumberReplacements(filenames); + if (component_ == "lex") { + replacements.push_back({.has_file = false, + .re = std::make_shared(R"(line: (\s*\d+))"), + // The `{{{{` becomes `{{`. + .line_formatv = "{{{{ *}}{0}"}); + } + return replacements; } auto DoExtraCheckReplacements(std::string& check_line) -> void override {