diff --git a/grammars/csharp.tmLanguage b/grammars/csharp.tmLanguage index 6b6a385..633efa1 100644 --- a/grammars/csharp.tmLanguage +++ b/grammars/csharp.tmLanguage @@ -660,7 +660,7 @@ attribute-section begin - (\[)(assembly|module|field|event|method|param|property|return|type)?(\:)? + (\[)(assembly|module|event|field|method|param|property|return|type|typevar)?(\:)? beginCaptures 1 @@ -2725,12 +2725,38 @@ include #ref-modifier + + include + #lambda-expression + include #expression + lambda-expression + + begin + (?=(?:\[.*\].*)?\(.*\).*=>) + end + (?=;) + patterns + + + include + #attribute-section + + + include + #parenthesized-parameter-list + + + include + #expression-body + + + expression-body begin @@ -7270,6 +7296,10 @@ include #parameter + + include + #parameter-identifier + include #punctuation-comma @@ -7333,6 +7363,13 @@ + parameter-identifier + + name + entity.name.variable.parameter.cs + match + (?<!\.)@?\b[_[:alpha:]][_[:alnum:]]*\b(?!\.) + argument-list begin diff --git a/grammars/csharp.tmLanguage.cson b/grammars/csharp.tmLanguage.cson index 3f09e3e..c3252c7 100644 --- a/grammars/csharp.tmLanguage.cson +++ b/grammars/csharp.tmLanguage.cson @@ -441,7 +441,7 @@ repository: } ] "attribute-section": - begin: "(\\[)(assembly|module|field|event|method|param|property|return|type)?(\\:)?" + begin: "(\\[)(assembly|module|event|field|method|param|property|return|type|typevar)?(\\:)?" beginCaptures: "1": name: "punctuation.squarebracket.open.cs" @@ -1738,10 +1738,27 @@ repository: { include: "#ref-modifier" } + { + include: "#lambda-expression" + } { include: "#expression" } ] + "lambda-expression": + begin: "(?=(?:\\[.*\\].*)?\\(.*\\).*=>)" + end: "(?=;)" + patterns: [ + { + include: "#attribute-section" + } + { + include: "#parenthesized-parameter-list" + } + { + include: "#expression-body" + } + ] "expression-body": begin: "=>" beginCaptures: @@ -4383,6 +4400,9 @@ repository: { include: "#parameter" } + { + include: "#parameter-identifier" + } { include: "#punctuation-comma" } @@ -4430,6 +4450,9 @@ repository: ] "7": name: "entity.name.variable.parameter.cs" + "parameter-identifier": + name: "entity.name.variable.parameter.cs" + match: "(?) + end: (?=;) + patterns: + - include: '#attribute-section' + - include: '#parenthesized-parameter-list' + - include: '#expression-body' + expression-body: begin: => beginCaptures: @@ -2823,6 +2832,7 @@ repository: - include: '#comment' - include: '#attribute-section' - include: '#parameter' + - include: '#lambda-parameter' - include: '#punctuation-comma' - include: '#variable-initializer' @@ -2865,6 +2875,10 @@ repository: # '6': ? is a sub-expression. It's final value is not considered. 7: { name: entity.name.variable.parameter.cs } + lambda-parameter: + name: entity.name.variable.parameter.cs + match: '(? { + const input = Input.InMethod(` +var concat = ([DisallowNull] string a, [DisallowNull] string b) => a + b; +var inc = [return: NotNullIfNotNull(nameof(s))] (int? s) => s.HasValue ? s++ : null; +Func parse = [ProvidesNullCheck] (s) => (s is not null) ? int.Parse(s) : null; +`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.Keyword.Definition.Var, + Token.Identifier.LocalName("concat"), + Token.Operator.Assignment, + Token.Punctuation.OpenParen, + Token.Punctuation.OpenBracket, + Token.Type("DisallowNull"), + Token.Punctuation.CloseBracket, + Token.PrimitiveType.String, + Token.Identifier.ParameterName("a"), + Token.Punctuation.Comma, + Token.Punctuation.OpenBracket, + Token.Type("DisallowNull"), + Token.Punctuation.CloseBracket, + Token.PrimitiveType.String, + Token.Identifier.ParameterName("b"), + Token.Punctuation.CloseParen, + Token.Operator.Arrow, + Token.Variable.ReadWrite("a"), + Token.Operator.Arithmetic.Addition, + Token.Variable.ReadWrite("b"), + Token.Punctuation.Semicolon, + + Token.Keyword.Definition.Var, + Token.Identifier.LocalName("inc"), + Token.Operator.Assignment, + Token.Punctuation.OpenBracket, + Token.Keyword.AttributeSpecifier("return"), + Token.Punctuation.Colon, + Token.Type("NotNullIfNotNull"), + Token.Punctuation.OpenParen, + Token.Operator.Expression.NameOf, + Token.Punctuation.OpenParen, + Token.Variable.ReadWrite("s"), + Token.Punctuation.CloseParen, + Token.Punctuation.CloseParen, + Token.Punctuation.CloseBracket, + Token.Punctuation.OpenParen, + Token.PrimitiveType.Int, + Token.Punctuation.QuestionMark, + Token.Identifier.ParameterName("s"), + Token.Punctuation.CloseParen, + Token.Operator.Arrow, + Token.Variable.Object("s"), + Token.Punctuation.Accessor, + Token.Variable.Property("HasValue"), + Token.Operator.Conditional.QuestionMark, + Token.Variable.ReadWrite("s"), + Token.Operator.Increment, + Token.Operator.Conditional.Colon, + Token.Literal.Null, + Token.Punctuation.Semicolon, + + Token.Type("Func"), + Token.Punctuation.TypeParameter.Begin, + Token.PrimitiveType.String, + Token.Punctuation.QuestionMark, + Token.Punctuation.Comma, + Token.PrimitiveType.Int, + Token.Punctuation.QuestionMark, + Token.Punctuation.TypeParameter.End, + Token.Identifier.LocalName("parse"), + Token.Operator.Assignment, + Token.Punctuation.OpenBracket, + Token.Type("ProvidesNullCheck"), + Token.Punctuation.CloseBracket, + Token.Punctuation.OpenParen, + Token.Identifier.ParameterName("s"), + Token.Punctuation.CloseParen, + Token.Operator.Arrow, + Token.Punctuation.OpenParen, + Token.Variable.ReadWrite("s"), + Token.Operator.Pattern.Is, + Token.Operator.Pattern.Not, + Token.Literal.Null, + Token.Punctuation.CloseParen, + Token.Operator.Conditional.QuestionMark, + Token.PrimitiveType.Int, + Token.Punctuation.Accessor, + Token.Identifier.MethodName("Parse"), + Token.Punctuation.OpenParen, + Token.Variable.ReadWrite("s"), + Token.Punctuation.CloseParen, + Token.Operator.Conditional.Colon, + Token.Literal.Null, + Token.Punctuation.Semicolon + ]); + }); + it("async lambda assigned to dotted name (issue #142)", async () => { const input = Input.InMethod( `Something.listener = async args => { return true; };`