Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CodeFormatCore/include/CodeFormatCore/Config/LuaStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ class LuaStyle {
bool break_before_braces = false;

BreakTableList break_table_list = BreakTableList::Smart;

// keep/always/never: break between '=' and its value
BreakAfterAssign break_after_assignment_statement = BreakAfterAssign::Never;
// [preference]
bool ignore_space_after_colon = false;

Expand Down
10 changes: 10 additions & 0 deletions CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ enum class BreakTableList {
Lazy
};

// Controls the line break between an assignment/table-field '=' and its value.
enum class BreakAfterAssign {
// Leave the source as it is.
Keep,
// Always place the value on a new line after '='.
Always,
// Never break after '='; collapse the value onto the '=' line.
Never,
};

enum class SpaceAroundStyle {
// for false and none
None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class LineBreakAnalyzer : public FormatAnalyzer {

void AnalyzeTableExpr(FormatState &f, LuaSyntaxNode table, const LuaSyntaxTree &t);

void AnalyzeAssignBreak(FormatState &f, LuaSyntaxNode assignNode, const LuaSyntaxTree &t);

bool CanBreakAll(FormatState &f, LuaSyntaxNode n, const LuaSyntaxTree &t);

bool CanCollapseLines(FormatState &f, LuaSyntaxNode &n, const LuaSyntaxTree &t);
Expand Down
10 changes: 10 additions & 0 deletions CodeFormatCore/src/Config/LuaStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,16 @@ void LuaStyle::Parse(std::map<std::string, std::string, std::less<>> &configMap)
}
}

IF_EXIST(break_after_assignment_statement) {
if (value == "keep") {
break_after_assignment_statement = BreakAfterAssign::Keep;
} else if (value == "always") {
break_after_assignment_statement = BreakAfterAssign::Always;
} else if (value == "never") {
break_after_assignment_statement = BreakAfterAssign::Never;
}
}

BOOL_OPTION(ignore_space_after_colon)

BOOL_OPTION(remove_call_expression_list_finish_comma)
Expand Down
46 changes: 46 additions & 0 deletions CodeFormatCore/src/Format/Analyzer/LineBreakAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,17 @@ void LineBreakAnalyzer::ComplexAnalyze(FormatState &f, const LuaSyntaxTree &t) {
case LuaSyntaxNodeKind::LocalStatement:
case LuaSyntaxNodeKind::AssignStatement:
case LuaSyntaxNodeKind::ReturnStatement: {
AnalyzeAssignBreak(f, syntaxNode, t);
auto exprList = syntaxNode.GetChildSyntaxNode(NodeKind::ExpressionList, t);
if (exprList.IsNode(t)) {
AnalyzeExprList(f, exprList, t);
}
break;
}
case LuaSyntaxNodeKind::TableField: {
AnalyzeAssignBreak(f, syntaxNode, t);
break;
}
case LuaSyntaxNodeKind::IfStatement: {
auto exprs = syntaxNode.GetChildSyntaxNodes(LuaSyntaxMultiKind::Expression, t);
for (auto expr: exprs) {
Expand Down Expand Up @@ -317,6 +322,39 @@ void LineBreakAnalyzer::AnalyzeSuffixedExpr(FormatState &f, LuaSyntaxNode expr,
}
}

void LineBreakAnalyzer::AnalyzeAssignBreak(FormatState &f, LuaSyntaxNode assignNode, const LuaSyntaxTree &t) {
auto strategy = f.GetStyle().break_after_assignment_statement;
if (strategy == BreakAfterAssign::Keep) {
return;
}

auto eq = assignNode.GetChildToken('=', t);
if (!eq.IsToken(t)) {
return;
}

auto next = eq.GetNextToken(t);
if (!next.IsToken(t)) {
return;
}

// a comment after '=' must stay on its own line
auto nextKind = next.GetTokenKind(t);
if (nextKind == TK_SHORT_COMMENT || nextKind == TK_LONG_COMMENT) {
return;
}

if (strategy == BreakAfterAssign::Never) {
// break_before_braces wins for a table value
if (f.GetStyle().break_before_braces && nextKind == '{') {
return;
}
CancelBreakAfter(eq, t);
} else {
BreakAfter(eq, t, LineSpace(1));
}
}

// 是格式化的重点内容
void LineBreakAnalyzer::AnalyzeTableExpr(FormatState &f, LuaSyntaxNode table, const LuaSyntaxTree &t) {

Expand All @@ -335,6 +373,14 @@ void LineBreakAnalyzer::AnalyzeTableExpr(FormatState &f, LuaSyntaxNode table, co
return;
}

// a multi-line table puts its closing '}' on its own line
if (!table.IsSingleLineNode(t)) {
auto rightBrace = table.GetChildToken('}', t);
if (rightBrace.IsToken(t)) {
BreakBefore(rightBrace, t, LineSpace(LineSpaceType::Keep));
}
}

// force break
bool breakAllList = f.GetStyle().break_all_list_when_line_exceed && CanBreakAll(f, tableFieldList, t);
if (!breakAllList && f.GetStyle().break_table_list == BreakTableList::Smart) {
Expand Down
28 changes: 24 additions & 4 deletions Test/src/FormatResult_unitest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ local t =
}
)",
R"(
local t =
{
local t = {
a = 123
}
)"));
Expand Down Expand Up @@ -107,13 +106,34 @@ a, b, c, d
}
)",
R"(
t =
{
t = {
a, b, c, d
}
)"));
}

TEST(Format, MultiLineTableRightBrace) {
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
t = {
{ aaa = 1, bbb = 2 },
{ ccc = 3, ddd = 4 } }
)",
R"(
t = {
{ aaa = 1, bbb = 2 },
{ ccc = 3, ddd = 4 }
}
)"));
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
t = { a, b, c }
)",
R"(
t = { a, b, c }
)"));
}

TEST(Format, IfStatement) {
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
Expand Down
82 changes: 80 additions & 2 deletions Test/src/FormatStyle_unitest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,13 @@ local t = { {
R"(
local t = { function()
local t = 123
end }
end
}

local t = { {
okokok = 123,
} }
}
}
)",
style));
}
Expand Down Expand Up @@ -1682,6 +1684,82 @@ local t =
style));
}

TEST(FormatByStyleOption, break_after_assignment_statement) {
LuaStyle style;

style.break_after_assignment_statement = BreakAfterAssign::Never;
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
local t =
{
a = 123
}
local d =
{
aaa =
{ 1, 2, 3 }
}
)",
R"(
local t = {
a = 123
}
local d = {
aaa = { 1, 2, 3 }
}
)",
style));

style.break_after_assignment_statement = BreakAfterAssign::Keep;
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
local t =
{
a = 123
}
local d = { a = 123 }
)",
R"(
local t =
{
a = 123
}
local d = { a = 123 }
)",
style));

style.break_after_assignment_statement = BreakAfterAssign::Always;
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
local t = 123
local d = { a = 123 }
)",
R"(
local t =
123
local d =
{ a =
123 }
)",
style));

style.break_after_assignment_statement = BreakAfterAssign::Never;
style.break_before_braces = true;
EXPECT_TRUE(TestHelper::TestFormatted(
R"(
local t = {
a = 123
}
)",
R"(
local t =
{
a = 123
}
)",
style));
}

TEST(FormatByStyleOption, end_statement_with_semicolon) {
LuaStyle style;

Expand Down
14 changes: 14 additions & 0 deletions docs/format_config_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,20 @@ This option means that when an expression with a list exceeds the row width sett

This option means that expressions on the list should not be interrupted after evaluation, they will all collapse to the same row, the default value is false, and it is currently only valid for tables

### break_after_assignment_statement

This option controls the line break between an assignment/table-field `=` and its value. It applies to assignment statements, local statements and table fields.

The possible values are:
- never (default)
never break after `=`; the value is collapsed onto the same line as `=`, for example `key =\n{ ... }` becomes `key = { ... }`
- keep
leave the source layout as it is
- always
always place the value on a new line after `=`

When the value is a table and `break_before_braces` is enabled, `break_before_braces` takes precedence and the `never` behaviour is skipped for that value. A comment immediately after `=` is never merged onto the `=` line.

## Preferences

### ignore_space_after_colon
Expand Down
3 changes: 3 additions & 0 deletions lua.template.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ auto_collapse_lines = false

break_before_braces = false

# never / keep / always
break_after_assignment_statement = never

# [preference]
ignore_space_after_colon = false

Expand Down