| // Copyright 2017-2020 The Verible Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "common/formatting/format_token.h" | |
| #include <sstream> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/strings/string_view.h" | |
| #include "common/formatting/unwrapped_line.h" | |
| #include "common/formatting/unwrapped_line_test_utils.h" | |
| #include "common/text/token_info.h" | |
| #include "common/util/range.h" | |
| #include "gtest/gtest.h" | |
| namespace verible { | |
| namespace { | |
| // Tests the string representation of the SpacingOptions enum. | |
| TEST(BreakDecisionTest, StringRep) { | |
| { | |
| std::ostringstream stream; | |
| stream << SpacingOptions::Undecided; | |
| EXPECT_EQ(stream.str(), "undecided"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << SpacingOptions::MustAppend; | |
| EXPECT_EQ(stream.str(), "must-append"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << SpacingOptions::MustWrap; | |
| EXPECT_EQ(stream.str(), "must-wrap"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << SpacingOptions::Preserve; | |
| EXPECT_EQ(stream.str(), "preserve"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << SpacingOptions::AppendAligned; | |
| EXPECT_EQ(stream.str(), "append-aligned"); | |
| } | |
| } | |
| // Tests the string representation of the GroupBalancing enum. | |
| TEST(GroupBalancingTest, StringRep) { | |
| { | |
| std::ostringstream stream; | |
| stream << GroupBalancing::None; | |
| EXPECT_EQ(stream.str(), "none"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << GroupBalancing::Open; | |
| EXPECT_EQ(stream.str(), "open"); | |
| } | |
| { | |
| std::ostringstream stream; | |
| stream << GroupBalancing::Close; | |
| EXPECT_EQ(stream.str(), "close"); | |
| } | |
| } | |
| // Test that InterTokenInfo initializes to reasonable values. | |
| TEST(InterTokenInfoTest, Initialization) { | |
| InterTokenInfo info; | |
| EXPECT_EQ(0, info.spaces_required); | |
| EXPECT_EQ(0, info.break_penalty); | |
| EXPECT_EQ(info.break_decision, SpacingOptions::Undecided); | |
| } | |
| // Test for InterTokenInfo equality. | |
| TEST(InterTokenInfoTest, Equality) { | |
| InterTokenInfo info1, info2; | |
| EXPECT_EQ(info1, info1); | |
| EXPECT_EQ(info1, info2); | |
| } | |
| // Test for InterTokenInfo inequality. | |
| TEST(InterTokenInfoTest, Inequality) { | |
| InterTokenInfo info1; | |
| { | |
| InterTokenInfo info2; | |
| info2.spaces_required = 66; | |
| EXPECT_NE(info1, info2); | |
| } | |
| { | |
| InterTokenInfo info3; | |
| info3.break_penalty = 44; | |
| EXPECT_NE(info1, info3); | |
| } | |
| { | |
| InterTokenInfo info4; | |
| info4.break_decision = SpacingOptions::MustAppend; | |
| EXPECT_NE(info1, info4); | |
| } | |
| { | |
| InterTokenInfo info5; | |
| info5.break_decision = SpacingOptions::MustWrap; | |
| EXPECT_NE(info1, info5); | |
| } | |
| } | |
| // Test that PreFormatToken initializes correctly. | |
| TEST(PreFormatTokenTest, DefaultCtor) { | |
| PreFormatToken ftoken; | |
| EXPECT_EQ(ftoken.token, nullptr); | |
| } | |
| // Test that vector of PreFormatToken is resizable. | |
| TEST(PreFormatTokenTest, VectorResizeable) { | |
| std::vector<PreFormatToken> ftokens; | |
| ftokens.resize(4); | |
| EXPECT_EQ(ftokens.size(), 4); | |
| } | |
| TEST(PreFormatTokenTest, OriginalLeadingSpaces) { | |
| const absl::string_view text("abcdefgh"); | |
| const TokenInfo tok1(1, text.substr(1, 3)), tok2(2, text.substr(5, 2)); | |
| { | |
| PreFormatToken p1(&tok1), p2(&tok2); | |
| // original spacing not set | |
| EXPECT_TRUE(p1.OriginalLeadingSpaces().empty()); | |
| EXPECT_TRUE(p2.OriginalLeadingSpaces().empty()); | |
| } | |
| { | |
| PreFormatToken p1(&tok1), p2(&tok2); | |
| // set original spacing | |
| p1.before.preserved_space_start = text.begin(); | |
| p2.before.preserved_space_start = tok1.text().end(); | |
| EXPECT_TRUE(BoundsEqual(p1.OriginalLeadingSpaces(), text.substr(0, 1))); | |
| EXPECT_TRUE(BoundsEqual(p2.OriginalLeadingSpaces(), text.substr(4, 1))); | |
| } | |
| } | |
| TEST(PreFormatTokenTest, ExcessSpacesNoNewline) { | |
| const absl::string_view text("abcdefgh"); | |
| const TokenInfo tok(1, text.substr(1, 3)); | |
| PreFormatToken p(&tok); // before.preserved_space_start == nullptr | |
| EXPECT_EQ(p.ExcessSpaces(), 0); | |
| p.before.preserved_space_start = text.begin(); | |
| p.before.spaces_required = 0; | |
| EXPECT_EQ(p.ExcessSpaces(), 1); | |
| p.before.spaces_required = 2; | |
| EXPECT_EQ(p.ExcessSpaces(), -1); | |
| } | |
| TEST(PreFormatTokenTest, ExcessSpacesNewline) { | |
| const absl::string_view text("\nbcdefgh"); | |
| const TokenInfo tok(1, text.substr(1, 3)); | |
| PreFormatToken p(&tok); // before.preserved_space_start == nullptr | |
| EXPECT_EQ(p.ExcessSpaces(), 0); | |
| p.before.preserved_space_start = text.begin(); | |
| p.before.spaces_required = 0; | |
| EXPECT_EQ(p.ExcessSpaces(), 0); | |
| p.before.spaces_required = 2; | |
| EXPECT_EQ(p.ExcessSpaces(), 0); | |
| } | |
| TEST(PreFormatTokenTest, LeadingSpacesLength) { | |
| const absl::string_view text("abcdefgh"); | |
| const TokenInfo tok1(1, text.substr(1, 3)), tok2(2, text.substr(5, 2)); | |
| { | |
| PreFormatToken p1(&tok1), p2(&tok2); | |
| p1.before.spaces_required = 0; | |
| p2.before.spaces_required = 3; | |
| // original spacing not set | |
| EXPECT_EQ(p1.LeadingSpacesLength(), 0); | |
| EXPECT_EQ(p2.LeadingSpacesLength(), 3); | |
| } | |
| { | |
| PreFormatToken p1(&tok1), p2(&tok2); | |
| // set original spacing, but not preserve mode. | |
| p1.before.preserved_space_start = text.begin(); | |
| p1.before.break_decision = SpacingOptions::Undecided; | |
| p1.before.spaces_required = 1; | |
| p2.before.preserved_space_start = tok1.text().end(); | |
| p2.before.break_decision = SpacingOptions::Undecided; | |
| p2.before.spaces_required = 2; | |
| EXPECT_EQ(p1.LeadingSpacesLength(), 1); | |
| EXPECT_EQ(p2.LeadingSpacesLength(), 2); | |
| } | |
| { | |
| PreFormatToken p1(&tok1), p2(&tok2); | |
| // set original spacing and preserve mode. | |
| p1.before.preserved_space_start = text.begin(); | |
| p1.before.break_decision = SpacingOptions::Preserve; | |
| p1.before.spaces_required = 2; | |
| p2.before.preserved_space_start = tok1.text().end(); | |
| p2.before.break_decision = SpacingOptions::Preserve; | |
| p2.before.spaces_required = 4; | |
| EXPECT_EQ(p1.LeadingSpacesLength(), 1); // "a" | |
| EXPECT_EQ(p2.LeadingSpacesLength(), 1); // "d" | |
| } | |
| } | |
| class ConnectPreFormatTokensPreservedSpaceStartsTest | |
| : public ::testing::Test, | |
| public UnwrappedLineMemoryHandler {}; | |
| TEST_F(ConnectPreFormatTokensPreservedSpaceStartsTest, Empty) { | |
| constexpr absl::string_view text(""); | |
| CreateTokenInfosExternalStringBuffer({}); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| EXPECT_TRUE(pre_format_tokens_.empty()); | |
| } | |
| TEST_F(ConnectPreFormatTokensPreservedSpaceStartsTest, OneToken) { | |
| constexpr absl::string_view text("xyz"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 3)}, | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| EXPECT_TRUE(BoundsEqual(pre_format_tokens_.front().OriginalLeadingSpaces(), | |
| text.substr(0, 0))); | |
| } | |
| TEST_F(ConnectPreFormatTokensPreservedSpaceStartsTest, OneTokenLeadingSpace) { | |
| constexpr absl::string_view text(" xyz"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(2, 3)}, // "xyz" | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| EXPECT_TRUE(BoundsEqual(pre_format_tokens_.front().OriginalLeadingSpaces(), | |
| text.substr(0, 2))); // " " | |
| } | |
| TEST_F(ConnectPreFormatTokensPreservedSpaceStartsTest, MultipleTokens) { | |
| constexpr absl::string_view text(" xyz\t\t\nabc"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(2, 3)}, // "xyz" | |
| {2, text.substr(8, 3)}, // "abc" | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| EXPECT_TRUE(BoundsEqual(pre_format_tokens_.front().OriginalLeadingSpaces(), | |
| text.substr(0, 2))); // " " | |
| EXPECT_TRUE(BoundsEqual(pre_format_tokens_.back().OriginalLeadingSpaces(), | |
| text.substr(5, 3))); // "\t\t\n" | |
| } | |
| class PreserveSpacesOnDisabledTokenRangesTest | |
| : public ::testing::Test, | |
| public UnwrappedLineMemoryHandler {}; | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, DisableNone) { | |
| constexpr absl::string_view text("a b c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ByteOffsetSet disabled_bytes; // empty | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| for (const auto& ftoken : pre_format_tokens_) { | |
| EXPECT_EQ(ftoken.before.break_decision, SpacingOptions::Undecided); | |
| } | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, DisableSpaceBeforeText) { | |
| constexpr absl::string_view text("a b c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ByteOffsetSet disabled_bytes{{5, 7}}; // substring " d" | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[3].before.break_decision, | |
| SpacingOptions::Preserve); // before "d" | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, DisableSpaceAfterText) { | |
| constexpr absl::string_view text("a b c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ByteOffsetSet disabled_bytes{{4, 6}}; // substring "c " | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Preserve); // "c" | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, DisableSpanningTwoTokens) { | |
| constexpr absl::string_view text("a b c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ByteOffsetSet disabled_bytes{{4, 7}}; // substring "c d" | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(ftokens[2].before.break_decision, | |
| SpacingOptions::Preserve); // before "c" | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, DisableSpanningMustWrap) { | |
| constexpr absl::string_view text("a b c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| ByteOffsetSet disabled_bytes{{2, 5}}; // substring "b c" | |
| pre_format_tokens_[2].before.break_decision = SpacingOptions::MustWrap; | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_TRUE( | |
| BoundsEqual(ftokens[0].OriginalLeadingSpaces(), text.substr(0, 0))); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_TRUE( | |
| BoundsEqual(ftokens[1].OriginalLeadingSpaces(), text.substr(1, 1))); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_TRUE( | |
| BoundsEqual(ftokens[2].OriginalLeadingSpaces(), text.substr(3, 1))); | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_TRUE( | |
| BoundsEqual(ftokens[3].OriginalLeadingSpaces(), text.substr(5, 1))); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_TRUE( | |
| BoundsEqual(ftokens[4].OriginalLeadingSpaces(), text.substr(7, 1))); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, | |
| DisableSpanningMustWrapWithNewline) { | |
| constexpr absl::string_view text("a\nb\nc d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| ByteOffsetSet disabled_bytes{{2, 5}}; // substring "b\nc" | |
| pre_format_tokens_[1].before.break_decision = SpacingOptions::MustWrap; | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| auto indices = [&text](const absl::string_view& range) { | |
| return SubRangeIndices(range, text); | |
| }; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[0].OriginalLeadingSpaces()), | |
| indices(text.substr(0, 0))); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ( // \n was consumed | |
| indices(ftokens[1].OriginalLeadingSpaces()), indices(text.substr(2, 0))); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(indices(ftokens[2].OriginalLeadingSpaces()), | |
| indices(text.substr(3, 1))); | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[3].OriginalLeadingSpaces()), | |
| indices(text.substr(5, 1))); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[4].OriginalLeadingSpaces()), | |
| indices(text.substr(7, 1))); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, | |
| DisableSpanningMustWrapWithNewlineKeepIndentation) { | |
| constexpr absl::string_view text("a\n b\n c d e"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(4, 1)}, | |
| {1, text.substr(8, 1)}, | |
| {3, text.substr(10, 1)}, | |
| {2, text.substr(12, 1)}, | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| ByteOffsetSet disabled_bytes{{4, 9}}; // substring "b\n c" | |
| pre_format_tokens_[1].before.break_decision = SpacingOptions::MustWrap; | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| auto indices = [&text](const absl::string_view& range) { | |
| return SubRangeIndices(range, text); | |
| }; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[0].OriginalLeadingSpaces()), | |
| indices(text.substr(0, 0))); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ( // \n was consumed, " " remains | |
| indices(ftokens[1].OriginalLeadingSpaces()), indices(text.substr(2, 2))); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(indices(ftokens[2].OriginalLeadingSpaces()), | |
| indices(text.substr(5, 3))); | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[3].OriginalLeadingSpaces()), | |
| indices(text.substr(9, 1))); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[4].OriginalLeadingSpaces()), | |
| indices(text.substr(11, 1))); | |
| } | |
| TEST_F(PreserveSpacesOnDisabledTokenRangesTest, MultipleOffsetRanges) { | |
| constexpr absl::string_view text("a\nb\nc d e ff gg"); | |
| CreateTokenInfosExternalStringBuffer({ | |
| {1, text.substr(0, 1)}, | |
| {2, text.substr(2, 1)}, | |
| {1, text.substr(4, 1)}, | |
| {3, text.substr(6, 1)}, | |
| {2, text.substr(8, 1)}, | |
| {2, text.substr(10, 2)}, | |
| {2, text.substr(13, 2)}, | |
| }); | |
| ConnectPreFormatTokensPreservedSpaceStarts(text.begin(), &pre_format_tokens_); | |
| ByteOffsetSet disabled_bytes{{2, 5}, {8, 12}}; // substrings "b\nc", "e ff" | |
| pre_format_tokens_[1].before.break_decision = SpacingOptions::MustWrap; | |
| PreserveSpacesOnDisabledTokenRanges(&pre_format_tokens_, disabled_bytes, | |
| text); | |
| const auto& ftokens = pre_format_tokens_; | |
| auto indices = [&text](const absl::string_view& range) { | |
| return SubRangeIndices(range, text); | |
| }; | |
| EXPECT_EQ(ftokens[0].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[0].OriginalLeadingSpaces()), | |
| indices(text.substr(0, 0))); | |
| EXPECT_EQ(ftokens[1].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ( // \n was consumed | |
| indices(ftokens[1].OriginalLeadingSpaces()), indices(text.substr(2, 0))); | |
| EXPECT_EQ(ftokens[2].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(indices(ftokens[2].OriginalLeadingSpaces()), | |
| indices(text.substr(3, 1))); | |
| EXPECT_EQ(ftokens[3].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[3].OriginalLeadingSpaces()), | |
| indices(text.substr(5, 1))); | |
| EXPECT_EQ(ftokens[4].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(indices(ftokens[4].OriginalLeadingSpaces()), | |
| indices(text.substr(7, 1))); | |
| EXPECT_EQ(ftokens[5].before.break_decision, SpacingOptions::Preserve); | |
| EXPECT_EQ(indices(ftokens[5].OriginalLeadingSpaces()), | |
| indices(text.substr(9, 1))); | |
| EXPECT_EQ(ftokens[6].before.break_decision, SpacingOptions::Undecided); | |
| EXPECT_EQ(indices(ftokens[6].OriginalLeadingSpaces()), | |
| indices(text.substr(12, 1))); | |
| } | |
| // Test that FormattedText prints correctly. | |
| TEST(FormattedTokenTest, FormattedText) { | |
| TokenInfo token(0, "roobar"); | |
| PreFormatToken ptoken(&token); | |
| { | |
| FormattedToken ftoken(ptoken); | |
| std::ostringstream stream; | |
| stream << ftoken; | |
| EXPECT_EQ("roobar", stream.str()); | |
| } | |
| { | |
| FormattedToken ftoken(ptoken); | |
| ftoken.before.spaces = 3; | |
| std::ostringstream stream; | |
| stream << ftoken; | |
| EXPECT_EQ(" roobar", stream.str()); | |
| } | |
| { | |
| FormattedToken ftoken(ptoken); | |
| ftoken.before.action = SpacingDecision::Wrap; | |
| std::ostringstream stream; | |
| stream << ftoken; | |
| EXPECT_EQ("\nroobar", stream.str()); | |
| } | |
| { | |
| FormattedToken ftoken(ptoken); | |
| ftoken.before.action = SpacingDecision::Wrap; | |
| ftoken.before.spaces = 2; | |
| std::ostringstream stream; | |
| stream << ftoken; | |
| EXPECT_EQ("\n roobar", stream.str()); | |
| } | |
| } | |
| TEST(FormattedTokenTest, OriginalLeadingSpaces) { | |
| const absl::string_view text("abcdefgh"); | |
| const TokenInfo tok1(1, text.substr(1, 3)), tok2(2, text.substr(5, 2)); | |
| const PreFormatToken p1(&tok1), p2(&tok2); | |
| { | |
| FormattedToken ft1(p1), ft2(p2); | |
| // original spacing not set | |
| EXPECT_TRUE(ft1.OriginalLeadingSpaces().empty()); | |
| EXPECT_TRUE(ft2.OriginalLeadingSpaces().empty()); | |
| } | |
| { | |
| FormattedToken ft1(p1), ft2(p2); | |
| // set original spacing | |
| ft1.before.preserved_space_start = text.begin(); | |
| ft2.before.preserved_space_start = tok1.text().end(); | |
| EXPECT_TRUE(BoundsEqual(ft1.OriginalLeadingSpaces(), text.substr(0, 1))); | |
| EXPECT_TRUE(BoundsEqual(ft2.OriginalLeadingSpaces(), text.substr(4, 1))); | |
| } | |
| } | |
| TEST(FormattedTokenTest, PreservedSpaces) { | |
| const absl::string_view text("abcdefgh"); | |
| const TokenInfo tok1(1, text.substr(1, 3)), tok2(2, text.substr(5, 2)); | |
| const PreFormatToken p1(&tok1), p2(&tok2); | |
| { | |
| FormattedToken ft1(p1), ft2(p2); | |
| ft1.before.spaces = 2; | |
| ft2.before.spaces = 3; | |
| std::ostringstream stream; | |
| stream << ft1 << ft2; | |
| EXPECT_EQ(stream.str(), " bcd fg"); | |
| } | |
| { | |
| FormattedToken ft1(p1), ft2(p2); | |
| ft1.before.spaces = 2; // ignored | |
| ft1.before.action = SpacingDecision::Preserve; | |
| ft2.before.spaces = 3; // ignored | |
| ft2.before.action = SpacingDecision::Preserve; | |
| // preserved_space_start takes precedence over the other attributes | |
| ft1.before.preserved_space_start = text.begin(); | |
| ft2.before.preserved_space_start = tok1.text().end(); | |
| std::ostringstream stream; | |
| stream << ft1 << ft2; | |
| // For testing purposes, it doesn't matter what text was in the gap between | |
| // the tokens, need not be space. | |
| EXPECT_EQ(stream.str(), "abcdefg"); | |
| } | |
| } | |
| // Test for InterTokenInfo string representation. | |
| TEST(InterTokenInfoTest, StringRep) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| stream << info; | |
| EXPECT_EQ( | |
| R"str({ | |
| spaces_required: 0 | |
| break_penalty: 0 | |
| break_decision: undecided | |
| preserve_space?: 0 | |
| })str", | |
| stream.str()); | |
| } | |
| TEST(InterTokenInfoTest, CompactNotationUndecided) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| info.break_decision = SpacingOptions::Undecided; | |
| info.spaces_required = 3; | |
| info.break_penalty = 25; | |
| info.CompactNotation(stream); | |
| EXPECT_EQ(stream.str(), "<_3,25>"); | |
| } | |
| TEST(InterTokenInfoTest, CompactNotationMustAppend) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| info.break_decision = SpacingOptions::MustAppend; | |
| info.spaces_required = 2; | |
| info.CompactNotation(stream); | |
| EXPECT_EQ(stream.str(), "<+_2>"); | |
| } | |
| TEST(InterTokenInfoTest, CompactNotationMustWrap) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| info.break_decision = SpacingOptions::MustWrap; | |
| info.CompactNotation(stream); | |
| EXPECT_EQ(stream.str(), "<\\n>"); | |
| } | |
| TEST(InterTokenInfoTest, CompactNotationAppendAligned) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| info.break_decision = SpacingOptions::AppendAligned; | |
| info.spaces_required = 3; | |
| info.CompactNotation(stream); | |
| EXPECT_EQ(stream.str(), "<|_3>"); | |
| } | |
| TEST(InterTokenInfoTest, CompactNotationPreserve) { | |
| std::ostringstream stream; | |
| InterTokenInfo info; | |
| info.break_decision = SpacingOptions::Preserve; | |
| info.CompactNotation(stream); | |
| EXPECT_EQ(stream.str(), "<pre>"); | |
| } | |
| // Test that Length() returns the correct distance between L and R location of | |
| // an Empty TokenInfo | |
| TEST(PreFormatTokenTest, FormatTokenLengthEmptyTest) { | |
| // Empty | |
| TokenInfo empty_token_info(0, ""); | |
| PreFormatToken empty_format_token(&empty_token_info); | |
| EXPECT_EQ(0, empty_format_token.Length()); | |
| } | |
| // Test that Length() returns the correct distance between L and R location of | |
| // TokenInfo | |
| TEST(PreFormatTokenTest, FormatTokenLengthTest) { | |
| // Valid Location | |
| TokenInfo token_info(1, "Hello World!"); | |
| PreFormatToken format_token(&token_info); | |
| EXPECT_EQ(12, format_token.Length()); | |
| } | |
| // Test for PreFormatToken's string representation. | |
| TEST(PreFormatTokenTest, StringRep) { | |
| TokenInfo token_info(1, "Hello"); | |
| PreFormatToken format_token(&token_info); | |
| std::string str(format_token.ToString()); | |
| absl::string_view strv(str); | |
| EXPECT_NE(strv.find("TokenInfo:"), strv.npos); | |
| EXPECT_NE(strv.find("before:"), strv.npos); | |
| EXPECT_NE(strv.find("break_decision:"), strv.npos); | |
| } | |
| } // namespace | |
| } // namespace verible |