diff --git a/CodeFormatCore/CMakeLists.txt b/CodeFormatCore/CMakeLists.txt index 4a41cd80..6aeceb0c 100644 --- a/CodeFormatCore/CMakeLists.txt +++ b/CodeFormatCore/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(CodeFormatCore src/Format/Analyzer/FormatDocAnalyze.cpp src/Format/Analyzer/AlignAnalyzer.cpp src/Format/Analyzer/TokenAnalyzer.cpp + src/Format/Analyzer/SemicolonAnalyzer.cpp src/Format/Analyzer/FormatResolve.cpp src/Format/Analyzer/SyntaxNodeHelper.cpp # rangeFormat @@ -51,7 +52,7 @@ target_sources(CodeFormatCore src/Diagnostic/Spell/TextParser.cpp # diagnostic/codestyle src/Diagnostic/CodeStyle/CodeStyleChecker.cpp - ) + ) if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_compile_options(CodeFormatCore PUBLIC /utf-8) diff --git a/CodeFormatCore/include/CodeFormatCore/Config/LuaStyle.h b/CodeFormatCore/include/CodeFormatCore/Config/LuaStyle.h index 29e4ab3f..0785961c 100644 --- a/CodeFormatCore/include/CodeFormatCore/Config/LuaStyle.h +++ b/CodeFormatCore/include/CodeFormatCore/Config/LuaStyle.h @@ -152,4 +152,6 @@ class LuaStyle { bool leading_comma_style = false; bool table_list_special_continue_indent = true; + + EndStmtWithSemicolon end_statement_with_semicolon = EndStmtWithSemicolon(EndStmtWithSemicolon::Keep); }; diff --git a/CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h b/CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h index 3837aced..560b4cd9 100644 --- a/CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h +++ b/CodeFormatCore/include/CodeFormatCore/Config/LuaStyleEnum.h @@ -83,4 +83,11 @@ enum class AlignChainExpr { None, Always, OnlyCallStmt +}; + +enum class EndStmtWithSemicolon { + Keep, + Never, + Always, + SameLine }; \ No newline at end of file diff --git a/CodeFormatCore/include/CodeFormatCore/Diagnostic/DiagnosticType.h b/CodeFormatCore/include/CodeFormatCore/Diagnostic/DiagnosticType.h index 6e4665c6..62662d24 100644 --- a/CodeFormatCore/include/CodeFormatCore/Diagnostic/DiagnosticType.h +++ b/CodeFormatCore/include/CodeFormatCore/Diagnostic/DiagnosticType.h @@ -11,6 +11,7 @@ enum class DiagnosticType { StatementLineSpace, EndWithNewLine, Indent, + Semicolon, NameStyle, Spell }; diff --git a/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatAnalyzerType.h b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatAnalyzerType.h index ecedf449..c56d601e 100644 --- a/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatAnalyzerType.h +++ b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatAnalyzerType.h @@ -7,7 +7,7 @@ enum class FormatAnalyzerType { AlignAnalyzer, TokenAnalyzer, FormatDocAnalyze, - + SemicolonAnalyzer, Count, }; diff --git a/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatStrategy.h b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatStrategy.h index 4f81116c..dfc57018 100644 --- a/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatStrategy.h +++ b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/FormatStrategy.h @@ -24,13 +24,16 @@ enum class TokenStrategy { StringDoubleQuote, TableSepSemicolon, TableSepComma, - OriginRange + OriginRange, + StmtEndSemicolon, + NewLineBeforeToken }; enum class TokenAddStrategy { None, TableAddColon, - TableAddComma + TableAddComma, + StmtEndSemicolon }; enum class IndentStrategy { @@ -120,3 +123,9 @@ struct AlignGroup { bool Resolve; std::size_t AlignPos; }; + +enum class SemicolonStrategy { + Add, + Remove, + InsertNewLine +}; \ No newline at end of file diff --git a/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/SemicolonAnalyzer.h b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/SemicolonAnalyzer.h new file mode 100644 index 00000000..e242477f --- /dev/null +++ b/CodeFormatCore/include/CodeFormatCore/Format/Analyzer/SemicolonAnalyzer.h @@ -0,0 +1,28 @@ +#pragma once + +#include "FormatAnalyzer.h" +#include "FormatStrategy.h" +#include +#include + +class SemicolonAnalyzer : public FormatAnalyzer { +public: + DECLARE_FORMAT_ANALYZER(SemicolonAnalyzer) + + SemicolonAnalyzer(); + + void Analyze(FormatState& f, const LuaSyntaxTree& t) override; + + void Query(FormatState& f, LuaSyntaxNode syntaxNode, const LuaSyntaxTree& t, FormatResolve& resolve) override; + +private: + void AddSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t); + void InsertNewLineBeforeNode(LuaSyntaxNode n, const LuaSyntaxTree& t); + void RemoveSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t); + bool IsFirstStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree& t); + bool IsLastStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree& t); + bool EndsWithSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t); + LuaSyntaxNode GetLastNonCommentToken(LuaSyntaxNode n, const LuaSyntaxTree& t); + + std::unordered_map _semicolon; +}; \ No newline at end of file diff --git a/CodeFormatCore/src/Config/LuaStyle.cpp b/CodeFormatCore/src/Config/LuaStyle.cpp index a927733e..36712c19 100644 --- a/CodeFormatCore/src/Config/LuaStyle.cpp +++ b/CodeFormatCore/src/Config/LuaStyle.cpp @@ -268,4 +268,26 @@ void LuaStyle::ParseFromMap(std::map> &con BOOL_OPTION(ignore_space_after_colon) BOOL_OPTION(remove_call_expression_list_finish_comma) + + //if (configMap.count("align_chain_expr")) { + // if (configMap.at("align_chain_expr") == "none") { + // align_chain_expr = AlignChainExpr::None; + // } else if (configMap.at("align_chain_expr") == "always") { + // align_chain_expr = AlignChainExpr::Always; + // } else if (configMap.at("align_chain_expr") == "only_call_stmt") { + // align_chain_expr = AlignChainExpr::OnlyCallStmt; + // } + //} + + if (configMap.count("end_statement_with_semicolon")) { + if (configMap.at("end_statement_with_semicolon") == "keep") { + end_statement_with_semicolon = EndStmtWithSemicolon::Keep; + } else if (configMap.at("end_statement_with_semicolon") == "always") { + end_statement_with_semicolon = EndStmtWithSemicolon::Always; + } else if (configMap.at("end_statement_with_semicolon") == "never") { + end_statement_with_semicolon = EndStmtWithSemicolon::Never; + } else if (configMap.at("end_statement_with_semicolon") == "sameLine") { + end_statement_with_semicolon = EndStmtWithSemicolon::SameLine; + } + } } diff --git a/CodeFormatCore/src/Diagnostic/CodeStyle/CodeStyleChecker.cpp b/CodeFormatCore/src/Diagnostic/CodeStyle/CodeStyleChecker.cpp index 52f783df..3a431a25 100644 --- a/CodeFormatCore/src/Diagnostic/CodeStyle/CodeStyleChecker.cpp +++ b/CodeFormatCore/src/Diagnostic/CodeStyle/CodeStyleChecker.cpp @@ -94,11 +94,35 @@ void CodeStyleChecker::BasicResolve(LuaSyntaxNode syntaxNode, const LuaSyntaxTre break; } + case TokenStrategy::StmtEndSemicolon: { + switch (d.GetState().GetStyle().end_statement_with_semicolon) { + case EndStmtWithSemicolon::Never: + d.PushDiagnostic(DiagnosticType::Semicolon, textRange, + LText("Statement should not end with ;")); + break; + case EndStmtWithSemicolon::SameLine: + d.PushDiagnostic(DiagnosticType::Semicolon, textRange, + LText("; should only separate multiple statements on a single line")); + break; + default: + break; + } + break; + } default: { break; } } + switch (resolve.GetTokenAddStrategy()) { + case TokenAddStrategy::StmtEndSemicolon: + d.PushDiagnostic(DiagnosticType::Semicolon, textRange, + LText("Missing ; at end of statement")); + break; + default: + break; + } + switch (resolve.GetNextSpaceStrategy()) { case NextSpaceStrategy::Space: { auto nextToken = syntaxNode.GetNextToken(t); @@ -115,6 +139,18 @@ void CodeStyleChecker::BasicResolve(LuaSyntaxNode syntaxNode, const LuaSyntaxTre } } } + if (syntaxNode.IsNode(t)) { + auto textRange = syntaxNode.GetTextRange(t); + switch (resolve.GetTokenStrategy()) { + case TokenStrategy::StmtEndSemicolon: { + d.PushDiagnostic(DiagnosticType::Indent, textRange, LText("semicolon diagnostic")); + break; + } + default: { + break; + } + } + } } void CodeStyleChecker::ProcessSpaceDiagnostic(LuaSyntaxNode &node, LuaSyntaxNode &next, size_t shouldSpace, diff --git a/CodeFormatCore/src/Format/Analyzer/SemicolonAnalyzer.cpp b/CodeFormatCore/src/Format/Analyzer/SemicolonAnalyzer.cpp new file mode 100644 index 00000000..17525fc2 --- /dev/null +++ b/CodeFormatCore/src/Format/Analyzer/SemicolonAnalyzer.cpp @@ -0,0 +1,135 @@ +#include "CodeFormatCore/Format/Analyzer/SemicolonAnalyzer.h" +#include "CodeFormatCore/Format/FormatState.h" +#include "CodeFormatCore/Config/LuaStyleEnum.h" +#include +#include + +SemicolonAnalyzer::SemicolonAnalyzer() { + +} + +void SemicolonAnalyzer::Analyze(FormatState& f, const LuaSyntaxTree& t) { + if (f.GetStyle().end_statement_with_semicolon == EndStmtWithSemicolon::Keep) { + return; // No analysis needed + } + + for (auto syntaxNode : t.GetSyntaxNodes()) { + if (syntaxNode.IsNode(t)) { + if (detail::multi_match::StatementMatch(syntaxNode.GetSyntaxKind(t))) { + auto text = syntaxNode.GetText(t); + switch (f.GetStyle().end_statement_with_semicolon) { + case EndStmtWithSemicolon::Always: + // TODO handle stray semicolons that are unnecessarily added! + /*if (syntaxNode.GetTextRange(t).Length < 2) + break;*/ + if (!EndsWithSemicolon(syntaxNode, t)) { + AddSemicolon(syntaxNode, t); + } + break; + case EndStmtWithSemicolon::Never: + // is on same line as other statement -> needs to go on new line + if (!IsFirstStmtOfLine(syntaxNode, t)) { + InsertNewLineBeforeNode(syntaxNode, t); + } + if (EndsWithSemicolon(syntaxNode, t)) { + RemoveSemicolon(syntaxNode, t); + } + break; + case EndStmtWithSemicolon::SameLine: + if (EndsWithSemicolon(syntaxNode, t)) { + if (IsLastStmtOfLine(syntaxNode, t)) { + RemoveSemicolon(syntaxNode, t); + } + } + break; + default: + break; + } + } + } + } +} + +void SemicolonAnalyzer::Query(FormatState& f, LuaSyntaxNode n, const LuaSyntaxTree& t, FormatResolve& resolve) { + auto it = _semicolon.find(n.GetIndex()); + if (it != _semicolon.end()) { + auto& strategy = it->second; + switch (strategy) { + case SemicolonStrategy::Add: + resolve.SetTokenAddStrategy(TokenAddStrategy::StmtEndSemicolon); + break; + case SemicolonStrategy::Remove: + resolve.SetTokenStrategy(TokenStrategy::StmtEndSemicolon); + break; + case SemicolonStrategy::InsertNewLine: + resolve.SetTokenStrategy(TokenStrategy::NewLineBeforeToken); + break; + default: + break; + } + } +} + +void SemicolonAnalyzer::AddSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t) { + auto token = GetLastNonCommentToken(n, t); + if (token.IsToken(t)) { + _semicolon[token.GetIndex()] = SemicolonStrategy::Add; + } +} + +void SemicolonAnalyzer::InsertNewLineBeforeNode(LuaSyntaxNode n, const LuaSyntaxTree& t) { + auto token = n.GetFirstToken(t); // line breaks are put in front of the statement itself by non-first statements + if (token.IsToken(t)) { + _semicolon[token.GetIndex()] = SemicolonStrategy::InsertNewLine; + } +} + +void SemicolonAnalyzer::RemoveSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t) { + auto token = GetLastNonCommentToken(n, t); + if (token.IsToken(t)) { + _semicolon[token.GetIndex()] = SemicolonStrategy::Remove; + } +} + +bool SemicolonAnalyzer::IsFirstStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree& t) { + // check if current stmt starts on same line as the previous one ends + auto startCurrent = n.GetStartLine(t); + auto prev = n.GetPrevToken(t); + if (!prev.IsNull(t)) { + auto endPrev = prev.GetEndLine(t); + return endPrev < startCurrent; + } + return true; // there's no previous token +} + +bool SemicolonAnalyzer::IsLastStmtOfLine(LuaSyntaxNode n, const LuaSyntaxTree& t) { + // check if next stmt starts on same line as the current one ends + auto currentEnd = n.GetEndLine(t); + auto nextToken = n.GetNextToken(t); + if (!nextToken.IsNull(t)) { + auto nextStart = nextToken.GetStartLine(t); + return currentEnd != nextStart; + } + return true; // there's no next token +} + +bool SemicolonAnalyzer::EndsWithSemicolon(LuaSyntaxNode n, const LuaSyntaxTree& t) { + auto token = GetLastNonCommentToken(n, t); + auto text = token.GetText(t); + + return text == ";"; +} + +LuaSyntaxNode SemicolonAnalyzer::GetLastNonCommentToken(LuaSyntaxNode n, const LuaSyntaxTree& t) { + auto token = n.GetLastToken(t); + switch (token.GetTokenKind(t)) { + case TK_SHORT_COMMENT: + case TK_LONG_COMMENT: + case TK_SHEBANG: { + return token.GetPrevToken(t); + } + default: { + return token; + } + } +} \ No newline at end of file diff --git a/CodeFormatCore/src/Format/FormatBuilder.cpp b/CodeFormatCore/src/Format/FormatBuilder.cpp index 9b2bafa5..959c30c0 100644 --- a/CodeFormatCore/src/Format/FormatBuilder.cpp +++ b/CodeFormatCore/src/Format/FormatBuilder.cpp @@ -79,6 +79,7 @@ void FormatBuilder::DoResolve(LuaSyntaxNode &syntaxNode, const LuaSyntaxTree &t, WriteSyntaxNode(syntaxNode, t); break; } + case TokenStrategy::StmtEndSemicolon: case TokenStrategy::Remove: { break; } @@ -139,6 +140,11 @@ void FormatBuilder::DoResolve(LuaSyntaxNode &syntaxNode, const LuaSyntaxTree &t, } return; } + case TokenStrategy::NewLineBeforeToken: { + WriteLine(1); + WriteSyntaxNode(syntaxNode, t); + break; + } default: { break; } @@ -153,6 +159,10 @@ void FormatBuilder::DoResolve(LuaSyntaxNode &syntaxNode, const LuaSyntaxTree &t, WriteChar(';'); break; } + case TokenAddStrategy::StmtEndSemicolon: { + WriteChar(';'); + break; + } default: { break; } diff --git a/CodeFormatCore/src/Format/FormatState.cpp b/CodeFormatCore/src/Format/FormatState.cpp index 5b4f87a4..e8e69cdb 100644 --- a/CodeFormatCore/src/Format/FormatState.cpp +++ b/CodeFormatCore/src/Format/FormatState.cpp @@ -5,6 +5,7 @@ #include "CodeFormatCore/Format/Analyzer/LineBreakAnalyzer.h" #include "CodeFormatCore/Format/Analyzer/SpaceAnalyzer.h" #include "CodeFormatCore/Format/Analyzer/TokenAnalyzer.h" +#include FormatState::FormatState(Mode mode) : _currentWidth(0), @@ -52,6 +53,7 @@ void FormatState::Analyze(const LuaSyntaxTree &t) { AddAnalyzer(); AddAnalyzer(); AddAnalyzer(); + AddAnalyzer(); _fileEndOfLine = t.GetFile().GetEndOfLine(); for (const auto &analyzer: _analyzers) { @@ -161,7 +163,8 @@ void FormatState::DfsForeach(std::vector &startNodes, } } for (auto &analyzer: _analyzers) { - analyzer->Query(*this, traverse.Node, t, resolve); + if(analyzer) + analyzer->Query(*this, traverse.Node, t, resolve); } auto children = traverse.Node.GetChildren(t); // 不采用 diff --git a/CodeFormatLib/src/CodeFormatLib.cpp b/CodeFormatLib/src/CodeFormatLib.cpp index eab75dfb..dcb7be72 100644 --- a/CodeFormatLib/src/CodeFormatLib.cpp +++ b/CodeFormatLib/src/CodeFormatLib.cpp @@ -41,6 +41,8 @@ std::string GetDiagnosisString(DiagnosticType type) { return "spell"; case DiagnosticType::StringQuote: return "string-quote"; + case DiagnosticType::Semicolon: + return "semicolon"; default: { break; } diff --git a/CodeFormatServer/src/Service/CodeActionService.cpp b/CodeFormatServer/src/Service/CodeActionService.cpp index 1bed66af..43ca7f74 100644 --- a/CodeFormatServer/src/Service/CodeActionService.cpp +++ b/CodeFormatServer/src/Service/CodeActionService.cpp @@ -18,7 +18,7 @@ bool CodeActionService::Initialize() { CodeProtocol(DiagnosticType::StringQuote, "string-quote", &CodeActionService::Reformat); CodeProtocol(DiagnosticType::EndWithNewLine, "end-with-new-line"); CodeProtocol(DiagnosticType::NameStyle, "name-style"); - + CodeProtocol(DiagnosticType::Semicolon, "semicolon"); return true; } diff --git a/LuaParser/src/Parse/LuaParser.cpp b/LuaParser/src/Parse/LuaParser.cpp index b852a7a3..2d727d65 100644 --- a/LuaParser/src/Parse/LuaParser.cpp +++ b/LuaParser/src/Parse/LuaParser.cpp @@ -218,6 +218,8 @@ void LuaParser::IfStatement() { } CheckAndNext(TK_END); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::IfStatement); } @@ -235,6 +237,8 @@ void LuaParser::WhileStatement() { CheckAndNext(TK_END); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::WhileStatement); } @@ -247,6 +251,8 @@ void LuaParser::DoStatement() { CheckAndNext(TK_END); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::DoStatement); } @@ -324,6 +330,8 @@ void LuaParser::ForBody() { CheckAndNext(TK_END); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::ForBody); } @@ -339,6 +347,8 @@ void LuaParser::RepeatStatement() { Condition(); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::RepeatStatement); } @@ -399,6 +409,8 @@ void LuaParser::LabelStatement() { CheckAndNext(TK_DBCOLON); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::LabelStatement); } @@ -697,6 +709,8 @@ void LuaParser::FunctionBody() { CheckAndNext(TK_END); + TestAndNext(';'); + m.Complete(*this, LuaSyntaxNodeKind::FunctionBody); } diff --git a/Test/src/FormatStyle_unitest.cpp b/Test/src/FormatStyle_unitest.cpp index b263cc0e..9a246ad4 100644 --- a/Test/src/FormatStyle_unitest.cpp +++ b/Test/src/FormatStyle_unitest.cpp @@ -1529,6 +1529,117 @@ local t = { a = 123 } +)", + style)); +} + +TEST(FormatByStyleOption, end_statement_with_semicolon) { + LuaStyle style; + + style.end_statement_with_semicolon = EndStmtWithSemicolon::Keep; + EXPECT_TRUE(TestHelper::TestFormatted( + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False") + end; +end; +local table1 = { 1, 2, 3 } +)", + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False") + end; +end; +local table1 = { 1, 2, 3 } +)", + style)); + + style.end_statement_with_semicolon = EndStmtWithSemicolon::Always; + EXPECT_TRUE(TestHelper::TestFormatted( + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False") + end; +end; +local table1 = { 1, 2, 3 } +)", + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World"); +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False"); + end; +end; +local table1 = { 1, 2, 3 }; +)", + style)); + + style.end_statement_with_semicolon = EndStmtWithSemicolon::Never; + EXPECT_TRUE(TestHelper::TestFormatted( + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False") + end; +end; +local table1 = { 1, 2, 3 } +)", + R"(local func = testFunc +print(type(nil)) -- nil; +print("Hello") +print(" ") --[[ test comment --]] +print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True") + else + print(i, v, "False") + end +end +local table1 = { 1, 2, 3 } +)", + style)); + + style.end_statement_with_semicolon = EndStmtWithSemicolon::SameLine; + EXPECT_TRUE(TestHelper::TestFormatted( + R"(local func = testFunc; print(type(nil)); -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True"); + else + print(i, v, "False") + end; +end; +local table1 = { 1, 2, 3 } +)", + R"(local func = testFunc; print(type(nil)) -- nil; +print("Hello"); print(" "); --[[ test comment --]] print("World") +for i, v in ipairs(values) do + if v then + print(i, v, "True") + else + print(i, v, "False") + end +end +local table1 = { 1, 2, 3 } )", style)); } \ No newline at end of file diff --git a/docs/format_config.md b/docs/format_config.md index 1a68140f..c053c7eb 100644 --- a/docs/format_config.md +++ b/docs/format_config.md @@ -527,3 +527,16 @@ line_space_after_comment = keep 该选项表示移除调用表达式中末尾逗号(这是一个扩展语法) +end_statement_with_semicolon + +该选项设置如何处理语句末尾的分号。 + +可能的值有 +- keep + 停用该选项 +- always + 每条语句都应该以分号结束,缺失的分号将被添加。 +- sameLine + 单行中的多个语句可以用必要的分号分隔,但可选的分号将被移除 +- never + 任何语句都不能以分号结束,语句末尾的所有分号都将被移除,包含多个语句的行将被分隔成多行 diff --git a/docs/format_config_EN.md b/docs/format_config_EN.md index 7fe35291..bbfe311e 100644 --- a/docs/format_config_EN.md +++ b/docs/format_config_EN.md @@ -523,3 +523,17 @@ This option indicates that formatting of blanks after the colon is ignored ### remove_call_expression_list_finish_comma This option removes the comma at the end of the invocation expression (this is an extended syntax) + +### end_statement_with_semicolon + +This option configures how the optional semicolon at the end of a statement should be handled. + +The possible values are: +- keep + deactivates this option +- always + every statement should end with semicolon, missing semicolons will be added +- sameLine + multiple statements in a single line may be separated by necessary semicolons, but optional semicolons will be removed +- never + 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 diff --git a/lua.template.editorconfig b/lua.template.editorconfig index 9c729d8b..9501fc14 100644 --- a/lua.template.editorconfig +++ b/lua.template.editorconfig @@ -141,3 +141,5 @@ break_before_braces = false ignore_space_after_colon = false remove_call_expression_list_finish_comma = false + +end_statement_with_semicolon = keep