From 56a1d5843cf7732916594bef38f39a3ca853fb12 Mon Sep 17 00:00:00 2001 From: Daniel Jeong Date: Mon, 14 Aug 2023 13:23:03 +0000 Subject: [PATCH] WIP --- grammars/csharp.tmLanguage | 54 +++-- grammars/csharp.tmLanguage.cson | 41 ++-- src/csharp.tmLanguage.yml | 34 +-- test/patterns.tests.ts | 354 ++++++++++++++++++++++++++++++-- 4 files changed, 435 insertions(+), 48 deletions(-) diff --git a/grammars/csharp.tmLanguage b/grammars/csharp.tmLanguage index 905f1c4..23a0fa7 100644 --- a/grammars/csharp.tmLanguage +++ b/grammars/csharp.tmLanguage @@ -427,6 +427,10 @@ include #conditional-operator + + include + #assignment-expression + include #expression-operators @@ -3311,7 +3315,7 @@ end - (?=[)}\];:?=&|^]|!=) + (?=[)}\],;:?=&|^]|!=) patterns @@ -3431,7 +3435,7 @@ end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3453,7 +3457,7 @@ end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3530,14 +3534,14 @@ begin (?=@?[_[:alpha:]][_[:alnum:]]*) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns begin \G end - (?=\s|[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=\s|[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3566,7 +3570,7 @@ begin (?=\s) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3594,7 +3598,7 @@ begin (?=\() end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3634,7 +3638,7 @@ begin (?<=\)) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3658,7 +3662,7 @@ begin (?={) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3698,7 +3702,7 @@ begin (?<=\}) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3756,7 +3760,7 @@ begin (?=\[) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -3796,7 +3800,7 @@ begin (?<=\]) end - (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns @@ -6156,6 +6160,32 @@ + assignment-expression + + begin + (=)(?!=|>) + beginCaptures + + 1 + + name + keyword.operator.assignment.cs + + + end + (?=[,\)\];}]) + patterns + + + include + #ref-modifier + + + include + #expression + + + expression-operators patterns diff --git a/grammars/csharp.tmLanguage.cson b/grammars/csharp.tmLanguage.cson index 72c5344..63907e9 100644 --- a/grammars/csharp.tmLanguage.cson +++ b/grammars/csharp.tmLanguage.cson @@ -303,6 +303,9 @@ repository: { include: "#conditional-operator" } + { + include: "#assignment-expression" + } { include: "#expression-operators" } @@ -2042,7 +2045,7 @@ repository: beginCaptures: "1": name: "keyword.other.is.cs" - end: "(?=[)}\\];:?=&|^]|!=)" + end: "(?=[)}\\],;:?=&|^]|!=)" patterns: [ { include: "#pattern" @@ -2119,7 +2122,7 @@ repository: beginCaptures: "0": name: "keyword.operator.relational.cs" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#expression" @@ -2130,7 +2133,7 @@ repository: beginCaptures: "1": name: "keyword.other.var.cs" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#designation-pattern" @@ -2175,11 +2178,11 @@ repository: ] "type-pattern": begin: "(?=@?[_[:alpha:]][_[:alnum:]]*)" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { begin: "\\G" - end: "(?=\\s|[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=\\s|[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#type-builtin" @@ -2200,7 +2203,7 @@ repository: } { begin: "(?=\\s)" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#intrusive" @@ -2219,7 +2222,7 @@ repository: ] "positional-pattern": begin: "(?=\\()" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { begin: "\\(" @@ -2241,7 +2244,7 @@ repository: } { begin: "(?<=\\))" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#intrusive" @@ -2257,7 +2260,7 @@ repository: ] "property-pattern": begin: "(?={)" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { begin: "\\{" @@ -2279,7 +2282,7 @@ repository: } { begin: "(?<=\\})" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#intrusive" @@ -2314,7 +2317,7 @@ repository: ] "list-pattern": begin: "(?=\\[)" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { begin: "\\[" @@ -2336,7 +2339,7 @@ repository: } { begin: "(?<=\\])" - end: "(?=[)}\\];:?=&|^]|!=|\\b(and|or|when)\\b)" + end: "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)" patterns: [ { include: "#intrusive" @@ -3660,6 +3663,20 @@ repository: endCaptures: "0": name: "punctuation.separator.colon.cs" + "assignment-expression": + begin: "(=)(?!=|>)" + beginCaptures: + "1": + name: "keyword.operator.assignment.cs" + end: "(?=[,\\)\\];}])" + patterns: [ + { + include: "#ref-modifier" + } + { + include: "#expression" + } + ] "expression-operators": patterns: [ { diff --git a/src/csharp.tmLanguage.yml b/src/csharp.tmLanguage.yml index 478c32c..41fd2cc 100644 --- a/src/csharp.tmLanguage.yml +++ b/src/csharp.tmLanguage.yml @@ -123,6 +123,7 @@ repository: - include: '#switch-statement-or-expression' - include: '#with-expression' - include: '#conditional-operator' + - include: '#assignment-expression' - include: '#expression-operators' - include: '#await-expression' - include: '#query-expression' @@ -1216,7 +1217,7 @@ repository: begin: (?=? beginCaptures: 0: { name: keyword.operator.relational.cs } - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#expression' @@ -1264,7 +1265,7 @@ repository: begin: \b(var)\b beginCaptures: 1: { name: keyword.other.var.cs } - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#designation-pattern' @@ -1290,10 +1291,10 @@ repository: type-pattern: begin: (?=@?[_[:alpha:]][_[:alnum:]]*) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - begin: \G - end: (?=\s|[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=\s|[)}\],;:?=&|^]|!=|\b(and|or|when)\b) # hacky solution - can't have whitespace/comments/preprocessor around dot patterns: # - include: '#intrusive' @@ -1303,7 +1304,7 @@ repository: - include: '#type-array-suffix' - include: '#type-nullable-suffix' - begin: (?=\s) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#intrusive' - include: '#positional-pattern' @@ -1312,7 +1313,7 @@ repository: positional-pattern: begin: (?=\() - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - begin: \( beginCaptures: @@ -1324,7 +1325,7 @@ repository: - include: '#subpattern' - include: '#punctuation-comma' - begin: (?<=\)) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#intrusive' - include: '#property-pattern' @@ -1332,7 +1333,7 @@ repository: property-pattern: begin: (?={) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - begin: \{ beginCaptures: @@ -1344,7 +1345,7 @@ repository: - include: '#subpattern' - include: '#punctuation-comma' - begin: (?<=\}) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#intrusive' - include: '#simple-designation-pattern' @@ -1363,7 +1364,7 @@ repository: list-pattern: begin: (?=\[) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - begin: \[ beginCaptures: @@ -1375,7 +1376,7 @@ repository: - include: '#pattern' - include: '#punctuation-comma' - begin: (?<=\]) - end: (?=[)}\];:?=&|^]|!=|\b(and|or|when)\b) + end: (?=[)}\],;:?=&|^]|!=|\b(and|or|when)\b) patterns: - include: '#intrusive' - include: '#simple-designation-pattern' @@ -2327,6 +2328,15 @@ repository: endCaptures: '0': { name: punctuation.separator.colon.cs } + assignment-expression: + begin: (=)(?!=|>) + beginCaptures: + 1: { name: keyword.operator.assignment.cs } + end: (?=[,\)\];}]) + patterns: + - include: '#ref-modifier' + - include: '#expression' + expression-operators: patterns: - name: keyword.operator.assignment.compound.cs diff --git a/test/patterns.tests.ts b/test/patterns.tests.ts index c950c52..a4a1bc0 100644 --- a/test/patterns.tests.ts +++ b/test/patterns.tests.ts @@ -5,51 +5,381 @@ describe("Patterns", () => { before(should); describe("is operator", () => { - it("relational pattern", async () => { + it("Discard pattern", async () => { + const input = Input.InMethod(` +if (var is _) { } +`); + const tokens = await tokenize(input); + tokens.should.deep.equal([ + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Variables.Discard, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + ]); }); - it("constant pattern", async () => { + it("Constant pattern", async () => { + const input = Input.InMethod(` +if (var is 0) { } +if (var is null) { } +if (var is "") { } +if (var is true) { } +`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Literals.Numeric.Decimal("0"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Literals.Null, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Punctuation.String.Begin, + Token.Punctuation.String.End, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Literals.Boolean.True, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + ]); }); - it("declaration pattern", async () => { + it("Relational pattern", async () => { + const input = Input.InMethod(` +if (var is > 0) { } +if (var is < 0) { } +if (var is >= 0) { } +if (var is <= 0) { } +`); + const tokens = await tokenize(input); + tokens.should.deep.equal([ + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Operators.Relational.GreaterThan, + Token.Literals.Numeric.Decimal("0"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Operators.Relational.LessThan, + Token.Literals.Numeric.Decimal("0"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Operators.Relational.GreaterThanOrEqual, + Token.Literals.Numeric.Decimal("0"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Operators.Relational.LessThanOrEqual, + Token.Literals.Numeric.Decimal("0"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + ]); }); - it("var pattern", async () => { + it("Declaration pattern", async () => { + const input = Input.InMethod(` +if (var is string str) { } +if (var is List list) { } +if (var is int[,] arr) { } +if (var is Dictionary> dict) { } +`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.PrimitiveType.String, + Token.Identifiers.LocalName("str"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Type("List"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.Int, + Token.Punctuation.TypeParameters.End, + Token.Identifiers.LocalName("list"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.PrimitiveType.Int, + Token.Punctuation.OpenBracket, + Token.Punctuation.Comma, + Token.Punctuation.CloseBracket, + Token.Identifiers.LocalName("arr"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Type("Dictionary"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.String, + Token.Punctuation.Comma, + Token.Type("List"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.Int, + Token.Punctuation.TypeParameters.End, + Token.Punctuation.TypeParameters.End, + Token.Identifiers.LocalName("dict"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + ]); }); - it("type pattern", async () => { + it("var pattern", async () => { + const input = Input.InMethod(` +if (var is var var) { } +if (var is var (var, var)) { } +if (var is var _) { } +if (var is var (var, _)) { } +`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Keywords.Var, + Token.Identifiers.LocalName("var"), + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Keywords.Var, + Token.Punctuation.OpenParen, + Token.Identifiers.LocalName("var"), + Token.Punctuation.Comma, + Token.Identifiers.LocalName("var"), + Token.Punctuation.CloseParen, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Keywords.Var, + Token.Variables.Discard, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + + Token.Keywords.Control.If, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("var"), + Token.Keywords.Is, + Token.Keywords.Var, + Token.Punctuation.OpenParen, + Token.Identifiers.LocalName("var"), + Token.Punctuation.Comma, + Token.Variables.Discard, + Token.Punctuation.CloseParen, + Token.Punctuation.CloseParen, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + ]); }); - it("positional pattern", async () => { + it("Type pattern", async () => { + const input = Input.InMethod(` +result = obj is string; +result = obj is List; +result = obj is int[,]; +result = obj is Dictionary>; +`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.Variables.ReadWrite("result"), + Token.Operators.Assignment, + Token.Variables.ReadWrite("obj"), + Token.Keywords.Is, + Token.PrimitiveType.String, + Token.Punctuation.Semicolon, + + Token.Variables.ReadWrite("result"), + Token.Operators.Assignment, + Token.Variables.ReadWrite("obj"), + Token.Keywords.Is, + Token.Type("List"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.Int, + Token.Punctuation.TypeParameters.End, + Token.Punctuation.Semicolon, + + Token.Variables.ReadWrite("result"), + Token.Operators.Assignment, + Token.Variables.ReadWrite("obj"), + Token.Keywords.Is, + Token.PrimitiveType.Int, + Token.Punctuation.OpenBracket, + Token.Punctuation.Comma, + Token.Punctuation.CloseBracket, + Token.Punctuation.Semicolon, + Token.Variables.ReadWrite("result"), + Token.Operators.Assignment, + Token.Variables.ReadWrite("obj"), + Token.Keywords.Is, + Token.Type("Dictionary"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.String, + Token.Punctuation.Comma, + Token.Type("List"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.Int, + Token.Punctuation.TypeParameters.End, + Token.Punctuation.TypeParameters.End, + Token.Punctuation.Semicolon, + ]); }); - it("property pattern", async () => { + it("Positional sub-pattern", async () => { + const input = Input.InMethod(` +result = (a, b, c, d, e) is +( + _, + null, + c: > 3, + string str, + e: List, +); +`); + const tokens = await tokenize(input); + tokens.should.deep.equal([ + Token.Variables.ReadWrite("result"), + Token.Operators.Assignment, + Token.Punctuation.OpenParen, + Token.Variables.ReadWrite("a"), + Token.Punctuation.Comma, + Token.Variables.ReadWrite("b"), + Token.Punctuation.Comma, + Token.Variables.ReadWrite("c"), + Token.Punctuation.Comma, + Token.Variables.ReadWrite("d"), + Token.Punctuation.Comma, + Token.Variables.ReadWrite("e"), + Token.Punctuation.CloseParen, + Token.Keywords.Is, + Token.Punctuation.OpenParen, + + Token.Variables.Discard, + Token.Punctuation.Comma, + + Token.Literals.Null, + Token.Punctuation.Comma, + + Token.Variables.Property("c"), + Token.Punctuation.Colon, + Token.Operators.Relational.GreaterThan, + Token.Literals.Numeric.Decimal("3"), + Token.Punctuation.Comma, + + Token.PrimitiveType.String, + Token.Identifiers.LocalName("str"), + Token.Punctuation.Comma, + + Token.Variables.Property("e"), + Token.Punctuation.Colon, + Token.Type("List"), + Token.Punctuation.TypeParameters.Begin, + Token.PrimitiveType.Object, + Token.Punctuation.TypeParameters.End, + Token.Punctuation.Comma, + + Token.Punctuation.CloseParen, + Token.Punctuation.Semicolon, + ]); }); - it("discard pattern", async () => { + it("Property pattern", async () => { }); - it("list pattern", async () => { + it("List pattern", async () => { }); - it("slice pattern", async () => { + it("Slice pattern", async () => { }); - it("pattern combinators", async () => { + it("Pattern combinators", async () => { }); - it("parenthesized pattern", async () => { + it("Parenthesized pattern", async () => { }); });