diff --git a/grammars/csharp.tmLanguage b/grammars/csharp.tmLanguage
index 3906d58..81ce2a8 100644
--- a/grammars/csharp.tmLanguage
+++ b/grammars/csharp.tmLanguage
@@ -4878,6 +4878,10 @@
include
#local-tuple-var-deconstruction
+
+ include
+ #local-tuple-declaration-deconstruction
+
local-variable-declaration
@@ -5176,6 +5180,26 @@
+ local-tuple-declaration-deconstruction
+
+ match
+ (?x) # e.g. (int x, var y) = GetPoint();
+(?<tuple>\((?:[^\(\)]|\g<tuple>)+\))\s*
+(?!=>|==)(?==)
+ captures
+
+ 1
+
+ patterns
+
+
+ include
+ #tuple-declaration-deconstruction-element-list
+
+
+
+
+
tuple-deconstruction-assignment
match
diff --git a/grammars/csharp.tmLanguage.cson b/grammars/csharp.tmLanguage.cson
index 0fb74a7..650104c 100644
--- a/grammars/csharp.tmLanguage.cson
+++ b/grammars/csharp.tmLanguage.cson
@@ -2984,6 +2984,9 @@ repository:
{
include: "#local-tuple-var-deconstruction"
}
+ {
+ include: "#local-tuple-declaration-deconstruction"
+ }
]
"local-variable-declaration":
begin: '''
@@ -3196,6 +3199,19 @@ repository:
include: "#variable-initializer"
}
]
+ "local-tuple-declaration-deconstruction":
+ match: '''
+ (?x) # e.g. (int x, var y) = GetPoint();
+ (?\\((?:[^\\(\\)]|\\g)+\\))\\s*
+ (?!=>|==)(?==)
+ '''
+ captures:
+ "1":
+ patterns: [
+ {
+ include: "#tuple-declaration-deconstruction-element-list"
+ }
+ ]
"tuple-deconstruction-assignment":
match: '''
(?x)
diff --git a/src/csharp.tmLanguage.yml b/src/csharp.tmLanguage.yml
index 4576f37..6dd0cf9 100644
--- a/src/csharp.tmLanguage.yml
+++ b/src/csharp.tmLanguage.yml
@@ -1770,6 +1770,7 @@ repository:
- include: '#local-variable-declaration'
- include: '#local-function-declaration'
- include: '#local-tuple-var-deconstruction'
+ - include: '#local-tuple-declaration-deconstruction'
local-variable-declaration:
begin: |-
@@ -1930,6 +1931,16 @@ repository:
- include: '#comment'
- include: '#variable-initializer'
+ local-tuple-declaration-deconstruction:
+ match: |-
+ (?x) # e.g. (int x, var y) = GetPoint();
+ (?\((?:[^\(\)]|\g)+\))\s*
+ (?!=>|==)(?==)
+ captures:
+ '1':
+ patterns:
+ - include: '#tuple-declaration-deconstruction-element-list'
+
tuple-deconstruction-assignment:
match: |-
(?x)
diff --git a/test/tuple.tests.ts b/test/tuple.tests.ts
index f18c8df..7f37a42 100644
--- a/test/tuple.tests.ts
+++ b/test/tuple.tests.ts
@@ -423,5 +423,115 @@ describe("Tuples", () => {
Token.Punctuation.CloseBrace
]);
});
+
+ it("Deconstruct with mixed type and var (int _, var _)", async () => {
+ const input = Input.InMethod(`(int _, var _) = (1, 2);`);
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.OpenParen,
+ Token.PrimitiveType.Int,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.CloseParen,
+ Token.Operator.Assignment,
+ Token.Punctuation.OpenParen,
+ Token.Literal.Numeric.Decimal("1"),
+ Token.Punctuation.Comma,
+ Token.Literal.Numeric.Decimal("2"),
+ Token.Punctuation.CloseParen,
+ Token.Punctuation.Semicolon
+ ]);
+ });
+
+ it("Deconstruct with all vars and discards (var _, var _, var _)", async () => {
+ const input = Input.InMethod(`(var _, var _, var _) = ('a', 'b', 'c');`);
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.OpenParen,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.CloseParen,
+ Token.Operator.Assignment,
+ Token.Punctuation.OpenParen,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("a"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.Comma,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("b"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.Comma,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("c"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.CloseParen,
+ Token.Punctuation.Semicolon
+ ]);
+ });
+
+ it("Deconstruct with mixed type and var at top level (int _, var _)", async () => {
+ const input = Input.FromText(`(int _, var _) = (1, 2);`);
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.OpenParen,
+ Token.PrimitiveType.Int,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.CloseParen,
+ Token.Operator.Assignment,
+ Token.Punctuation.OpenParen,
+ Token.Literal.Numeric.Decimal("1"),
+ Token.Punctuation.Comma,
+ Token.Literal.Numeric.Decimal("2"),
+ Token.Punctuation.CloseParen,
+ Token.Punctuation.Semicolon
+ ]);
+ });
+
+ it("Deconstruct with all vars and discards at top level (var _, var _, var _)", async () => {
+ const input = Input.FromText(`(var _, var _, var _) = ('a', 'b', 'c');`);
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.OpenParen,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.Comma,
+ Token.Keyword.Definition.Var,
+ Token.Identifier.TupleElementName("_"),
+ Token.Punctuation.CloseParen,
+ Token.Operator.Assignment,
+ Token.Punctuation.OpenParen,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("a"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.Comma,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("b"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.Comma,
+ Token.Punctuation.Char.Begin,
+ Token.Literal.Char("c"),
+ Token.Punctuation.Char.End,
+ Token.Punctuation.CloseParen,
+ Token.Punctuation.Semicolon
+ ]);
+ });
});
});