Skip to content

Commit 7be3c5d

Browse files
authored
Merge pull request #138 from AlWoSp/awa/fix-semicolon-reformatting
Improve Formatter for Semicolon Rule
2 parents 1f15e10 + 528b52f commit 7be3c5d

File tree

8 files changed

+29
-31
lines changed

8 files changed

+29
-31
lines changed

CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ enum class AlignChainExpr {
8787

8888
enum class EndStmtWithSemicolon {
8989
Keep,
90-
Never,
90+
ReplaceWithNewline,
9191
Always,
9292
SameLine
9393
};

CodeFormatCore/include/CodeFormatCore/Format/Analyzer/SemicolonAnalyzer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ class SemicolonAnalyzer : public FormatAnalyzer {
1717

1818
private:
1919
void AddSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t);
20-
void InsertNewLineBeforeNode(LuaSyntaxNode n, const LuaSyntaxTree &t);
20+
void InsertNewLineBeforeNextNode(LuaSyntaxNode n, const LuaSyntaxTree &t);
2121
void RemoveSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t);
22-
bool IsFirstStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree &t);
2322
bool IsLastStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree &t);
2423
bool EndsWithSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t);
24+
bool ContainsSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t);
2525
LuaSyntaxNode GetLastNonCommentToken(LuaSyntaxNode n, const LuaSyntaxTree &t);
2626

2727
std::unordered_map<std::size_t, SemicolonStrategy> _semicolon;

CodeFormatCore/src/Config/LuaStyle.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ void LuaStyle::Parse(std::map<std::string, std::string, std::less<>> &configMap)
293293
end_statement_with_semicolon = EndStmtWithSemicolon::Keep;
294294
} else if (configMap.at("end_statement_with_semicolon") == "always") {
295295
end_statement_with_semicolon = EndStmtWithSemicolon::Always;
296-
} else if (configMap.at("end_statement_with_semicolon") == "never") {
297-
end_statement_with_semicolon = EndStmtWithSemicolon::Never;
296+
} else if (configMap.at("end_statement_with_semicolon") == "replace_with_newline") {
297+
end_statement_with_semicolon = EndStmtWithSemicolon::ReplaceWithNewline;
298298
} else if (configMap.at("end_statement_with_semicolon") == "same_line") {
299299
end_statement_with_semicolon = EndStmtWithSemicolon::SameLine;
300300
}

CodeFormatCore/src/Diagnostic/CodeStyle/CodeStyleChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ void CodeStyleChecker::BasicResolve(LuaSyntaxNode syntaxNode, const LuaSyntaxTre
9696
}
9797
case TokenStrategy::StmtEndSemicolon: {
9898
switch (d.GetState().GetStyle().end_statement_with_semicolon) {
99-
case EndStmtWithSemicolon::Never: {
99+
case EndStmtWithSemicolon::ReplaceWithNewline: {
100100
d.PushDiagnostic(DiagnosticType::Semicolon, textRange,
101101
LText("expected statement not to end with ;"));
102102
break;

CodeFormatCore/src/Format/Analyzer/SemicolonAnalyzer.cpp

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ void SemicolonAnalyzer::Analyze(FormatState &f, const LuaSyntaxTree &t) {
1717
switch (f.GetStyle().end_statement_with_semicolon) {
1818
case EndStmtWithSemicolon::Always: {
1919
if (syntaxNode.GetSyntaxKind(t) == LuaSyntaxNodeKind::LabelStatement) {
20-
break; // labels should not end with semicolons
20+
break;// labels should not end with semicolons
2121
}
2222
if (!EndsWithSemicolon(syntaxNode, t)) {
2323
AddSemicolon(syntaxNode, t);
2424
}
2525
break;
2626
}
27-
case EndStmtWithSemicolon::Never: {
28-
// is on same line as other statement -> needs to go on new line
29-
if (!IsFirstStmtOfLine(syntaxNode, t)) {
30-
InsertNewLineBeforeNode(syntaxNode, t);
31-
}
32-
if (EndsWithSemicolon(syntaxNode, t)) {
33-
RemoveSemicolon(syntaxNode, t);
27+
case EndStmtWithSemicolon::ReplaceWithNewline: {
28+
// no action needed when there's no semicolons at all!
29+
if (ContainsSemicolon(syntaxNode, t)) {
30+
if (EndsWithSemicolon(syntaxNode, t)) {
31+
RemoveSemicolon(syntaxNode, t);
32+
InsertNewLineBeforeNextNode(syntaxNode, t);
33+
}
3434
}
3535
break;
3636
}
@@ -82,9 +82,9 @@ void SemicolonAnalyzer::AddSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t) {
8282
}
8383
}
8484

85-
void SemicolonAnalyzer::InsertNewLineBeforeNode(LuaSyntaxNode n, const LuaSyntaxTree &t) {
86-
auto token = n.GetFirstToken(t); // line breaks are put in front of the statement itself by non-first statements
87-
if (token.IsToken(t)) {
85+
void SemicolonAnalyzer::InsertNewLineBeforeNextNode(LuaSyntaxNode n, const LuaSyntaxTree &t) {
86+
auto token = n.GetNextTokenSkipComment(t);
87+
if (token.IsToken(t) && token.GetStartLine(t) == n.GetEndLine(t)) {
8888
_semicolon[token.GetIndex()] = SemicolonStrategy::InsertNewLine;
8989
}
9090
}
@@ -96,17 +96,6 @@ void SemicolonAnalyzer::RemoveSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t)
9696
}
9797
}
9898

99-
bool SemicolonAnalyzer::IsFirstStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree &t) {
100-
// check if current stmt starts on same line as the previous one ends
101-
auto startCurrent = n.GetStartLine(t);
102-
auto prev = n.GetPrevToken(t);
103-
if (!prev.IsNull(t)) {
104-
auto endPrev = prev.GetEndLine(t);
105-
return endPrev < startCurrent;
106-
}
107-
return true;// there's no previous token
108-
}
109-
11099
bool SemicolonAnalyzer::IsLastStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree &t) {
111100
// check if next stmt starts on same line as the current one ends
112101
auto currentEnd = n.GetEndLine(t);
@@ -123,6 +112,10 @@ bool SemicolonAnalyzer::EndsWithSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &
123112
return token.GetTokenKind(t) == ';';
124113
}
125114

115+
bool SemicolonAnalyzer::ContainsSemicolon(LuaSyntaxNode n, const LuaSyntaxTree &t) {
116+
return n.GetChildToken(';', t).IsToken(t);
117+
}
118+
126119
LuaSyntaxNode SemicolonAnalyzer::GetLastNonCommentToken(LuaSyntaxNode n, const LuaSyntaxTree &t) {
127120
auto token = n.GetLastToken(t);
128121
switch (token.GetTokenKind(t)) {

Test/src/FormatStyle_unitest.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,7 @@ local table1 = { 1, 2, 3 };
16211621
)",
16221622
style));
16231623

1624-
style.end_statement_with_semicolon = EndStmtWithSemicolon::Never;
1624+
style.end_statement_with_semicolon = EndStmtWithSemicolon::ReplaceWithNewline;
16251625
EXPECT_TRUE(TestHelper::TestFormatted(
16261626
R"(
16271627
local func = testFunc; print(type(nil)); -- nil;
@@ -1634,6 +1634,8 @@ for i, v in ipairs(values) do
16341634
end;
16351635
end;
16361636
local table1 = { 1, 2, 3 }
1637+
local opts = { on_exit = function() job = nil end }
1638+
local opts = { on_exit = function() job = nil; end };
16371639
)",
16381640
R"(
16391641
local func = testFunc
@@ -1649,6 +1651,9 @@ for i, v in ipairs(values) do
16491651
end
16501652
end
16511653
local table1 = { 1, 2, 3 }
1654+
local opts = { on_exit = function() job = nil end }
1655+
local opts = { on_exit = function() job = nil
1656+
end }
16521657
)",
16531658
style));
16541659

docs/format_config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,5 +538,5 @@ end_statement_with_semicolon
538538
每条语句都应该以分号结束,缺失的分号将被添加。
539539
- same_line
540540
单行中的多个语句可以用必要的分号分隔,但可选的分号将被移除
541-
- never
541+
- replace_with_newline
542542
任何语句都不能以分号结束,语句末尾的所有分号都将被移除,包含多个语句的行将被分隔成多行

docs/format_config_EN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,5 +535,5 @@ The possible values are:
535535
every statement should end with semicolon, missing semicolons will be added
536536
- same_line
537537
multiple statements in a single line may be separated by necessary semicolons, but optional semicolons will be removed
538-
- never
538+
- replace_with_newline
539539
no statement should end with semicolon, all semicolons at the end of statements will be removed, lines with multiple statements will be separated into multiple lines

0 commit comments

Comments
 (0)