aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvvvv <vvvv@ydb.tech>2023-03-01 15:42:46 +0300
committervvvv <vvvv@ydb.tech>2023-03-01 15:42:46 +0300
commit0a4eb28a1cfee4927aaf1539d9f6c65282764880 (patch)
tree58b3b858ae205e1f85b8f2b5953f5e17ad025c22
parente1562439ec58ebe106f3ddce6de45c32617cb3f1 (diff)
downloadydb-0a4eb28a1cfee4927aaf1539d9f6c65282764880.tar.gz
handle of multiline & tail commas
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format.cpp163
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format_ut.cpp378
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);
+ }
}