diff options
author | vvvv <vvvv@ydb.tech> | 2023-03-01 15:42:46 +0300 |
---|---|---|
committer | vvvv <vvvv@ydb.tech> | 2023-03-01 15:42:46 +0300 |
commit | 0a4eb28a1cfee4927aaf1539d9f6c65282764880 (patch) | |
tree | 58b3b858ae205e1f85b8f2b5953f5e17ad025c22 | |
parent | e1562439ec58ebe106f3ddce6de45c32617cb3f1 (diff) | |
download | ydb-0a4eb28a1cfee4927aaf1539d9f6c65282764880.tar.gz |
handle of multiline & tail commas
-rw-r--r-- | ydb/library/yql/sql/v1/format/sql_format.cpp | 163 | ||||
-rw-r--r-- | ydb/library/yql/sql/v1/format/sql_format_ut.cpp | 378 |
2 files changed, 524 insertions, 17 deletions
diff --git a/ydb/library/yql/sql/v1/format/sql_format.cpp b/ydb/library/yql/sql/v1/format/sql_format.cpp index eabca3cec7..96227ff72b 100644 --- a/ydb/library/yql/sql/v1/format/sql_format.cpp +++ b/ydb/library/yql/sql/v1/format/sql_format.cpp @@ -259,8 +259,9 @@ struct TStaticData { class TVisitor { friend struct TStaticData; public: - TVisitor(const TVector<NSQLTranslation::TParsedToken>& comments) + TVisitor(const TParsedTokenList& parsedTokens, const TParsedTokenList& comments) : StaticData(TStaticData::GetInstance()) + , ParsedTokens(parsedTokens) , Comments(comments) { } @@ -269,7 +270,14 @@ public: addLine = true; IsSimpleStatement.emplace_back(); Scopes.push_back(EScope::Default); + MarkedTokens.reserve(ParsedTokens.size()); + MarkTokens(msg); + Y_ENSURE(MarkTokenStack.empty()); + Y_ENSURE(TokenIndex == ParsedTokens.size()); + TokenIndex = 0; Visit(msg); + Y_ENSURE(TokenIndex == ParsedTokens.size()); + Y_ENSURE(MarkTokenStack.empty()); for (; LastComment < Comments.size(); ++LastComment) { const auto text = Comments[LastComment].Content; AddComment(text); @@ -285,6 +293,14 @@ public: } private: + struct TTokenInfo { + bool OpeningBracket = false; + bool ClosingBracket = false; + ui32 ClosingBracketIndex = 0; + }; + + using TMarkTokenStack = TVector<ui32>; + void Out(TStringBuf s) { for (ui32 i = 0; i < s.Size(); ++i) { Out(s[i], i == 0); @@ -327,6 +343,79 @@ private: Out(text); } + void MarkTokens(const NProtoBuf::Message& msg) { + const NProtoBuf::Descriptor* descr = msg.GetDescriptor(); + auto scopePtr = StaticData.ScopeDispatch.FindPtr(descr); + if (scopePtr) { + if (*scopePtr == EScope::TypeName) { + ++InsideType; + } + + Scopes.push_back(*scopePtr); + } + + if (descr == TToken::GetDescriptor()) { + const auto& token = dynamic_cast<const TToken&>(msg); + MarkToken(token); + } + + if (descr == TRule_lambda_body::GetDescriptor()) { + Y_ENSURE(TokenIndex >= 1); + auto prevIndex = TokenIndex - 1; + Y_ENSURE(prevIndex < ParsedTokens.size()); + Y_ENSURE(ParsedTokens[prevIndex].Content == "{"); + MarkedTokens[prevIndex].OpeningBracket = false; + } + + VisitAllFieldsImpl<&TVisitor::MarkTokens>(descr, msg); + if (scopePtr) { + if (*scopePtr == EScope::TypeName) { + --InsideType; + } + + Scopes.pop_back(); + } + } + + void MarkToken(const TToken& token) { + auto str = token.GetValue(); + if (str == "<EOF>") { + return; + } + + MarkedTokens.emplace_back(); + if (str == "(" || str == "[" || str == "{" || str == "<|" || (InsideType && str == "<")) { + MarkTokenStack.push_back(TokenIndex); + auto& info = MarkedTokens[TokenIndex]; + info.OpeningBracket = true; + } else if (str == ")") { + PopBracket("("); + } else if (str == "]") { + PopBracket("["); + } else if (str == "}") { + PopBracket("{"); + } else if (str == "|>") { + PopBracket("<|"); + } else if (InsideType && str == ">") { + PopBracket("<"); + } + + TokenIndex++; + } + + void PopBracket(const TString& expected) { + Y_ENSURE(!MarkTokenStack.empty()); + Y_ENSURE(MarkTokenStack.back() < ParsedTokens.size()); + Y_ENSURE(ParsedTokens[MarkTokenStack.back()].Content == expected); + auto& openInfo = MarkedTokens[MarkTokenStack.back()]; + if (openInfo.OpeningBracket) { + openInfo.ClosingBracketIndex = TokenIndex; + MarkedTokens[TokenIndex].ClosingBracket = true; + } + + MarkTokenStack.pop_back(); + } + void Visit(const NProtoBuf::Message& msg) { const NProtoBuf::Descriptor* descr = msg.GetDescriptor(); //Cerr << descr->name() << "\n"; @@ -988,30 +1077,36 @@ private: VisitAllFields(TRule_drop_object_stmt::GetDescriptor(), msg); } - void VisitCreateExternalDataSource(const TRule_create_external_data_source_stmt& msg) { - PosFromToken(msg.GetToken1()); - NewLine(); - VisitAllFields(TRule_create_external_data_source_stmt::GetDescriptor(), msg); - } - + void VisitCreateExternalDataSource(const TRule_create_external_data_source_stmt& msg) {
+ PosFromToken(msg.GetToken1());
+ NewLine();
+ VisitAllFields(TRule_create_external_data_source_stmt::GetDescriptor(), msg);
+ }
+
void VisitDropExternalDataSource(const TRule_drop_external_data_source_stmt& msg) { - PosFromToken(msg.GetToken1()); - NewLine(); - VisitAllFields(TRule_drop_external_data_source_stmt::GetDescriptor(), msg); + MarkAsSimple();
+ PosFromToken(msg.GetToken1());
+ NewLine();
+ VisitAllFields(TRule_drop_external_data_source_stmt::GetDescriptor(), msg);
} - void VisitAllFields(const NProtoBuf::Descriptor* descr, const NProtoBuf::Message& msg) { + template <void (TVisitor::*Func)(const NProtoBuf::Message&)> + void VisitAllFieldsImpl(const NProtoBuf::Descriptor* descr, const NProtoBuf::Message& msg) { for (int i = 0; i < descr->field_count(); ++i) { const NProtoBuf::FieldDescriptor* fd = descr->field(i); NProtoBuf::TConstField field(msg, fd); if (field.IsMessage()) { for (size_t j = 0; j < field.Size(); ++j) { - Visit(*field.template Get<NProtoBuf::Message>(j)); + (this->*Func)(*field.template Get<NProtoBuf::Message>(j)); } } } } + void VisitAllFields(const NProtoBuf::Descriptor* descr, const NProtoBuf::Message& msg) { + VisitAllFieldsImpl<&TVisitor::Visit>(descr, msg); + } + void WriteComments() { while (LastComment < Comments.size()) { const auto& c = Comments[LastComment]; @@ -1082,10 +1177,41 @@ private: AfterDollarOrAt = (str == "$" || str == "@"); + const auto& markedInfo = MarkedTokens[TokenIndex]; + if (markedInfo.ClosingBracket) { + Y_ENSURE(!MarkTokenStack.empty()); + auto beginTokenIndex = MarkTokenStack.back(); + if (ParsedTokens[beginTokenIndex].Line != ParsedTokens[TokenIndex].Line) { + // multiline + PopCurrentIndent(); + NewLine(); + } + + MarkTokenStack.pop_back(); + } + Out(str); if (str == ";") { Out('\n'); } + + if (markedInfo.OpeningBracket) { + MarkTokenStack.push_back(TokenIndex); + if (ParsedTokens[TokenIndex].Line != ParsedTokens[markedInfo.ClosingBracketIndex].Line) { + // multiline + PushCurrentIndent(); + NewLine(); + } + } + + if (str == "," && !MarkTokenStack.empty()) { + // add line for trailing comma + if (TokenIndex + 1 < ParsedTokens.size() && ParsedTokens[TokenIndex].Line != ParsedTokens[TokenIndex + 1].Line) { + NewLine(); + } + } + + TokenIndex++; } void VisitIntoValuesSource(const TRule_into_values_source& msg) { @@ -1747,7 +1873,8 @@ private: private: const TStaticData& StaticData; - const TVector<NSQLTranslation::TParsedToken>& Comments; + const TParsedTokenList& ParsedTokens; + const TParsedTokenList& Comments; TStringBuilder SB; ui32 OutColumn = 0; ui32 OutLine = 1; @@ -1767,6 +1894,10 @@ private: bool AfterQuestion = false; bool AfterLess = false; bool AfterKeyExpr = false; + + ui32 TokenIndex = 0; + TMarkTokenStack MarkTokenStack; + TVector<TTokenInfo> MarkedTokens; }; template <typename T> @@ -1935,11 +2066,13 @@ public: } TVector<NSQLTranslation::TParsedToken> comments; - TParsedTokenList stmtTokens; + TParsedTokenList parsedTokens, stmtTokens; auto onNextRawToken = [&](NSQLTranslation::TParsedToken&& token) { stmtTokens.push_back(token); if (token.Name == "COMMENT") { comments.emplace_back(std::move(token)); + } else if (token.Name != "WS" && token.Name != "EOF") { + parsedTokens.emplace_back(std::move(token)); } }; @@ -1954,7 +2087,7 @@ public: continue; } - TVisitor visitor(comments); + TVisitor visitor(parsedTokens, comments); bool addLine; auto currentFormattedQuery = visitor.Process(*message, addLine); TParsedTokenList stmtFormattedTokens; diff --git a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp index 2866b0d452..6b6befeb09 100644 --- a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp +++ b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp @@ -167,7 +167,7 @@ Y_UNIT_TEST_SUITE(CheckSqlFormatter) { TCases cases = { {"values (1);","VALUES\n\t(1);\n\n"}, {"values (1,2),(3,4);","VALUES\n\t(1, 2),\n\t(3, 4);\n\n"}, - {"values ('a\nb');","VALUES\n\t('a\nb');\n\n"}, + {"values ('a\nb');","VALUES\n\t(\n\t\t'a\nb'\n\t);\n\n"}, }; TSetup setup; @@ -276,7 +276,7 @@ Y_UNIT_TEST_SUITE(CheckSqlFormatter) { Y_UNIT_TEST(ExternalDataSourceOperations) { TCases cases = { {"creAte exTernAl daTa SouRce usEr With (a = \"b\")", - "CREATE EXTERNAL DATA SOURCE usEr WITH (a = \"b\");\n"}, + "CREATE EXTERNAL DATA SOURCE usEr WITH (a = \"b\");\n\n"}, {"dRop exTerNal Data SouRce usEr", "DROP EXTERNAL DATA SOURCE usEr;\n"}, }; @@ -783,4 +783,378 @@ Y_UNIT_TEST_SUITE(CheckSqlFormatter) { TSetup setup; setup.Run(cases); } + + Y_UNIT_TEST(MultiLineList) { + TCases cases = { + {"select [\n]", + "SELECT\n\t[\n\t];\n\n"}, + {"select [1\n]", + "SELECT\n\t[\n\t\t1\n\t];\n\n"}, + {"select [\n1]", + "SELECT\n\t[\n\t\t1\n\t];\n\n"}, + {"select [1,\n]", + "SELECT\n\t[\n\t\t1,\n\t];\n\n"}, + {"select [1\n,]", + "SELECT\n\t[\n\t\t1,\n\t];\n\n"}, + {"select [\n1,]", + "SELECT\n\t[\n\t\t1,\n\t];\n\n"}, + {"select [1,2,\n3,4]", + "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4\n\t];\n\n"}, + {"select [1,2,\n3,4,]", + "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4,\n\t];\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineTuple) { + TCases cases = { + {"select (\n)", + "SELECT\n\t(\n\t);\n\n"}, + {"select (1,\n)", + "SELECT\n\t(\n\t\t1,\n\t);\n\n"}, + {"select (1\n,)", + "SELECT\n\t(\n\t\t1,\n\t);\n\n"}, + {"select (\n1,)", + "SELECT\n\t(\n\t\t1,\n\t);\n\n"}, + {"select (1,2,\n3,4)", + "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4\n\t);\n\n"}, + {"select (1,2,\n3,4,)", + "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4,\n\t);\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineSet) { + TCases cases = { + {"select {\n}", + "SELECT\n\t{\n\t};\n\n"}, + {"select {1\n}", + "SELECT\n\t{\n\t\t1\n\t};\n\n"}, + {"select {\n1}", + "SELECT\n\t{\n\t\t1\n\t};\n\n"}, + {"select {1,\n}", + "SELECT\n\t{\n\t\t1,\n\t};\n\n"}, + {"select {1\n,}", + "SELECT\n\t{\n\t\t1,\n\t};\n\n"}, + {"select {\n1,}", + "SELECT\n\t{\n\t\t1,\n\t};\n\n"}, + {"select {1,2,\n3,4}", + "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4\n\t};\n\n"}, + {"select {1,2,\n3,4,}", + "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4,\n\t};\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineDict) { + TCases cases = { + {"select {0:1\n}", + "SELECT\n\t{\n\t\t0: 1\n\t};\n\n"}, + {"select {\n0:1}", + "SELECT\n\t{\n\t\t0: 1\n\t};\n\n"}, + {"select {0:1,\n}", + "SELECT\n\t{\n\t\t0: 1,\n\t};\n\n"}, + {"select {0:1\n,}", + "SELECT\n\t{\n\t\t0: 1,\n\t};\n\n"}, + {"select {\n0:1,}", + "SELECT\n\t{\n\t\t0: 1,\n\t};\n\n"}, + {"select {10:1,20:2,\n30:3,40:4}", + "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4\n\t};\n\n"}, + {"select {10:1,20:2,\n30:3,40:4,}", + "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4,\n\t};\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineFuncCall) { + TCases cases = { + {"select f(\n)", + "SELECT\n\tf(\n\t);\n\n"}, + {"select f(1\n)", + "SELECT\n\tf(\n\t\t1\n\t);\n\n"}, + {"select f(\n1)", + "SELECT\n\tf(\n\t\t1\n\t);\n\n"}, + {"select f(1,\n)", + "SELECT\n\tf(\n\t\t1,\n\t);\n\n"}, + {"select f(1\n,)", + "SELECT\n\tf(\n\t\t1,\n\t);\n\n"}, + {"select f(\n1,)", + "SELECT\n\tf(\n\t\t1,\n\t);\n\n"}, + {"select f(1,2,\n3,4)", + "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4\n\t);\n\n"}, + {"select f(1,2,\n3,4,)", + "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4,\n\t);\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineStruct) { + TCases cases = { + {"select <|\n|>", + "SELECT\n\t<|\n\t|>;\n\n"}, + {"select <|a:1\n|>", + "SELECT\n\t<|\n\t\ta: 1\n\t|>;\n\n"}, + {"select <|\na:1|>", + "SELECT\n\t<|\n\t\ta: 1\n\t|>;\n\n"}, + {"select <|a:1,\n|>", + "SELECT\n\t<|\n\t\ta: 1,\n\t|>;\n\n"}, + {"select <|a:1\n,|>", + "SELECT\n\t<|\n\t\ta: 1,\n\t|>;\n\n"}, + {"select <|\na:1,|>", + "SELECT\n\t<|\n\t\ta: 1,\n\t|>;\n\n"}, + {"select <|a:1,b:2,\nc:3,d:4|>", + "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4\n\t|>;\n\n"}, + {"select <|a:1,b:2,\nc:3,d:4,|>", + "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4,\n\t|>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineListType) { + TCases cases = { + {"select list<int32\n>", + "SELECT\n\tlist<\n\t\tint32\n\t>;\n\n"}, + {"select list<\nint32>", + "SELECT\n\tlist<\n\t\tint32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineOptionalType) { + TCases cases = { + {"select optional<int32\n>", + "SELECT\n\toptional<\n\t\tint32\n\t>;\n\n"}, + {"select optional<\nint32>", + "SELECT\n\toptional<\n\t\tint32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineStreamType) { + TCases cases = { + {"select stream<int32\n>", + "SELECT\n\tstream<\n\t\tint32\n\t>;\n\n"}, + {"select stream<\nint32>", + "SELECT\n\tstream<\n\t\tint32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineFlowType) { + TCases cases = { + {"select flow<int32\n>", + "SELECT\n\tflow<\n\t\tint32\n\t>;\n\n"}, + {"select flow<\nint32>", + "SELECT\n\tflow<\n\t\tint32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineSetType) { + TCases cases = { + {"select set<int32\n>", + "SELECT\n\tset<\n\t\tint32\n\t>;\n\n"}, + {"select set<\nint32>", + "SELECT\n\tset<\n\t\tint32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineTupleType) { + TCases cases = { + {"select tuple<\n>", + "SELECT\n\ttuple<\n\t\t \n\t>;\n\n"}, + {"select tuple<int32\n>", + "SELECT\n\ttuple<\n\t\tint32\n\t>;\n\n"}, + {"select tuple<\nint32>", + "SELECT\n\ttuple<\n\t\tint32\n\t>;\n\n"}, + {"select tuple<int32,\n>", + "SELECT\n\ttuple<\n\t\tint32,\n\t>;\n\n"}, + {"select tuple<int32\n,>", + "SELECT\n\ttuple<\n\t\tint32,\n\t>;\n\n"}, + {"select tuple<\nint32,>", + "SELECT\n\ttuple<\n\t\tint32,\n\t>;\n\n"}, + {"select tuple<\nint32,string,\ndouble,bool>", + "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool\n\t>;\n\n"}, + {"select tuple<\nint32,string,\ndouble,bool,>", + "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineStructType) { + TCases cases = { + {"select struct<\n>", + "SELECT\n\tstruct<\n\t\t \n\t>;\n\n"}, + {"select struct<a:int32\n>", + "SELECT\n\tstruct<\n\t\ta: int32\n\t>;\n\n"}, + {"select struct<\na:int32>", + "SELECT\n\tstruct<\n\t\ta: int32\n\t>;\n\n"}, + {"select struct<a:int32,\n>", + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>;\n\n"}, + {"select struct<a:int32\n,>", + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>;\n\n"}, + {"select struct<\na:int32,>", + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>;\n\n"}, + {"select struct<\na:int32,b:string,\nc:double,d:bool>", + "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>;\n\n"}, + {"select struct<\na:int32,b:string,\nc:double,d:bool,>", + "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineVariantOverTupleType) { + TCases cases = { + {"select variant<int32\n>", + "SELECT\n\tvariant<\n\t\tint32\n\t>;\n\n"}, + {"select variant<\nint32>", + "SELECT\n\tvariant<\n\t\tint32\n\t>;\n\n"}, + {"select variant<int32,\n>", + "SELECT\n\tvariant<\n\t\tint32,\n\t>;\n\n"}, + {"select variant<int32\n,>", + "SELECT\n\tvariant<\n\t\tint32,\n\t>;\n\n"}, + {"select variant<\nint32,>", + "SELECT\n\tvariant<\n\t\tint32,\n\t>;\n\n"}, + {"select variant<\nint32,string,\ndouble,bool>", + "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool\n\t>;\n\n"}, + {"select variant<\nint32,string,\ndouble,bool,>", + "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineVariantOverStructType) { + TCases cases = { + {"select variant<a:int32\n>", + "SELECT\n\tvariant<\n\t\ta: int32\n\t>;\n\n"}, + {"select variant<\na:int32>", + "SELECT\n\tvariant<\n\t\ta: int32\n\t>;\n\n"}, + {"select variant<a:int32,\n>", + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>;\n\n"}, + {"select variant<a:int32\n,>", + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>;\n\n"}, + {"select variant<\na:int32,>", + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>;\n\n"}, + {"select variant<\na:int32,b:string,\nc:double,d:bool>", + "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>;\n\n"}, + {"select variant<\na:int32,b:string,\nc:double,d:bool,>", + "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineEnum) { + TCases cases = { + {"select enum<a\n>", + "SELECT\n\tenum<\n\t\ta\n\t>;\n\n"}, + {"select enum<\na>", + "SELECT\n\tenum<\n\t\ta\n\t>;\n\n"}, + {"select enum<a,\n>", + "SELECT\n\tenum<\n\t\ta,\n\t>;\n\n"}, + {"select enum<a\n,>", + "SELECT\n\tenum<\n\t\ta,\n\t>;\n\n"}, + {"select enum<\na,>", + "SELECT\n\tenum<\n\t\ta,\n\t>;\n\n"}, + {"select enum<\na,b,\nc,d>", + "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d\n\t>;\n\n"}, + {"select enum<\na,b,\nc,d,>", + "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d,\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineResourceType) { + TCases cases = { + {"select resource<foo\n>", + "SELECT\n\tresource<\n\t\tfoo\n\t>;\n\n"}, + {"select resource<\nfoo>", + "SELECT\n\tresource<\n\t\tfoo\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineTaggedType) { + TCases cases = { + {"select tagged<int32,foo\n>", + "SELECT\n\ttagged<\n\t\tint32, foo\n\t>;\n\n"}, + {"select tagged<int32,\nfoo>", + "SELECT\n\ttagged<\n\t\tint32,\n\t\tfoo\n\t>;\n\n"}, + {"select tagged<int32\n,foo>", + "SELECT\n\ttagged<\n\t\tint32, foo\n\t>;\n\n"}, + {"select tagged<\nint32,foo>", + "SELECT\n\ttagged<\n\t\tint32, foo\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineDictType) { + TCases cases = { + {"select dict<int32,string\n>", + "SELECT\n\tdict<\n\t\tint32, string\n\t>;\n\n"}, + {"select dict<int32,\nstring>", + "SELECT\n\tdict<\n\t\tint32,\n\t\tstring\n\t>;\n\n"}, + {"select dict<int32\n,string>", + "SELECT\n\tdict<\n\t\tint32, string\n\t>;\n\n"}, + {"select dict<\nint32,string>", + "SELECT\n\tdict<\n\t\tint32, string\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } + + Y_UNIT_TEST(MultiLineCallableType) { + TCases cases = { + {"select callable<()->int32\n>", + "SELECT\n\tcallable<\n\t\t() -> int32\n\t>;\n\n"}, + {"select callable<\n()->int32>", + "SELECT\n\tcallable<\n\t\t() -> int32\n\t>;\n\n"}, + {"select callable<\n(int32)->int32>", + "SELECT\n\tcallable<\n\t\t(int32) -> int32\n\t>;\n\n"}, + {"select callable<\n(int32,\ndouble)->int32>", + "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32,\n\t\t\tdouble\n\t\t) -> int32\n\t>;\n\n"}, + {"select callable<\n(int32\n,double)->int32>", + "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32, double\n\t\t) -> int32\n\t>;\n\n"}, + }; + + TSetup setup; + setup.Run(cases); + } } |