diff --git a/grammars/csharp.tmLanguage b/grammars/csharp.tmLanguage index 3906d58..8c01b55 100644 --- a/grammars/csharp.tmLanguage +++ b/grammars/csharp.tmLanguage @@ -2109,13 +2109,18 @@ begin - \b(get)\b\s*(?=\{|;|=>|//|/\*|$) + (?:\b(readonly)\s+)?\b(get)\b\s*(?=\{|;|=>|//|/\*|$) beginCaptures 1 name - storage.type.accessor.$1.cs + storage.modifier.readonly.cs + + 2 + + name + storage.type.accessor.get.cs end diff --git a/grammars/csharp.tmLanguage.cson b/grammars/csharp.tmLanguage.cson index 0fb74a7..1ddb83f 100644 --- a/grammars/csharp.tmLanguage.cson +++ b/grammars/csharp.tmLanguage.cson @@ -1361,10 +1361,12 @@ repository: match: "\\b(private|protected|internal)\\b" } { - begin: "\\b(get)\\b\\s*(?=\\{|;|=>|//|/\\*|$)" + begin: "(?:\\b(readonly)\\s+)?\\b(get)\\b\\s*(?=\\{|;|=>|//|/\\*|$)" beginCaptures: "1": - name: "storage.type.accessor.$1.cs" + name: "storage.modifier.readonly.cs" + "2": + name: "storage.type.accessor.get.cs" end: "(?<=\\}|;)|(?=\\})" patterns: [ { diff --git a/src/csharp.tmLanguage.yml b/src/csharp.tmLanguage.yml index 4576f37..b2db184 100644 --- a/src/csharp.tmLanguage.yml +++ b/src/csharp.tmLanguage.yml @@ -773,9 +773,10 @@ repository: - include: '#attribute-section' - name: storage.modifier.$1.cs match: \b(private|protected|internal)\b - - begin: \b(get)\b\s*(?=\{|;|=>|//|/\*|$) + - begin: (?:\b(readonly)\s+)?\b(get)\b\s*(?=\{|;|=>|//|/\*|$) beginCaptures: - '1': { name: storage.type.accessor.$1.cs } + '1': { name: storage.modifier.readonly.cs } + '2': { name: storage.type.accessor.get.cs } end: (?<=\}|;)|(?=\}) patterns: - include: '#accessor-getter' diff --git a/test/property.tests.ts b/test/property.tests.ts index fda76e2..bdb7115 100644 --- a/test/property.tests.ts +++ b/test/property.tests.ts @@ -503,5 +503,71 @@ int Property // comment Token.Punctuation.CloseBrace, ]); }); + + it("readonly getter (expression body)", async () => { + const input = Input.InClass(` +public int this[int i] +{ + readonly get => counter; + set { } +}`); + const tokens = await tokenize(input, "meta.accessor."); + + tokens.should.deep.equal([ + Token.Keyword.Modifier.Public, + Token.PrimitiveType.Int, + Token.Variable.This, + Token.Punctuation.OpenBracket, + Token.PrimitiveType.Int, + Token.Identifier.ParameterName("i"), + Token.Punctuation.CloseBracket, + Token.Punctuation.OpenBrace, + Token.Keyword.Modifier.ReadOnly, + Token.Keyword.Definition.Get, + Token.Operator.Arrow, + ...Scope.Accessor.Getter( + Token.Variable.ReadWrite("counter"), + ), + Token.Punctuation.Semicolon, + Token.Keyword.Definition.Set, + Token.Punctuation.OpenBrace, + Token.Punctuation.CloseBrace, + Token.Punctuation.CloseBrace]); + }); + + it("readonly getter (block body)", async () => { + const input = Input.InClass(` +public int Counter +{ + readonly get { return counter; } + set { counter = value; } +}`); + const tokens = await tokenize(input, "meta.accessor."); + + tokens.should.deep.equal([ + Token.Keyword.Modifier.Public, + Token.PrimitiveType.Int, + Token.Identifier.PropertyName("Counter"), + Token.Punctuation.OpenBrace, + Token.Keyword.Modifier.ReadOnly, + Token.Keyword.Definition.Get, + Token.Punctuation.OpenBrace, + ...Scope.Accessor.Getter( + Token.Keyword.Flow.Return, + Token.Variable.ReadWrite("counter"), + Token.Punctuation.Semicolon, + ), + Token.Punctuation.CloseBrace, + Token.Keyword.Definition.Set, + Token.Punctuation.OpenBrace, + ...Scope.Accessor.Setter( + Token.Variable.ReadWrite("counter"), + Token.Operator.Assignment, + Token.Variable.Value, + Token.Punctuation.Semicolon, + ), + Token.Punctuation.CloseBrace, + Token.Punctuation.CloseBrace]); + }); }); });