Skip to content

Commit 10e8692

Browse files
committed
Classify generic constraints
Fixes #301
1 parent 0febdc7 commit 10e8692

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

grammars/csharp.tmLanguage

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,24 @@
15661566
<key>match</key>
15671567
<string>\bstruct\b</string>
15681568
</dict>
1569+
<dict>
1570+
<key>name</key>
1571+
<string>keyword.other.constraint.default.cs</string>
1572+
<key>match</key>
1573+
<string>\bdefault\b</string>
1574+
</dict>
1575+
<dict>
1576+
<key>name</key>
1577+
<string>keyword.other.constraint.notnull.cs</string>
1578+
<key>match</key>
1579+
<string>\bnotnull\b</string>
1580+
</dict>
1581+
<dict>
1582+
<key>name</key>
1583+
<string>keyword.other.constraint.unmanaged.cs</string>
1584+
<key>match</key>
1585+
<string>\bunmanaged\b</string>
1586+
</dict>
15691587
<dict>
15701588
<key>match</key>
15711589
<string>(new)\s*(\()\s*(\))</string>

grammars/csharp.tmLanguage.cson

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,18 @@ repository:
979979
name: "storage.type.struct.cs"
980980
match: "\\bstruct\\b"
981981
}
982+
{
983+
name: "keyword.other.constraint.default.cs"
984+
match: "\\bdefault\\b"
985+
}
986+
{
987+
name: "keyword.other.constraint.notnull.cs"
988+
match: "\\bnotnull\\b"
989+
}
990+
{
991+
name: "keyword.other.constraint.unmanaged.cs"
992+
match: "\\bunmanaged\\b"
993+
}
982994
{
983995
match: "(new)\\s*(\\()\\s*(\\))"
984996
captures:

src/csharp.tmLanguage.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,12 @@ repository:
496496
match: \bclass\b
497497
- name: storage.type.struct.cs
498498
match: \bstruct\b
499+
- name: keyword.other.constraint.default.cs
500+
match: \bdefault\b
501+
- name: keyword.other.constraint.notnull.cs
502+
match: \bnotnull\b
503+
- name: keyword.other.constraint.unmanaged.cs
504+
match: \bunmanaged\b
499505
- match: (new)\s*(\()\s*(\))
500506
captures:
501507
'1': { name: keyword.operator.expression.new.cs }

test/class.tests.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,65 @@ unsafe class C
330330
Token.Punctuation.CloseBrace]);
331331
});
332332

333+
it(`class with various generic type constraints (#301)`, async () => {
334+
const input = Input.InNamespace(`
335+
class NotNullContainer<T> where T : notnull
336+
{
337+
private unsafe static void DisplaySize<T>()
338+
where T : unmanaged { }
339+
public override void M<T>(T? item)
340+
where T : default { }
341+
}`, namespaceStyle);
342+
const tokens = await tokenize(input);
343+
344+
tokens.should.deep.equal([
345+
Token.Keyword.Definition.Class,
346+
Token.Identifier.ClassName("NotNullContainer"),
347+
Token.Punctuation.TypeParameter.Begin,
348+
Token.Identifier.TypeParameterName("T"),
349+
Token.Punctuation.TypeParameter.End,
350+
Token.Keyword.Modifier.Where,
351+
Token.Identifier.TypeParameterName("T"),
352+
Token.Punctuation.Colon,
353+
Token.Keyword.Constraint.NotNull,
354+
Token.Punctuation.OpenBrace,
355+
Token.Keyword.Modifier.Private,
356+
Token.Keyword.Modifier.Unsafe,
357+
Token.Keyword.Modifier.Static,
358+
Token.PrimitiveType.Void,
359+
Token.Identifier.MethodName("DisplaySize"),
360+
Token.Punctuation.TypeParameter.Begin,
361+
Token.Identifier.TypeParameterName("T"),
362+
Token.Punctuation.TypeParameter.End,
363+
Token.Punctuation.OpenParen,
364+
Token.Punctuation.CloseParen,
365+
Token.Keyword.Modifier.Where,
366+
Token.Identifier.TypeParameterName("T"),
367+
Token.Punctuation.Colon,
368+
Token.Keyword.Constraint.Unmanaged,
369+
Token.Punctuation.OpenBrace,
370+
Token.Punctuation.CloseBrace,
371+
Token.Keyword.Modifier.Public,
372+
Token.Keyword.Modifier.Override,
373+
Token.PrimitiveType.Void,
374+
Token.Identifier.MethodName("M"),
375+
Token.Punctuation.TypeParameter.Begin,
376+
Token.Identifier.TypeParameterName("T"),
377+
Token.Punctuation.TypeParameter.End,
378+
Token.Punctuation.OpenParen,
379+
Token.Type("T"),
380+
Token.Punctuation.QuestionMark,
381+
Token.Identifier.ParameterName("item"),
382+
Token.Punctuation.CloseParen,
383+
Token.Keyword.Modifier.Where,
384+
Token.Identifier.TypeParameterName("T"),
385+
Token.Punctuation.Colon,
386+
Token.Keyword.Constraint.Default,
387+
Token.Punctuation.OpenBrace,
388+
Token.Punctuation.CloseBrace,
389+
Token.Punctuation.CloseBrace]);
390+
});
391+
333392
it(`primary constructor (${styleName} Namespace)`, async () => {
334393

335394
const input = Input.InNamespace(`

test/utils/tokenize.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ export namespace Token {
269269
export const When = createToken('when', 'keyword.control.conditional.when.cs');
270270
}
271271

272+
export namespace Constraint {
273+
export const Default = createToken('default', 'keyword.other.constraint.default.cs');
274+
export const NotNull = createToken('notnull', 'keyword.other.constraint.notnull.cs');
275+
export const Unmanaged = createToken('unmanaged', 'keyword.other.constraint.unmanaged.cs');
276+
}
277+
272278
export namespace Context {
273279
export const Checked = createToken('checked', 'keyword.control.context.checked.cs');
274280
export const Fixed = createToken('fixed', 'keyword.control.context.fixed.cs');

0 commit comments

Comments
 (0)