blob: b957a34bb7d4f0d4838c5c3865917091691ed1f5 [file] [log] [blame]
// Copyright 2017-2021 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/layout_optimizer.h"
#include <sstream>
#include <string>
#include <vector>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "common/formatting/basic_format_style.h"
#include "common/formatting/layout_optimizer_internal.h"
#include "common/formatting/token_partition_tree.h"
#include "common/formatting/token_partition_tree_test_utils.h"
#include "common/formatting/unwrapped_line.h"
#include "common/formatting/unwrapped_line_test_utils.h"
#include "common/strings/split.h"
#include "common/util/spacer.h"
#include "gtest/gtest.h"
namespace verible {
namespace {
template <typename T>
std::string ToString(const T& value) {
std::ostringstream s;
s << value;
return s.str();
}
std::ostream& PrintIndented(std::ostream& stream, absl::string_view str,
int indentation) {
for (const auto& line : verible::SplitLinesKeepLineTerminator(str))
stream << verible::Spacer(indentation) << line;
return stream;
}
template <typename Value>
void PrintInvalidValueMessage(std::ostream& stream,
absl::string_view value_name, const Value& actual,
const Value& expected, int indentation = 0,
bool multiline = false) {
using ::testing::PrintToString;
using verible::Spacer;
stream << Spacer(indentation) << "invalid " << value_name << ":\n";
if (multiline) {
stream << Spacer(indentation) << " actual:\n";
PrintIndented(stream, PrintToString(actual), indentation + 4) << "\n";
stream << Spacer(indentation) << " expected:\n";
PrintIndented(stream, PrintToString(expected), indentation + 4) << "\n";
} else {
stream << Spacer(indentation) << " actual: " << actual << "\n"
<< Spacer(indentation) << " expected: " << expected << "\n\n";
}
}
void ExpectLayoutFunctionsEqual(const LayoutFunction& actual,
const LayoutFunction& expected, int line_no) {
using ::testing::PrintToString;
std::ostringstream msg;
if (actual.size() != expected.size()) {
PrintInvalidValueMessage(msg, "size()", actual.size(), expected.size());
}
for (int i = 0; i < std::min(actual.size(), expected.size()); ++i) {
std::ostringstream segment_msg;
if (actual[i].column != expected[i].column) {
PrintInvalidValueMessage(segment_msg, "column", actual[i].column,
expected[i].column, 2);
}
if (actual[i].intercept != expected[i].intercept) {
PrintInvalidValueMessage(segment_msg, "intercept", actual[i].intercept,
expected[i].intercept, 2);
}
if (actual[i].gradient != expected[i].gradient) {
PrintInvalidValueMessage(segment_msg, "gradient", actual[i].gradient,
expected[i].gradient, 2);
}
if (actual[i].span != expected[i].span) {
PrintInvalidValueMessage(segment_msg, "span", actual[i].span,
expected[i].span, 2);
}
auto layout_diff = DeepEqual(actual[i].layout, expected[i].layout);
if (layout_diff.left != nullptr) {
PrintInvalidValueMessage(segment_msg, "layout (fragment)",
*layout_diff.left, *layout_diff.right, 2, true);
}
if (auto str = segment_msg.str(); !str.empty())
msg << "segment[" << i << "]:\n" << str << "\n";
}
if (const auto str = msg.str(); !str.empty()) {
ADD_FAILURE_AT(__FILE__, line_no) << "LayoutFunctions differ.\nActual:\n"
<< actual << "\nExpected:\n"
<< expected << "\n\nDetails:\n\n"
<< str;
} else {
SUCCEED();
}
}
BasicFormatStyle CreateStyle() {
BasicFormatStyle style;
// Hardcode everything to prevent failures when defaults change.
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.column_limit = 40;
style.over_column_limit_penalty = 100;
style.line_break_penalty = 2;
return style;
}
TEST(LayoutTypeTest, ToString) {
EXPECT_EQ(ToString(LayoutType::kLine), "line");
EXPECT_EQ(ToString(LayoutType::kJuxtaposition), "juxtaposition");
EXPECT_EQ(ToString(LayoutType::kStack), "stack");
EXPECT_EQ(ToString(static_cast<LayoutType>(-1)), "???");
}
bool TokenRangeEqual(const UnwrappedLine& left, const UnwrappedLine& right) {
return left.TokensRange() == right.TokensRange();
}
class LayoutTest : public ::testing::Test, public UnwrappedLineMemoryHandler {
public:
LayoutTest()
: sample_(
"short_line\n"
"loooooong_line"),
tokens_(absl::StrSplit(sample_, '\n')) {
for (const auto token : tokens_) {
ftokens_.emplace_back(TokenInfo{1, token});
}
CreateTokenInfos(ftokens_);
}
protected:
const std::string sample_;
const std::vector<absl::string_view> tokens_;
std::vector<TokenInfo> ftokens_;
};
TEST_F(LayoutTest, LineLayoutItemToString) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine short_line(0, begin);
short_line.SpanUpToToken(begin + 1);
UnwrappedLine long_line(0, begin + 1);
long_line.SpanUpToToken(begin + 2);
UnwrappedLine empty_line(0, begin);
pre_format_tokens_[0].before.spaces_required = 1;
pre_format_tokens_[1].before.break_decision = SpacingOptions::MustWrap;
{
LayoutItem item(short_line, 0);
EXPECT_EQ(ToString(item),
"[ short_line ], length: 10, indentation: 0, spacing: 1, must "
"wrap: no");
}
{
LayoutItem item(short_line, 3);
EXPECT_EQ(ToString(item),
"[ short_line ], length: 10, indentation: 3, spacing: 1, must "
"wrap: no");
}
{
LayoutItem item(long_line, 5);
EXPECT_EQ(
ToString(item),
"[ loooooong_line ], length: 14, indentation: 5, spacing: 0, must "
"wrap: YES");
}
{
LayoutItem item(long_line, 7);
EXPECT_EQ(
ToString(item),
"[ loooooong_line ], length: 14, indentation: 7, spacing: 0, must "
"wrap: YES");
}
{
LayoutItem item(empty_line, 11);
EXPECT_EQ(ToString(item),
"[ ], length: 0, indentation: 11, spacing: 0, must wrap: no");
}
{
LayoutItem item(empty_line, 13);
EXPECT_EQ(ToString(item),
"[ ], length: 0, indentation: 13, spacing: 0, must wrap: no");
}
}
TEST_F(LayoutTest, JuxtapositionLayoutItemToString) {
{
LayoutItem item(LayoutType::kJuxtaposition, 3, false, 5);
EXPECT_EQ(ToString(item),
"[<juxtaposition>], indentation: 5, spacing: 3, must wrap: no");
}
{
LayoutItem item(LayoutType::kJuxtaposition, 7, true, 11);
EXPECT_EQ(ToString(item),
"[<juxtaposition>], indentation: 11, spacing: 7, must wrap: YES");
}
}
TEST_F(LayoutTest, StackLayoutItemToString) {
{
LayoutItem item(LayoutType::kStack, 3, false, 5);
EXPECT_EQ(ToString(item),
"[<stack>], indentation: 5, spacing: 3, must wrap: no");
}
{
LayoutItem item(LayoutType::kStack, 7, true, 11);
EXPECT_EQ(ToString(item),
"[<stack>], indentation: 11, spacing: 7, must wrap: YES");
}
}
TEST_F(LayoutTest, TokensRange) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine short_line(0, begin);
short_line.SpanUpToToken(begin + 1);
LayoutItem layout_short(short_line);
const auto tokens = layout_short.TokensRange();
EXPECT_EQ(tokens.begin(), short_line.TokensRange().begin());
EXPECT_EQ(tokens.end(), short_line.TokensRange().end());
}
TEST_F(LayoutTest, LineLayout) {
const auto begin = pre_format_tokens_.begin();
{
UnwrappedLine short_line(0, begin);
short_line.SpanUpToToken(begin + 1);
LayoutItem layout(short_line);
EXPECT_EQ(layout.Type(), LayoutType::kLine);
EXPECT_EQ(layout.IndentationSpaces(), 0);
EXPECT_EQ(layout.SpacesBefore(), 0);
EXPECT_EQ(layout.MustWrap(), false);
EXPECT_EQ(layout.Length(), 10);
EXPECT_EQ(layout.Text(), "short_line");
EXPECT_EQ(layout.TokensRange().begin(), begin);
EXPECT_EQ(layout.TokensRange().end(), begin + 1);
}
{
UnwrappedLine empty_line(0, begin);
LayoutItem layout(empty_line);
EXPECT_EQ(layout.Type(), LayoutType::kLine);
EXPECT_EQ(layout.IndentationSpaces(), 0);
EXPECT_EQ(layout.SpacesBefore(), 0);
EXPECT_EQ(layout.MustWrap(), false);
EXPECT_EQ(layout.Length(), 0);
EXPECT_EQ(layout.Text(), "");
EXPECT_EQ(layout.TokensRange().begin(), begin);
EXPECT_EQ(layout.TokensRange().end(), begin);
}
}
TEST_F(LayoutTest, TestHorizontalAndVerticalLayouts) {
const auto spaces_before = 3;
LayoutItem horizontal_layout(LayoutType::kJuxtaposition, spaces_before,
false);
EXPECT_EQ(horizontal_layout.Type(), LayoutType::kJuxtaposition);
EXPECT_EQ(horizontal_layout.SpacesBefore(), spaces_before);
EXPECT_EQ(horizontal_layout.MustWrap(), false);
LayoutItem vertical_layout(LayoutType::kStack, spaces_before, true);
EXPECT_EQ(vertical_layout.Type(), LayoutType::kStack);
EXPECT_EQ(vertical_layout.SpacesBefore(), spaces_before);
EXPECT_EQ(vertical_layout.MustWrap(), true);
}
class LayoutFunctionTest : public ::testing::Test {
public:
LayoutFunctionTest()
: layout_function_(LayoutFunction{{0, layout_, 10, 101.0F, 11},
{1, layout_, 20, 202.0F, 22},
{2, layout_, 30, 303.0F, 33},
{3, layout_, 40, 404.0F, 44},
{40, layout_, 50, 505.0F, 55},
{50, layout_, 60, 606.0F, 66}}),
const_layout_function_(layout_function_) {}
protected:
static const LayoutTree layout_;
LayoutFunction layout_function_;
const LayoutFunction const_layout_function_;
};
const LayoutTree LayoutFunctionTest::layout_ =
LayoutTree(LayoutItem(LayoutType::kLine, 0, false));
TEST_F(LayoutFunctionTest, LayoutFunctionSegmentToString) {
EXPECT_EQ(
ToString(layout_function_[0]),
"[ 0] (101.000 + 11*x), span: 10, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must wrap: no) }");
EXPECT_EQ(
ToString(layout_function_[5]),
"[ 50] (606.000 + 66*x), span: 60, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must wrap: no) }");
}
TEST_F(LayoutFunctionTest, LayoutFunctionToString) {
EXPECT_EQ(ToString(layout_function_),
"{\n"
" [ 0] ( 101.000 + 11*x), span: 10, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
" [ 1] ( 202.000 + 22*x), span: 20, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
" [ 2] ( 303.000 + 33*x), span: 30, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
" [ 3] ( 404.000 + 44*x), span: 40, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
" [ 40] ( 505.000 + 55*x), span: 50, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
" [ 50] ( 606.000 + 66*x), span: 60, layout:\n"
" { ([ ], length: 0, indentation: 0, spacing: 0, must "
"wrap: no) }\n"
"}");
EXPECT_EQ(ToString(LayoutFunction{}), "{}");
}
TEST_F(LayoutFunctionTest, Size) {
EXPECT_EQ(layout_function_.size(), 6);
EXPECT_FALSE(layout_function_.empty());
EXPECT_EQ(const_layout_function_.size(), 6);
EXPECT_FALSE(const_layout_function_.empty());
LayoutFunction empty_layout_function{};
EXPECT_EQ(empty_layout_function.size(), 0);
EXPECT_TRUE(empty_layout_function.empty());
}
TEST_F(LayoutFunctionTest, Iteration) {
static const auto columns = {0, 1, 2, 3, 40, 50};
{
auto it = layout_function_.begin();
EXPECT_NE(it, layout_function_.end());
EXPECT_EQ(it + 6, layout_function_.end());
EXPECT_EQ(it->column, 0);
auto column_it = columns.begin();
for (auto& segment : layout_function_) {
EXPECT_EQ(segment.column, *column_it);
EXPECT_NE(column_it, columns.end());
++column_it;
}
EXPECT_EQ(column_it, columns.end());
}
{
auto it = const_layout_function_.begin();
EXPECT_NE(it, const_layout_function_.end());
EXPECT_EQ(it + 6, const_layout_function_.end());
EXPECT_EQ(it->column, 0);
auto column_it = columns.begin();
for (auto& segment : const_layout_function_) {
EXPECT_EQ(segment.column, *column_it);
EXPECT_NE(column_it, columns.end());
++column_it;
}
EXPECT_EQ(column_it, columns.end());
}
{
LayoutFunction empty_layout_function{};
auto it = empty_layout_function.begin();
EXPECT_EQ(it, empty_layout_function.end());
for (auto& segment [[maybe_unused]] : empty_layout_function) {
EXPECT_FALSE(true);
}
}
}
TEST_F(LayoutFunctionTest, AtOrToTheLeftOf) {
{
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(0), layout_function_.begin());
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(1),
layout_function_.begin() + 1);
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(2),
layout_function_.begin() + 2);
for (int i = 3; i < 40; ++i) {
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(i),
layout_function_.begin() + 3)
<< "i: " << i;
}
for (int i = 40; i < 50; ++i) {
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(i),
layout_function_.begin() + 4)
<< "i: " << i;
}
for (int i = 50; i < 70; ++i) {
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(i),
layout_function_.begin() + 5)
<< "i: " << i;
}
EXPECT_EQ(layout_function_.AtOrToTheLeftOf(std::numeric_limits<int>::max()),
layout_function_.begin() + 5);
}
{
LayoutFunction empty_layout_function{};
EXPECT_EQ(empty_layout_function.AtOrToTheLeftOf(0),
empty_layout_function.end());
EXPECT_EQ(empty_layout_function.AtOrToTheLeftOf(1),
empty_layout_function.end());
EXPECT_EQ(
empty_layout_function.AtOrToTheLeftOf(std::numeric_limits<int>::max()),
empty_layout_function.end());
}
{
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(0),
const_layout_function_.begin());
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(1),
const_layout_function_.begin() + 1);
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(2),
const_layout_function_.begin() + 2);
for (int i = 3; i < 40; ++i) {
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(i),
const_layout_function_.begin() + 3)
<< "i: " << i;
}
for (int i = 40; i < 50; ++i) {
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(i),
const_layout_function_.begin() + 4)
<< "i: " << i;
}
for (int i = 50; i < 70; ++i) {
EXPECT_EQ(const_layout_function_.AtOrToTheLeftOf(i),
const_layout_function_.begin() + 5)
<< "i: " << i;
}
EXPECT_EQ(
const_layout_function_.AtOrToTheLeftOf(std::numeric_limits<int>::max()),
const_layout_function_.begin() + 5);
}
{
const LayoutFunction empty_layout_function{};
EXPECT_EQ(empty_layout_function.AtOrToTheLeftOf(0),
empty_layout_function.end());
EXPECT_EQ(empty_layout_function.AtOrToTheLeftOf(1),
empty_layout_function.end());
EXPECT_EQ(
empty_layout_function.AtOrToTheLeftOf(std::numeric_limits<int>::max()),
empty_layout_function.end());
}
}
TEST_F(LayoutFunctionTest, Insertion) {
layout_function_.push_back({60, layout_, 1, 6.0F, 6});
ASSERT_EQ(layout_function_.size(), 7);
EXPECT_EQ(layout_function_[6].column, 60);
layout_function_.push_back({70, layout_, 1, 6.0F, 6});
ASSERT_EQ(layout_function_.size(), 8);
EXPECT_EQ(layout_function_[6].column, 60);
EXPECT_EQ(layout_function_[7].column, 70);
for (int i = 0; i < 6; ++i) {
EXPECT_EQ(layout_function_[i].column, const_layout_function_[i].column)
<< "i: " << i;
}
}
TEST_F(LayoutFunctionTest, Subscript) {
EXPECT_EQ(layout_function_[0].column, 0);
EXPECT_EQ(layout_function_[1].column, 1);
EXPECT_EQ(layout_function_[2].column, 2);
EXPECT_EQ(layout_function_[3].column, 3);
EXPECT_EQ(layout_function_[4].column, 40);
EXPECT_EQ(layout_function_[5].column, 50);
layout_function_[5].column += 5;
EXPECT_EQ(layout_function_[5].column, 55);
EXPECT_EQ(const_layout_function_[0].column, 0);
EXPECT_EQ(const_layout_function_[1].column, 1);
EXPECT_EQ(const_layout_function_[2].column, 2);
EXPECT_EQ(const_layout_function_[3].column, 3);
EXPECT_EQ(const_layout_function_[4].column, 40);
EXPECT_EQ(const_layout_function_[5].column, 50);
}
class LayoutFunctionIteratorTest : public LayoutFunctionTest {};
TEST_F(LayoutFunctionIteratorTest, ToString) {
{
std::ostringstream addr;
addr << &layout_function_;
EXPECT_EQ(ToString(layout_function_.begin()),
absl::StrCat(addr.str(), "[0/6]"));
EXPECT_EQ(ToString(layout_function_.end()),
absl::StrCat(addr.str(), "[6/6]"));
}
{
std::ostringstream addr;
addr << &const_layout_function_;
EXPECT_EQ(ToString(const_layout_function_.begin()),
absl::StrCat(addr.str(), "[0/6]"));
EXPECT_EQ(ToString(const_layout_function_.end()),
absl::StrCat(addr.str(), "[6/6]"));
}
{
LayoutFunction empty_layout_function{};
std::ostringstream addr;
addr << &empty_layout_function;
EXPECT_EQ(ToString(empty_layout_function.begin()),
absl::StrCat(addr.str(), "[0/0]"));
EXPECT_EQ(ToString(empty_layout_function.end()),
absl::StrCat(addr.str(), "[0/0]"));
}
}
TEST_F(LayoutFunctionIteratorTest, MoveToKnotAtOrToTheLeftOf) {
{
auto it = layout_function_.begin();
it.MoveToKnotAtOrToTheLeftOf(2);
EXPECT_EQ(it, layout_function_.begin() + 2);
it.MoveToKnotAtOrToTheLeftOf(0);
EXPECT_EQ(it, layout_function_.begin());
it.MoveToKnotAtOrToTheLeftOf(std::numeric_limits<int>::max());
EXPECT_EQ(it, layout_function_.begin() + 5);
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, layout_function_.begin() + 1);
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, layout_function_.begin() + 1);
for (int i = 3; i < 40; ++i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, layout_function_.begin() + 3) << "i: " << i;
}
for (int i = 50; i < 70; ++i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, layout_function_.begin() + 5) << "i: " << i;
}
for (int i = 49; i >= 40; --i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, layout_function_.begin() + 4) << "i: " << i;
}
}
{
LayoutFunction empty_layout_function{};
auto it = empty_layout_function.begin();
it.MoveToKnotAtOrToTheLeftOf(0);
EXPECT_EQ(it, empty_layout_function.end());
it.MoveToKnotAtOrToTheLeftOf(std::numeric_limits<int>::max());
EXPECT_EQ(it, empty_layout_function.end());
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, empty_layout_function.end());
}
{
auto it = const_layout_function_.begin();
it.MoveToKnotAtOrToTheLeftOf(2);
EXPECT_EQ(it, const_layout_function_.begin() + 2);
it.MoveToKnotAtOrToTheLeftOf(0);
EXPECT_EQ(it, const_layout_function_.begin());
it.MoveToKnotAtOrToTheLeftOf(std::numeric_limits<int>::max());
EXPECT_EQ(it, const_layout_function_.begin() + 5);
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, const_layout_function_.begin() + 1);
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, const_layout_function_.begin() + 1);
for (int i = 3; i < 40; ++i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, const_layout_function_.begin() + 3) << "i: " << i;
}
for (int i = 50; i < 70; ++i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, const_layout_function_.begin() + 5) << "i: " << i;
}
for (int i = 49; i >= 40; --i) {
it.MoveToKnotAtOrToTheLeftOf(i);
EXPECT_EQ(it, const_layout_function_.begin() + 4) << "i: " << i;
}
}
{
const LayoutFunction empty_layout_function{};
auto it = empty_layout_function.begin();
it.MoveToKnotAtOrToTheLeftOf(0);
EXPECT_EQ(it, empty_layout_function.end());
it.MoveToKnotAtOrToTheLeftOf(std::numeric_limits<int>::max());
EXPECT_EQ(it, empty_layout_function.end());
it.MoveToKnotAtOrToTheLeftOf(1);
EXPECT_EQ(it, empty_layout_function.end());
}
}
TEST_F(LayoutFunctionIteratorTest, ContainerRelatedMethods) {
{
int i = 0;
auto it = layout_function_.begin();
while (it != layout_function_.end()) {
EXPECT_EQ(&it.Container(), &layout_function_);
EXPECT_EQ(it.Index(), i);
EXPECT_FALSE(it.IsEnd());
++it;
++i;
}
EXPECT_EQ(&it.Container(), &layout_function_);
EXPECT_EQ(it.Index(), i);
EXPECT_TRUE(it.IsEnd());
}
{
int i = 0;
auto it = const_layout_function_.begin();
while (it != const_layout_function_.end()) {
EXPECT_EQ(&it.Container(), &const_layout_function_);
EXPECT_EQ(it.Index(), i);
EXPECT_FALSE(it.IsEnd());
++it;
++i;
}
EXPECT_EQ(&it.Container(), &const_layout_function_);
EXPECT_EQ(it.Index(), i);
EXPECT_TRUE(it.IsEnd());
}
}
class LayoutFunctionFactoryTest : public ::testing::Test,
public UnwrappedLineMemoryHandler {
public:
LayoutFunctionFactoryTest()
: sample_(
// : |10 : |20 : |30 : |40
"This line is short.\n"
"This line is so long that it exceeds column limit.\n"
" Indented line with many spaces .\n"
"One under 40 column limit (39 columns).\n"
"Exactly at 40 column limit (40 columns).\n"
"One over 40 column limit (41 characters).\n"
"One under 30 limit (29 cols).\n"
"Exactly at 30 limit (30 cols).\n"
"One over 30 limit (31 columns).\n"
"10 columns"),
tokens_(
absl::StrSplit(sample_, absl::ByAnyChar(" \n"), absl::SkipEmpty())),
style_(CreateStyle()),
factory_(LayoutFunctionFactory(style_)) {
// Create two sets of tokens
const size_t number_of_tokens_in_set = tokens_.size();
ftokens_.reserve(number_of_tokens_in_set * 2);
for (const auto token : tokens_) ftokens_.emplace_back(TokenInfo{1, token});
for (const auto token : tokens_) ftokens_.emplace_back(TokenInfo{1, token});
CreateTokenInfosExternalStringBuffer(ftokens_);
auto must_wrap_pre_format_tokens = verible::make_range(
pre_format_tokens_.begin(),
pre_format_tokens_.begin() + number_of_tokens_in_set);
auto joinable_pre_format_tokens = verible::make_range(
pre_format_tokens_.begin() + number_of_tokens_in_set,
pre_format_tokens_.end());
// Setup pointers for OriginalLeadingSpaces()
auto must_wrap_token = must_wrap_pre_format_tokens.begin();
auto joinable_token = joinable_pre_format_tokens.begin();
const char* buffer_start = sample_.data();
for (size_t i = 0; i < number_of_tokens_in_set; ++i) {
must_wrap_token->before.preserved_space_start = buffer_start;
joinable_token->before.preserved_space_start = buffer_start;
++must_wrap_token;
++joinable_token;
buffer_start = tokens_[i].end();
}
ProcessTokensAndCreateUnwrappedLines(true, &must_wrap_pre_format_tokens,
&lines_.uwlines_);
ProcessTokensAndCreateUnwrappedLines(false, &joinable_pre_format_tokens,
&joinable_lines_.uwlines_);
}
protected:
using PreFormatTokensIterator = decltype(pre_format_tokens_)::iterator;
static void ProcessTokensAndCreateUnwrappedLines(
bool first_on_line_must_wrap,
verible::iterator_range<PreFormatTokensIterator>* pftokens,
std::vector<UnwrappedLine>* uwlines) {
uwlines->emplace_back(0, pftokens->begin());
for (auto token = pftokens->begin(); token != pftokens->end(); ++token) {
const auto leading_spaces = token->OriginalLeadingSpaces();
// First token in a line
if (absl::StrContains(leading_spaces, '\n')) {
if (first_on_line_must_wrap)
token->before.break_decision = SpacingOptions::MustWrap;
uwlines->back().SpanUpToToken(token);
uwlines->emplace_back(0, token);
}
// Count spaces preceding the token and set spaces_required accordingly
auto last_non_space_offset = leading_spaces.find_last_not_of(' ');
if (last_non_space_offset != absl::string_view::npos) {
token->before.spaces_required =
leading_spaces.size() - 1 - last_non_space_offset;
} else {
token->before.spaces_required = leading_spaces.size();
}
}
uwlines->back().SpanUpToToken(pftokens->end());
}
// Wrapper for UnwrappedLine vector with readable getter for each line
struct NamedUnwrappedLines {
const UnwrappedLine& Short() const { return uwlines_.at(0); }
const UnwrappedLine& Long() const { return uwlines_.at(1); }
const UnwrappedLine& Indented() const { return uwlines_.at(2); }
const UnwrappedLine& OneUnder40Limit() const { return uwlines_.at(3); }
const UnwrappedLine& ExactlyAt40Limit() const { return uwlines_.at(4); }
const UnwrappedLine& OneOver40Limit() const { return uwlines_.at(5); }
const UnwrappedLine& OneUnder30Limit() const { return uwlines_.at(6); }
const UnwrappedLine& ExactlyAt30Limit() const { return uwlines_.at(7); }
const UnwrappedLine& OneOver30Limit() const { return uwlines_.at(8); }
const UnwrappedLine& Exactly10Columns() const { return uwlines_.at(9); }
std::vector<UnwrappedLine> uwlines_;
};
const std::string sample_;
const std::vector<absl::string_view> tokens_;
std::vector<TokenInfo> ftokens_;
NamedUnwrappedLines lines_;
NamedUnwrappedLines joinable_lines_;
const BasicFormatStyle style_;
const LayoutFunctionFactory factory_;
};
TEST_F(LayoutFunctionFactoryTest, Line) {
using LT = LayoutTree;
using LI = LayoutItem;
{
const auto lf = factory_.Line(lines_.Short());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.Short())), 19, 0.0F, 0},
{21, LT(LI(lines_.Short())), 19, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Line(lines_.Long());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.Long())), 50, 1000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Line(lines_.Indented());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.Indented())), 36, 0.0F, 0},
{4, LT(LI(lines_.Indented())), 36, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Line(lines_.OneUnder40Limit());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.OneUnder40Limit())), 39, 0.0F, 0},
{1, LT(LI(lines_.OneUnder40Limit())), 39, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Line(lines_.ExactlyAt40Limit());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.ExactlyAt40Limit())), 40, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Line(lines_.OneOver40Limit());
const auto expected_lf = LayoutFunction{
{0, LT(LI(lines_.OneOver40Limit())), 41, 100.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, Stack) {
using LT = LayoutTree;
using LI = LayoutItem;
{
const auto lf = factory_.Stack({});
const auto expected_lf = LayoutFunction{};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto line = factory_.Line(lines_.Short());
const auto lf = factory_.Stack({line});
const auto& expected_lf = line;
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 2.0F, 0},
{21, expected_layout, 10, 2.0F, 100},
{30, expected_layout, 10, 902.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 19, 2.0F, 0},
{21, expected_layout, 19, 2.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Long()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Long())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 50, 1002.0F, 100},
{21, expected_layout, 50, 3102.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Long()),
factory_.Line(lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(lines_.Long())), //
LT(LI(lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 19, 1002.0F, 100},
{21, expected_layout, 19, 3102.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Long()),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Long())), //
LT(LI(lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 1004.0F, 100},
{21, expected_layout, 10, 3104.0F, 200},
{30, expected_layout, 10, 4904.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Indented()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Indented())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 36, 2.0F, 0},
{4, expected_layout, 36, 2.0F, 100},
{21, expected_layout, 36, 1702.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.OneUnder40Limit()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.OneUnder40Limit())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 39, 2.0F, 0},
{1, expected_layout, 39, 2.0F, 100},
{21, expected_layout, 39, 2002.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.OneOver40Limit()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.OneOver40Limit())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 41, 102.0F, 100},
{21, expected_layout, 41, 2202.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.ExactlyAt40Limit()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.ExactlyAt40Limit())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 40, 2.0F, 100},
{21, expected_layout, 40, 2102.0F, 100},
};
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.OneUnder40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(lines_.OneUnder40Limit())), //
LT(LI(lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 19, 2.0F, 0},
{1, expected_layout, 19, 2.0F, 100},
{21, expected_layout, 19, 2002.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.OneOver40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(lines_.OneOver40Limit())), //
LT(LI(lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 19, 102.0F, 100},
{21, expected_layout, 19, 2202.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.ExactlyAt40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(lines_.ExactlyAt40Limit())), //
LT(LI(lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 40, 2.0F, 100},
{21, expected_layout, 40, 2102.0F, 100},
};
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Long()),
factory_.Stack({
factory_.Line(lines_.Indented()),
factory_.Line(lines_.OneUnder40Limit()),
factory_.Line(lines_.ExactlyAt40Limit()),
factory_.Line(lines_.OneOver40Limit()),
factory_.Line(lines_.Exactly10Columns()),
}),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Long())), //
LT(LI(lines_.Indented())), //
LT(LI(lines_.OneUnder40Limit())), //
LT(LI(lines_.ExactlyAt40Limit())), //
LT(LI(lines_.OneOver40Limit())), //
LT(LI(lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 1112.0F, 300},
{1, expected_layout, 10, 1412.0F, 400},
{4, expected_layout, 10, 2612.0F, 500},
{21, expected_layout, 10, 11112.0F, 600},
{30, expected_layout, 10, 16512.0F, 700},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
// Expected result here is the same as in the test case above
const auto lf = factory_.Stack({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Long()),
factory_.Line(lines_.Indented()),
factory_.Stack({
factory_.Line(lines_.OneUnder40Limit()),
factory_.Line(lines_.ExactlyAt40Limit()),
factory_.Line(lines_.OneOver40Limit()),
}),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Long())), //
LT(LI(lines_.Indented())), //
LT(LI(lines_.OneUnder40Limit())), //
LT(LI(lines_.ExactlyAt40Limit())), //
LT(LI(lines_.OneOver40Limit())), //
LT(LI(lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 1112.0F, 300},
{1, expected_layout, 10, 1412.0F, 400},
{4, expected_layout, 10, 2612.0F, 500},
{21, expected_layout, 10, 11112.0F, 600},
{30, expected_layout, 10, 16512.0F, 700},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, Juxtaposition) {
using LT = LayoutTree;
using LI = LayoutItem;
static const auto kSampleStackLayout =
LT(LI(LayoutType::kStack, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(lines_.Long())), //
LT(LI(lines_.Exactly10Columns())));
// Result of:
// factory_.Stack({
// factory_.Line(lines_.Short()),
// factory_.Line(lines_.Long()),
// factory_.Line(lines_.Exactly10Columns()),
// });
static const auto kSampleStackLayoutFunction = LayoutFunction{
{0, kSampleStackLayout, 10, 1004.0F, 100},
{21, kSampleStackLayout, 10, 3104.0F, 200},
{30, kSampleStackLayout, 10, 4904.0F, 300},
};
{
const auto lf = factory_.Juxtaposition({});
const auto expected_lf = LayoutFunction{};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto line = factory_.Line(lines_.Short());
const auto lf = factory_.Juxtaposition({line});
const auto& expected_lf = line;
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 29, 0.0F, 0},
{11, expected_layout, 29, 0.0F, 100},
{21, expected_layout, 29, 1000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
factory_.Line(joinable_lines_.Exactly10Columns()),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(joinable_lines_.Exactly10Columns())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 39, 0.0F, 0},
{1, expected_layout, 39, 0.0F, 100},
{11, expected_layout, 39, 1000.0F, 100},
{21, expected_layout, 39, 2000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Exactly10Columns()),
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kJuxtaposition, 0, true), //
LT(LI(lines_.Exactly10Columns())), //
LT(LI(joinable_lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 29, 0.0F, 0},
{11, expected_layout, 29, 0.0F, 100},
{30, expected_layout, 29, 1900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
factory_.Line(joinable_lines_.Indented()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(joinable_lines_.Indented())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 63, 2300.0F, 100},
{21, expected_layout, 63, 3600.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Indented()),
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout = LT(LI(LayoutType::kJuxtaposition, 8, true), //
LT(LI(lines_.Indented())), //
LT(LI(joinable_lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 55, 1500.0F, 100},
{4, expected_layout, 55, 1900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
kSampleStackLayoutFunction,
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
kSampleStackLayout, //
LT(LI(joinable_lines_.Short())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 29, 1004.0F, 100},
{11, expected_layout, 29, 2104.0F, 200},
{21, expected_layout, 29, 4104.0F, 300},
{30, expected_layout, 29, 6804.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
kSampleStackLayoutFunction,
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
kSampleStackLayout);
const auto expected_lf = LayoutFunction{
{0, expected_layout, 29, 2904.0F, 100},
{2, expected_layout, 29, 3104.0F, 200},
{11, expected_layout, 29, 4904.0F, 300},
{21, expected_layout, 29, 7904.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition(
{factory_.Line(lines_.OneUnder30Limit()),
factory_.Line(joinable_lines_.Exactly10Columns())});
const auto expected_layout = LT(LI(LayoutType::kJuxtaposition, 0, true), //
LT(LI(lines_.OneUnder30Limit())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 39, 0.0F, 0},
{1, expected_layout, 39, 0.0F, 100},
{11, expected_layout, 39, 1000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition(
{factory_.Line(lines_.ExactlyAt30Limit()),
factory_.Line(joinable_lines_.Exactly10Columns())});
const auto expected_layout = LT(LI(LayoutType::kJuxtaposition, 0, true), //
LT(LI(lines_.ExactlyAt30Limit())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 40, 0.0F, 100},
{10, expected_layout, 40, 1000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition(
{factory_.Line(lines_.OneOver30Limit()),
factory_.Line(joinable_lines_.Exactly10Columns())});
const auto expected_layout = LT(LI(LayoutType::kJuxtaposition, 0, true), //
LT(LI(lines_.OneOver30Limit())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 41, 100.0F, 100},
{9, expected_layout, 41, 1000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
factory_.Line(joinable_lines_.Long()),
factory_.Juxtaposition({
factory_.Line(joinable_lines_.Indented()),
factory_.Line(joinable_lines_.OneUnder40Limit()),
factory_.Line(joinable_lines_.ExactlyAt40Limit()),
factory_.Line(joinable_lines_.OneOver40Limit()),
factory_.Line(joinable_lines_.Exactly10Columns()),
}),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(joinable_lines_.Long())), //
LT(LI(joinable_lines_.Indented())), //
LT(LI(joinable_lines_.OneUnder40Limit())), //
LT(LI(joinable_lines_.ExactlyAt40Limit())), //
LT(LI(joinable_lines_.OneOver40Limit())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 243, 19500.0F, 100},
{21, expected_layout, 243, 21600.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
// Expected result here is the same as in the test case above
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Short()),
factory_.Line(joinable_lines_.Long()),
factory_.Line(joinable_lines_.Indented()),
factory_.Juxtaposition({
factory_.Line(joinable_lines_.OneUnder40Limit()),
factory_.Line(joinable_lines_.ExactlyAt40Limit()),
factory_.Line(joinable_lines_.OneOver40Limit()),
}),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(lines_.Short())), //
LT(LI(joinable_lines_.Long())), //
LT(LI(joinable_lines_.Indented())), //
LT(LI(joinable_lines_.OneUnder40Limit())), //
LT(LI(joinable_lines_.ExactlyAt40Limit())), //
LT(LI(joinable_lines_.OneOver40Limit())), //
LT(LI(joinable_lines_.Exactly10Columns())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 243, 19500.0F, 100},
{21, expected_layout, 243, 21600.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, Choice) {
using LT = LayoutTree;
using LI = LayoutItem;
struct ChoiceTestCase {
int line_no;
const std::initializer_list<LayoutFunction> choices;
const LayoutFunction expected;
};
// Layout doesn't really matter in this test
static const auto layout = LT(LI(LayoutType::kLine, 0, false));
static const ChoiceTestCase kTestCases[] = {
{__LINE__, {}, LayoutFunction{}},
{__LINE__,
{
LayoutFunction{{0, layout, 10, 100.0F, 10}},
},
LayoutFunction{{0, layout, 10, 100.0F, 10}}},
{__LINE__,
{
LayoutFunction{{0, layout, 10, 100.0F, 10}},
LayoutFunction{{0, layout, 10, 200.0F, 10}},
},
LayoutFunction{{0, layout, 10, 100.0F, 10}}},
{__LINE__,
{
LayoutFunction{{0, layout, 10, 200.0F, 10}},
LayoutFunction{{0, layout, 10, 100.0F, 10}},
},
LayoutFunction{{0, layout, 10, 100.0F, 10}}},
{__LINE__,
{
LayoutFunction{{0, layout, 10, 100.0F, 10}},
LayoutFunction{{0, layout, 10, 100.0F, 10}},
},
LayoutFunction{{0, layout, 10, 100.0F, 10}}},
{__LINE__,
{
LayoutFunction{{0, layout, 10, 100.0F, 1}},
LayoutFunction{{0, layout, 10, 0.0F, 3}},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 150.0F, 1},
}},
{__LINE__,
{
LayoutFunction{
{0, layout, 10, 100.0F, 1},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 150.0F, 0},
},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 150.0F, 0},
}},
{__LINE__,
{
LayoutFunction{
{0, layout, 10, 100.0F, 1},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 160.0F, 0},
},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 150.0F, 1},
{60, layout, 10, 160.0F, 0},
}},
{__LINE__,
{
LayoutFunction{
{0, layout, 10, 100.0F, 1},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 160.0F, 0},
},
},
LayoutFunction{
{0, layout, 10, 0.0F, 3},
{50, layout, 10, 150.0F, 1},
{60, layout, 10, 160.0F, 0},
}},
{__LINE__,
{
LayoutFunction{
{0, layout, 10, 100.0F, 1},
{50, layout, 10, 150.0F, 0},
},
LayoutFunction{
{0, layout, 10, 125.0F, 0},
{75, layout, 10, 125.0F, 1},
},
},
LayoutFunction{
{0, layout, 10, 100.0F, 1},
{25, layout, 10, 125.0F, 0},
{75, layout, 10, 125.0F, 1},
{100, layout, 10, 150.0F, 0},
}},
{__LINE__,
{
LayoutFunction{
{0, layout, 1, 50.0F, 0},
},
LayoutFunction{
{0, layout, 2, 0.0F, 10},
},
LayoutFunction{
{0, layout, 3, 999.0F, 0},
{10, layout, 3, 0.0F, 10},
},
LayoutFunction{
{0, layout, 4, 999.0F, 0},
{20, layout, 4, 0.0F, 10},
},
},
LayoutFunction{
{0, layout, 2, 0.0F, 10},
{5, layout, 1, 50.0F, 0},
{10, layout, 3, 0.0F, 10},
{15, layout, 1, 50.0F, 0},
{20, layout, 4, 0.0F, 10},
{25, layout, 1, 50.0F, 0},
}},
};
for (const auto& test_case : kTestCases) {
const LayoutFunction choice_result = factory_.Choice(test_case.choices);
ExpectLayoutFunctionsEqual(choice_result, test_case.expected,
test_case.line_no);
}
}
TEST_F(LayoutFunctionFactoryTest, Wrap) {
using LT = LayoutTree;
using LI = LayoutItem;
{
const auto lf = factory_.Wrap({});
const auto expected_lf = LayoutFunction{};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Short()),
});
const auto expected_lf = factory_.Line(lines_.Short());
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Exactly10Columns()),
factory_.Line(lines_.Short()),
factory_.Line(lines_.Short()),
});
const auto expected_layout_vh =
LT(LI(LayoutType::kStack, 0, true), //
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.Exactly10Columns()), //
LI(lines_.Short())), //
LI(lines_.Short()));
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.Exactly10Columns()), //
LI(lines_.Short()), //
LI(lines_.Short()));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.Exactly10Columns()), //
LI(lines_.Short()), //
LI(lines_.Short()));
const auto expected_lf = LayoutFunction{
{0, expected_layout_vh, 19, 2.0F, 0},
{11, expected_layout_vh, 19, 2.0F, 100},
{12, expected_layout_v, 19, 4.0F, 0},
{21, expected_layout_v, 19, 4.0F, 200},
{30, expected_layout_v, 19, 1804.0F, 300},
{40, expected_layout_h, 48, 4800.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Short()),
factory_.Line(lines_.Exactly10Columns()),
factory_.Line(lines_.Short()),
});
const auto expected_layout_hv =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short()), //
LI(lines_.Exactly10Columns())), //
LI(lines_.Short()));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short()), //
LI(lines_.Exactly10Columns()), //
LI(lines_.Short()));
const auto expected_lf = LayoutFunction{
{0, expected_layout_hv, 29, 2.0F, 0},
{11, expected_layout_hv, 29, 2.0F, 100},
{12, expected_layout_v, 19, 4.0F, 0},
{21, expected_layout_v, 19, 4.0F, 200},
{30, expected_layout_v, 19, 1804.0F, 300},
{40, expected_layout_hv, 29, 4802.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.OneUnder40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.OneUnder40Limit()), //
LI(lines_.Short()));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.OneUnder40Limit()), //
LI(lines_.Short()));
const auto expected_lf = LayoutFunction{
{0, expected_layout_v, 19, 2.0F, 0},
{1, expected_layout_v, 19, 2.0F, 100},
{21, expected_layout_v, 19, 2002.0F, 200},
{40, expected_layout_h, 58, 5800.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.ExactlyAt40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.ExactlyAt40Limit()), //
LI(lines_.Short()));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.ExactlyAt40Limit()), //
LI(lines_.Short()));
const auto expected_lf = LayoutFunction{
{0, expected_layout_v, 19, 2.0F, 100},
{21, expected_layout_v, 19, 2102.0F, 200},
{40, expected_layout_h, 59, 5900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.OneOver40Limit()),
factory_.Line(lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.OneOver40Limit()), //
LI(lines_.Short()));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.OneOver40Limit()), //
LI(lines_.Short()));
const auto expected_lf = LayoutFunction{
{0, expected_layout_v, 19, 102.0F, 100},
{21, expected_layout_v, 19, 2202.0F, 200},
{40, expected_layout_h, 60, 6000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap(
{
factory_.Line(lines_.OneOver40Limit()),
factory_.Line(lines_.Short()),
factory_.Line(lines_.Indented()),
},
false, 7);
const auto expected_layout_vv =
LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.OneOver40Limit()), //
LT(LI(LayoutType::kStack, 0, false, 7), //
LI(lines_.Short(), 0), //
LI(lines_.Indented(), 0)));
const auto expected_layout_vh =
LT(LI(LayoutType::kStack, 0, true), //
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.OneOver40Limit(), 0), //
LI(lines_.Short(), 0)),
LI(lines_.Indented(), 7));
const auto expected_lf = LayoutFunction{
{0, expected_layout_vv, 43, 404.0F, 200},
{14, expected_layout_vv, 43, 3204.0F, 300},
{33, expected_layout_vh, 43, 8902.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, Indent) {
using LT = LayoutTree;
using LI = LayoutItem;
{
const auto lf =
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 29);
const auto expected_layout = LT(LI(lines_.Exactly10Columns(), 29));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 39, 0.0F, 0},
{1, expected_layout, 39, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf =
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 30);
const auto expected_layout = LT(LI(lines_.Exactly10Columns(), 30));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 40, 0.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf =
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 31);
const auto expected_layout = LT(LI(lines_.Exactly10Columns(), 31));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 41, 100.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Indent(factory_.Line(lines_.Long()), 5);
const auto expected_layout = LT(LI(lines_.Long(), 5));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 55, 1500.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, IndentWithOtherCombinators) {
using LT = LayoutTree;
using LI = LayoutItem;
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(joinable_lines_.Exactly10Columns()), 9),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(joinable_lines_.Exactly10Columns(), 9), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 39, 0.0F, 0},
{1, expected_layout, 39, 0.0F, 100},
{11, expected_layout, 39, 1000.0F, 100},
{30, expected_layout, 39, 2900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(joinable_lines_.Exactly10Columns()), 10),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(joinable_lines_.Exactly10Columns(), 10), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 40, 0.0F, 100},
{10, expected_layout, 40, 1000.0F, 100},
{30, expected_layout, 40, 3000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Juxtaposition({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(joinable_lines_.Exactly10Columns()), 11),
factory_.Line(joinable_lines_.Exactly10Columns()),
});
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(joinable_lines_.Exactly10Columns(), 11), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 41, 100.0F, 100},
{9, expected_layout, 41, 1000.0F, 100},
{30, expected_layout, 41, 3100.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 29),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(lines_.Exactly10Columns(), 29), //
LI(lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 4.0F, 0},
{1, expected_layout, 10, 4.0F, 100},
{30, expected_layout, 10, 2904.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 30),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(lines_.Exactly10Columns(), 30), //
LI(lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 4.0F, 100},
{30, expected_layout, 10, 3004.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(lines_.Exactly10Columns()),
factory_.Indent(factory_.Line(lines_.Exactly10Columns()), 31),
factory_.Line(lines_.Exactly10Columns()),
});
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LI(lines_.Exactly10Columns(), 0), //
LI(lines_.Exactly10Columns(), 31), //
LI(lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 10, 104.0F, 100},
{30, expected_layout, 10, 3104.0F, 300},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Short()),
factory_.Indent(factory_.Line(joinable_lines_.Short()), 1),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 1));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 1));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 39, 0.0F, 0},
{1, expected_layout_h, 39, 0.0F, 100},
{2, expected_layout_v, 20, 2.0F, 0},
{20, expected_layout_v, 20, 2.0F, 100},
{21, expected_layout_v, 20, 102.0F, 200},
{40, expected_layout_h, 39, 3900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Short()),
factory_.Indent(factory_.Line(joinable_lines_.Short()), 2),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 2));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 2));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 40, 0.0F, 100},
{1, expected_layout_v, 21, 2.0F, 0},
{19, expected_layout_v, 21, 2.0F, 100},
{21, expected_layout_v, 21, 202.0F, 200},
{40, expected_layout_h, 40, 4000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Line(lines_.Short()),
factory_.Indent(factory_.Line(joinable_lines_.Short()), 3),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 3));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 0), //
LI(joinable_lines_.Short(), 3));
const auto expected_lf = LayoutFunction{
{0, expected_layout_v, 22, 2.0F, 0},
{18, expected_layout_v, 22, 2.0F, 100},
{21, expected_layout_v, 22, 302.0F, 200},
{40, expected_layout_h, 41, 4100.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Indent(factory_.Line(lines_.Short()), 1),
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 1), //
LI(joinable_lines_.Short(), 0));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 1), //
LI(joinable_lines_.Short(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 39, 0.0F, 0},
{1, expected_layout_h, 39, 0.0F, 100},
{2, expected_layout_v, 19, 2.0F, 0},
{20, expected_layout_v, 19, 2.0F, 100},
{21, expected_layout_v, 19, 102.0F, 200},
{40, expected_layout_h, 39, 3900.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Indent(factory_.Line(lines_.Short()), 2),
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 2), //
LI(joinable_lines_.Short(), 0));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 2), //
LI(joinable_lines_.Short(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 40, 0.0F, 100},
{1, expected_layout_v, 19, 2.0F, 0},
{19, expected_layout_v, 19, 2.0F, 100},
{21, expected_layout_v, 19, 202.0F, 200},
{40, expected_layout_h, 40, 4000.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto lf = factory_.Wrap({
factory_.Indent(factory_.Line(lines_.Short()), 3),
factory_.Line(joinable_lines_.Short()),
});
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(lines_.Short(), 3), //
LI(joinable_lines_.Short(), 0));
const auto expected_layout_v = LT(LI(LayoutType::kStack, 0, false), //
LI(lines_.Short(), 3), //
LI(joinable_lines_.Short(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout_v, 19, 2.0F, 0},
{18, expected_layout_v, 19, 2.0F, 100},
{21, expected_layout_v, 19, 302.0F, 200},
{40, expected_layout_h, 41, 4100.0F, 100},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
TEST_F(LayoutFunctionFactoryTest, DifferentLayoutsInDifferentSegments) {
using LT = LayoutTree;
using LI = LayoutItem;
const auto juxtaposition_or_wrap = factory_.Choice({
factory_.Juxtaposition({
factory_.Line(joinable_lines_.OneUnder30Limit()),
factory_.Line(joinable_lines_.Exactly10Columns()),
}),
factory_.Stack({
factory_.Line(joinable_lines_.OneUnder30Limit()),
factory_.Line(joinable_lines_.Exactly10Columns()),
}),
});
{
const auto expected_layout_h =
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(joinable_lines_.OneUnder30Limit(), 0), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_layout_v =
LT(LI(LayoutType::kStack, 0, false), //
LI(joinable_lines_.OneUnder30Limit(), 0), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 39, 0.0F, 0},
{1, expected_layout_h, 39, 0.0F, 100},
{2, expected_layout_v, 10, 2.0F, 0},
{11, expected_layout_v, 10, 2.0F, 100},
{30, expected_layout_v, 10, 1902.0F, 200},
{40, expected_layout_h, 39, 3900.0F, 100},
};
ExpectLayoutFunctionsEqual(juxtaposition_or_wrap, expected_lf, __LINE__);
}
{
const auto lf = factory_.Stack({
factory_.Line(joinable_lines_.Short()),
juxtaposition_or_wrap,
});
const auto expected_layout_h =
LT(LI(LayoutType::kStack, 0, false), //
LI(joinable_lines_.Short(), 0), //
LT(LI(LayoutType::kJuxtaposition, 0, false), //
LI(joinable_lines_.OneUnder30Limit(), 0), //
LI(joinable_lines_.Exactly10Columns(), 0)));
const auto expected_layout_v =
LT(LI(LayoutType::kStack, 0, false), //
LI(joinable_lines_.Short(), 0), //
LI(joinable_lines_.OneUnder30Limit(), 0), //
LI(joinable_lines_.Exactly10Columns(), 0));
const auto expected_lf = LayoutFunction{
{0, expected_layout_h, 39, 2.0F, 0},
{1, expected_layout_h, 39, 2.0F, 100},
{2, expected_layout_v, 10, 4.0F, 0},
{11, expected_layout_v, 10, 4.0F, 100},
{21, expected_layout_v, 10, 1004.0F, 200},
{30, expected_layout_v, 10, 2804.0F, 300},
{40, expected_layout_h, 39, 5802.0F, 200},
};
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
class TreeReconstructorTest : public ::testing::Test,
public UnwrappedLineMemoryHandler {
public:
TreeReconstructorTest()
: sample_("first_line second_line third_line fourth_line"),
tokens_(absl::StrSplit(sample_, ' ')) {
for (const auto token : tokens_) {
ftokens_.emplace_back(TokenInfo{1, token});
}
CreateTokenInfos(ftokens_);
}
protected:
const std::string sample_;
const std::vector<absl::string_view> tokens_;
std::vector<TokenInfo> ftokens_;
};
TEST_F(TreeReconstructorTest, SingleLine) {
using TPT = TokenPartitionTreeBuilder;
using LT = LayoutTree;
using LI = LayoutItem;
const auto tree_expected =
TPT(0, {0, 1}, PartitionPolicyEnum::kAlreadyFormatted)
.build(pre_format_tokens_);
const auto layout_tree = LT(LI(tree_expected.Value()));
auto optimized_tree = TokenPartitionTree();
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
EXPECT_PRED_FORMAT2(TokenPartitionTreesEqualPredFormat, optimized_tree,
tree_expected);
}
TEST_F(TreeReconstructorTest, HorizontalLayoutWithOneLine) {
using TPT = TokenPartitionTreeBuilder;
using LT = LayoutTree;
using LI = LayoutItem;
const auto tree_expected =
TPT(0, {0, 1}, PartitionPolicyEnum::kAlreadyFormatted)
.build(pre_format_tokens_);
const auto layout_tree = LT(LI(LayoutType::kJuxtaposition, 0, false),
LT(LI(tree_expected.Value())));
auto optimized_tree = TokenPartitionTree();
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
EXPECT_PRED_FORMAT2(TokenPartitionTreesEqualPredFormat, optimized_tree,
tree_expected);
}
TEST_F(TreeReconstructorTest, HorizontalLayoutSingleLines) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine left_line(0, begin);
left_line.SpanUpToToken(begin + 1);
UnwrappedLine right_line(0, begin + 1);
right_line.SpanUpToToken(begin + 2);
UnwrappedLine all(0, left_line.TokensRange().begin());
all.SpanUpToToken(right_line.TokensRange().end());
const auto layout_tree = LayoutTree(
LayoutItem(LayoutType::kJuxtaposition, 0,
left_line.TokensRange().front().before.break_decision ==
SpacingOptions::MustWrap),
LayoutTree(LayoutItem(left_line)), LayoutTree(LayoutItem(right_line)));
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree(UnwrappedLine(0, begin));
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected(all);
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, EmptyHorizontalLayout) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine upper_line(0, begin);
upper_line.SpanUpToToken(begin + 1);
UnwrappedLine lower_line(0, begin + 1);
lower_line.SpanUpToToken(begin + 2);
UnwrappedLine all(0, upper_line.TokensRange().begin());
all.SpanUpToToken(lower_line.TokensRange().end());
const auto layout_tree =
LayoutTree(LayoutItem(LayoutType::kJuxtaposition, 0, false),
LayoutTree(LayoutItem(upper_line)),
LayoutTree(LayoutItem(LayoutType::kJuxtaposition, 0, false)),
LayoutTree(LayoutItem(lower_line)));
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{all};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, VerticalLayoutWithOneLine) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine uwline(0, begin);
uwline.SpanUpToToken(begin + 1);
const auto layout_tree = LayoutTree(LayoutItem(LayoutType::kStack, 0, false),
LayoutTree(LayoutItem(uwline)));
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{uwline};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, VerticalLayoutSingleLines) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine upper_line(0, begin);
upper_line.SpanUpToToken(begin + 1);
UnwrappedLine lower_line(0, begin + 1);
lower_line.SpanUpToToken(begin + 2);
UnwrappedLine all(0, upper_line.TokensRange().begin());
all.SpanUpToToken(lower_line.TokensRange().end());
const auto layout_tree = LayoutTree(
LayoutItem(LayoutType::kStack, 0,
upper_line.TokensRange().front().before.break_decision ==
SpacingOptions::MustWrap),
LayoutTree(LayoutItem(upper_line)), LayoutTree(LayoutItem(lower_line)));
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{all, //
Tree{upper_line}, //
Tree{lower_line}};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, EmptyVerticalLayout) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine upper_line(0, begin);
upper_line.SpanUpToToken(begin + 1);
UnwrappedLine lower_line(0, begin + 1);
lower_line.SpanUpToToken(begin + 2);
UnwrappedLine all(0, upper_line.TokensRange().begin());
all.SpanUpToToken(lower_line.TokensRange().end());
const auto layout_tree =
LayoutTree(LayoutItem(LayoutType::kStack, 0, false),
LayoutTree(LayoutItem(upper_line)),
LayoutTree(LayoutItem(LayoutType::kStack, 0, false)),
LayoutTree(LayoutItem(lower_line)));
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{all, //
Tree{upper_line}, //
Tree{lower_line}};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, VerticallyJoinHorizontalLayouts) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine first_line(0, begin);
first_line.SpanUpToToken(begin + 1);
UnwrappedLine second_line(0, begin + 1);
second_line.SpanUpToToken(begin + 2);
UnwrappedLine third_line(0, begin + 2);
third_line.SpanUpToToken(begin + 3);
UnwrappedLine fourth_line(0, begin + 3);
fourth_line.SpanUpToToken(begin + 4);
UnwrappedLine upper_line(0, first_line.TokensRange().begin());
upper_line.SpanUpToToken(second_line.TokensRange().end());
UnwrappedLine lower_line(0, third_line.TokensRange().begin());
lower_line.SpanUpToToken(fourth_line.TokensRange().end());
UnwrappedLine all(0, upper_line.TokensRange().begin());
all.SpanUpToToken(lower_line.TokensRange().end());
const LayoutTree layout_tree{
LayoutItem(LayoutType::kStack, 0, false),
LayoutTree(LayoutItem(LayoutType::kJuxtaposition, 0, false),
LayoutTree(LayoutItem(first_line)),
LayoutTree(LayoutItem(second_line))),
LayoutTree(LayoutItem(LayoutType::kJuxtaposition, 0, false),
LayoutTree(LayoutItem(third_line)),
LayoutTree(LayoutItem(fourth_line)))};
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{all, //
Tree{upper_line}, //
Tree{lower_line}};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, HorizontallyJoinVerticalLayouts) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine first_line(0, begin);
first_line.SpanUpToToken(begin + 1);
UnwrappedLine second_line(0, begin + 1);
second_line.SpanUpToToken(begin + 2);
UnwrappedLine third_line(0, begin + 2);
third_line.SpanUpToToken(begin + 3);
UnwrappedLine fourth_line(0, begin + 3);
fourth_line.SpanUpToToken(begin + 4);
UnwrappedLine upper_line(0, first_line.TokensRange().begin());
upper_line.SpanUpToToken(first_line.TokensRange().end());
UnwrappedLine middle_line(0, second_line.TokensRange().begin());
middle_line.SpanUpToToken(third_line.TokensRange().end());
UnwrappedLine bottom_line(0, fourth_line.TokensRange().begin());
bottom_line.SpanUpToToken(fourth_line.TokensRange().end());
UnwrappedLine all(0, upper_line.TokensRange().begin());
all.SpanUpToToken(bottom_line.TokensRange().end());
const LayoutTree layout_tree{
LayoutItem(LayoutType::kJuxtaposition, 0, false),
LayoutTree(LayoutItem(LayoutType::kStack, 0, false),
LayoutTree(LayoutItem(first_line)),
LayoutTree(LayoutItem(second_line))),
LayoutTree(LayoutItem(LayoutType::kStack, 0, false),
LayoutTree(LayoutItem(third_line)),
LayoutTree(LayoutItem(fourth_line)))};
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{all, //
Tree{upper_line}, //
Tree{middle_line}, //
Tree{bottom_line}};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
}
TEST_F(TreeReconstructorTest, IndentSingleLine) {
const auto begin = pre_format_tokens_.begin();
UnwrappedLine single_line(0, begin);
single_line.SpanUpToToken(begin + 1);
const auto indent = 7;
LayoutTree layout_tree{LayoutItem(single_line)};
layout_tree.Value().SetIndentationSpaces(indent);
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
auto optimized_tree = TokenPartitionTree{UnwrappedLine(0, begin)};
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
using Tree = TokenPartitionTree;
const Tree tree_expected{single_line};
const auto diff = DeepEqual(optimized_tree, tree_expected, TokenRangeEqual);
EXPECT_EQ(diff.left, nullptr) << "Expected:\n"
<< tree_expected << "\nGot:\n"
<< optimized_tree << "\n";
EXPECT_EQ(optimized_tree.Value().IndentationSpaces(), indent);
}
TEST_F(TreeReconstructorTest, InlineSpacingReconstruction) {
using TPT = TokenPartitionTreeBuilder;
using LT = LayoutTree;
using LI = LayoutItem;
const auto tree_expected =
TPT(1, PartitionPolicyEnum::kAlreadyFormatted,
{
TPT(0, {0, 1}, PartitionPolicyEnum::kInline),
TPT(2, {1, 2}, PartitionPolicyEnum::kInline),
TPT(3, {2, 3}, PartitionPolicyEnum::kInline),
})
.build(pre_format_tokens_);
const auto layout_tree =
LT(LI(LayoutType::kJuxtaposition, 1, true), //
LT(LI(tree_expected.Children()[0].Value(), true, 1)), //
LT(LI(tree_expected.Children()[1].Value())), //
LT(LI(tree_expected.Children()[2].Value())));
auto optimized_tree = TokenPartitionTree();
TreeReconstructor tree_reconstructor(0);
tree_reconstructor.TraverseTree(layout_tree);
tree_reconstructor.ReplaceTokenPartitionTreeNode(&optimized_tree);
EXPECT_PRED_FORMAT2(TokenPartitionTreesEqualPredFormat, optimized_tree,
tree_expected);
}
class OptimizeTokenPartitionTreeTest : public ::testing::Test,
public UnwrappedLineMemoryHandler {
public:
OptimizeTokenPartitionTreeTest()
: sample_(
"function_fffffffffff( type_a_aaaa, "
"type_b_bbbbb, type_c_cccccc, "
"type_d_dddddddd, type_e_eeeeeeee, type_f_ffff); "
"seven eight nine ten eleven twelve"),
tokens_(absl::StrSplit(sample_, ' ')) {
for (const auto token : tokens_) {
ftokens_.emplace_back(TokenInfo{1, token});
}
CreateTokenInfos(ftokens_);
}
protected:
const std::string sample_;
const std::vector<absl::string_view> tokens_;
std::vector<TokenInfo> ftokens_;
};
TEST_F(OptimizeTokenPartitionTreeTest, AppendToLineWithInlinePartitions) {
using TPT = TokenPartitionTreeBuilder;
using PP = PartitionPolicyEnum;
auto tree = TPT(PP::kFitOnLineElseExpand,
{
TPT(PP::kAlreadyFormatted,
{
TPT(1, {7, 8}, PP::kInline),
TPT(3, {8, 9}, PP::kInline),
TPT(5, {9, 10}, PP::kInline),
}),
TPT(PP::kAlwaysExpand,
{
TPT({10, 11}, PP::kFitOnLineElseExpand),
TPT({11, 12}, PP::kFitOnLineElseExpand),
TPT({12, 13}, PP::kFitOnLineElseExpand),
}),
})
.build(pre_format_tokens_);
const auto expected_tree = TPT(PP::kAlwaysExpand,
{
TPT(1, PP::kAlreadyFormatted,
{
TPT(0, {7, 8}, PP::kInline),
TPT(3, {8, 9}, PP::kInline),
TPT(5, {9, 11}, PP::kInline),
}),
TPT(23, {11, 12}, PP::kAlreadyFormatted),
TPT(23, {12, 13}, PP::kAlreadyFormatted),
})
.build(pre_format_tokens_);
static const BasicFormatStyle style = CreateStyle();
OptimizeTokenPartitionTree(style, &tree);
EXPECT_PRED_FORMAT2(TokenPartitionTreesEqualPredFormat, tree, expected_tree);
}
class TokenPartitionsLayoutOptimizerTest : public ::testing::Test,
public UnwrappedLineMemoryHandler {
public:
TokenPartitionsLayoutOptimizerTest()
: sample_(
// : |10 : |20 : |30 : |40
"one two three four\n"
"eleven twelve thirteen fourteen\n"),
tokens_(
absl::StrSplit(sample_, absl::ByAnyChar(" \n"), absl::SkipEmpty())),
style_(CreateStyle()),
factory_(LayoutFunctionFactory(style_)) {
for (const auto token : tokens_) {
ftokens_.emplace_back(TokenInfo{1, token});
}
CreateTokenInfosExternalStringBuffer(ftokens_);
ConnectPreFormatTokensPreservedSpaceStarts(sample_.data(),
&pre_format_tokens_);
// Set token properties
for (auto token_it = pre_format_tokens_.begin();
token_it != pre_format_tokens_.end(); ++token_it) {
const auto leading_spaces = token_it->OriginalLeadingSpaces();
// First token in a line
if (absl::StrContains(leading_spaces, '\n')) {
token_it->before.break_decision = SpacingOptions::MustWrap;
auto last_non_space_offset = leading_spaces.find_last_not_of(' ');
if (last_non_space_offset != absl::string_view::npos) {
token_it->before.spaces_required =
leading_spaces.size() - 1 - last_non_space_offset;
}
} else {
token_it->before.spaces_required = leading_spaces.size();
}
}
pre_format_tokens_.front().before.break_decision = SpacingOptions::MustWrap;
}
protected:
const std::string sample_;
const std::vector<absl::string_view> tokens_;
std::vector<TokenInfo> ftokens_;
const BasicFormatStyle style_;
const LayoutFunctionFactory factory_;
};
TEST_F(TokenPartitionsLayoutOptimizerTest, CalculateOptimalLayout) {
using TPT = TokenPartitionTreeBuilder;
using PP = PartitionPolicyEnum;
using LT = LayoutTree;
using LI = LayoutItem;
const auto optimizer = TokenPartitionsLayoutOptimizer(style_);
{
const auto tree = TPT(4, PP::kAlwaysExpand,
{
TPT(4, {0, 1}),
TPT(4, {1, 2}),
TPT(4, {2, 3}),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value())), //
LT(LI(tree.Children()[1].Value())), //
LT(LI(tree.Children()[2].Value())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 5, 4.0F, 0},
{35, expected_layout, 5, 4.0F, 100},
{37, expected_layout, 5, 204.0F, 300},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(PP::kAlwaysExpand,
{
TPT(1, {0, 1}),
TPT(2, {1, 2}),
TPT(3, {2, 3}),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value(), 1)), //
LT(LI(tree.Children()[1].Value(), 2)), //
LT(LI(tree.Children()[2].Value(), 3)));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 8, 4.0F, 0},
{32, expected_layout, 8, 4.0F, 100},
{35, expected_layout, 8, 304.0F, 200},
{36, expected_layout, 8, 504.0F, 300},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(2, PP::kTabularAlignment,
{
TPT(2, {0, 1}, PP::kAlreadyFormatted),
TPT(2, {1, 2}, PP::kAlreadyFormatted),
TPT(2, {2, 3}, PP::kAlreadyFormatted),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value())), //
LT(LI(tree.Children()[1].Value())), //
LT(LI(tree.Children()[2].Value())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 5, 4.0F, 0},
{35, expected_layout, 5, 4.0F, 100},
{37, expected_layout, 5, 204.0F, 300},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(PP::kTabularAlignment,
{
TPT(1, {0, 1}, PP::kAlreadyFormatted),
TPT(2, {1, 2}, PP::kAlreadyFormatted),
TPT(3, {2, 3}, PP::kAlreadyFormatted),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value(), 1)), //
LT(LI(tree.Children()[1].Value(), 2)), //
LT(LI(tree.Children()[2].Value(), 3)));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 8, 4.0F, 0},
{32, expected_layout, 8, 4.0F, 100},
{35, expected_layout, 8, 304.0F, 200},
{36, expected_layout, 8, 504.0F, 300},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(PP::kAppendFittingSubPartitions,
{
TPT(3, {0, 4}),
TPT(5, {4, 8}),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value())), //
LT(LI(tree.Children()[1].Value())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 31, 2.0F, 0},
{9, expected_layout, 31, 2.0F, 100},
{22, expected_layout, 31, 1302.0F, 200},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(PP::kFitOnLineElseExpand,
{
TPT(3, {0, 4}),
TPT(5, {4, 8}),
})
.build(pre_format_tokens_);
const auto expected_layout = LT(LI(LayoutType::kStack, 0, true), //
LT(LI(tree.Children()[0].Value())), //
LT(LI(tree.Children()[1].Value())));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 31, 2.0F, 0},
{9, expected_layout, 31, 2.0F, 100},
{22, expected_layout, 31, 1302.0F, 200},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
{
const auto tree = TPT(PP::kAlreadyFormatted,
{
TPT(3, {0, 1}, PP::kInline),
TPT(5, {1, 2}, PP::kInline),
TPT(7, {2, 4}, PP::kInline),
})
.build(pre_format_tokens_);
const auto expected_layout =
LT(LI(LayoutType::kJuxtaposition, 3, true),
LT(LI(tree.Children()[0].Value(), true, 3)),
LT(LI(tree.Children()[1].Value(), false, 0)),
LT(LI(tree.Children()[2].Value(), false, 0)));
const auto expected_lf = LayoutFunction{
{0, expected_layout, 31, 0.0, 0},
{9, expected_layout, 31, 0.0, 100},
{26, expected_layout, 31, 1000.0, 100},
{34, expected_layout, 31, 1300.0, 100},
};
const LayoutFunction lf = optimizer.CalculateOptimalLayout(tree);
ExpectLayoutFunctionsEqual(lf, expected_lf, __LINE__);
}
}
} // namespace
} // namespace verible